From c4b687d0127b1a8ad7c391d528735d6b3c145daf Mon Sep 17 00:00:00 2001 From: Matthieu Sieben Date: Thu, 7 Nov 2024 11:58:50 +0100 Subject: [PATCH] Forbid use of implicit any --- .changeset/eighty-carrots-arrive.md | 30 ++++++++ .changeset/eleven-dolphins-rhyme.md | 5 ++ .changeset/twelve-trainers-bathe.md | 5 ++ packages/api/src/agent.ts | 4 +- packages/api/src/moderation/decision.ts | 14 ++-- packages/api/tests/atp-agent.test.ts | 3 +- packages/api/tests/dispatcher.test.ts | 8 ++ packages/api/tsconfig.build.json | 1 + packages/api/tsconfig.tests.json | 3 +- packages/aws/src/s3.ts | 1 + packages/bsky/package.json | 1 + .../src/api/app/bsky/feed/getAuthorFeed.ts | 4 +- packages/bsky/src/api/util.ts | 2 +- packages/bsky/src/cache/read-through.ts | 2 +- packages/bsky/src/config.ts | 2 +- packages/bsky/src/data-plane/client.ts | 2 +- .../db/migrations/20230309T045948368Z-init.ts | 15 +++- .../bsky/src/data-plane/server/db/util.ts | 5 +- .../src/data-plane/server/indexing/index.ts | 15 ++-- .../data-plane/server/indexing/processor.ts | 6 +- .../src/data-plane/server/routes/profile.ts | 8 +- packages/bsky/src/hydration/util.ts | 9 ++- packages/bsky/src/logger.ts | 2 +- packages/bsky/src/redis.ts | 12 ++- packages/bsky/tsconfig.build.json | 3 +- packages/bsky/tsconfig.tests.json | 3 +- packages/bsync/src/logger.ts | 2 +- packages/bsync/tsconfig.build.json | 3 +- packages/common-web/src/arrays.ts | 5 +- packages/common-web/src/async.ts | 6 +- packages/common-web/src/ipld.ts | 59 +++++++++++---- packages/common-web/src/strings.ts | 16 ++-- packages/common-web/src/util.ts | 19 +++-- packages/common/src/logger.ts | 12 +-- packages/dev-env/src/seed/client.ts | 59 ++++++++------- packages/dev-env/tsconfig.build.json | 3 +- packages/did/src/did-error.ts | 12 ++- packages/internal/fetch-node/src/safe.ts | 15 +++- packages/internal/fetch/src/fetch-error.ts | 3 +- packages/internal/fetch/src/fetch-request.ts | 4 +- packages/internal/fetch/src/fetch-wrap.ts | 6 +- .../src/node-resolve-txt-factory.ts | 4 +- .../package.json | 1 + .../internal/simple-store-memory/src/util.ts | 2 +- packages/lex-cli/src/codegen/client.ts | 8 +- packages/lex-cli/src/codegen/common.ts | 4 +- packages/lex-cli/src/codegen/server.ts | 14 ++-- packages/lex-cli/src/codegen/util.ts | 4 +- packages/lex-cli/src/mdgen/index.ts | 8 +- packages/lex-cli/src/util.ts | 2 +- packages/lexicon/src/serialize.ts | 27 ++++--- packages/lexicon/tsconfig.build.json | 1 + .../auth/credential/use-credential-auth.ts | 23 +++--- .../src/browser-oauth-database.ts | 2 +- packages/oauth/oauth-client/src/fetch-dpop.ts | 7 +- packages/oauth/oauth-client/src/runtime.ts | 10 +-- packages/oauth/oauth-client/src/util.ts | 12 +-- packages/oauth/oauth-provider/package.json | 1 + .../src/assets/app/backend-data.ts | 4 +- .../assets/app/components/sign-in-form.tsx | 1 + .../oauth-provider/src/assets/app/lib/api.ts | 12 ++- .../src/client/client-manager.ts | 6 +- .../oauth/oauth-provider/src/lib/html/html.ts | 2 +- .../oauth-provider/src/lib/http/parser.ts | 15 ++-- .../src/output/build-error-payload.ts | 7 +- packages/oauth/oauth-types/src/util.ts | 2 +- packages/ozone/package.json | 1 + packages/ozone/src/logger.ts | 2 +- packages/ozone/src/mod-service/views.ts | 9 ++- packages/ozone/src/sequencer/outbox.ts | 2 +- .../ozone/src/tag-service/language-tagger.ts | 8 +- packages/ozone/tsconfig.build.json | 1 + packages/ozone/tsconfig.tests.json | 3 +- packages/pds/package.json | 4 + packages/pds/src/account-manager/index.ts | 4 +- packages/pds/src/actor-store/record/reader.ts | 8 +- .../src/api/com/atproto/repo/applyWrites.ts | 4 + .../src/api/com/atproto/repo/createRecord.ts | 2 + .../pds/src/api/com/atproto/repo/putRecord.ts | 7 +- .../src/api/com/atproto/repo/uploadBlob.ts | 2 +- packages/pds/src/auth-verifier.ts | 15 ++-- packages/pds/src/db/db.ts | 2 +- packages/pds/src/db/util.ts | 10 +-- packages/pds/src/logger.ts | 2 +- packages/pds/src/pipethrough.ts | 2 +- packages/pds/src/repo/prepare.ts | 22 +++--- packages/pds/src/repo/types.ts | 4 + packages/pds/src/sequencer/outbox.ts | 2 +- packages/pds/tsconfig.build.json | 3 +- packages/pds/tsconfig.tests.json | 3 +- packages/repo/src/storage/types.ts | 2 +- packages/sync/src/firehose/index.ts | 8 +- packages/sync/tsconfig.build.json | 3 +- packages/syntax/src/aturi_validation.ts | 8 +- packages/xrpc-server/package.json | 1 + packages/xrpc-server/src/server.ts | 44 +++++++++-- .../xrpc-server/src/stream/subscription.ts | 3 +- .../src/stream/websocket-keepalive.ts | 18 ++++- packages/xrpc-server/src/types.ts | 15 ++-- packages/xrpc/src/types.ts | 20 +++-- packages/xrpc/src/util.ts | 5 +- pnpm-lock.yaml | 74 ++++++++++++++++++- tsconfig/base.json | 3 +- 103 files changed, 626 insertions(+), 268 deletions(-) create mode 100644 .changeset/eighty-carrots-arrive.md create mode 100644 .changeset/eleven-dolphins-rhyme.md create mode 100644 .changeset/twelve-trainers-bathe.md diff --git a/.changeset/eighty-carrots-arrive.md b/.changeset/eighty-carrots-arrive.md new file mode 100644 index 00000000000..7f38994b074 --- /dev/null +++ b/.changeset/eighty-carrots-arrive.md @@ -0,0 +1,30 @@ +--- +"@atproto/oauth-client-browser-example": patch +"@atproto-labs/handle-resolver-node": patch +"@atproto-labs/simple-store-memory": patch +"@atproto/oauth-client-browser": patch +"@atproto/oauth-provider": patch +"@atproto-labs/fetch-node": patch +"@atproto/oauth-client": patch +"@atproto/oauth-types": patch +"@atproto-labs/fetch": patch +"@atproto/xrpc-server": patch +"@atproto/common-web": patch +"@atproto/dev-env": patch +"@atproto/lex-cli": patch +"@atproto/lexicon": patch +"@atproto/common": patch +"@atproto/syntax": patch +"@atproto/bsync": patch +"@atproto/ozone": patch +"@atproto/bsky": patch +"@atproto/repo": patch +"@atproto/sync": patch +"@atproto/xrpc": patch +"@atproto/api": patch +"@atproto/aws": patch +"@atproto/did": patch +"@atproto/pds": patch +--- + +Fix "implicit any" types diff --git a/.changeset/eleven-dolphins-rhyme.md b/.changeset/eleven-dolphins-rhyme.md new file mode 100644 index 00000000000..2e5a9e5ff0e --- /dev/null +++ b/.changeset/eleven-dolphins-rhyme.md @@ -0,0 +1,5 @@ +--- +"@atproto/common-web": patch +--- + +Expose isCid utility function diff --git a/.changeset/twelve-trainers-bathe.md b/.changeset/twelve-trainers-bathe.md new file mode 100644 index 00000000000..cd9a070a2cc --- /dev/null +++ b/.changeset/twelve-trainers-bathe.md @@ -0,0 +1,5 @@ +--- +"@atproto/lexicon": patch +--- + +Small performance improvements diff --git a/packages/api/src/agent.ts b/packages/api/src/agent.ts index e96358e366a..110721a5e02 100644 --- a/packages/api/src/agent.ts +++ b/packages/api/src/agent.ts @@ -352,7 +352,7 @@ export class Agent extends XrpcClient { }) // assemble a map of labeler dids to the interpreted label value definitions - const labelDefs = {} + const labelDefs: Record = {} if (labelers.data) { for (const labeler of labelers.data .views as AppBskyLabelerDefs.LabelerViewDetailed[]) { @@ -1531,7 +1531,7 @@ export class Agent extends XrpcClient { .filter((pref) => !AppBskyActorDefs.isSavedFeedsPref(pref)) .concat([feedsPref]) }) - return res + return res! } private async updateSavedFeedsV2Preferences( diff --git a/packages/api/src/moderation/decision.ts b/packages/api/src/moderation/decision.ts index 042a90bbe45..ccb41875f06 100644 --- a/packages/api/src/moderation/decision.ts +++ b/packages/api/src/moderation/decision.ts @@ -251,11 +251,15 @@ export class ModerationDecision { addLabel(target: LabelTarget, label: Label, opts: ModerationOpts) { // look up the label definition - const labelDef = CUSTOM_LABEL_VALUE_RE.test(label.val) - ? opts.labelDefs?.[label.src]?.find( - (def) => def.identifier === label.val, - ) || LABELS[label.val] - : LABELS[label.val] + const labelDef = + (CUSTOM_LABEL_VALUE_RE.test(label.val) + ? opts.labelDefs?.[label.src]?.find( + (def) => def.identifier === label.val, + ) + : undefined) || + (Object.hasOwn(LABELS, label.val) + ? LABELS[label.val as keyof typeof LABELS] + : undefined) if (!labelDef) { // ignore labels we don't understand return diff --git a/packages/api/tests/atp-agent.test.ts b/packages/api/tests/atp-agent.test.ts index c259582d4d1..5bb1d57bbeb 100644 --- a/packages/api/tests/atp-agent.test.ts +++ b/packages/api/tests/atp-agent.test.ts @@ -3341,4 +3341,5 @@ describe('agent', () => { }) }) -const byType = (a, b) => a.$type.localeCompare(b.$type) +const byType = (a: { $type: string }, b: { $type: string }) => + a.$type.localeCompare(b.$type) diff --git a/packages/api/tests/dispatcher.test.ts b/packages/api/tests/dispatcher.test.ts index 0c686aa966a..719022acee5 100644 --- a/packages/api/tests/dispatcher.test.ts +++ b/packages/api/tests/dispatcher.test.ts @@ -449,16 +449,19 @@ describe('AtpAgent', () => { const agent2 = new AtpAgent({ service: `http://localhost:${port}` }) const res1 = await agent.com.atproto.server.describeServer() + // @ts-expect-error unspecced expect(res1.data['atproto-accept-labelers']).toEqual( `${BSKY_LABELER_DID};redact`, ) AtpAgent.configure({ appLabelers: ['did:plc:test1', 'did:plc:test2'] }) const res2 = await agent.com.atproto.server.describeServer() + // @ts-expect-error unspecced expect(res2.data['atproto-accept-labelers']).toEqual( 'did:plc:test1;redact, did:plc:test2;redact', ) const res3 = await agent2.com.atproto.server.describeServer() + // @ts-expect-error unspecced expect(res3.data['atproto-accept-labelers']).toEqual( 'did:plc:test1;redact, did:plc:test2;redact', ) @@ -476,12 +479,14 @@ describe('AtpAgent', () => { agent.configureLabelers(['did:plc:test1']) const res1 = await agent.com.atproto.server.describeServer() + // @ts-expect-error unspecced expect(res1.data['atproto-accept-labelers']).toEqual( `${BSKY_LABELER_DID};redact, did:plc:test1`, ) agent.configureLabelers(['did:plc:test1', 'did:plc:test2']) const res2 = await agent.com.atproto.server.describeServer() + // @ts-expect-error unspecced expect(res2.data['atproto-accept-labelers']).toEqual( `${BSKY_LABELER_DID};redact, did:plc:test1, did:plc:test2`, ) @@ -497,10 +502,12 @@ describe('AtpAgent', () => { const agent = new AtpAgent({ service: `http://localhost:${port}` }) const res1 = await agent.com.atproto.server.describeServer() + // @ts-expect-error unspecced expect(res1.data['atproto-proxy']).toBeFalsy() agent.configureProxy('did:plc:test1#atproto_labeler') const res2 = await agent.com.atproto.server.describeServer() + // @ts-expect-error unspecced expect(res2.data['atproto-proxy']).toEqual( 'did:plc:test1#atproto_labeler', ) @@ -508,6 +515,7 @@ describe('AtpAgent', () => { const res3 = await agent .withProxy('atproto_labeler', 'did:plc:test2') .com.atproto.server.describeServer() + // @ts-expect-error unspecced expect(res3.data['atproto-proxy']).toEqual( 'did:plc:test2#atproto_labeler', ) diff --git a/packages/api/tsconfig.build.json b/packages/api/tsconfig.build.json index 2a319212737..ee2c8b89aad 100644 --- a/packages/api/tsconfig.build.json +++ b/packages/api/tsconfig.build.json @@ -3,6 +3,7 @@ "compilerOptions": { "rootDir": "./src", "outDir": "./dist", + "noPropertyAccessFromIndexSignature": false, "noUnusedLocals": false }, "include": ["./src"] diff --git a/packages/api/tsconfig.tests.json b/packages/api/tsconfig.tests.json index bd21d2eeb5c..d01de36eb7e 100644 --- a/packages/api/tsconfig.tests.json +++ b/packages/api/tsconfig.tests.json @@ -4,7 +4,8 @@ "rootDir": ".", "types": ["jest", "./jest.d.ts"], "noEmit": true, - "noUnusedLocals": false + "noUnusedLocals": false, + "noPropertyAccessFromIndexSignature": false }, "include": ["./tests"] } diff --git a/packages/aws/src/s3.ts b/packages/aws/src/s3.ts index 81014d63f7d..ae583a32872 100644 --- a/packages/aws/src/s3.ts +++ b/packages/aws/src/s3.ts @@ -218,6 +218,7 @@ export class S3BlobStore implements BlobStore { } const handleErr = (err: unknown) => { + // @ts-expect-error (implicit any) if (err?.['Code'] === 'NoSuchKey') { throw new BlobNotFoundError() } else { diff --git a/packages/bsky/package.json b/packages/bsky/package.json index f9bc5a26294..4aa6277b67e 100644 --- a/packages/bsky/package.json +++ b/packages/bsky/package.json @@ -71,6 +71,7 @@ "@bufbuild/protoc-gen-es": "^1.5.0", "@connectrpc/protoc-gen-connect-es": "^1.1.4", "@did-plc/server": "^0.0.1", + "@types/compression": "^1.7.5", "@types/cors": "^2.8.12", "@types/express": "^4.17.13", "@types/express-serve-static-core": "^4.17.36", diff --git a/packages/bsky/src/api/app/bsky/feed/getAuthorFeed.ts b/packages/bsky/src/api/app/bsky/feed/getAuthorFeed.ts index d58500c07c4..c007d485e87 100644 --- a/packages/bsky/src/api/app/bsky/feed/getAuthorFeed.ts +++ b/packages/bsky/src/api/app/bsky/feed/getAuthorFeed.ts @@ -93,7 +93,9 @@ export const skeleton = async (inputs: { actorDid: did, limit: params.limit, cursor: params.cursor, - feedType: FILTER_TO_FEED_TYPE[params.filter], + feedType: Object.hasOwn(FILTER_TO_FEED_TYPE, params.filter) + ? FILTER_TO_FEED_TYPE[params.filter as keyof typeof FILTER_TO_FEED_TYPE] + : undefined, }) let items: FeedItem[] = res.items.map((item) => ({ diff --git a/packages/bsky/src/api/util.ts b/packages/bsky/src/api/util.ts index 3ee0ea2c59b..eaf77bd580c 100644 --- a/packages/bsky/src/api/util.ts +++ b/packages/bsky/src/api/util.ts @@ -11,7 +11,7 @@ type ResHeaderOpts = { export const resHeaders = ( opts: Partial, ): Record => { - const headers = {} + const headers: Record = {} if (opts.labelers) { headers[ATPROTO_CONTENT_LABELERS] = formatLabelerHeader(opts.labelers) } diff --git a/packages/bsky/src/cache/read-through.ts b/packages/bsky/src/cache/read-through.ts index aa2d207fae5..21af1bbd573 100644 --- a/packages/bsky/src/cache/read-through.ts +++ b/packages/bsky/src/cache/read-through.ts @@ -82,7 +82,7 @@ export class ReadThroughCache { if (opts?.revalidate) { return this.fetchAndCacheMany(keys) } - let cached: Record + let cached: Record try { cached = await this.redis.getMulti(keys) } catch (err) { diff --git a/packages/bsky/src/config.ts b/packages/bsky/src/config.ts index 629ab485a48..7ba957ff860 100644 --- a/packages/bsky/src/config.ts +++ b/packages/bsky/src/config.ts @@ -335,7 +335,7 @@ export class ServerConfig { function stripUndefineds( obj: Record, ): Record { - const result = {} + const result: Record = {} Object.entries(obj).forEach(([key, val]) => { if (val !== undefined) { result[key] = val diff --git a/packages/bsky/src/data-plane/client.ts b/packages/bsky/src/data-plane/client.ts index 11e68a6680c..c00c13a2890 100644 --- a/packages/bsky/src/data-plane/client.ts +++ b/packages/bsky/src/data-plane/client.ts @@ -32,7 +32,7 @@ export const createDataPlaneClient = ( const client = randomElement(remainingClients) assert(client, 'no clients available') try { - return await client.lib[method.localName](...args) + return await (client.lib as any)[method.localName](...args) } catch (err) { if ( err instanceof ConnectError && diff --git a/packages/bsky/src/data-plane/server/db/migrations/20230309T045948368Z-init.ts b/packages/bsky/src/data-plane/server/db/migrations/20230309T045948368Z-init.ts index 1ddfa30acbc..3df05db169c 100644 --- a/packages/bsky/src/data-plane/server/db/migrations/20230309T045948368Z-init.ts +++ b/packages/bsky/src/data-plane/server/db/migrations/20230309T045948368Z-init.ts @@ -11,9 +11,18 @@ export async function up(db: Kysely): Promise { db, ) } catch (err: unknown) { - // The "if not exists" isn't bulletproof against races, and we see test suites racing to - // create the extension. So we can just ignore errors indicating the extension already exists. - if (!err?.['detail']?.includes?.('(pg_trgm) already exists')) throw err + if ( + err instanceof Error && + 'detail' in err && + Array.isArray(err.detail) && + err.detail.includes('(pg_trgm) already exists') + ) { + // The "if not exists" isn't bulletproof against races, and we see test suites racing to + // create the extension. So we can just ignore errors indicating the extension already exists. + return + } + + throw err } // duplicateRecords diff --git a/packages/bsky/src/data-plane/server/db/util.ts b/packages/bsky/src/data-plane/server/db/util.ts index cee5d100f3d..53c25fcb0bd 100644 --- a/packages/bsky/src/data-plane/server/db/util.ts +++ b/packages/bsky/src/data-plane/server/db/util.ts @@ -2,6 +2,7 @@ import { DummyDriver, DynamicModule, ExpressionBuilder, + Kysely, RawBuilder, SelectQueryBuilder, sql, @@ -31,7 +32,7 @@ export const softDeleted = (actorOrRecord: { takedownRef: string | null }) => { export const countAll = sql`count(*)` // For use with doUpdateSet() -export const excluded = (db: DatabaseSchema, col) => { +export const excluded = (db: DatabaseSchema, col: string) => { return sql`${db.dynamic.ref(`excluded.${col}`)}` } @@ -49,7 +50,7 @@ export const dummyDialect = { createDriver() { return new DummyDriver() }, - createIntrospector(db) { + createIntrospector(db: Kysely) { return new SqliteIntrospector(db) }, createQueryCompiler() { diff --git a/packages/bsky/src/data-plane/server/indexing/index.ts b/packages/bsky/src/data-plane/server/indexing/index.ts index eb07b1d123d..a7859fe6356 100644 --- a/packages/bsky/src/data-plane/server/indexing/index.ts +++ b/packages/bsky/src/data-plane/server/indexing/index.ts @@ -1,4 +1,4 @@ -import { sql } from 'kysely' +import { ExpressionBuilder, sql } from 'kysely' import { CID } from 'multiformats/cid' import { AtpAgent, ComAtprotoSyncGetLatestCommit } from '@atproto/api' import { @@ -13,6 +13,7 @@ import { IdResolver, getPds } from '@atproto/identity' import { DAY, HOUR } from '@atproto/common' import { ValidationError } from '@atproto/lexicon' import { Database } from '../db' +import { DatabaseSchemaType } from '../db/database-schema' import { Actor } from '../db/tables/actor' import * as Post from './plugins/post' import * as Threadgate from './plugins/thread-gate' @@ -246,10 +247,10 @@ export class IndexingService { } findIndexerForCollection(collection: string) { - const indexers = Object.values( - this.records as Record>, - ) - return indexers.find((indexer) => indexer.collection === collection) + const indexers = Object.values(this.records) + return indexers.find((indexer) => indexer.collection === collection) as + | RecordProcessor + | undefined } async updateActorStatus(did: string, active: boolean, status: string = '') { @@ -325,7 +326,9 @@ export class IndexingService { .where('creator', '=', did) .execute() // posts - const postByUser = (qb) => + const postByUser = ( + qb: ExpressionBuilder, + ) => qb .selectFrom('post') .where('post.creator', '=', did) diff --git a/packages/bsky/src/data-plane/server/indexing/processor.ts b/packages/bsky/src/data-plane/server/indexing/processor.ts index d88d230dd5d..1f14d71762f 100644 --- a/packages/bsky/src/data-plane/server/indexing/processor.ts +++ b/packages/bsky/src/data-plane/server/indexing/processor.ts @@ -2,7 +2,7 @@ import { Insertable } from 'kysely' import { CID } from 'multiformats/cid' import { AtUri } from '@atproto/syntax' import { chunkArray } from '@atproto/common' -import { jsonStringToLex, stringifyLex } from '@atproto/lexicon' +import { jsonStringToLex, LexValue, stringifyLex } from '@atproto/lexicon' import { lexicons } from '../../../lexicon/lexicons' import { Database } from '../db' import DatabaseSchema from '../db/database-schema' @@ -75,7 +75,7 @@ export class RecordProcessor { uri: uri.toString(), cid: cid.toString(), did: uri.host, - json: stringifyLex(obj), + json: stringifyLex(obj as LexValue), indexedAt: timestamp, }) .onConflict((oc) => oc.doNothing()) @@ -127,7 +127,7 @@ export class RecordProcessor { .where('uri', '=', uri.toString()) .set({ cid: cid.toString(), - json: stringifyLex(obj), + json: stringifyLex(obj as LexValue), indexedAt: timestamp, }) .execute() diff --git a/packages/bsky/src/data-plane/server/routes/profile.ts b/packages/bsky/src/data-plane/server/routes/profile.ts index ae3819ebd5a..85e0cac0bc1 100644 --- a/packages/bsky/src/data-plane/server/routes/profile.ts +++ b/packages/bsky/src/data-plane/server/routes/profile.ts @@ -42,7 +42,7 @@ export default (db: Database): Partial> => ({ const row = byDid[did] const chatDeclaration = parseRecordBytes( chatDeclarations.records[i].record, - ) + ) as any return { exists: !!row, handle: row?.handle ?? undefined, @@ -68,11 +68,11 @@ export default (db: Database): Partial> => ({ if (handles.length === 0) { return { dids: [] } } - const res = await db.db + const res = (await db.db .selectFrom('actor') .where('handle', 'in', handles) - .selectAll() - .execute() + .select(['did', 'handle']) + .execute()) as { did: string; handle: string }[] const byHandle = keyBy(res, 'handle') const dids = handles.map((handle) => byHandle[handle]?.did ?? '') return { dids } diff --git a/packages/bsky/src/hydration/util.ts b/packages/bsky/src/hydration/util.ts index 88b386d07a5..55d22acb1c9 100644 --- a/packages/bsky/src/hydration/util.ts +++ b/packages/bsky/src/hydration/util.ts @@ -4,6 +4,7 @@ import { CID } from 'multiformats/cid' import * as ui8 from 'uint8arrays' import { lexicons } from '../lexicon/lexicons' import { Record } from '../proto/bsky_pb' +import { isTypeofObject, JsonValue } from '@atproto/common' export class HydrationMap extends Map implements Merges { merge(map: HydrationMap): this { @@ -83,8 +84,12 @@ export const parseRecord = ( } const isValidRecord = (json: unknown) => { - const lexRecord = jsonToLex(json) - if (typeof lexRecord?.['$type'] !== 'string') { + const lexRecord = jsonToLex(json as JsonValue) + if ( + !isTypeofObject(lexRecord) || + !('$type' in lexRecord) || + typeof lexRecord['$type'] !== 'string' + ) { return false } try { diff --git a/packages/bsky/src/logger.ts b/packages/bsky/src/logger.ts index 0355ac3455f..dab1f985c3d 100644 --- a/packages/bsky/src/logger.ts +++ b/packages/bsky/src/logger.ts @@ -21,7 +21,7 @@ export const httpLogger: ReturnType = export const loggerMiddleware = pinoHttp({ logger: httpLogger, serializers: { - err: (err: unknown) => ({ + err: (err: any) => ({ code: err?.['code'], message: err?.['message'], }), diff --git a/packages/bsky/src/redis.ts b/packages/bsky/src/redis.ts index 3104f021e4a..34a47435756 100644 --- a/packages/bsky/src/redis.ts +++ b/packages/bsky/src/redis.ts @@ -54,7 +54,13 @@ export class Redis { } results.push(result) for (const [seqBuf, values] of messages) { - const message = { cursor: seqBuf.toString(), contents: {} } + const message: { + cursor: string + contents: Record + } = { + cursor: seqBuf.toString(), + contents: {}, + } result.messages.push(message) for (let i = 0; i < values.length; ++i) { if (i % 2 === 0) continue @@ -116,10 +122,10 @@ export class Redis { async getMulti(keys: string[]) { const namespaced = keys.map((k) => this.ns(k)) const got = await this.driver.mget(...namespaced) - const results = {} + const results: Record = {} for (let i = 0; i < keys.length; i++) { const key = keys[i] - results[key] = got[i] + results[key] = got[i] ?? undefined } return results } diff --git a/packages/bsky/tsconfig.build.json b/packages/bsky/tsconfig.build.json index 944827a6f62..d57dd4fc682 100644 --- a/packages/bsky/tsconfig.build.json +++ b/packages/bsky/tsconfig.build.json @@ -3,7 +3,8 @@ "compilerOptions": { "rootDir": "./src", "outDir": "./dist", - "noUnusedLocals": false + "noUnusedLocals": false, + "noPropertyAccessFromIndexSignature": false }, "include": ["./src"] } diff --git a/packages/bsky/tsconfig.tests.json b/packages/bsky/tsconfig.tests.json index 7fac0ed90d5..405415af695 100644 --- a/packages/bsky/tsconfig.tests.json +++ b/packages/bsky/tsconfig.tests.json @@ -2,7 +2,8 @@ "extends": "../../tsconfig/tests.json", "compilerOptions": { "rootDir": ".", - "noUnusedLocals": false + "noUnusedLocals": false, + "noPropertyAccessFromIndexSignature": false }, "include": ["./tests"] } diff --git a/packages/bsync/src/logger.ts b/packages/bsync/src/logger.ts index daf2e039016..c7e740861c9 100644 --- a/packages/bsync/src/logger.ts +++ b/packages/bsync/src/logger.ts @@ -13,7 +13,7 @@ export const loggerMiddleware = pinoHttp({ paths: ['req.headers.authorization'], }, serializers: { - err: (err: unknown) => ({ + err: (err: any) => ({ code: err?.['code'], message: err?.['message'], }), diff --git a/packages/bsync/tsconfig.build.json b/packages/bsync/tsconfig.build.json index fafdab3d6f7..f82e48d9cf8 100644 --- a/packages/bsync/tsconfig.build.json +++ b/packages/bsync/tsconfig.build.json @@ -2,7 +2,8 @@ "extends": "../../tsconfig/node.json", "compilerOptions": { "rootDir": "./src", - "outDir": "./dist" + "outDir": "./dist", + "noPropertyAccessFromIndexSignature": false }, "include": ["./src"] } diff --git a/packages/common-web/src/arrays.ts b/packages/common-web/src/arrays.ts index 69fb9415cbe..f4d125db48b 100644 --- a/packages/common-web/src/arrays.ts +++ b/packages/common-web/src/arrays.ts @@ -1,4 +1,7 @@ -export const keyBy = (arr: T[], key: string): Record => { +export function keyBy< + T extends { [_ in K]: string }, + K extends string = string, +>(arr: T[], key: K): Record { return arr.reduce( (acc, cur) => { acc[cur[key]] = cur diff --git a/packages/common-web/src/async.ts b/packages/common-web/src/async.ts index e6da0fa6200..b97aac89e42 100644 --- a/packages/common-web/src/async.ts +++ b/packages/common-web/src/async.ts @@ -49,11 +49,11 @@ export type Deferrable = { } export const createDeferrable = (): Deferrable => { - let resolve - const promise: Promise = new Promise((res) => { + let resolve: () => void + const promise = new Promise((res) => { resolve = () => res() }) - return { resolve, complete: promise } + return { resolve: resolve!, complete: promise } } export const createDeferrables = (count: number): Deferrable[] => { diff --git a/packages/common-web/src/ipld.ts b/packages/common-web/src/ipld.ts index 27e7bf2397a..5fa6192e5c6 100644 --- a/packages/common-web/src/ipld.ts +++ b/packages/common-web/src/ipld.ts @@ -7,7 +7,6 @@ export type JsonValue = | string | null | undefined - | unknown | Array | { [key: string]: JsonValue } @@ -18,16 +17,25 @@ export type IpldValue = | Array | { [key: string]: IpldValue } +export type ExtractTypeofObject = Exclude< + T, + // eslint-disable-next-line @typescript-eslint/ban-types + null | undefined | string | number | boolean | symbol | Function +> + +export const isTypeofObject = (val: V): val is ExtractTypeofObject => + val != null && typeof val === 'object' + // @NOTE avoiding use of check.is() here only because it makes // these implementations slow, and they often live in hot paths. export const jsonToIpld = (val: JsonValue): IpldValue => { // walk arrays if (Array.isArray(val)) { - return val.map((item) => jsonToIpld(item)) + return val.map(jsonToIpld) } // objects - if (val && typeof val === 'object') { + if (isTypeofObject(val)) { // check for dag json values if (typeof val['$link'] === 'string' && Object.keys(val).length === 1) { return CID.parse(val['$link']) @@ -36,7 +44,7 @@ export const jsonToIpld = (val: JsonValue): IpldValue => { return ui8.fromString(val['$bytes'], 'base64') } // walk plain objects - const toReturn = {} + const toReturn: { [key: string]: IpldValue } = {} for (const key of Object.keys(val)) { toReturn[key] = jsonToIpld(val[key]) } @@ -60,13 +68,13 @@ export const ipldToJson = (val: IpldValue): JsonValue => { } } // convert cids - if (CID.asCID(val)) { + if (isCid(val)) { return { - $link: (val as CID).toString(), + $link: CID.asCID(val)!.toString(), } } // walk plain objects - const toReturn = {} + const toReturn: { [key: string]: JsonValue } = {} for (const key of Object.keys(val)) { toReturn[key] = ipldToJson(val[key]) } @@ -78,29 +86,50 @@ export const ipldToJson = (val: IpldValue): JsonValue => { export const ipldEquals = (a: IpldValue, b: IpldValue): boolean => { // walk arrays - if (Array.isArray(a) && Array.isArray(b)) { + if (Array.isArray(a)) { + if (!Array.isArray(b)) return false + if (a.length !== b.length) return false for (let i = 0; i < a.length; i++) { if (!ipldEquals(a[i], b[i])) return false } return true + } else if (Array.isArray(b)) { + return false } + // objects - if (a && b && typeof a === 'object' && typeof b === 'object') { + if (isTypeofObject(a)) { + if (!isTypeofObject(b)) return false + // check bytes - if (a instanceof Uint8Array && b instanceof Uint8Array) { - return ui8.equals(a, b) + if (a instanceof Uint8Array) { + return b instanceof Uint8Array && ui8.equals(a, b) + } else if (b instanceof Uint8Array) { + return false } + // check cids - if (CID.asCID(a) && CID.asCID(b)) { - return CID.asCID(a)?.equals(CID.asCID(b)) + if (isCid(a)) { + return CID.asCID(b)?.equals(CID.asCID(a)!) ?? false + } else if (isCid(b)) { + return false } + // walk plain objects - if (Object.keys(a).length !== Object.keys(b).length) return false - for (const key of Object.keys(a)) { + const aKeys = Object.keys(a) + if (aKeys.length !== Object.keys(b).length) return false + for (const key of aKeys) { if (!ipldEquals(a[key], b[key])) return false } return true + } else if (isTypeofObject(b)) { + return false } + return a === b } + +export function isCid(value: unknown): value is CID { + return CID.asCID(value) != null +} diff --git a/packages/common-web/src/strings.ts b/packages/common-web/src/strings.ts index 57702c47ae0..5d98b42b51d 100644 --- a/packages/common-web/src/strings.ts +++ b/packages/common-web/src/strings.ts @@ -25,14 +25,14 @@ export const parseLanguage = (langTag: string): LanguageTag | null => { if (!parsed?.groups) return null const parts = parsed.groups return { - grandfathered: parts.grandfathered, - language: parts.language, - extlang: parts.extlang, - script: parts.script, - region: parts.region, - variant: parts.variant, - extension: parts.extension, - privateUse: parts.privateUseA || parts.privateUseB, + grandfathered: parts['grandfathered'], + language: parts['language'], + extlang: parts['extlang'], + script: parts['script'], + region: parts['region'], + variant: parts['variant'], + extension: parts['extension'], + privateUse: parts['privateUseA'] || parts['privateUseB'], } } diff --git a/packages/common-web/src/util.ts b/packages/common-web/src/util.ts index 3082b045b78..3dfadb66cf7 100644 --- a/packages/common-web/src/util.ts +++ b/packages/common-web/src/util.ts @@ -28,7 +28,7 @@ export function omit( if (!src) return src - const dst = {} + const dst: Record = {} const srcKeys = Object.keys(src) for (let i = 0; i < srcKeys.length; i++) { const key = srcKeys[i] @@ -53,7 +53,7 @@ export type BailableWait = { } export const bailableWait = (ms: number): BailableWait => { - let bail + let bail: () => void const waitPromise = new Promise((res) => { const timeout = setTimeout(res, ms) bail = () => { @@ -61,7 +61,7 @@ export const bailableWait = (ms: number): BailableWait => { res() } }) - return { bail, wait: () => waitPromise } + return { bail: bail!, wait: () => waitPromise } } export const flattenUint8Arrays = (arrs: Uint8Array[]): Uint8Array => { @@ -117,12 +117,17 @@ export const asyncFilter = async ( export const isErrnoException = ( err: unknown, -): err is NodeJS.ErrnoException => { - return !!err && err['code'] +): err is Error & { code: string } => { + return err instanceof Error && 'code' in err && typeof err.code === 'string' } -export const errHasMsg = (err: unknown, msg: string): boolean => { - return !!err && typeof err === 'object' && err['message'] === msg +export const errHasMsg = ( + err: unknown, + msg: M, +): err is { message: M } => { + return ( + !!err && typeof err === 'object' && 'message' in err && err.message === msg + ) } export const chunkArray = (arr: T[], chunkSize: number): T[][] => { diff --git a/packages/common/src/logger.ts b/packages/common/src/logger.ts index 857d32ee9f2..1c93474428d 100644 --- a/packages/common/src/logger.ts +++ b/packages/common/src/logger.ts @@ -1,23 +1,23 @@ import pino from 'pino' -const allSystemsEnabled = !process.env.LOG_SYSTEMS -const enabledSystems = (process.env.LOG_SYSTEMS || '') +const allSystemsEnabled = !process.env['LOG_SYSTEMS'] +const enabledSystems = (process.env['LOG_SYSTEMS'] || '') .replace(',', ' ') .split(' ') -const enabledEnv = process.env.LOG_ENABLED +const enabledEnv = process.env['LOG_ENABLED'] const enabled = enabledEnv === 'true' || enabledEnv === 't' || enabledEnv === '1' -const level = process.env.LOG_LEVEL || 'info' +const level = process.env['LOG_LEVEL'] || 'info' const config = { enabled, level, } -const rootLogger = process.env.LOG_DESTINATION - ? pino(config, pino.destination(process.env.LOG_DESTINATION)) +const rootLogger = process.env['LOG_DESTINATION'] + ? pino(config, pino.destination(process.env['LOG_DESTINATION'])) : pino(config) const subsystems: Record = {} diff --git a/packages/dev-env/src/seed/client.ts b/packages/dev-env/src/seed/client.ts index 8b858fcac2f..3aa05e6b7d6 100644 --- a/packages/dev-env/src/seed/client.ts +++ b/packages/dev-env/src/seed/client.ts @@ -168,41 +168,40 @@ export class SeedClient< '../dev-env/src/seed/img/key-portrait-small.jpg', ) - let avatarBlob - { - const res = await this.agent.com.atproto.repo.uploadBlob(AVATAR_IMG, { - encoding: 'image/jpeg', - headers: this.getHeaders(by), - } as any) - avatarBlob = res.data.blob - } + const { + data: { blob: avatarBlob }, + } = await this.agent.com.atproto.repo.uploadBlob(AVATAR_IMG, { + encoding: 'image/jpeg', + headers: this.getHeaders(by), + }) - { - const res = await this.agent.app.bsky.actor.profile.create( - { repo: by }, - { - displayName, - description, - avatar: avatarBlob, - labels: selfLabels - ? { - $type: 'com.atproto.label.defs#selfLabels', - values: selfLabels.map((val) => ({ val })), - } - : undefined, - joinedViaStarterPack: joinedViaStarterPack?.raw, - createdAt: new Date().toISOString(), - }, - this.getHeaders(by), - ) - this.profiles[by] = { + const res = await this.agent.app.bsky.actor.profile.create( + { repo: by }, + { displayName, description, avatar: avatarBlob, - joinedViaStarterPack, - ref: new RecordRef(res.uri, res.cid), - } + labels: selfLabels + ? { + $type: 'com.atproto.label.defs#selfLabels', + values: selfLabels.map((val) => ({ val })), + } + : undefined, + joinedViaStarterPack: joinedViaStarterPack?.raw, + createdAt: new Date().toISOString(), + }, + this.getHeaders(by), + ) + + this.profiles[by] = { + displayName, + description, + // @ts-expect-error BlobRef does not spec "cid" + avatar: avatarBlob, + joinedViaStarterPack, + ref: new RecordRef(res.uri, res.cid), } + return this.profiles[by] } diff --git a/packages/dev-env/tsconfig.build.json b/packages/dev-env/tsconfig.build.json index fafdab3d6f7..f82e48d9cf8 100644 --- a/packages/dev-env/tsconfig.build.json +++ b/packages/dev-env/tsconfig.build.json @@ -2,7 +2,8 @@ "extends": "../../tsconfig/node.json", "compilerOptions": { "rootDir": "./src", - "outDir": "./dist" + "outDir": "./dist", + "noPropertyAccessFromIndexSignature": false }, "include": ["./src"] } diff --git a/packages/did/src/did-error.ts b/packages/did/src/did-error.ts index 17fc96c296d..b83554f52d8 100644 --- a/packages/did/src/did-error.ts +++ b/packages/did/src/did-error.ts @@ -33,10 +33,14 @@ export class DidError extends Error { : 'An unknown error occurred' const status = - (typeof cause?.['statusCode'] === 'number' - ? cause['statusCode'] - : undefined) ?? - (typeof cause?.['status'] === 'number' ? cause['status'] : undefined) + cause != null && typeof cause === 'object' + ? ('statusCode' in cause && typeof cause['statusCode'] === 'number' + ? cause['statusCode'] + : undefined) ?? + ('status' in cause && typeof cause['status'] === 'number' + ? cause['status'] + : undefined) + : undefined return new DidError(did, message, 'did-unknown-error', status, cause) } diff --git a/packages/internal/fetch-node/src/safe.ts b/packages/internal/fetch-node/src/safe.ts index c5eea6335f4..703e5bf0492 100644 --- a/packages/internal/fetch-node/src/safe.ts +++ b/packages/internal/fetch-node/src/safe.ts @@ -25,7 +25,7 @@ export type SafeFetchWrapOptions = NonNullable< * @see {@link https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html} */ export function safeFetchWrap({ - fetch = globalThis.fetch as Fetch, + fetch = globalThis.fetch, responseMaxSize = 512 * 1024, // 512kB ssrfProtection = true, allowCustomPort = !ssrfProtection, @@ -34,7 +34,18 @@ export function safeFetchWrap({ allowIpHost = true, allowPrivateIps = !ssrfProtection, timeout = 10e3, - forbiddenDomainNames = DEFAULT_FORBIDDEN_DOMAIN_NAMES as Iterable, + forbiddenDomainNames = DEFAULT_FORBIDDEN_DOMAIN_NAMES, +}: { + fetch?: Fetch + responseMaxSize?: number + ssrfProtection?: boolean + allowCustomPort?: boolean + allowData?: boolean + allowHttp?: boolean + allowIpHost?: boolean + allowPrivateIps?: boolean + timeout?: number + forbiddenDomainNames?: Iterable } = {}): Fetch { return toRequestTransformer( pipe( diff --git a/packages/internal/fetch/src/fetch-error.ts b/packages/internal/fetch/src/fetch-error.ts index d73e818ea94..5c5266cd747 100644 --- a/packages/internal/fetch/src/fetch-error.ts +++ b/packages/internal/fetch/src/fetch-error.ts @@ -37,7 +37,8 @@ function extractInfo(err: unknown): [statusCode: number, message: string] { return [500, 'Failed to fetch'] } - const code = err['code'] + const code = + err != null && typeof err === 'object' && 'code' in err && err['code'] if (typeof code === 'string') { switch (true) { case code === 'ENOTFOUND': diff --git a/packages/internal/fetch/src/fetch-request.ts b/packages/internal/fetch/src/fetch-request.ts index eabe02851f7..26325ba484a 100644 --- a/packages/internal/fetch/src/fetch-request.ts +++ b/packages/internal/fetch/src/fetch-request.ts @@ -32,7 +32,9 @@ export function protocolCheckRequestTransform(protocols: { const request = asRequest(input, init) const config: undefined | boolean | { allowCustomPort?: boolean } = - Object.hasOwn(protocols, protocol) ? protocols[protocol] : undefined + Object.hasOwn(protocols, protocol) + ? protocols[protocol as keyof typeof protocols] + : undefined if (!config) { throw new FetchRequestError( diff --git a/packages/internal/fetch/src/fetch-wrap.ts b/packages/internal/fetch/src/fetch-wrap.ts index e619aac863d..43469ec8245 100644 --- a/packages/internal/fetch/src/fetch-wrap.ts +++ b/packages/internal/fetch/src/fetch-wrap.ts @@ -13,7 +13,7 @@ export function loggedFetch({ }) { const onRequest = logRequest === true - ? async (request) => { + ? async (request: Request) => { const requestMessage = await stringifyMessage(request) console.info( `> ${request.method} ${request.url}\n${padLines(requestMessage, ' ')}`, @@ -23,7 +23,7 @@ export function loggedFetch({ const onResponse = logResponse === true - ? async (response) => { + ? async (response: Response) => { const responseMessage = await stringifyMessage(response.clone()) console.info( `< HTTP/1.1 ${response.status} ${response.statusText}\n${padLines(responseMessage, ' ')}`, @@ -33,7 +33,7 @@ export function loggedFetch({ const onError = logError === true - ? async (error) => { + ? async (error: unknown) => { console.error(`< Error:`, error) } : logError || undefined diff --git a/packages/internal/handle-resolver-node/src/node-resolve-txt-factory.ts b/packages/internal/handle-resolver-node/src/node-resolve-txt-factory.ts index 2429ea139f0..bada5425b90 100644 --- a/packages/internal/handle-resolver-node/src/node-resolve-txt-factory.ts +++ b/packages/internal/handle-resolver-node/src/node-resolve-txt-factory.ts @@ -68,10 +68,10 @@ function handleError(err: unknown) { // If the hostname does not resolve, return null if (err instanceof Error) { - if (err['code'] === 'ENOTFOUND') return null + if ('code' in err && err.code === 'ENOTFOUND') return null // Hostname is not a valid domain name - if (err['code'] === 'EBADNAME') throw err + if ('code' in err && err.code === 'EBADNAME') throw err // DNS server unreachable // if (err['code'] === 'ETIMEOUT') throw err diff --git a/packages/internal/rollup-plugin-bundle-manifest/package.json b/packages/internal/rollup-plugin-bundle-manifest/package.json index 8578f0414a6..ef78404534a 100644 --- a/packages/internal/rollup-plugin-bundle-manifest/package.json +++ b/packages/internal/rollup-plugin-bundle-manifest/package.json @@ -30,6 +30,7 @@ "rollup": "^4.0.0" }, "devDependencies": { + "@types/mime": "^3.0.1", "rollup": "^4.10.0", "typescript": "^5.6.3" }, diff --git a/packages/internal/simple-store-memory/src/util.ts b/packages/internal/simple-store-memory/src/util.ts index 0fb05fee470..a1fde3dcb2e 100644 --- a/packages/internal/simple-store-memory/src/util.ts +++ b/packages/internal/simple-store-memory/src/util.ts @@ -51,7 +51,7 @@ export function roughSizeOfObject(value: unknown): number { for (let i = 0; i < keys.length; i++) { bytes += 4 const key = keys[i] - const val = value[key] + const val: unknown = value[key as keyof typeof value] if (val !== undefined) stack.push(val) stack.push(key) } diff --git a/packages/lex-cli/src/codegen/client.ts b/packages/lex-cli/src/codegen/client.ts index 83225da5605..1945aecd93a 100644 --- a/packages/lex-cli/src/codegen/client.ts +++ b/packages/lex-cli/src/codegen/client.ts @@ -429,14 +429,18 @@ function genRecordCls(file: SourceFile, nsid: string, lexRecord: LexRecord) { } } -const lexiconTs = (project, lexicons: Lexicons, lexiconDoc: LexiconDoc) => +const lexiconTs = ( + project: Project, + lexicons: Lexicons, + lexiconDoc: LexiconDoc, +) => gen( project, `/types/${lexiconDoc.id.split('.').join('/')}.ts`, async (file) => { const imports: Set = new Set() - const main = lexiconDoc.defs.main + const main = lexiconDoc.defs['main'] if ( main?.type === 'query' || main?.type === 'subscription' || diff --git a/packages/lex-cli/src/codegen/common.ts b/packages/lex-cli/src/codegen/common.ts index a824d634def..b07c562a2cf 100644 --- a/packages/lex-cli/src/codegen/common.ts +++ b/packages/lex-cli/src/codegen/common.ts @@ -11,7 +11,7 @@ const PRETTIER_OPTS = { trailingComma: 'all' as const, } -export const utilTs = (project) => +export const utilTs = (project: Project) => gen(project, '/util.ts', async (file) => { file.replaceWithText(` export type OmitKey = { @@ -57,7 +57,7 @@ export function is$typed( `) }) -export const lexiconsTs = (project, lexicons: LexiconDoc[]) => +export const lexiconsTs = (project: Project, lexicons: LexiconDoc[]) => gen(project, '/lexicons.ts', async (file) => { const nsidToEnum = (nsid: string): string => { return nsid diff --git a/packages/lex-cli/src/codegen/server.ts b/packages/lex-cli/src/codegen/server.ts index bd7c1cfa3e7..5ca2900a3d3 100644 --- a/packages/lex-cli/src/codegen/server.ts +++ b/packages/lex-cli/src/codegen/server.ts @@ -85,9 +85,9 @@ const indexTs = ( // generate type imports for (const lexiconDoc of lexiconDocs) { if ( - lexiconDoc.defs.main?.type !== 'query' && - lexiconDoc.defs.main?.type !== 'subscription' && - lexiconDoc.defs.main?.type !== 'procedure' + lexiconDoc.defs['main']?.type !== 'query' && + lexiconDoc.defs['main']?.type !== 'subscription' && + lexiconDoc.defs['main']?.type !== 'procedure' ) { continue } @@ -314,14 +314,18 @@ function genNamespaceCls(file: SourceFile, ns: DefTreeNode) { } } -const lexiconTs = (project, lexicons: Lexicons, lexiconDoc: LexiconDoc) => +const lexiconTs = ( + project: Project, + lexicons: Lexicons, + lexiconDoc: LexiconDoc, +) => gen( project, `/types/${lexiconDoc.id.split('.').join('/')}.ts`, async (file) => { const imports: Set = new Set() - const main = lexiconDoc.defs.main + const main = lexiconDoc.defs['main'] if (main?.type === 'query' || main?.type === 'procedure') { //= import express from 'express' file.addImportDeclaration({ diff --git a/packages/lex-cli/src/codegen/util.ts b/packages/lex-cli/src/codegen/util.ts index c3b7a7322d4..bef99ddb5c1 100644 --- a/packages/lex-cli/src/codegen/util.ts +++ b/packages/lex-cli/src/codegen/util.ts @@ -17,11 +17,11 @@ export interface DefTreeNode { export function lexiconsToDefTree(lexicons: LexiconDoc[]): DefTreeNode[] { const tree: DefTreeNode[] = [] for (const lexicon of lexicons) { - if (!lexicon.defs.main) { + if (!lexicon.defs['main']) { continue } const node = getOrCreateNode(tree, lexicon.id.split('.').slice(0, -1)) - node.userTypes.push({ nsid: lexicon.id, def: lexicon.defs.main }) + node.userTypes.push({ nsid: lexicon.id, def: lexicon.defs['main'] }) } return tree } diff --git a/packages/lex-cli/src/mdgen/index.ts b/packages/lex-cli/src/mdgen/index.ts index ada79595897..70c9a52a2dc 100644 --- a/packages/lex-cli/src/mdgen/index.ts +++ b/packages/lex-cli/src/mdgen/index.ts @@ -68,10 +68,10 @@ function merge(arr: StringTree): string { .join('\n') } -function matchesStart(line) { - return /