@happyvertical/smrt-scanner 0.35.3 → 0.35.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -531,7 +531,7 @@ function extractSmrtImports(body) {
|
|
|
531
531
|
for (const node of body) {
|
|
532
532
|
if (node.type !== "ImportDeclaration") continue;
|
|
533
533
|
const source = node.source;
|
|
534
|
-
if (!source ||
|
|
534
|
+
if (!source || typeof source.value !== "string") continue;
|
|
535
535
|
const moduleName = source.value;
|
|
536
536
|
if (!moduleName.startsWith("@happyvertical/smrt-")) continue;
|
|
537
537
|
if (!imports.has(moduleName)) {
|
|
@@ -578,7 +578,7 @@ function extractTypeAliases(body) {
|
|
|
578
578
|
if (enumDecl) {
|
|
579
579
|
const name = enumDecl.id?.name;
|
|
580
580
|
const members = enumDecl.body?.members ?? enumDecl.members;
|
|
581
|
-
if (name && isSafeObjectKey(name) && members
|
|
581
|
+
if (name && isSafeObjectKey(name) && members && members.length > 0) {
|
|
582
582
|
const values = members.map((m) => {
|
|
583
583
|
if (m.initializer?.type === "Literal") {
|
|
584
584
|
const val = m.initializer.value;
|
|
@@ -586,7 +586,7 @@ function extractTypeAliases(body) {
|
|
|
586
586
|
if (typeof val === "number") return String(val);
|
|
587
587
|
}
|
|
588
588
|
return null;
|
|
589
|
-
}).filter(
|
|
589
|
+
}).filter((v) => v !== null);
|
|
590
590
|
if (values.length > 0) {
|
|
591
591
|
const allStrings = values.every((v) => v.startsWith("'"));
|
|
592
592
|
if (allStrings) {
|
|
@@ -933,8 +933,11 @@ function extractTypeName(type) {
|
|
|
933
933
|
return "object";
|
|
934
934
|
case "TSFunctionType":
|
|
935
935
|
return "Function";
|
|
936
|
+
// oxc-parser emits many TSType kinds the scanner does not resolve
|
|
937
|
+
// (e.g. intersections, tuples, conditional types); fall through to null.
|
|
938
|
+
default:
|
|
939
|
+
return null;
|
|
936
940
|
}
|
|
937
|
-
return null;
|
|
938
941
|
}
|
|
939
942
|
function getQualifiedName(node) {
|
|
940
943
|
const parts = [];
|
|
@@ -2114,4 +2117,4 @@ export {
|
|
|
2114
2117
|
extractSmrtImports as e,
|
|
2115
2118
|
parseFile as p
|
|
2116
2119
|
};
|
|
2117
|
-
//# sourceMappingURL=scanner-
|
|
2120
|
+
//# sourceMappingURL=scanner-BBNdy6xM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanner-BBNdy6xM.js","sources":["../../src/inheritance-resolver.ts","../../src/oxc-parser.ts","../../src/manifest-adapter.ts","../../src/scanner.ts"],"sourcesContent":["/**\n * Inheritance Resolver\n *\n * Resolves class inheritance chains using in-memory class map.\n * Handles STI (Single Table Inheritance) detection and field merging.\n */\n\nimport type {\n ExternalManifest,\n RawClassDefinition,\n RawFieldDefinition,\n ResolvedClassDefinition,\n} from './types.js';\n\n/**\n * Framework base classes that are always recognized.\n *\n * Hardcoded list — every framework abstract base class that consuming\n * packages can subclass without needing `@smrt()` must appear here, or\n * the scanner will silently drop undecorated subclasses from the manifest.\n *\n * `SmrtJunction`, `SmrtHierarchical`, and `SmrtPolymorphicAssociation` are\n * stopgap entries pending a manifest-driven base-class detection scheme —\n * core would export its abstract bases in its manifest and dependents would\n * resolve through them via the existing cross-package chain walker (see\n * `findClassDefinition`). After tracing the wiring at R3 kickoff\n * (2026-05-18), generalization was deferred: new `SmartObjectManifest →\n * ExternalManifest` adapter, new vite-plugin scan-path failure modes,\n * new sync-I/O surface — large cost for ~two saved lines per future\n * abstract base. R4 added the third base and re-confirmed the call: a new\n * abstract base is still two lines here + two in\n * `FRAMEWORK_ABSTRACT_BASE_NAMES`, far cheaper than the generalization's\n * new failure surface. Extend this list instead.\n */\nconst FRAMEWORK_BASE_CLASSES = new Set([\n 'SmrtObject',\n 'SmrtClass',\n 'SmrtCollection',\n 'SmrtJunction',\n 'SmrtHierarchical',\n 'SmrtPolymorphicAssociation',\n]);\n\n/**\n * Resolves class inheritance chains and STI hierarchies from raw OXC scan output.\n *\n * After {@link OxcScanner} parses files, `InheritanceResolver` builds a\n * class map from the raw definitions and walks each class's `extends` chain\n * to produce fully-resolved {@link ResolvedClassDefinition} objects.\n *\n * Key responsibilities:\n * - Walking extends chains across local classes and external package manifests.\n * - Detecting which classes participate in STI (Single Table Inheritance).\n * - Merging fields from ancestor classes for STI subclasses (base fields first).\n * - Caching resolved chains to avoid repeated traversals.\n *\n * Framework base classes (`SmrtObject`, `SmrtClass`, `SmrtCollection`) are\n * recognized without needing to appear in source files.\n *\n * @example\n * ```typescript\n * import { InheritanceResolver } from '@happyvertical/smrt-scanner';\n *\n * const resolver = new InheritanceResolver({ baseClasses: ['MyBaseClass'] });\n * resolver.addClasses(rawClasses);\n * const resolved = resolver.resolveAll();\n * ```\n *\n * @see {@link OxcScanner} which owns and drives this resolver internally.\n */\nexport class InheritanceResolver {\n /** Map of className -> RawClassDefinition */\n private classMap: Map<string, RawClassDefinition> = new Map();\n\n /** External package manifests for cross-package resolution */\n private externalManifests: Map<string, ExternalManifest> = new Map();\n\n /** Known base classes (user-provided) */\n private knownBaseClasses: Set<string>;\n\n /** Cache of resolved inheritance chains */\n private chainCache: Map<string, string[]> = new Map();\n\n /**\n * Create a new `InheritanceResolver`.\n *\n * @param options.baseClasses - Additional class names to treat as known\n * framework base classes (beyond the built-in `SmrtObject`, `SmrtClass`,\n * and `SmrtCollection`).\n * @param options.externalManifests - Pre-loaded external package manifests\n * keyed by package name, used for cross-package parent class resolution.\n */\n constructor(\n options: {\n baseClasses?: string[];\n externalManifests?: Map<string, ExternalManifest>;\n } = {},\n ) {\n this.knownBaseClasses = new Set([\n ...FRAMEWORK_BASE_CLASSES,\n ...(options.baseClasses || []),\n ]);\n this.externalManifests = options.externalManifests || new Map();\n }\n\n /**\n * Register raw class definitions from a scan pass.\n *\n * Adds each class to the internal class map by `className`. Calling this\n * clears the inheritance chain cache so subsequent calls to\n * {@link resolveAll} or {@link resolveInheritanceChain} reflect the new\n * classes.\n *\n * @param classes - Array of {@link RawClassDefinition} objects from\n * {@link ScanResults.classes}.\n */\n addClasses(classes: RawClassDefinition[]): void {\n for (const classDef of classes) {\n this.classMap.set(classDef.className, classDef);\n }\n // Clear cache when classes are added\n this.chainCache.clear();\n }\n\n /**\n * Register an external package manifest for cross-package base class resolution.\n *\n * Clears the chain cache after registration so re-resolution picks up the\n * new definitions.\n *\n * @param manifest - External package manifest providing class definitions\n * that may appear as base classes in the local project.\n *\n * @see {@link ExternalManifest}\n */\n addExternalManifest(manifest: ExternalManifest): void {\n this.externalManifests.set(manifest.packageName, manifest);\n this.chainCache.clear();\n }\n\n /**\n * Resolve all registered classes and return fully-resolved definitions.\n *\n * A class is included in the output if it either:\n * 1. Has an `@smrt()` decorator, or\n * 2. Directly or transitively extends a framework base class\n * (`SmrtObject`, `SmrtClass`, `SmrtCollection`) — this captures\n * collection classes such as `class MeetingCollection extends\n * SmrtCollection<Meeting>` that do not carry `@smrt()` themselves.\n *\n * @returns An array of {@link ResolvedClassDefinition} — one entry per\n * eligible class, with inheritance chain, STI metadata, and merged fields\n * populated.\n *\n * @see {@link resolve} to resolve a single class definition.\n */\n resolveAll(): ResolvedClassDefinition[] {\n const resolved: ResolvedClassDefinition[] = [];\n\n for (const classDef of this.classMap.values()) {\n // Include classes with @smrt() decorator\n // OR classes that extend framework base classes\n const extendsFrameworkBase = this.extendsFrameworkBase(classDef);\n if (!classDef.hasSmartDecorator && !extendsFrameworkBase) continue;\n\n const resolvedClass = this.resolve(classDef);\n resolved.push(resolvedClass);\n }\n\n return resolved;\n }\n\n /**\n * Check if a class extends a framework base class\n * (SmrtObject, SmrtClass, or SmrtCollection)\n */\n private extendsFrameworkBase(classDef: RawClassDefinition): boolean {\n // Direct extension of framework base\n if (\n classDef.extendsClause &&\n this.knownBaseClasses.has(classDef.extendsClause)\n ) {\n return true;\n }\n\n // Walk inheritance chain to check indirect extension\n const chain = this.resolveInheritanceChain(classDef.className);\n return chain.some((className) => this.knownBaseClasses.has(className));\n }\n\n /**\n * Resolve a single raw class definition into a fully-resolved definition.\n *\n * Computes the inheritance chain, determines the effective table strategy,\n * detects STI membership, and merges ancestor fields for STI classes.\n *\n * @param classDef - The raw class definition to resolve.\n * @returns A {@link ResolvedClassDefinition} with all inherited metadata\n * applied. The `packageName` field is left as `null` and must be set by\n * the caller (e.g. {@link ManifestAdapter}).\n *\n * @see {@link resolveAll} to resolve every registered class at once.\n */\n resolve(classDef: RawClassDefinition): ResolvedClassDefinition {\n const inheritanceChain = this.resolveInheritanceChain(classDef.className);\n const stiBase = this.findSTIBase(inheritanceChain);\n const effectiveTableStrategy = this.determineTableStrategy(\n classDef,\n inheritanceChain,\n );\n const isFrameworkBase = this.knownBaseClasses.has(classDef.className);\n const isSTI = effectiveTableStrategy === 'sti';\n\n // Merge fields for STI classes. For non-STI classes, the\n // ManifestGenerator in core selectively merges fields from framework\n // abstract bases (e.g. `SmrtHierarchical.parentId`) — see\n // `FRAMEWORK_ABSTRACT_BASE_NAMES` in\n // `packages/core/src/scanner/manifest-generator.ts`. Doing that merge\n // here too would compound with subtly different field shapes and\n // regress universal-baseline expectations in `fieldsFromClass`.\n const allFields = isSTI\n ? this.mergeFieldsForSTI(inheritanceChain)\n : classDef.fields;\n\n return {\n ...classDef,\n inheritanceChain,\n stiBase,\n effectiveTableStrategy,\n isSTI,\n isFrameworkBase,\n allFields,\n packageName: null, // Will be set by manifest adapter\n };\n }\n\n /**\n * Resolve the full inheritance chain for a named class, from the root base\n * class down to the named class itself.\n *\n * Results are memoised in an internal cache that is cleared whenever\n * {@link addClasses} or {@link addExternalManifest} is called.\n *\n * @param className - Name of the class to resolve.\n * @returns An ordered array of class names starting from the furthest\n * ancestor and ending with `className`.\n *\n * @example\n * ```typescript\n * // Given: class Article extends Content, class Content extends SmrtObject\n * resolver.resolveInheritanceChain('Article');\n * // => ['SmrtObject', 'Content', 'Article']\n * ```\n */\n resolveInheritanceChain(className: string): string[] {\n // Check cache\n const cached = this.chainCache.get(className);\n if (cached) return cached;\n\n const chain: string[] = [];\n const visited = new Set<string>();\n let current: string | null = className;\n\n while (current && !visited.has(current)) {\n visited.add(current);\n chain.unshift(current);\n\n // Check if this is a framework base class\n if (this.knownBaseClasses.has(current)) {\n break;\n }\n\n // Find parent class\n const classDef = this.findClassDefinition(current);\n current = classDef?.extendsClause || null;\n }\n\n // Cache result\n this.chainCache.set(className, chain);\n\n return chain;\n }\n\n /**\n * Look up a class definition by name, searching in priority order:\n * 1. Local classes added via {@link addClasses}.\n * 2. External package manifests added via {@link addExternalManifest}.\n * 3. Built-in framework base classes (`SmrtObject`, `SmrtClass`,\n * `SmrtCollection`) — returns a minimal stub definition so chain walking\n * can terminate cleanly.\n *\n * @param className - Class name to look up.\n * @returns The {@link RawClassDefinition} if found, or `null` if the class\n * is unknown to the resolver.\n */\n findClassDefinition(className: string): RawClassDefinition | null {\n // 1. Check local classes\n const local = this.classMap.get(className);\n if (local) return local;\n\n // 2. Check external manifests\n for (const manifest of this.externalManifests.values()) {\n const external = manifest.classes.get(className);\n if (external) return external;\n }\n\n // 3. Check if it's a known base class\n if (this.knownBaseClasses.has(className)) {\n // Return a minimal definition for framework bases\n return {\n className,\n filePath: '',\n extendsClause: null,\n extendsTypeArg: null,\n decoratorConfig: null,\n hasSmartDecorator: false,\n fields: [],\n methods: [],\n startLine: 0,\n endLine: 0,\n };\n }\n\n return null;\n }\n\n /**\n * Find the STI root class in a resolved inheritance chain.\n *\n * Walks the chain from base to leaf and returns the name of the first class\n * whose `@smrt()` decorator explicitly declares `tableStrategy: 'sti'`.\n *\n * @param chain - Ordered inheritance chain (base → leaf) as returned by\n * {@link resolveInheritanceChain}.\n * @returns The class name of the STI root, or `null` if no class in the\n * chain uses `tableStrategy: 'sti'`.\n */\n findSTIBase(chain: string[]): string | null {\n for (const className of chain) {\n const classDef = this.findClassDefinition(className);\n if (classDef?.decoratorConfig?.tableStrategy === 'sti') {\n return className;\n }\n }\n return null;\n }\n\n /**\n * Determine the effective table strategy (`'sti'` or `'cti'`) for a class.\n *\n * Resolution order:\n * 1. The class's own `@smrt({ tableStrategy })` declaration, if present.\n * 2. The nearest ancestor that declares `tableStrategy: 'sti'` — STI is\n * inherited automatically by all subclasses.\n * 3. Defaults to `'cti'` if no STI ancestor is found.\n *\n * @param classDef - Raw class definition whose strategy is being determined.\n * @param chain - Pre-resolved inheritance chain for `classDef` (base → leaf).\n * @returns `'sti'` or `'cti'`.\n */\n determineTableStrategy(\n classDef: RawClassDefinition,\n chain: string[],\n ): 'sti' | 'cti' {\n // Check if this class explicitly declares a strategy\n if (classDef.decoratorConfig?.tableStrategy) {\n return classDef.decoratorConfig.tableStrategy;\n }\n\n // Check ancestors for STI\n for (const className of chain) {\n if (className === classDef.className) continue;\n\n const ancestorDef = this.findClassDefinition(className);\n if (ancestorDef?.decoratorConfig?.tableStrategy === 'sti') {\n return 'sti';\n }\n }\n\n return 'cti';\n }\n\n /**\n * Merge fields from all classes in an STI inheritance chain.\n *\n * Iterates from the root base class to the leaf class so that base class\n * fields appear first in the returned array. If a field name is declared in\n * both an ancestor and a descendant, the ancestor's definition takes\n * precedence (first-seen wins), preserving the base-class column layout.\n *\n * @param chain - Ordered inheritance chain (base → leaf) as returned by\n * {@link resolveInheritanceChain}.\n * @returns A deduplicated, ordered array of {@link RawFieldDefinition}\n * covering every field in the STI hierarchy.\n */\n mergeFieldsForSTI(chain: string[]): RawFieldDefinition[] {\n const allFields: RawFieldDefinition[] = [];\n const seenNames = new Set<string>();\n\n for (const className of chain) {\n const classDef = this.findClassDefinition(className);\n if (!classDef) continue;\n\n for (const field of classDef.fields) {\n // Skip if already seen (child overrides parent)\n if (seenNames.has(field.name)) continue;\n\n seenNames.add(field.name);\n allFields.push(field);\n }\n }\n\n return allFields;\n }\n\n /**\n * Return all known descendants of a class.\n *\n * Useful for STI schema generation where the base table must accommodate\n * columns from every subclass.\n *\n * @param className - The ancestor class name to search from.\n * @returns An array of class names (local classes only) whose resolved\n * inheritance chain includes `className`. Does not include `className`\n * itself.\n */\n getDescendants(className: string): string[] {\n const descendants: string[] = [];\n\n for (const [name] of this.classMap) {\n if (name === className) continue;\n\n const chain = this.resolveInheritanceChain(name);\n if (chain.includes(className)) {\n descendants.push(name);\n }\n }\n\n return descendants;\n }\n\n /**\n * Check whether a class participates in an STI hierarchy.\n *\n * @param className - Name of the class to check.\n * @returns `true` if any class in the resolved inheritance chain declares\n * `tableStrategy: 'sti'`, `false` otherwise.\n */\n isSTIClass(className: string): boolean {\n const chain = this.resolveInheritanceChain(className);\n return this.findSTIBase(chain) !== null;\n }\n\n /**\n * Return aggregate statistics about the classes registered with this resolver.\n *\n * @returns An object with:\n * - `totalClasses` — total number of classes in the class map.\n * - `smrtClasses` — classes that carry `@smrt()`.\n * - `stiClasses` — `@smrt()` classes in an STI hierarchy.\n * - `maxInheritanceDepth` — length of the deepest inheritance chain among\n * `@smrt()` classes.\n */\n getStats(): {\n totalClasses: number;\n smrtClasses: number;\n stiClasses: number;\n maxInheritanceDepth: number;\n } {\n let smrtClasses = 0;\n let stiClasses = 0;\n let maxInheritanceDepth = 0;\n\n for (const classDef of this.classMap.values()) {\n if (classDef.hasSmartDecorator) {\n smrtClasses++;\n\n const chain = this.resolveInheritanceChain(classDef.className);\n maxInheritanceDepth = Math.max(maxInheritanceDepth, chain.length);\n\n if (this.findSTIBase(chain)) {\n stiClasses++;\n }\n }\n }\n\n return {\n totalClasses: this.classMap.size,\n smrtClasses,\n stiClasses,\n maxInheritanceDepth,\n };\n }\n}\n","/**\n * OXC-based TypeScript parser for SMRT class extraction\n *\n * Uses oxc-parser for high-performance syntactic parsing of TypeScript files.\n * Extracts @smrt() decorated classes with their fields, methods, and inheritance.\n *\n * @see https://oxc.rs/docs/guide/usage/parser.html\n */\n\nimport { readFileSync } from 'node:fs';\nimport { parseSync } from 'oxc-parser';\nimport type {\n FileScanResult,\n RawClassDefinition,\n RawDecorator,\n RawDecoratorConfig,\n RawFieldDefinition,\n RawMethodDefinition,\n RawParameterDefinition,\n ScanError,\n} from './types.js';\n\n/**\n * Get file extension for oxc-parser lang option\n */\nfunction getLangFromFilename(filename: string): 'ts' | 'tsx' | 'js' | 'jsx' {\n if (filename.endsWith('.tsx')) return 'tsx';\n if (filename.endsWith('.ts')) return 'ts';\n if (filename.endsWith('.jsx')) return 'jsx';\n return 'js';\n}\n\n/**\n * Extract line/column from offset in source text\n * Note: oxc-parser v0.108+ removed magicString, so we compute manually\n * @internal Exported for testing\n */\nexport function getLineColumn(\n sourceText: string,\n offset: number,\n): { line: number; column: number } | undefined {\n if (offset < 0 || offset > sourceText.length) {\n return undefined;\n }\n\n let line = 1;\n let lastNewlinePos = -1;\n\n for (let i = 0; i < offset; i++) {\n if (sourceText[i] === '\\n') {\n line++;\n lastNewlinePos = i;\n }\n }\n\n return {\n line,\n column: offset - lastNewlinePos, // 1-based column\n };\n}\n\n// ============================================================================\n// AST Node Types (TS-ESTree format from oxc-parser)\n// ============================================================================\n\ninterface Position {\n line: number;\n column: number;\n}\n\ninterface SourceLocation {\n start: Position;\n end: Position;\n}\n\ninterface BaseNode {\n type: string;\n loc?: SourceLocation;\n range?: [number, number];\n start?: number;\n end?: number;\n}\n\n/**\n * Get source range from an AST node.\n * oxc-parser v0.108+ uses start/end instead of range.\n */\nfunction getRange(node: BaseNode): [number, number] | null {\n if (node.range) return node.range;\n if (node.start !== undefined && node.end !== undefined)\n return [node.start, node.end];\n return null;\n}\n\n/**\n * Slice source text from an AST node's range.\n */\nfunction sliceSource(node: BaseNode, sourceText: string): string | null {\n const range = getRange(node);\n return range ? sourceText.slice(range[0], range[1]) : null;\n}\n\ninterface Program extends BaseNode {\n type: 'Program';\n body: Statement[];\n comments?: Comment[];\n}\n\ninterface Comment extends BaseNode {\n type: 'Line' | 'Block';\n value: string;\n}\n\ninterface ImportDeclaration extends BaseNode {\n type: 'ImportDeclaration';\n specifiers?: ImportSpecifierLike[];\n source: Literal;\n}\n\ntype ImportSpecifierLike =\n | ImportSpecifier\n | ImportNamespaceSpecifier\n | ImportDefaultSpecifier;\n\ninterface ImportSpecifier extends BaseNode {\n type: 'ImportSpecifier';\n imported: Identifier;\n local: Identifier;\n}\n\ninterface ImportNamespaceSpecifier extends BaseNode {\n type: 'ImportNamespaceSpecifier';\n local: Identifier;\n}\n\ninterface ImportDefaultSpecifier extends BaseNode {\n type: 'ImportDefaultSpecifier';\n local: Identifier;\n}\n\ntype Statement =\n | ClassDeclaration\n | ExportNamedDeclaration\n | ExportDefaultDeclaration\n | ImportDeclaration\n | TSTypeAliasDeclaration\n | TSEnumDeclaration;\n\ninterface ClassDeclaration extends BaseNode {\n type: 'ClassDeclaration';\n id: Identifier | null;\n superClass: Expression | null;\n superTypeParameters?: TSTypeParameterInstantiation;\n // oxc-parser v0.108+ renamed superTypeParameters to superTypeArguments\n superTypeArguments?: TSTypeParameterInstantiation;\n body: ClassBody;\n decorators?: Decorator[];\n}\n\ninterface TSTypeAliasDeclaration extends BaseNode {\n type: 'TSTypeAliasDeclaration';\n id: Identifier;\n typeAnnotation: TSType;\n}\n\ninterface TSEnumDeclaration extends BaseNode {\n type: 'TSEnumDeclaration';\n id: Identifier;\n // oxc-parser wraps members in a TSEnumBody node; older shapes expose\n // `members` directly on the declaration.\n body?: TSEnumBody;\n members?: TSEnumMember[];\n}\n\ninterface TSEnumBody extends BaseNode {\n type: 'TSEnumBody';\n members: TSEnumMember[];\n}\n\ninterface TSEnumMember extends BaseNode {\n type: 'TSEnumMember';\n initializer?: Expression;\n}\n\ninterface ClassBody extends BaseNode {\n type: 'ClassBody';\n body: ClassElement[];\n}\n\ntype ClassElement = PropertyDefinition | MethodDefinition;\n\ninterface PropertyDefinition extends BaseNode {\n type: 'PropertyDefinition';\n key: Expression;\n value: Expression | null;\n computed: boolean;\n static: boolean;\n readonly?: boolean;\n optional?: boolean;\n accessibility?: 'public' | 'private' | 'protected';\n typeAnnotation?: TSTypeAnnotation;\n decorators?: Decorator[];\n}\n\ninterface MethodDefinition extends BaseNode {\n type: 'MethodDefinition';\n key: Expression;\n value: FunctionExpression;\n kind: 'constructor' | 'method' | 'get' | 'set';\n computed: boolean;\n static: boolean;\n accessibility?: 'public' | 'private' | 'protected';\n}\n\ninterface FunctionExpression extends BaseNode {\n type: 'FunctionExpression';\n async: boolean;\n params: Pattern[];\n returnType?: TSTypeAnnotation;\n body: BlockStatement;\n}\n\ninterface BlockStatement extends BaseNode {\n type: 'BlockStatement';\n body: Statement[];\n}\n\ntype Pattern =\n | Identifier\n | AssignmentPattern\n | RestElement\n | ObjectPattern\n | ArrayPattern;\n\ninterface Identifier extends BaseNode {\n type: 'Identifier';\n name: string;\n typeAnnotation?: TSTypeAnnotation;\n optional?: boolean;\n}\n\ninterface AssignmentPattern extends BaseNode {\n type: 'AssignmentPattern';\n left: Pattern;\n right: Expression;\n}\n\ninterface RestElement extends BaseNode {\n type: 'RestElement';\n argument: Pattern;\n typeAnnotation?: TSTypeAnnotation;\n}\n\ninterface ObjectPattern extends BaseNode {\n type: 'ObjectPattern';\n properties: (Property | RestElement)[];\n typeAnnotation?: TSTypeAnnotation;\n}\n\ninterface ArrayPattern extends BaseNode {\n type: 'ArrayPattern';\n elements: (Pattern | null)[];\n typeAnnotation?: TSTypeAnnotation;\n}\n\ninterface Property extends BaseNode {\n type: 'Property';\n key: Expression;\n value: Expression | Pattern;\n kind: 'init' | 'get' | 'set';\n method: boolean;\n shorthand: boolean;\n computed: boolean;\n}\n\ntype Expression =\n | Identifier\n | Literal\n | CallExpression\n | MemberExpression\n | ObjectExpression\n | ArrayExpression\n | NewExpression\n | UnaryExpression;\n\ninterface Literal extends BaseNode {\n type: 'Literal';\n value: string | number | boolean | null | RegExp | bigint;\n raw?: string;\n}\n\ninterface UnaryExpression extends BaseNode {\n type: 'UnaryExpression';\n operator: string;\n argument: Expression;\n}\n\ninterface CallExpression extends BaseNode {\n type: 'CallExpression';\n callee: Expression;\n arguments: Expression[];\n typeParameters?: TSTypeParameterInstantiation;\n}\n\ninterface MemberExpression extends BaseNode {\n type: 'MemberExpression';\n object: Expression;\n property: Expression;\n computed: boolean;\n}\n\ninterface ObjectExpression extends BaseNode {\n type: 'ObjectExpression';\n properties: (Property | SpreadElement)[];\n}\n\ninterface SpreadElement extends BaseNode {\n type: 'SpreadElement';\n argument: Expression;\n}\n\ninterface ArrayExpression extends BaseNode {\n type: 'ArrayExpression';\n elements: (Expression | SpreadElement | null)[];\n}\n\ninterface NewExpression extends BaseNode {\n type: 'NewExpression';\n callee: Expression;\n arguments: Expression[];\n}\n\ninterface Decorator extends BaseNode {\n type: 'Decorator';\n expression: Expression;\n}\n\ninterface ExportNamedDeclaration extends BaseNode {\n type: 'ExportNamedDeclaration';\n declaration: Statement | null;\n specifiers: ExportSpecifier[];\n}\n\ninterface ExportDefaultDeclaration extends BaseNode {\n type: 'ExportDefaultDeclaration';\n declaration: Statement | Expression;\n}\n\ninterface ExportSpecifier extends BaseNode {\n type: 'ExportSpecifier';\n local: Identifier;\n exported: Identifier;\n}\n\ninterface TSTypeAnnotation extends BaseNode {\n type: 'TSTypeAnnotation';\n typeAnnotation: TSType;\n}\n\ntype TSType =\n | TSStringKeyword\n | TSNumberKeyword\n | TSBooleanKeyword\n | TSAnyKeyword\n | TSVoidKeyword\n | TSNullKeyword\n | TSUndefinedKeyword\n | TSTypeReference\n | TSArrayType\n | TSUnionType\n | TSTypeLiteral\n | TSLiteralType\n | TSFunctionType;\n\ninterface TSLiteralType extends BaseNode {\n type: 'TSLiteralType';\n // oxc-parser models the literal as a generic `Literal` node.\n literal?: Literal;\n}\n\ninterface TSFunctionType extends BaseNode {\n type: 'TSFunctionType';\n}\n\ninterface TSStringKeyword extends BaseNode {\n type: 'TSStringKeyword';\n}\n\ninterface TSNumberKeyword extends BaseNode {\n type: 'TSNumberKeyword';\n}\n\ninterface TSBooleanKeyword extends BaseNode {\n type: 'TSBooleanKeyword';\n}\n\ninterface TSAnyKeyword extends BaseNode {\n type: 'TSAnyKeyword';\n}\n\ninterface TSVoidKeyword extends BaseNode {\n type: 'TSVoidKeyword';\n}\n\ninterface TSNullKeyword extends BaseNode {\n type: 'TSNullKeyword';\n}\n\ninterface TSUndefinedKeyword extends BaseNode {\n type: 'TSUndefinedKeyword';\n}\n\ninterface TSTypeReference extends BaseNode {\n type: 'TSTypeReference';\n typeName: Identifier | TSQualifiedName;\n typeParameters?: TSTypeParameterInstantiation;\n // oxc-parser v0.108+ renamed typeParameters to typeArguments\n typeArguments?: TSTypeParameterInstantiation;\n}\n\ninterface TSQualifiedName extends BaseNode {\n type: 'TSQualifiedName';\n left: Identifier | TSQualifiedName;\n right: Identifier;\n}\n\ninterface TSArrayType extends BaseNode {\n type: 'TSArrayType';\n elementType: TSType;\n}\n\ninterface TSUnionType extends BaseNode {\n type: 'TSUnionType';\n types: TSType[];\n}\n\ninterface TSTypeLiteral extends BaseNode {\n type: 'TSTypeLiteral';\n members: TSTypeElement[];\n}\n\ntype TSTypeElement =\n | TSPropertySignature\n | TSMethodSignature\n | TSIndexSignature;\n\ninterface TSPropertySignature extends BaseNode {\n type: 'TSPropertySignature';\n key: Expression;\n typeAnnotation?: TSTypeAnnotation;\n optional?: boolean;\n readonly?: boolean;\n}\n\ninterface TSMethodSignature extends BaseNode {\n type: 'TSMethodSignature';\n key: Expression;\n params: Pattern[];\n returnType?: TSTypeAnnotation;\n}\n\ninterface TSIndexSignature extends BaseNode {\n type: 'TSIndexSignature';\n parameters: Identifier[];\n typeAnnotation?: TSTypeAnnotation;\n}\n\ninterface TSTypeParameterInstantiation extends BaseNode {\n type: 'TSTypeParameterInstantiation';\n params: TSType[];\n}\n\n// ============================================================================\n// Parser Implementation\n// ============================================================================\n\n/**\n * Parse a single TypeScript file and extract SMRT class definitions.\n *\n * Reads the file from disk, runs oxc-parser on it, and returns all class\n * definitions found, any parse errors, accumulated type aliases, and\n * `@happyvertical/smrt-*` import metadata.\n *\n * @param filePath - Absolute path to the `.ts` or `.tsx` file to parse.\n * @returns A {@link FileScanResult} containing classes, errors, type aliases,\n * SMRT imports, and timing information for the file.\n *\n * @example\n * ```typescript\n * import { parseFile } from '@happyvertical/smrt-scanner';\n *\n * const result = parseFile('/project/src/models/Product.ts');\n * console.log(result.classes.map((c) => c.className));\n * // ['Product', 'ProductCollection']\n * ```\n *\n * @see {@link parseSource} to parse a source string directly (e.g. in tests).\n */\nexport function parseFile(filePath: string): FileScanResult {\n const startTime = performance.now();\n const errors: ScanError[] = [];\n const classes: RawClassDefinition[] = [];\n let typeAliases: Record<string, string> = {};\n let smrtImports: Map<string, Set<string>> | undefined;\n\n try {\n const sourceText = readFileSync(filePath, 'utf-8');\n const result = parseSync(filePath, sourceText, {\n lang: getLangFromFilename(filePath),\n preserveParens: false,\n });\n\n // Collect parse errors\n if (result.errors && result.errors.length > 0) {\n for (const error of result.errors) {\n const loc = error.labels?.[0]\n ? getLineColumn(sourceText, error.labels[0].start)\n : undefined;\n errors.push({\n message: error.message || 'Parse error',\n filePath,\n line: loc?.line,\n column: loc?.column,\n severity: error.severity === 'Error' ? 'error' : 'warning',\n });\n }\n }\n\n // Extract classes from AST\n const program = result.program as Program;\n if (program?.body) {\n const importAliases = extractImportAliases(program.body);\n typeAliases = extractTypeAliases(program.body);\n smrtImports = extractSmrtImports(program.body);\n for (const node of program.body) {\n const extracted = extractClassFromNode(\n node,\n filePath,\n sourceText,\n importAliases,\n );\n if (extracted) {\n classes.push(extracted);\n }\n }\n }\n } catch (error) {\n errors.push({\n message: error instanceof Error ? error.message : String(error),\n filePath,\n severity: 'error',\n });\n }\n\n const result2: FileScanResult = {\n filePath,\n classes,\n errors,\n parseTimeMs: performance.now() - startTime,\n typeAliases,\n };\n if (smrtImports && smrtImports.size > 0) {\n result2.smrtImports = smrtImports;\n }\n return result2;\n}\n\n/**\n * Parse TypeScript source text directly and extract SMRT class definitions.\n *\n * Identical to {@link parseFile} but accepts a source string instead of a\n * file path. Primarily used in tests and tooling that constructs source\n * programmatically.\n *\n * @param sourceText - Raw TypeScript source code to parse.\n * @param filename - Virtual filename used to determine the parser language\n * mode (`.ts`, `.tsx`, `.js`, `.jsx`) and to populate `filePath` fields in\n * the result. Defaults to `'test.ts'`.\n * @returns A {@link FileScanResult} containing classes, errors, type aliases,\n * and SMRT import metadata extracted from the source text.\n *\n * @example\n * ```typescript\n * import { parseSource } from '@happyvertical/smrt-scanner';\n *\n * const src = `\n * import { smrt } from '@happyvertical/smrt-core';\n * @smrt()\n * export class Widget extends SmrtObject {\n * label: string = '';\n * }\n * `;\n * const result = parseSource(src, 'Widget.ts');\n * console.log(result.classes[0].className); // 'Widget'\n * ```\n *\n * @see {@link parseFile} to parse a file from disk.\n */\nexport function parseSource(\n sourceText: string,\n filename = 'test.ts',\n): FileScanResult {\n const startTime = performance.now();\n const errors: ScanError[] = [];\n const classes: RawClassDefinition[] = [];\n let typeAliases: Record<string, string> = {};\n let smrtImports: Map<string, Set<string>> | undefined;\n\n try {\n const result = parseSync(filename, sourceText, {\n lang: getLangFromFilename(filename),\n preserveParens: false,\n });\n\n if (result.errors && result.errors.length > 0) {\n for (const error of result.errors) {\n const loc = error.labels?.[0]\n ? getLineColumn(sourceText, error.labels[0].start)\n : undefined;\n errors.push({\n message: error.message || 'Parse error',\n filePath: filename,\n line: loc?.line,\n column: loc?.column,\n severity: error.severity === 'Error' ? 'error' : 'warning',\n });\n }\n }\n\n const program = result.program as Program;\n if (program?.body) {\n const importAliases = extractImportAliases(program.body);\n typeAliases = extractTypeAliases(program.body);\n smrtImports = extractSmrtImports(program.body);\n for (const node of program.body) {\n const extracted = extractClassFromNode(\n node,\n filename,\n sourceText,\n importAliases,\n );\n if (extracted) {\n classes.push(extracted);\n }\n }\n }\n } catch (error) {\n errors.push({\n message: error instanceof Error ? error.message : String(error),\n filePath: filename,\n severity: 'error',\n });\n }\n\n const result2: FileScanResult = {\n filePath: filename,\n classes,\n errors,\n parseTimeMs: performance.now() - startTime,\n typeAliases,\n };\n if (smrtImports && smrtImports.size > 0) {\n result2.smrtImports = smrtImports;\n }\n return result2;\n}\n\n// ============================================================================\n// AST Extraction Helpers\n// ============================================================================\n\n/**\n * Property keys that must never be assigned onto a plain object built from\n * parsed source. Assigning `obj['__proto__'] = value` mutates the object's\n * prototype rather than adding an own property, which is a prototype-pollution\n * vector. `constructor` / `prototype` are blocked for defense-in-depth.\n *\n * Scanner input is developer-authored source consumed at build time (trusted),\n * so this is a hardening guard, not a fix for a remotely reachable bug: a class\n * field, decorator-config property, or type alias literally named `__proto__`\n * would otherwise silently corrupt the metadata object it is collected into.\n */\nconst FORBIDDEN_OBJECT_KEYS = new Set([\n '__proto__',\n 'constructor',\n 'prototype',\n]);\n\n/**\n * Whether a key is safe to assign as an own property on a plain object built\n * from parsed AST. See {@link FORBIDDEN_OBJECT_KEYS}.\n *\n * @internal Exported for testing.\n */\nexport function isSafeObjectKey(key: string): boolean {\n return !FORBIDDEN_OBJECT_KEYS.has(key);\n}\n\n/**\n * Extract import aliases from program body.\n * Maps local alias names to their original imported names.\n * e.g., `import { Performer as PerformerBase }` → Map { \"PerformerBase\" → \"Performer\" }\n */\nfunction extractImportAliases(body: Statement[]): Map<string, string> {\n const aliases = new Map<string, string>();\n for (const node of body) {\n if (node.type === 'ImportDeclaration' && node.specifiers) {\n for (const spec of node.specifiers) {\n if (spec.type === 'ImportSpecifier' && spec.imported && spec.local) {\n const original = spec.imported.name;\n const local = spec.local.name;\n if (original !== local) {\n aliases.set(local, original);\n }\n }\n }\n }\n }\n return aliases;\n}\n\n/**\n * Extract `@happyvertical/smrt-*` import declarations from an OXC program body.\n *\n * Scans the top-level AST statements for `ImportDeclaration` nodes whose\n * module specifier begins with `@happyvertical/smrt-` and collects the\n * PascalCase identifiers being imported. The result is used for tree-shaking:\n * only externally imported SMRT classes that appear in project source are\n * included in the generated manifest.\n *\n * Handles all import forms:\n * - Side-effect imports — `import '@happyvertical/smrt-messages'` (recorded as `'*'`)\n * - Named imports — `import { Person, Organization } from '@happyvertical/smrt-profiles'`\n * - Renamed named imports — `import { Person as PersonBase } from '...'` (records original name `Person`)\n * - Namespace imports — `import * as Profiles from '@happyvertical/smrt-profiles'` (recorded as `'*'`)\n * - Default imports — `import SomeClass from '@happyvertical/smrt-profiles'`\n *\n * Only PascalCase identifiers are recorded; utility function names (lowercase)\n * are ignored.\n *\n * @param body - The top-level statement array from the OXC-parsed `Program` node.\n * @returns A `Map` keyed by package name (e.g. `'@happyvertical/smrt-profiles'`)\n * whose values are `Set`s of the imported PascalCase class names (or `'*'`\n * for namespace imports).\n *\n * @example\n * ```typescript\n * import { parseSource, extractSmrtImports } from '@happyvertical/smrt-scanner';\n * import { parseSync } from 'oxc-parser';\n *\n * const src = `import { Person, Organization } from '@happyvertical/smrt-profiles';`;\n * const { program } = parseSync('file.ts', src, { lang: 'ts' });\n * const imports = extractSmrtImports(program.body);\n * // Map { '@happyvertical/smrt-profiles' => Set { 'Person', 'Organization' } }\n * ```\n *\n * @internal Exported for testing; use {@link OxcScanner.scanSmrtImports} for\n * production use cases.\n */\nexport function extractSmrtImports(\n body: Statement[],\n): Map<string, Set<string>> {\n const imports = new Map<string, Set<string>>();\n\n for (const node of body) {\n if (node.type !== 'ImportDeclaration') continue;\n\n // Get module specifier string\n const source = node.source;\n if (!source || typeof source.value !== 'string') continue;\n\n const moduleName = source.value;\n\n // Only process @happyvertical/smrt-* packages\n if (!moduleName.startsWith('@happyvertical/smrt-')) continue;\n\n // Get or create the set for this package\n if (!imports.has(moduleName)) {\n imports.set(moduleName, new Set());\n }\n const classSet = imports.get(moduleName)!;\n\n if (!node.specifiers || node.specifiers.length === 0) {\n classSet.add('*');\n continue;\n }\n\n for (const spec of node.specifiers) {\n if (spec.type === 'ImportSpecifier' && spec.imported && spec.local) {\n // Named import: use original (imported) name, not local alias\n const importedName = spec.imported.name;\n // Only include PascalCase names (likely classes)\n if (/^[A-Z][A-Za-z0-9]*$/.test(importedName)) {\n classSet.add(importedName);\n }\n } else if (spec.type === 'ImportNamespaceSpecifier') {\n // Namespace import: import * as X from '...'\n classSet.add('*');\n } else if (spec.type === 'ImportDefaultSpecifier' && spec.local) {\n // Default import: import SomeClass from '...'\n const defaultName = spec.local.name;\n if (/^[A-Z][A-Za-z0-9]*$/.test(defaultName)) {\n classSet.add(defaultName);\n }\n }\n }\n }\n\n return imports;\n}\n\n/**\n * Extract type alias declarations from program body.\n * Maps alias names to their resolved type strings.\n * e.g., `type Status = 'active' | 'inactive'` → { Status: \"'active' | 'inactive'\" }\n * @internal Exported for testing\n */\nexport function extractTypeAliases(body: Statement[]): Record<string, string> {\n const aliases: Record<string, string> = {};\n for (const node of body) {\n if (node.type === 'TSTypeAliasDeclaration') {\n const name = node.id?.name;\n const resolved = node.typeAnnotation\n ? extractTypeName(node.typeAnnotation)\n : null;\n if (name && resolved && isSafeObjectKey(name)) aliases[name] = resolved;\n }\n // Also check `export type X = ...` (ExportNamedDeclaration wrapping)\n if (\n node.type === 'ExportNamedDeclaration' &&\n node.declaration?.type === 'TSTypeAliasDeclaration'\n ) {\n const decl = node.declaration;\n const name = decl.id?.name;\n const resolved = decl.typeAnnotation\n ? extractTypeName(decl.typeAnnotation)\n : null;\n if (name && resolved && isSafeObjectKey(name)) aliases[name] = resolved;\n }\n\n // Extract enum declarations as string union types\n // e.g., enum Status { PENDING = 'pending', ACTIVE = 'active' }\n // → Status: \"'pending' | 'active'\"\n const enumDecl =\n node.type === 'TSEnumDeclaration'\n ? node\n : node.type === 'ExportNamedDeclaration' &&\n node.declaration?.type === 'TSEnumDeclaration'\n ? node.declaration\n : null;\n if (enumDecl) {\n const name = enumDecl.id?.name;\n // OXC wraps members in a TSEnumBody node: enumDecl.body.members\n const members = enumDecl.body?.members ?? enumDecl.members;\n if (name && isSafeObjectKey(name) && members && members.length > 0) {\n const values = members\n .map((m: TSEnumMember): string | null => {\n if (m.initializer?.type === 'Literal') {\n const val = m.initializer.value;\n if (typeof val === 'string') return `'${val}'`;\n if (typeof val === 'number') return String(val);\n }\n return null;\n })\n .filter((v): v is string => v !== null);\n\n if (values.length > 0) {\n // All string values → string union, all numeric → number union\n const allStrings = values.every((v) => v.startsWith(\"'\"));\n if (allStrings) {\n aliases[name] = values.join(' | ');\n }\n }\n }\n }\n }\n return aliases;\n}\n\n/**\n * Extract class definition from an AST node\n */\nfunction extractClassFromNode(\n node: Statement,\n filePath: string,\n sourceText: string,\n importAliases: Map<string, string>,\n): RawClassDefinition | null {\n // Handle export declarations\n if (node.type === 'ExportNamedDeclaration' && node.declaration) {\n return extractClassFromNode(\n node.declaration,\n filePath,\n sourceText,\n importAliases,\n );\n }\n if (node.type === 'ExportDefaultDeclaration' && node.declaration) {\n return extractClassFromNode(\n node.declaration as Statement,\n filePath,\n sourceText,\n importAliases,\n );\n }\n\n // Handle class declaration\n if (node.type === 'ClassDeclaration') {\n return extractClassDeclaration(node, filePath, sourceText, importAliases);\n }\n\n return null;\n}\n\n/**\n * Extract class declaration details\n */\nfunction extractClassDeclaration(\n node: ClassDeclaration,\n filePath: string,\n sourceText: string,\n importAliases: Map<string, string>,\n): RawClassDefinition {\n const className = node.id?.name || 'AnonymousClass';\n\n // Extract decorators\n const decorators = node.decorators || [];\n const smrtDecorator = decorators.find((d) => isSmrtDecorator(d));\n const tenantScopedDecorator = decorators.find((d) =>\n isNamedDecorator(d, 'TenantScoped'),\n );\n const hasSmartDecorator = !!smrtDecorator;\n const smrtConfig = smrtDecorator\n ? extractDecoratorConfig(smrtDecorator, sourceText)\n : null;\n const decoratorConfig = tenantScopedDecorator\n ? {\n ...(smrtConfig ?? {}),\n tenantScoped: extractDecoratorConfig(tenantScopedDecorator, sourceText),\n }\n : smrtConfig;\n\n // Extract extends clause\n const { extendsClause, extendsTypeArg } = extractExtendsClause(\n node,\n importAliases,\n );\n\n // Extract fields and methods\n const fields: RawFieldDefinition[] = [];\n const methods: RawMethodDefinition[] = [];\n\n for (const member of node.body.body) {\n if (member.type === 'PropertyDefinition') {\n const field = extractPropertyDefinition(member, sourceText);\n if (field) {\n fields.push(field);\n }\n } else if (member.type === 'MethodDefinition') {\n const method = extractMethodDefinition(member, sourceText);\n if (method) {\n methods.push(method);\n }\n }\n }\n\n return {\n className,\n filePath,\n extendsClause,\n extendsTypeArg,\n decoratorConfig,\n hasSmartDecorator,\n fields,\n methods,\n startLine: node.loc?.start.line || 1,\n endLine: node.loc?.end.line || 1,\n };\n}\n\n/**\n * Check if a decorator is @smrt()\n */\nfunction isSmrtDecorator(decorator: Decorator): boolean {\n return isNamedDecorator(decorator, 'smrt');\n}\n\nfunction isNamedDecorator(decorator: Decorator, name: string): boolean {\n const expr = decorator.expression;\n\n // @decoratorName() - CallExpression\n if (expr.type === 'CallExpression') {\n const callee = expr.callee;\n if (callee.type === 'Identifier' && callee.name === name) {\n return true;\n }\n }\n\n // @decoratorName - Identifier (no parentheses)\n if (expr.type === 'Identifier' && expr.name === name) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Extract @smrt() decorator configuration\n */\nfunction extractDecoratorConfig(\n decorator: Decorator,\n sourceText: string,\n): RawDecoratorConfig | null {\n const expr = decorator.expression;\n\n if (expr.type === 'CallExpression' && expr.arguments.length > 0) {\n const arg = expr.arguments[0];\n if (arg.type === 'ObjectExpression') {\n return extractObjectLiteral(arg, sourceText) as RawDecoratorConfig;\n }\n }\n\n // @smrt() with no config or @smrt\n return {};\n}\n\n/**\n * Extract object literal to plain object\n */\nfunction extractObjectLiteral(\n node: ObjectExpression,\n sourceText: string,\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const prop of node.properties) {\n if (prop.type === 'Property' && !prop.computed) {\n const key = getPropertyKey(prop.key);\n // Skip prototype-pollution keys (__proto__/constructor/prototype) so a\n // decorator-config property of that name cannot mutate the metadata\n // object's prototype.\n if (key && isSafeObjectKey(key)) {\n result[key] = extractValue(prop.value, sourceText);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Get property key as string\n */\nfunction getPropertyKey(node: Expression): string | null {\n if (node.type === 'Identifier') {\n return node.name;\n }\n if (node.type === 'Literal' && typeof node.value === 'string') {\n return node.value;\n }\n return null;\n}\n\n/**\n * Extract value from expression\n */\nfunction extractValue(node: Expression | Pattern, sourceText: string): unknown {\n switch (node.type) {\n case 'Literal':\n return node.value;\n\n case 'Identifier':\n // Handle special identifiers\n if (node.name === 'undefined') return undefined;\n if (node.name === 'null') return null;\n if (node.name === 'true') return true;\n if (node.name === 'false') return false;\n return node.name; // Return as string for class references\n\n case 'ArrayExpression':\n return node.elements\n .filter(\n (el: Expression | SpreadElement | null): el is Expression =>\n el !== null &&\n typeof el === 'object' &&\n 'type' in el &&\n el.type !== 'SpreadElement',\n )\n .map((el: Expression) => extractValue(el, sourceText));\n\n case 'ObjectExpression':\n return extractObjectLiteral(node, sourceText);\n\n case 'UnaryExpression':\n if (node.operator === '-' && node.argument?.type === 'Literal') {\n const value = node.argument.value;\n if (typeof value === 'number') {\n return -value;\n }\n }\n break;\n\n case 'CallExpression':\n case 'NewExpression': {\n // Return the raw source for complex expressions\n const src = sliceSource(node, sourceText);\n if (src) return src;\n break;\n }\n }\n\n // For complex expressions, return raw source if available\n const rawSrc = sliceSource(node, sourceText);\n if (rawSrc) return rawSrc;\n\n return undefined;\n}\n\n/**\n * Extract extends clause information\n */\nfunction extractExtendsClause(\n node: ClassDeclaration,\n importAliases: Map<string, string>,\n): {\n extendsClause: string | null;\n extendsTypeArg: string | null;\n} {\n if (!node.superClass) {\n return { extendsClause: null, extendsTypeArg: null };\n }\n\n let extendsClause: string | null = null;\n let extendsTypeArg: string | null = null;\n\n // Get class name\n if (node.superClass.type === 'Identifier') {\n extendsClause = node.superClass.name;\n } else if (node.superClass.type === 'MemberExpression') {\n // Handle Namespace.Class\n extendsClause = getMemberExpressionString(node.superClass);\n }\n\n // Resolve import aliases (e.g., import { Performer as PerformerBase })\n if (extendsClause && importAliases.has(extendsClause)) {\n extendsClause = importAliases.get(extendsClause)!;\n }\n\n // Get type argument (e.g., Meeting from SmrtCollection<Meeting>)\n // Note: oxc-parser v0.108+ renamed superTypeParameters to superTypeArguments\n const params =\n node.superTypeArguments?.params || node.superTypeParameters?.params;\n if (params && params.length > 0) {\n const typeParam = params[0];\n extendsTypeArg = extractTypeName(typeParam);\n }\n\n return { extendsClause, extendsTypeArg };\n}\n\n/**\n * Get member expression as dotted string\n */\nfunction getMemberExpressionString(node: MemberExpression): string {\n const parts: string[] = [];\n\n let current: Expression = node;\n while (current.type === 'MemberExpression') {\n if (current.property.type === 'Identifier') {\n parts.unshift(current.property.name);\n }\n current = current.object;\n }\n\n if (current.type === 'Identifier') {\n parts.unshift(current.name);\n }\n\n return parts.join('.');\n}\n\n/**\n * Reconstruct call expression string from AST\n * e.g., foreignKey(Customer) or decimal({ required: true })\n */\nfunction reconstructCallExpression(\n node: CallExpression,\n sourceText: string,\n): string | null {\n // Try range first\n const src = sliceSource(node, sourceText);\n if (src) return src;\n\n // Reconstruct from AST\n let callee = '';\n if (node.callee.type === 'Identifier') {\n callee = node.callee.name;\n } else if (node.callee.type === 'MemberExpression') {\n callee = getMemberExpressionString(node.callee);\n } else {\n return null;\n }\n\n // Reconstruct arguments\n const args: string[] = [];\n for (const arg of node.arguments) {\n const argSrc = sliceSource(arg, sourceText);\n if (argSrc) {\n args.push(argSrc);\n } else if (arg.type === 'Identifier') {\n args.push(arg.name);\n } else if (arg.type === 'Literal') {\n args.push(arg.raw || String(arg.value));\n } else if (arg.type === 'ObjectExpression') {\n // Simplified object reconstruction\n const objStr = reconstructObjectExpression(arg, sourceText);\n if (objStr) args.push(objStr);\n } else {\n // Skip complex arguments\n args.push('...');\n }\n }\n\n return `${callee}(${args.join(', ')})`;\n}\n\n/**\n * Reconstruct object expression string from AST\n */\nfunction reconstructObjectExpression(\n node: ObjectExpression,\n sourceText: string,\n): string | null {\n const src = sliceSource(node, sourceText);\n if (src) return src;\n\n const props: string[] = [];\n for (const prop of node.properties) {\n if (prop.type === 'SpreadElement') continue;\n if (prop.type === 'Property') {\n let key = '';\n if (prop.key.type === 'Identifier') {\n key = prop.key.name;\n } else if (prop.key.type === 'Literal') {\n key = String(prop.key.value);\n }\n if (!key) continue;\n\n let value = '';\n const valSrc = sliceSource(prop.value, sourceText);\n if (valSrc) {\n value = valSrc;\n } else if (prop.value.type === 'ObjectExpression') {\n // Recursively reconstruct nested objects (e.g., uiSlots.sources)\n value =\n reconstructObjectExpression(\n prop.value as ObjectExpression,\n sourceText,\n ) || '';\n } else if (prop.value.type === 'ArrayExpression') {\n value =\n reconstructArrayExpression(\n prop.value as ArrayExpression,\n sourceText,\n ) || '';\n } else if (prop.value.type === 'Identifier') {\n value = prop.value.name;\n } else if (prop.value.type === 'Literal') {\n value = prop.value.raw || String(prop.value.value);\n }\n\n if (value) {\n props.push(`${key}: ${value}`);\n }\n }\n }\n\n return `{ ${props.join(', ')} }`;\n}\n\n/**\n * Reconstruct array expression string from AST\n */\nfunction reconstructArrayExpression(\n node: ArrayExpression,\n sourceText: string,\n): string | null {\n const src = sliceSource(node, sourceText);\n if (src) return src;\n\n const elements: string[] = [];\n for (const el of node.elements) {\n if (!el) continue;\n if (el.type === 'SpreadElement') {\n elements.push('...');\n } else {\n const elSrc = sliceSource(el, sourceText);\n if (elSrc) {\n elements.push(elSrc);\n } else if (el.type === 'Identifier') {\n elements.push(el.name);\n } else if (el.type === 'Literal') {\n elements.push(el.raw || String(el.value));\n } else if (el.type === 'ObjectExpression') {\n const objStr = reconstructObjectExpression(\n el as ObjectExpression,\n sourceText,\n );\n if (objStr) elements.push(objStr);\n }\n }\n }\n\n return `[${elements.join(', ')}]`;\n}\n\n/**\n * Extract type name from TSType\n */\nfunction extractTypeName(type: TSType): string | null {\n switch (type.type) {\n case 'TSTypeReference': {\n let baseName: string | null = null;\n if (type.typeName.type === 'Identifier') {\n baseName = type.typeName.name;\n } else if (type.typeName.type === 'TSQualifiedName') {\n baseName = getQualifiedName(type.typeName);\n }\n\n // Include type parameters (e.g., Promise<any>, Map<string, number>)\n // Note: oxc-parser v0.108+ renamed typeParameters to typeArguments\n const typeParams =\n type.typeArguments?.params || type.typeParameters?.params;\n if (baseName && typeParams?.length) {\n const typeArgs = typeParams\n .map((p: TSType) => extractTypeName(p))\n .filter(Boolean);\n if (typeArgs.length > 0) {\n return `${baseName}<${typeArgs.join(', ')}>`;\n }\n }\n return baseName;\n }\n\n case 'TSStringKeyword':\n return 'string';\n case 'TSNumberKeyword':\n return 'number';\n case 'TSBooleanKeyword':\n return 'boolean';\n case 'TSAnyKeyword':\n return 'any';\n case 'TSVoidKeyword':\n return 'void';\n case 'TSNullKeyword':\n return 'null';\n case 'TSUndefinedKeyword':\n return 'undefined';\n\n case 'TSLiteralType': {\n const literal = type.literal;\n if (!literal) return null;\n // oxc-parser uses generic 'Literal' node type — distinguish by value type\n if (typeof literal.value === 'string') return `'${literal.value}'`;\n if (typeof literal.value === 'number') return String(literal.value);\n if (typeof literal.value === 'boolean') return String(literal.value);\n return null;\n }\n\n case 'TSArrayType': {\n const elementType = extractTypeName(type.elementType);\n return elementType ? `${elementType}[]` : null;\n }\n\n case 'TSUnionType': {\n const types = type.types\n .map((t: TSType) => extractTypeName(t))\n .filter(Boolean);\n return types.join(' | ');\n }\n\n // Inline object type literal: { subject?: string; from?: string; body?: string }\n // Maps to 'object' which the ManifestAdapter resolves as json\n case 'TSTypeLiteral':\n return 'object';\n case 'TSFunctionType':\n return 'Function';\n // oxc-parser emits many TSType kinds the scanner does not resolve\n // (e.g. intersections, tuples, conditional types); fall through to null.\n default:\n return null;\n }\n}\n\n/**\n * Get qualified name as string\n */\nfunction getQualifiedName(node: TSQualifiedName): string {\n const parts: string[] = [];\n\n let current: TSQualifiedName | Identifier = node;\n while (current.type === 'TSQualifiedName') {\n parts.unshift(current.right.name);\n current = current.left;\n }\n\n if (current.type === 'Identifier') {\n parts.unshift(current.name);\n }\n\n return parts.join('.');\n}\n\n/**\n * Extract property definition\n */\nfunction extractPropertyDefinition(\n node: PropertyDefinition,\n sourceText: string,\n): RawFieldDefinition | null {\n // Skip computed properties\n if (node.computed) return null;\n\n const name = getPropertyKey(node.key);\n if (!name) return null;\n // Reject prototype-polluting field names before they become manifest map keys\n // (a field literally named `__proto__`/`constructor`/`prototype`). The\n // type-alias/enum/object-literal extractors already gate on this; field\n // definitions must too (review #1559).\n if (!isSafeObjectKey(name)) return null;\n\n // Get type annotation\n const typeAnnotation = node.typeAnnotation\n ? extractTypeName(node.typeAnnotation.typeAnnotation)\n : null;\n\n // Get initializer\n let initializer: string | null = null;\n let hasDecimalPoint = false;\n let numericValue: number | null = null;\n\n if (node.value) {\n // Check for numeric literal with decimal point. Unwrap a leading unary\n // minus first: a negative initializer (`= -5`, `= -1.5`) parses as a\n // `UnaryExpression{ operator: '-', argument: Literal }`, not a bare\n // `Literal`, so without this the 0-vs-0.0 heuristic mis-infers negatives as\n // `integer` and drops the default. Mirrors the `extractValue` pattern above.\n if (\n node.value.type === 'UnaryExpression' &&\n node.value.operator === '-' &&\n node.value.argument?.type === 'Literal' &&\n typeof node.value.argument.value === 'number'\n ) {\n numericValue = -node.value.argument.value;\n // Check the inner literal's raw string for a decimal point (0.0 vs 0).\n if (node.value.argument.raw) {\n hasDecimalPoint = node.value.argument.raw.includes('.');\n }\n } else if (\n node.value.type === 'Literal' &&\n typeof node.value.value === 'number'\n ) {\n numericValue = node.value.value;\n // Check raw string for decimal point (0.0 vs 0)\n if (node.value.raw) {\n hasDecimalPoint = node.value.raw.includes('.');\n }\n }\n\n // Get raw initializer string - try range first for accurate source text\n const valueSrc = sliceSource(node.value, sourceText);\n if (valueSrc) {\n initializer = valueSrc;\n } else if (node.value.type === 'Literal' && node.value.raw) {\n // Fall back to raw property for literals\n initializer = node.value.raw;\n } else if (node.value.type === 'Literal') {\n // Convert literal value to string\n const val = node.value.value;\n if (typeof val === 'string') {\n initializer = `'${val}'`;\n } else if (val !== null && val !== undefined) {\n initializer = String(val);\n }\n } else if (\n node.value.type === 'CallExpression' ||\n node.value.type === 'NewExpression'\n ) {\n // Reconstruct call expression string from AST\n initializer = reconstructCallExpression(\n node.value as CallExpression,\n sourceText,\n );\n } else if (node.value.type === 'ArrayExpression') {\n // Reconstruct array expression\n initializer = reconstructArrayExpression(node.value, sourceText);\n } else if (node.value.type === 'ObjectExpression') {\n // Reconstruct object expression (e.g., static uiSlots = { ... })\n initializer = reconstructObjectExpression(\n node.value as ObjectExpression,\n sourceText,\n );\n }\n }\n\n // Extract decorators\n const decorators: RawDecorator[] = [];\n if (node.decorators) {\n for (const dec of node.decorators) {\n const extracted = extractFieldDecorator(dec, sourceText);\n if (extracted) {\n decorators.push(extracted);\n }\n }\n }\n\n return {\n name,\n typeAnnotation,\n initializer,\n hasDecimalPoint,\n numericValue,\n decorators,\n optional: node.optional || false,\n isStatic: node.static || false,\n readonly: node.readonly || false,\n accessibility: node.accessibility || 'public',\n line: node.loc?.start.line || 0,\n };\n}\n\n/**\n * Extract field decorator\n */\nfunction extractFieldDecorator(\n decorator: Decorator,\n sourceText: string,\n): RawDecorator | null {\n const expr = decorator.expression;\n\n let name: string | null = null;\n const args: string[] = [];\n\n if (expr.type === 'CallExpression') {\n if (expr.callee.type === 'Identifier') {\n name = expr.callee.name;\n }\n // Extract arguments as strings\n for (const arg of expr.arguments) {\n const argSrc = sliceSource(arg, sourceText);\n if (argSrc) args.push(argSrc);\n }\n } else if (expr.type === 'Identifier') {\n name = expr.name;\n }\n\n if (!name) return null;\n\n return { name, arguments: args };\n}\n\n/**\n * Extract method definition\n */\nfunction extractMethodDefinition(\n node: MethodDefinition,\n sourceText: string,\n): RawMethodDefinition | null {\n // Skip constructors, getters, setters\n if (node.kind !== 'method') return null;\n\n const name = getPropertyKey(node.key);\n if (!name) return null;\n\n const func = node.value;\n\n // Extract parameters\n const parameters: RawParameterDefinition[] = [];\n for (const param of func.params) {\n const extracted = extractParameter(param, sourceText);\n if (extracted) {\n parameters.push(extracted);\n }\n }\n\n // Extract return type\n const returnType = func.returnType\n ? extractTypeName(func.returnType.typeAnnotation)\n : null;\n\n return {\n name,\n async: func.async,\n isStatic: node.static,\n accessibility: node.accessibility || 'public',\n parameters,\n returnType,\n description: null, // TODO: Extract JSDoc\n line: node.loc?.start.line || 0,\n };\n}\n\n/**\n * Extract parameter definition\n */\nfunction extractParameter(\n param: Pattern,\n sourceText: string,\n): RawParameterDefinition | null {\n // Handle assignment pattern (default value)\n if (param.type === 'AssignmentPattern') {\n const left = param.left;\n if (left.type === 'Identifier') {\n return {\n name: left.name,\n type: left.typeAnnotation\n ? extractTypeName(left.typeAnnotation.typeAnnotation)\n : null,\n optional: true,\n defaultValue: sliceSource(param.right, sourceText),\n };\n }\n // Handle destructured parameter with default\n if (left.type === 'ObjectPattern' || left.type === 'ArrayPattern') {\n return {\n name: 'options',\n type: left.typeAnnotation\n ? extractTypeName(left.typeAnnotation.typeAnnotation)\n : 'any',\n optional: true,\n defaultValue: sliceSource(param.right, sourceText),\n };\n }\n return null;\n }\n\n // Handle rest parameter\n if (param.type === 'RestElement') {\n const arg = param.argument;\n if (arg.type === 'Identifier') {\n return {\n name: `...${arg.name}`,\n type: param.typeAnnotation\n ? extractTypeName(param.typeAnnotation.typeAnnotation)\n : null,\n optional: true,\n defaultValue: null,\n };\n }\n return null;\n }\n\n // Handle simple identifier\n if (param.type === 'Identifier') {\n return {\n name: param.name,\n type: param.typeAnnotation\n ? extractTypeName(param.typeAnnotation.typeAnnotation)\n : null,\n optional: param.optional || false,\n defaultValue: null,\n };\n }\n\n // Handle object pattern (destructured)\n if (param.type === 'ObjectPattern') {\n return {\n name: 'options',\n type: param.typeAnnotation\n ? extractTypeName(param.typeAnnotation.typeAnnotation)\n : 'any',\n optional: false,\n defaultValue: null,\n };\n }\n\n return null;\n}\n","/**\n * Manifest Adapter\n *\n * Converts OXC scanner output to smrt-core manifest format.\n * Ensures compatibility with existing manifest consumers.\n */\n\nimport { isSafeObjectKey } from './oxc-parser.js';\nimport type {\n FieldTypeInference,\n InferredFieldType,\n RawFieldDefinition,\n RawMethodDefinition,\n ResolvedClassDefinition,\n} from './types.js';\n\n// ============================================================================\n// smrt-core compatible types (copied to avoid circular dependency)\n// ============================================================================\n\n/**\n * Qualified class name format: \"@package/name:ClassName\"\n * Uniquely identifies classes across packages.\n */\ntype QualifiedClassName = `${string}:${string}`;\n\ninterface FieldDefinition {\n type:\n | 'text'\n | 'decimal'\n | 'boolean'\n | 'integer'\n | 'datetime'\n | 'json'\n | 'foreignKey'\n | 'crossPackageRef'\n | 'oneToMany'\n | 'manyToMany'\n | 'meta';\n required?: boolean;\n default?: unknown;\n min?: number;\n max?: number;\n maxLength?: number;\n minLength?: number;\n related?: string;\n description?: string;\n _meta?: Record<string, unknown>;\n transient?: boolean;\n /** Sensitive value — excluded from public serialization + where filtering. */\n sensitive?: boolean;\n /** Read-only over generated write surfaces — stripped from create/update bodies. */\n readonly?: boolean;\n}\n\ntype FieldDecoratorOptions = {\n type?: FieldDefinition['type'];\n required?: boolean;\n nullable?: boolean;\n default?: unknown;\n min?: number;\n max?: number;\n maxLength?: number;\n minLength?: number;\n related?: string;\n /** oneToMany explicit inverse foreign-key field on the target class */\n foreignKey?: string;\n description?: string;\n transient?: boolean;\n unique?: boolean;\n /** crossPackageRef opt-in save-time validation */\n validate?: boolean;\n /** manyToMany junction table name */\n through?: string;\n /** manyToMany override of the source-side join column */\n sourceKey?: string;\n /** manyToMany override of the target-side join column */\n targetKey?: string;\n /** meta opt-in JSON-path index */\n indexed?: boolean;\n /** sensitive value — excluded from public serialization + where filtering */\n sensitive?: boolean;\n /** read-only over generated write surfaces */\n readonly?: boolean;\n [key: string]: unknown;\n};\n\ninterface MethodDefinition {\n name: string;\n async: boolean;\n parameters: Array<{\n name: string;\n type: string;\n optional: boolean;\n default?: unknown;\n }>;\n returnType: string;\n description?: string;\n isStatic: boolean;\n isPublic: boolean;\n}\n\ninterface SmartObjectConfig {\n tableStrategy?: 'sti' | 'cti';\n idType?: 'uuid' | 'text';\n features?: Record<\n string,\n {\n defaultEnabled: boolean;\n label?: string;\n description?: string;\n metadata?: Record<string, unknown>;\n }\n >;\n api?: {\n include?: string[];\n exclude?: string[];\n };\n cli?:\n | boolean\n | {\n include?: string[];\n exclude?: string[];\n skipApiCheck?: boolean;\n http?: boolean;\n };\n mcp?: {\n include?: string[];\n exclude?: string[];\n };\n [key: string]: unknown;\n}\n\ninterface SmartObjectDefinition {\n name: string;\n className: string;\n qualifiedName?: QualifiedClassName; // NEW: @package/name:ClassName for namespace isolation (Issue #713)\n collection: string;\n filePath: string;\n packageName?: string;\n packageVersion?: string;\n importPath?: string;\n modulePath?: string;\n exportName?: string;\n collectionExportName?: string;\n fields: Record<string, FieldDefinition>;\n methods: Record<string, MethodDefinition>;\n decoratorConfig: SmartObjectConfig;\n extends?: string;\n extendsTypeArg?: string;\n staticProperties?: Record<string, unknown>;\n}\n\ninterface SmartObjectManifest {\n version: string;\n timestamp: number;\n packageName?: string;\n packageVersion?: string;\n objects: Record<string, SmartObjectDefinition>;\n moduleType?: string;\n smrtDependencies?: string[];\n}\n\n// ============================================================================\n// Utilities\n// ============================================================================\n\n/**\n * Property keys that must never appear as own properties on a manifest object.\n * Object literals authored as `{ constructor: ... }` or `{ prototype: ... }`\n * produce real own keys; spreading such a parsed object into a manifest\n * `_meta` / `staticProperties` entry (or assigning it under a class field name)\n * would carry a prototype-pollution gadget into the emitted JSON.\n */\n/**\n * Recursively strip prototype-pollution keys (via the shared\n * {@link isSafeObjectKey} guard — single source of truth with oxc-parser) from a\n * value parsed out of source. Returns a new plain object/array; primitives and\n * built-in objects pass through unchanged.\n */\nfunction sanitizeParsed(value: unknown, seen = new WeakSet<object>()): unknown {\n if (value === null || typeof value !== 'object') return value;\n\n const isArray = Array.isArray(value);\n // Preserve built-ins (Date, RegExp, Map, …) intact. They carry no\n // attacker-controlled own keys, and iterating their enumerable keys would\n // silently turn e.g. `@field({ default: new Date() })` into `{}` (review #1559).\n const proto = Object.getPrototypeOf(value);\n if (!isArray && proto !== Object.prototype && proto !== null) return value;\n\n // Cycle guard: a cyclic literal (e.g. an IIFE returning a self-referential\n // object) would otherwise recurse forever and hang the build (review #1559).\n if (seen.has(value as object)) return undefined;\n seen.add(value as object);\n\n if (isArray) {\n return (value as unknown[]).map((item) => sanitizeParsed(item, seen));\n }\n const clean: Record<string, unknown> = {};\n for (const key of Object.keys(value as Record<string, unknown>)) {\n if (!isSafeObjectKey(key)) continue;\n clean[key] = sanitizeParsed((value as Record<string, unknown>)[key], seen);\n }\n return clean;\n}\n\n/**\n * Parse a JavaScript literal (object or array) from source text.\n *\n * Uses the Function constructor to evaluate literal syntax at build time.\n * This is intentional — AST-based extraction can't handle computed keys,\n * template literals, or spread syntax that may appear in static initializers.\n *\n * The parsed result is run through {@link sanitizeParsed} to strip\n * prototype-pollution keys (`__proto__` / `constructor` / `prototype`) before\n * it is merged into a manifest object.\n *\n * WARNING: This executes the source text. It is only safe when scanning\n * your own trusted codebase at build time. Never run the scanner against\n * untrusted third-party code.\n */\nfunction parseLiteralInitializer(\n source: string,\n): Record<string, unknown> | unknown[] | null {\n const trimmed = source?.trim();\n if (!trimmed || (!trimmed.startsWith('{') && !trimmed.startsWith('[')))\n return null;\n try {\n // Use indirect eval via Function to parse the object/array literal\n // This runs at build time only, on trusted source code from our own codebase\n // The existing pattern (unchanged) uses Function constructor for object literal parsing\n // eslint-disable-next-line no-new-func\n const parsed = new Function(`return (${source})`)() as\n | Record<string, unknown>\n | unknown[];\n return sanitizeParsed(parsed) as Record<string, unknown> | unknown[];\n } catch {\n return null;\n }\n}\n\n/**\n * Strip surrounding quotes from a raw source string.\n * sliceSource() returns raw source text which includes quotes for string\n * literals (e.g., \"'TestProfile'\" or '\"TestProfile\"').\n */\nfunction stripQuotes(value: string | undefined): string | undefined {\n if (!value) return value;\n const match = value.match(/^(['\"`])(.+)\\1$/);\n return match ? match[2] : value;\n}\n\n// ============================================================================\n// Manifest Adapter\n// ============================================================================\n\n/**\n * Create a qualified name for a class (namespace isolation - Issue #713)\n * Format: @package/name:ClassName\n */\nfunction createQualifiedName(\n packageName: string,\n className: string,\n): QualifiedClassName {\n return `${packageName}:${className}` as QualifiedClassName;\n}\n\n/**\n * Converts OXC scanner output into the smrt-core `SmartObjectManifest` format\n * consumed by code generators, the Vitest plugin, and the SMRT CLI.\n *\n * The adapter handles field type inference (applying the `0` vs `0.0` integer /\n * decimal heuristic), decorator interpretation (`@foreignKey`, `@oneToMany`,\n * `@manyToMany`, `@field`), type alias resolution, STI `Meta<T>` unwrapping,\n * static property capture (`uiSlots`, `adminRoutes`), and qualified name\n * generation for namespace isolation across packages.\n *\n * @example\n * ```typescript\n * import { OxcScanner, ManifestAdapter } from '@happyvertical/smrt-scanner';\n *\n * const scanner = new OxcScanner({ cwd: process.cwd() });\n * const { results, resolved } = await scanner.scanAndResolve();\n *\n * const adapter = new ManifestAdapter();\n * const manifest = adapter.toManifest(resolved, {\n * packageName: '@my-org/my-package',\n * packageVersion: '1.0.0',\n * typeAliases: results.typeAliases,\n * });\n * ```\n *\n * @see {@link OxcScanner} for producing the `ResolvedClassDefinition[]` input.\n * @see {@link ResolvedClassDefinition} for the shape of each input element.\n */\nexport class ManifestAdapter {\n private typeAliases: Record<string, string> = {};\n private _aliasDepth?: number;\n\n /**\n * Convert an array of resolved class definitions into a `SmartObjectManifest`.\n *\n * Each class is converted to a `SmartObjectDefinition` via\n * {@link toSmartObjectDefinition} and stored under its qualified name key\n * (e.g. `@my-org/my-package:MyClass`) when `packageName` is provided, or\n * under its lowercased class name otherwise.\n *\n * @param resolved - Resolved class definitions from {@link OxcScanner.resolve}\n * or {@link OxcScanner.scanAndResolve}.\n * @param options.packageName - npm package name used to generate qualified\n * class names for namespace isolation across multi-package projects.\n * @param options.packageVersion - Package version recorded in the manifest\n * metadata.\n * @param options.typeAliases - Map of type alias names to their resolved type\n * strings (from {@link ScanResults.typeAliases}). Used to resolve custom\n * types like `type Status = 'active' | 'inactive'` during field inference.\n * @returns A complete `SmartObjectManifest` ready for serialisation.\n *\n * @example\n * ```typescript\n * const manifest = adapter.toManifest(resolved, {\n * packageName: '@my-org/my-package',\n * packageVersion: '1.0.0',\n * typeAliases: results.typeAliases,\n * });\n * fs.writeFileSync('manifest.json', JSON.stringify(manifest, null, 2));\n * ```\n */\n toManifest(\n resolved: ResolvedClassDefinition[],\n options: {\n packageName?: string;\n packageVersion?: string;\n typeAliases?: Record<string, string>;\n } = {},\n ): SmartObjectManifest {\n this.typeAliases = options.typeAliases || {};\n const objects: Record<string, SmartObjectDefinition> = {};\n\n for (const classDef of resolved) {\n const definition = this.toSmartObjectDefinition(classDef, options);\n\n // Use qualified name as key if packageName is available (Issue #713)\n // This enables namespace isolation for multi-package scenarios\n const manifestKey =\n definition.qualifiedName || definition.name.toLowerCase();\n objects[manifestKey] = definition;\n }\n\n return {\n version: '1.0.0',\n timestamp: Date.now(),\n packageName: options.packageName,\n packageVersion: options.packageVersion,\n objects,\n moduleType: 'smrt',\n };\n }\n\n /**\n * Convert a single resolved class definition to a `SmartObjectDefinition`.\n *\n * Handles:\n * - Static property capture (`uiSlots`, `adminRoutes`) with child-wins\n * semantics for overridden statics.\n * - Field conversion (non-static public fields only) via {@link convertField}.\n * - Method conversion (public instance/static methods) via {@link convertMethod}.\n * - Collection name pluralisation.\n * - Qualified name generation when `packageName` is supplied.\n *\n * @param classDef - A fully-resolved class definition.\n * @param options.packageName - Package name used to build the qualified class\n * name (`@pkg:ClassName`).\n * @param options.packageVersion - Package version (informational, stored in\n * the definition).\n * @returns A `SmartObjectDefinition` ready to be stored in a manifest.\n *\n * @see {@link toManifest} for the bulk conversion entry point.\n */\n toSmartObjectDefinition(\n classDef: ResolvedClassDefinition,\n options: { packageName?: string; packageVersion?: string } = {},\n ): SmartObjectDefinition {\n // Extract static properties (e.g., uiSlots, adminRoutes on Agent subclasses)\n // Use own fields (classDef.fields) not allFields — static properties use\n // child-wins semantics (static override), not parent-wins like STI columns.\n // Fall back to allFields for inherited static props not redeclared by child.\n let staticProperties: Record<string, unknown> | undefined;\n const knownStaticProps = ['uiSlots', 'adminRoutes', 'signalSubscriptions'];\n const ownStaticNames = new Set<string>();\n // First pass: own fields (child overrides win)\n for (const field of classDef.fields) {\n if (\n field.isStatic &&\n knownStaticProps.includes(field.name) &&\n field.initializer\n ) {\n try {\n const parsed = parseLiteralInitializer(field.initializer);\n if (parsed) {\n if (!staticProperties) staticProperties = {};\n staticProperties[field.name] = parsed;\n ownStaticNames.add(field.name);\n }\n } catch {\n // Failed to parse static property initializer — skip\n }\n }\n }\n // Second pass: inherited fields for any static props not overridden\n for (const field of classDef.allFields) {\n if (\n field.isStatic &&\n knownStaticProps.includes(field.name) &&\n field.initializer\n ) {\n if (ownStaticNames.has(field.name)) continue;\n try {\n const parsed = parseLiteralInitializer(field.initializer);\n if (parsed) {\n if (!staticProperties) staticProperties = {};\n staticProperties[field.name] = parsed;\n }\n } catch {\n // Failed to parse static property initializer — skip\n }\n }\n }\n\n // Convert fields (skip static fields — they're not database columns)\n const fields: Record<string, FieldDefinition> = {};\n for (const field of classDef.allFields) {\n if (field.isStatic) continue;\n const converted = this.convertField(field);\n if (converted) {\n fields[field.name] = converted;\n }\n }\n\n // Convert methods\n const methods: Record<string, MethodDefinition> = {};\n for (const method of classDef.methods) {\n const converted = this.convertMethod(method);\n if (converted) {\n methods[method.name] = converted;\n }\n }\n\n // Generate collection name (pluralize)\n const collection = this.pluralize(classDef.className);\n\n // Determine package name (prefer option, then classDef value)\n const packageName = options.packageName || classDef.packageName;\n\n // Generate qualified name if packageName is available (Issue #713)\n // Format: @package/name:ClassName for namespace isolation\n const qualifiedName = packageName\n ? createQualifiedName(packageName, classDef.className)\n : undefined;\n\n return {\n name: classDef.className.toLowerCase(),\n className: classDef.className,\n qualifiedName,\n collection,\n filePath: classDef.filePath,\n packageName: packageName || undefined,\n fields,\n methods,\n decoratorConfig: (classDef.decoratorConfig || {}) as SmartObjectConfig,\n extends: classDef.extendsClause || undefined,\n extendsTypeArg: classDef.extendsTypeArg || undefined,\n exportName: classDef.className,\n collectionExportName: `${classDef.className}Collection`,\n staticProperties,\n };\n }\n\n /**\n * Framework internal fields that should NOT be included in manifests\n * These are SmrtObject internals used by the framework, not user-defined fields\n */\n private static readonly FRAMEWORK_INTERNAL_FIELDS = new Set([\n '_tableName',\n 'options',\n '_loadedRelationships',\n '_db',\n '_ai',\n '_fs',\n '_isInitialized',\n '_errors',\n '_warnings',\n ]);\n\n /**\n * Convert a single raw field definition to a manifest `FieldDefinition`.\n *\n * Returns `null` for fields that should be omitted from the manifest:\n * - `private` or `protected` fields.\n * - Framework-internal fields (`_tableName`, `_db`, `_ai`, etc.).\n *\n * Delegates type inference to {@link inferFieldType} and applies additional\n * post-processing:\n * - Marks fields with `Function` type annotation as `transient`.\n * - Marks fields with `@field({ transient: true })` decorator as `transient`.\n * - Populates `_meta.underlyingType` for STI `Meta<T>` fields.\n *\n * @param field - Raw field definition from a scanned class.\n * @returns A `FieldDefinition` for the manifest, or `null` if the field\n * should be excluded.\n *\n * @see {@link inferFieldType} for the type inference logic.\n */\n convertField(field: RawFieldDefinition): FieldDefinition | null {\n // Skip private/protected fields\n if (field.accessibility !== 'public') {\n return null;\n }\n\n // Skip framework internal fields (SmrtObject internals)\n if (ManifestAdapter.FRAMEWORK_INTERNAL_FIELDS.has(field.name)) {\n return null;\n }\n\n // Check if field is a function type (automatically transient)\n const isFunctionType = field.typeAnnotation === 'Function';\n const fieldDecoratorOptions = this.extractFieldDecoratorOptions(field);\n\n const inference = this.inferFieldType(field);\n\n const definition: FieldDefinition = {\n type: inference.type as FieldDefinition['type'],\n required: inference.required,\n };\n\n if (inference.related) {\n definition.related = inference.related;\n }\n\n if (inference.defaultValue !== undefined) {\n definition.default = inference.defaultValue;\n }\n\n // Apply generic @field({...}) options to preserve manifest metadata used by\n // schema generation and runtime decorator merging.\n if (fieldDecoratorOptions.type) {\n definition.type = fieldDecoratorOptions.type;\n }\n\n if (fieldDecoratorOptions.nullable === true) {\n definition.required = false;\n } else if (fieldDecoratorOptions.required !== undefined) {\n definition.required = fieldDecoratorOptions.required;\n }\n\n if (fieldDecoratorOptions.default !== undefined) {\n definition.default = fieldDecoratorOptions.default;\n }\n\n if (fieldDecoratorOptions.related !== undefined) {\n definition.related = fieldDecoratorOptions.related;\n }\n\n if (fieldDecoratorOptions.description !== undefined) {\n definition.description = fieldDecoratorOptions.description;\n }\n\n if (fieldDecoratorOptions.min !== undefined) {\n definition.min = fieldDecoratorOptions.min;\n }\n\n if (fieldDecoratorOptions.max !== undefined) {\n definition.max = fieldDecoratorOptions.max;\n }\n\n if (fieldDecoratorOptions.minLength !== undefined) {\n definition.minLength = fieldDecoratorOptions.minLength;\n }\n\n if (fieldDecoratorOptions.maxLength !== undefined) {\n definition.maxLength = fieldDecoratorOptions.maxLength;\n }\n\n if (Object.keys(fieldDecoratorOptions).length > 0) {\n definition._meta = {\n ...definition._meta,\n ...fieldDecoratorOptions,\n };\n\n if (definition._meta?.type) {\n delete definition._meta.type;\n }\n\n if (definition.related !== undefined && definition._meta?.related) {\n delete definition._meta.related;\n }\n }\n\n // Carry through decorator-derived _meta (validate, through, indexed, etc.)\n if (inference._meta && Object.keys(inference._meta).length > 0) {\n definition._meta = {\n ...definition._meta,\n ...inference._meta,\n };\n }\n\n // For meta fields, store the underlying type for hydration coercion\n if (inference.underlyingType) {\n definition._meta = {\n ...definition._meta,\n underlyingType: inference.underlyingType,\n };\n }\n\n // Mark function type fields as transient (not persisted to database)\n if (isFunctionType) {\n definition.transient = true;\n }\n\n if (fieldDecoratorOptions.transient === true) {\n definition.transient = true;\n }\n\n // Promote security markers to first-class manifest metadata (also retained\n // in `_meta` via the spread above). Honored by `toPublicJSON()` and the\n // collection `where` builder at runtime.\n if (fieldDecoratorOptions.sensitive === true) {\n definition.sensitive = true;\n }\n\n if (fieldDecoratorOptions.readonly === true) {\n definition.readonly = true;\n }\n\n return definition;\n }\n\n /**\n * Infer the SMRT field type and required flag from a raw field definition.\n *\n * Inference is attempted in the following priority order:\n * 1. **Field helper call in initializer** — currently always returns `null`\n * (field helpers removed); reserved for future use.\n * 2. **Decorator** — `@foreignKey`, `@oneToMany`, `@manyToMany`, `@field({ type })`.\n * 3. **Type annotation** — `string` → `text`, `number` with `0` vs `0.0`\n * heuristic → `integer` / `decimal`, `boolean`, `Date` → `datetime`,\n * arrays → `json`, `Record<>` / `object` → `json`, union types with\n * `null`, inline string/number literal unions, `Meta<T>` wrapper,\n * and type alias resolution (up to depth 5).\n * 4. **Numeric literal without annotation** — `version = 1` → `integer`.\n * 5. **Boolean literal without annotation** — `isRead = false` → `boolean`.\n * 6. **Default** — falls back to `text`.\n *\n * @param field - The raw field definition to analyse.\n * @returns A {@link FieldTypeInference} describing the inferred type,\n * required flag, default value, related class name (for relationships),\n * and the inference source for debugging.\n *\n * @see {@link FieldTypeInference} for the result shape.\n * @see {@link InferredFieldType} for valid type values.\n */\n inferFieldType(field: RawFieldDefinition): FieldTypeInference {\n // 1. Check for field helper calls in initializer\n if (field.initializer) {\n const helperResult = this.inferFromHelper(field.initializer);\n if (helperResult) {\n return helperResult;\n }\n }\n\n // 2. Check decorators\n for (const decorator of field.decorators) {\n const decoratorResult = this.inferFromDecorator(decorator, field);\n if (decoratorResult) {\n return decoratorResult;\n }\n }\n\n // 3. Use type annotation with 0 vs 0.0 heuristic\n if (field.typeAnnotation) {\n return this.inferFromAnnotation(field);\n }\n\n // 3.5. Infer from numeric literal without type annotation\n // Handles cases like `version = 1` where there's no `: number` annotation\n if (field.numericValue !== null) {\n const fieldType: InferredFieldType = field.hasDecimalPoint\n ? 'decimal'\n : 'integer';\n return {\n type: fieldType,\n required: !field.optional,\n defaultValue: field.numericValue,\n source: 'heuristic',\n };\n }\n\n // 3.6. Infer from boolean literal without type annotation\n // Handles cases like `isRead = false` where there's no `: boolean` annotation\n if (field.initializer === 'true' || field.initializer === 'false') {\n return {\n type: 'boolean',\n required: !field.optional,\n defaultValue: field.initializer === 'true',\n source: 'heuristic',\n };\n }\n\n // 4. Default to text\n // A field is only required if it has no default value AND is not optional (?)\n // Fields with initializers (default values) should NOT be required\n const hasDefaultValue = field.initializer !== null;\n return {\n type: 'text',\n required: !field.optional && !hasDefaultValue,\n source: 'default',\n };\n }\n\n /**\n * Infer type from field helper call (removed)\n *\n * Field helpers have been removed in favor of decorators and TypeScript types:\n * - Use TypeScript types: name: string = '', price: number = 0.0\n * - Use @field() decorator for constraints: @field({ required: true })\n * - Use @foreignKey(), @oneToMany(), @manyToMany() decorators for relationships\n */\n private inferFromHelper(_initializer: string): FieldTypeInference | null {\n return null;\n }\n\n /**\n * Infer type from field decorator\n */\n private inferFromDecorator(\n decorator: {\n name: string;\n arguments: string[];\n },\n field: RawFieldDefinition,\n ): FieldTypeInference | null {\n // @field decorator with type config\n if (decorator.name === 'field' && decorator.arguments.length > 0) {\n const fieldOptions = this.parseFieldDecoratorOptions(\n decorator.arguments[0],\n );\n const type = this.normalizeFieldType(fieldOptions?.type);\n\n if (type) {\n const hasDefaultValue =\n field.initializer !== null || fieldOptions?.default !== undefined;\n let required = !field.optional && !hasDefaultValue;\n\n if (fieldOptions?.nullable === true) {\n required = false;\n } else if (fieldOptions?.required !== undefined) {\n required = fieldOptions.required;\n }\n\n return {\n type,\n required,\n defaultValue: fieldOptions?.default,\n related:\n typeof fieldOptions?.related === 'string'\n ? fieldOptions.related\n : undefined,\n source: 'decorator',\n };\n }\n }\n\n // @meta({ indexed?, required?, nullable?, ... }) decorator — flags the\n // field as STI meta storage AND preserves opt-in options like `indexed`\n // so the manifest-only schema path can emit the JSON-path index.\n if (decorator.name === 'meta') {\n const parsedOptions = this.parseFieldDecoratorOptions(\n decorator.arguments[0],\n );\n const hasDefaultValue = field.initializer !== null;\n const meta: Record<string, unknown> = {};\n if (parsedOptions?.indexed !== undefined)\n meta.indexed = parsedOptions.indexed;\n if (parsedOptions?.nullable !== undefined)\n meta.nullable = parsedOptions.nullable;\n return {\n type: 'meta',\n required:\n parsedOptions?.required !== undefined\n ? Boolean(parsedOptions.required)\n : !field.optional && !hasDefaultValue,\n defaultValue:\n parsedOptions?.default !== undefined\n ? parsedOptions.default\n : undefined,\n ...(Object.keys(meta).length > 0 ? { _meta: meta } : {}),\n source: 'decorator',\n };\n }\n\n // @foreignKey(RelatedClass) decorator\n if (decorator.name === 'foreignKey') {\n // First argument is the related class name\n // Strip surrounding quotes — sliceSource() returns raw source text\n // which includes quotes for string literals (e.g., \"'TestProfile'\")\n const relatedClass = stripQuotes(decorator.arguments[0]?.trim());\n const parsedOptions = this.parseFieldDecoratorOptions(\n decorator.arguments[1],\n );\n const meta: Record<string, unknown> = {};\n const META_KEYS = [\n 'required',\n 'nullable',\n 'unique',\n 'description',\n 'default',\n ] as const;\n if (parsedOptions) {\n for (const key of META_KEYS) {\n if (parsedOptions[key] !== undefined) {\n meta[key] = parsedOptions[key];\n }\n }\n }\n // Respect TypeScript optional marker (?) - fixes #846\n const hasDefaultValue = field.initializer !== null;\n return {\n type: 'foreignKey',\n related: relatedClass || undefined,\n required:\n parsedOptions?.required !== undefined\n ? Boolean(parsedOptions.required)\n : !field.optional && !hasDefaultValue,\n defaultValue:\n parsedOptions?.default !== undefined\n ? parsedOptions.default\n : undefined,\n ...(Object.keys(meta).length > 0 ? { _meta: meta } : {}),\n source: 'decorator',\n };\n }\n\n // @tenantId({ nullable?, required?, autoFilter?, autoPopulate? }) decorator\n if (decorator.name === 'tenantId') {\n const parsedOptions = this.parseFieldDecoratorOptions(\n decorator.arguments[0],\n );\n const nullable = parsedOptions?.nullable === true;\n const required =\n parsedOptions?.required !== undefined\n ? Boolean(parsedOptions.required)\n : !nullable;\n\n return {\n type: 'text',\n required,\n _meta: {\n sqlType: 'UUID',\n ...(parsedOptions ?? {}),\n __tenancy: {\n isTenantIdField: true,\n autoFilter: parsedOptions?.autoFilter ?? true,\n required,\n autoPopulate: parsedOptions?.autoPopulate ?? true,\n nullable,\n },\n },\n source: 'decorator',\n };\n }\n\n // @crossPackageRef('@pkg:Class', { validate?, unique?, nullable?, default?, description? }) decorator\n if (decorator.name === 'crossPackageRef') {\n const qualifiedName = stripQuotes(decorator.arguments[0]?.trim());\n const hasDefaultValue = field.initializer !== null;\n // Preserve every standard field option from the second argument so\n // manifest-only consumers generate the same schema/constraints that\n // the runtime decorator would produce.\n const parsedOptions = this.parseFieldDecoratorOptions(\n decorator.arguments[1],\n );\n const meta: Record<string, unknown> = {};\n const META_KEYS = [\n 'validate',\n 'nullable',\n 'unique',\n 'description',\n 'default',\n 'indexed',\n 'idType',\n ] as const;\n if (parsedOptions) {\n for (const key of META_KEYS) {\n if (parsedOptions[key] !== undefined) {\n meta[key] = parsedOptions[key];\n }\n }\n }\n return {\n type: 'crossPackageRef',\n related: qualifiedName || undefined,\n required:\n parsedOptions?.required !== undefined\n ? Boolean(parsedOptions.required)\n : !field.optional && !hasDefaultValue,\n defaultValue:\n parsedOptions?.default !== undefined\n ? parsedOptions.default\n : undefined,\n ...(Object.keys(meta).length > 0 ? { _meta: meta } : {}),\n source: 'decorator',\n };\n }\n\n // @oneToMany(RelatedClass, { foreignKey? }) decorator\n if (decorator.name === 'oneToMany') {\n const relatedClass = stripQuotes(decorator.arguments[0]?.trim());\n // Preserve an explicit inverse `foreignKey` so manifest-only consumers\n // disambiguate the inverse side the same way the runtime decorator does\n // (needed when the target declares multiple FKs back to this class).\n const parsedOptions = this.parseFieldDecoratorOptions(\n decorator.arguments[1],\n );\n const meta: Record<string, unknown> = {};\n if (parsedOptions?.foreignKey !== undefined) {\n meta.foreignKey = parsedOptions.foreignKey;\n }\n return {\n type: 'oneToMany',\n related: relatedClass || undefined,\n required: false,\n ...(Object.keys(meta).length > 0 ? { _meta: meta } : {}),\n source: 'decorator',\n };\n }\n\n // @manyToMany(RelatedClass, { through?, sourceKey?, targetKey? }) decorator\n if (decorator.name === 'manyToMany') {\n const relatedClass = stripQuotes(decorator.arguments[0]?.trim());\n // Preserve junction-table coordinates so manifest-only consumers can\n // execute manyToMany loads without the decorator firing in-process.\n const parsedOptions = this.parseFieldDecoratorOptions(\n decorator.arguments[1],\n );\n const meta: Record<string, unknown> = {};\n if (parsedOptions?.through !== undefined)\n meta.through = parsedOptions.through;\n if (parsedOptions?.sourceKey !== undefined)\n meta.sourceKey = parsedOptions.sourceKey;\n if (parsedOptions?.targetKey !== undefined)\n meta.targetKey = parsedOptions.targetKey;\n return {\n type: 'manyToMany',\n related: relatedClass || undefined,\n required: false,\n ...(Object.keys(meta).length > 0 ? { _meta: meta } : {}),\n source: 'decorator',\n };\n }\n\n return null;\n }\n\n private extractFieldDecoratorOptions(\n field: RawFieldDefinition,\n ): FieldDecoratorOptions {\n for (const decorator of field.decorators) {\n if (decorator.name !== 'field') continue;\n\n const parsed = this.parseFieldDecoratorOptions(decorator.arguments[0]);\n if (parsed) {\n return parsed;\n }\n }\n\n return {};\n }\n\n private parseFieldDecoratorOptions(\n rawArgument: string | undefined,\n ): FieldDecoratorOptions | null {\n if (!rawArgument) return null;\n\n const parsed = parseLiteralInitializer(rawArgument);\n if (!parsed || Array.isArray(parsed) || typeof parsed !== 'object') {\n return null;\n }\n\n return parsed as FieldDecoratorOptions;\n }\n\n private normalizeFieldType(\n value: unknown,\n ): FieldDefinition['type'] | undefined {\n switch (value) {\n case 'text':\n case 'decimal':\n case 'boolean':\n case 'integer':\n case 'datetime':\n case 'json':\n case 'foreignKey':\n case 'crossPackageRef':\n case 'oneToMany':\n case 'manyToMany':\n case 'meta':\n return value;\n default:\n return undefined;\n }\n }\n\n /**\n * Infer type from TypeScript type annotation\n */\n private inferFromAnnotation(field: RawFieldDefinition): FieldTypeInference {\n const type = field.typeAnnotation;\n\n // A field is only required if it has no default value AND is not optional (?)\n // Fields with initializers (default values) should NOT be required\n // This matches the behavior of the legacy TypeScript scanner\n const hasDefaultValue = field.initializer !== null;\n const isRequired = !field.optional && !hasDefaultValue;\n\n // Meta<T> wrapper for STI child fields\n // Extract the inner type T and mark as meta field\n if (type?.startsWith('Meta<') && type.endsWith('>')) {\n const innerType = type.slice(5, -1); // Extract type inside Meta<...>\n\n // Recursively infer the underlying type\n const underlyingInference = this.inferFromAnnotation({\n ...field,\n typeAnnotation: innerType,\n });\n\n return {\n type: 'meta',\n required: isRequired,\n defaultValue: underlyingInference.defaultValue,\n source: 'annotation',\n // Store underlying type for hydration coercion\n underlyingType: underlyingInference.type,\n };\n }\n\n // String types\n if (type === 'string') {\n return {\n type: 'text',\n required: isRequired,\n defaultValue: this.parseDefaultValue(field.initializer, 'string'),\n source: 'annotation',\n };\n }\n\n // Number with 0 vs 0.0 heuristic\n if (type === 'number') {\n const fieldType: InferredFieldType = field.hasDecimalPoint\n ? 'decimal'\n : 'integer';\n\n return {\n type: fieldType,\n required: isRequired,\n defaultValue: field.numericValue ?? undefined,\n source: 'heuristic',\n };\n }\n\n // Boolean\n if (type === 'boolean') {\n return {\n type: 'boolean',\n required: isRequired,\n defaultValue: this.parseDefaultValue(field.initializer, 'boolean'),\n source: 'annotation',\n };\n }\n\n // Date\n if (type === 'Date') {\n return {\n type: 'datetime',\n required: isRequired,\n source: 'annotation',\n };\n }\n\n // Arrays → JSON\n if (type?.endsWith('[]')) {\n return {\n type: 'json',\n required: isRequired,\n defaultValue: [],\n source: 'annotation',\n };\n }\n\n // Record/object → JSON\n if (type?.startsWith('Record<') || type === 'object') {\n return {\n type: 'json',\n required: isRequired,\n defaultValue: {},\n source: 'annotation',\n };\n }\n\n // Union types with null/undefined → nullable or optional\n if (\n type?.includes(' | null') ||\n type?.includes('null | ') ||\n type?.includes(' | undefined') ||\n type?.includes('undefined | ')\n ) {\n const baseType = type\n .replace(/\\s*\\|\\s*null/g, '')\n .replace(/\\s*\\|\\s*undefined/g, '')\n .replace(/\\bnull\\s*\\|\\s*/g, '')\n .replace(/\\bundefined\\s*\\|\\s*/g, '')\n .trim();\n const inference = this.inferFromAnnotation({\n ...field,\n typeAnnotation: baseType,\n optional: true,\n });\n return inference;\n }\n\n // Inline string literal union: 'pending' | 'ready' | 'archived'\n if (type && /^'[^']*'(\\s*\\|\\s*'[^']*')+$/.test(type)) {\n return {\n type: 'text',\n required: isRequired,\n defaultValue: this.parseDefaultValue(field.initializer, 'string'),\n source: 'annotation',\n };\n }\n\n // Inline number literal union: 1 | 2 | 3 (supports negatives: -1 | 0 | 1)\n if (type && /^-?\\d+(\\s*\\|\\s*-?\\d+)+$/.test(type)) {\n return {\n type: 'integer',\n required: isRequired,\n defaultValue: field.numericValue ?? undefined,\n source: 'annotation',\n };\n }\n\n // Type alias resolution: look up single-identifier types in typeAliases\n // Guard against circular aliases (e.g., type A = B; type B = A) with depth limit\n if (\n type &&\n !type.includes(' ') &&\n !type.includes('<') &&\n this.typeAliases[type] &&\n (this._aliasDepth ?? 0) < 5\n ) {\n const resolved = this.typeAliases[type];\n this._aliasDepth = (this._aliasDepth ?? 0) + 1;\n try {\n return this.inferFromAnnotation({ ...field, typeAnnotation: resolved });\n } finally {\n this._aliasDepth = (this._aliasDepth ?? 0) - 1;\n }\n }\n\n // String initializer heuristic: if initializer is a quoted string, infer text\n if (field.initializer?.match(/^(['\"]).*\\1$/)) {\n return {\n type: 'text',\n required: isRequired,\n defaultValue: this.parseDefaultValue(field.initializer, 'string'),\n source: 'heuristic',\n };\n }\n\n // Default to json for unknown/complex types\n // Matches the TS scanner behavior: custom interfaces, type aliases,\n // and other non-primitive types are stored as JSON\n return {\n type: 'json',\n required: isRequired,\n source: 'default',\n };\n }\n\n /**\n * Parse default value from initializer string\n */\n private parseDefaultValue(\n initializer: string | null,\n expectedType: 'string' | 'boolean' | 'number',\n ): string | number | boolean | undefined {\n if (!initializer) return undefined;\n\n switch (expectedType) {\n case 'string': {\n // Match quoted strings (backreference ensures same quote type)\n const stringMatch = initializer.match(/^(['\"`])(.*)\\1$/s);\n if (stringMatch) {\n return stringMatch[2];\n }\n break;\n }\n\n case 'boolean':\n if (initializer === 'true') return true;\n if (initializer === 'false') return false;\n break;\n\n case 'number': {\n const num = parseFloat(initializer);\n if (!Number.isNaN(num)) return num;\n break;\n }\n }\n\n return undefined;\n }\n\n /**\n * Convert a raw method definition to a manifest `MethodDefinition`.\n *\n * Returns `null` for `private` or `protected` methods, which are excluded\n * from the manifest. Parameters are mapped to the manifest parameter shape\n * and default values are parsed via `parseDefaultValue`.\n *\n * @param method - Raw method definition from a scanned class.\n * @returns A manifest-compatible `MethodDefinition`, or `null` if the method\n * should be excluded.\n */\n convertMethod(method: RawMethodDefinition): MethodDefinition | null {\n // Skip private/protected methods\n if (method.accessibility !== 'public') {\n return null;\n }\n\n return {\n name: method.name,\n async: method.async,\n parameters: method.parameters.map((p) => ({\n name: p.name,\n type: p.type || 'any',\n optional: p.optional,\n default: p.defaultValue\n ? this.parseDefaultValue(p.defaultValue, 'string')\n : undefined,\n })),\n returnType: method.returnType || 'any',\n description: method.description || undefined,\n isStatic: method.isStatic,\n isPublic: true,\n };\n }\n\n /**\n * Simple pluralization for collection names.\n *\n * This produces the manifest's `collection` label only; the authoritative DDL\n * table name is derived independently by core (`classnameToTablename` →\n * the `pluralize` library), so this needs to stay self-consistent rather than\n * cover every irregular plural. Note the `y → ies` rule fires only after a\n * consonant, so vowel+y words pluralise correctly (`Day` → `days`, not\n * `daies`).\n */\n private pluralize(name: string): string {\n // Lowercase the name first for consistent collection/table names\n const lower = name.toLowerCase();\n // Consonant + y → ies (City → cities); vowel + y → +s (Day → days).\n if (/[^aeiou]y$/.test(lower)) {\n return `${lower.slice(0, -1)}ies`;\n }\n if (lower.endsWith('s') || lower.endsWith('x') || lower.endsWith('z')) {\n return `${lower}es`;\n }\n if (lower.endsWith('ch') || lower.endsWith('sh')) {\n return `${lower}es`;\n }\n return `${lower}s`;\n }\n}\n","/**\n * OXC Scanner\n *\n * High-level scanner that orchestrates OXC parsing and inheritance resolution.\n * Provides a simple API for scanning TypeScript files for SMRT classes.\n */\n\nimport { resolve } from 'node:path';\nimport fg from 'fast-glob';\nimport { InheritanceResolver } from './inheritance-resolver.js';\nimport { parseFile } from './oxc-parser.js';\nimport type {\n ExternalManifest,\n FileScanResult,\n OxcScannerOptions,\n ResolvedClassDefinition,\n ScanResults,\n} from './types.js';\n\n/**\n * Default glob patterns for scanning\n */\nconst DEFAULT_INCLUDE = ['**/*.ts', '**/*.tsx'];\nconst DEFAULT_EXCLUDE = [\n '**/node_modules/**',\n '**/dist/**',\n '**/build/**',\n '**/*.d.ts',\n '**/*.test.ts',\n '**/*.spec.ts',\n '**/__tests__/**',\n];\n\n/**\n * High-performance TypeScript scanner that discovers `@smrt()`-decorated\n * classes in a project's source files.\n *\n * Orchestrates the two-phase scan pipeline:\n * 1. **Phase 1 — Parse** (`scan()`): uses OXC (Rust) to parse TypeScript files\n * in parallel and extract raw class, field, method, and decorator metadata.\n * 2. **Phase 2 — Resolve** (`resolve()`): walks inheritance chains, detects STI\n * hierarchies, and merges fields from ancestor classes.\n *\n * The common path is {@link scanAndResolve} which runs both phases in sequence.\n *\n * @example\n * ```typescript\n * import { OxcScanner } from '@happyvertical/smrt-scanner';\n *\n * const scanner = new OxcScanner({\n * cwd: process.cwd(),\n * include: ['src/**\\/*.ts'],\n * exclude: ['**\\/*.test.ts'],\n * });\n *\n * const { results, resolved } = await scanner.scanAndResolve();\n * console.log(`Found ${resolved.length} SMRT classes in ${results.fileCount} files`);\n * ```\n *\n * @see {@link OxcScannerOptions} for all available configuration options.\n * @see {@link scanDirectory} for a one-liner convenience wrapper.\n */\nexport class OxcScanner {\n private options: Required<OxcScannerOptions>;\n private resolver: InheritanceResolver;\n private scanResults: ScanResults | null = null;\n\n /**\n * Create a new `OxcScanner` with the given options.\n *\n * All options are optional. By default the scanner targets every `.ts` and\n * `.tsx` file under `process.cwd()`, excluding `node_modules`, `dist`,\n * `build`, declaration files, and test files.\n *\n * @param options - Scanner configuration. See {@link OxcScannerOptions}.\n */\n constructor(options: OxcScannerOptions = {}) {\n this.options = {\n include: options.include || DEFAULT_INCLUDE,\n exclude: options.exclude || DEFAULT_EXCLUDE,\n cwd: options.cwd || process.cwd(),\n tsconfig: options.tsconfig || '',\n followImports: options.followImports ?? false,\n baseClasses: options.baseClasses || [],\n includePrivateMethods: options.includePrivateMethods ?? false,\n includeStaticMethods: options.includeStaticMethods ?? true,\n externalManifests: options.externalManifests || new Map(),\n };\n\n this.resolver = new InheritanceResolver({\n baseClasses: this.options.baseClasses,\n externalManifests: this.options.externalManifests,\n });\n }\n\n /**\n * Phase 1 — Discover and parse TypeScript files using OXC.\n *\n * Uses `fast-glob` to enumerate matching files and then parses them in\n * parallel with OXC (Rust). The raw class definitions are registered with\n * the internal {@link InheritanceResolver} for use in the subsequent\n * {@link resolve} call.\n *\n * @returns A {@link ScanResults} object containing all classes found, any\n * parse errors, accumulated type aliases, SMRT import metadata, and\n * aggregate timing information.\n *\n * @example\n * ```typescript\n * const scanner = new OxcScanner({ cwd: '/project' });\n * const results = await scanner.scan();\n * console.log(`Parsed ${results.fileCount} files in ${results.totalParseTimeMs.toFixed(1)}ms`);\n * ```\n */\n async scan(): Promise<ScanResults> {\n const startTime = performance.now();\n\n // Discover files\n const files = await this.discoverFiles();\n\n // Parse files in parallel\n const fileResults = await Promise.all(\n files.map((filePath) => this.parseFileWithTiming(filePath)),\n );\n\n // Collect results\n const results: ScanResults = {\n files: fileResults,\n classes: [],\n errors: [],\n totalParseTimeMs: performance.now() - startTime,\n fileCount: files.length,\n typeAliases: {},\n };\n\n // Flatten classes, errors, and type aliases\n for (const file of fileResults) {\n for (const classDef of file.classes) {\n results.classes.push(classDef);\n }\n for (const error of file.errors) {\n results.errors.push(error);\n }\n Object.assign(results.typeAliases, file.typeAliases);\n }\n\n // Add classes to resolver\n this.resolver.addClasses(results.classes);\n\n this.scanResults = results;\n return results;\n }\n\n /**\n * Phase 2 — Resolve inheritance chains for all scanned classes.\n *\n * Must be called after {@link scan}. Walks each class's extends chain,\n * detects STI hierarchies, merges ancestor fields for STI subclasses, and\n * marks framework base classes.\n *\n * @returns An array of {@link ResolvedClassDefinition} objects — one for\n * every class that either carries `@smrt()` or extends a framework base\n * class (`SmrtObject`, `SmrtClass`, `SmrtCollection`).\n *\n * @throws {Error} If called before {@link scan}.\n *\n * @see {@link scanAndResolve} to run both phases in one call.\n */\n resolve(): ResolvedClassDefinition[] {\n if (!this.scanResults) {\n throw new Error('Must call scan() before resolve()');\n }\n\n return this.resolver.resolveAll();\n }\n\n /**\n * Run both scan phases in a single call.\n *\n * Equivalent to calling `await scanner.scan()` followed by\n * `scanner.resolve()`. This is the most common entry point for callers\n * that want the fully-resolved manifest-ready data in one step.\n *\n * @returns An object with:\n * - `results` — raw {@link ScanResults} from Phase 1.\n * - `resolved` — array of {@link ResolvedClassDefinition} from Phase 2.\n *\n * @example\n * ```typescript\n * const scanner = new OxcScanner({ cwd: '/project/src' });\n * const { results, resolved } = await scanner.scanAndResolve();\n * // resolved is ready to pass to ManifestAdapter.toManifest()\n * ```\n *\n * @see {@link ManifestAdapter} to convert `resolved` into a manifest JSON.\n */\n async scanAndResolve(): Promise<{\n results: ScanResults;\n resolved: ResolvedClassDefinition[];\n }> {\n const results = await this.scan();\n const resolved = this.resolve();\n\n return { results, resolved };\n }\n\n /**\n * Register an external package manifest for cross-package base class resolution.\n *\n * When a project class extends a class defined in an installed SMRT package,\n * the resolver needs access to that package's class definitions to walk the\n * full inheritance chain. Call this method with each external package's\n * {@link ExternalManifest} before calling {@link scan} or {@link resolve}.\n *\n * @param manifest - The external manifest to register, including `packageName`,\n * `packageVersion`, and a `classes` map keyed by class name.\n *\n * @see {@link ExternalManifest}\n */\n addExternalManifest(manifest: ExternalManifest): void {\n this.resolver.addExternalManifest(manifest);\n }\n\n /**\n * Scan all discovered files for @happyvertical/smrt-* imports.\n * Returns a map of package name → Set of imported class names.\n *\n * Used for tree-shaking: only external objects that are actually imported\n * in the project's source files will be included in the manifest.\n *\n * Must be called after scan() or as part of scanAndResolve().\n *\n * @example\n * ```typescript\n * const scanner = new OxcScanner({ cwd: process.cwd() });\n * await scanner.scan();\n * const imports = scanner.scanSmrtImports();\n * // Map { '@happyvertical/smrt-profiles' => Set { 'Person', 'Organization' } }\n * ```\n */\n scanSmrtImports(): Map<string, Set<string>> {\n if (!this.scanResults) {\n throw new Error('Must call scan() before scanSmrtImports()');\n }\n\n const merged = new Map<string, Set<string>>();\n\n for (const file of this.scanResults.files) {\n if (file.smrtImports) {\n for (const [pkg, classes] of file.smrtImports) {\n if (!merged.has(pkg)) {\n merged.set(pkg, new Set());\n }\n const mergedSet = merged.get(pkg)!;\n for (const cls of classes) {\n mergedSet.add(cls);\n }\n }\n }\n }\n\n return merged;\n }\n\n /**\n * Return aggregate statistics about the last scan.\n *\n * Can be called after {@link scan} has completed. Returns counts useful for\n * diagnostics and the `--stats` CLI flag.\n *\n * @returns An object with:\n * - `totalClasses` — total class declarations seen (including non-SMRT).\n * - `smrtClasses` — classes with `@smrt()` decorator.\n * - `stiClasses` — SMRT classes participating in an STI hierarchy.\n * - `maxInheritanceDepth` — length of the deepest inheritance chain.\n * - `fileCount` — number of files scanned.\n * - `parseTimeMs` — total wall-clock parse time in milliseconds.\n */\n getStats(): {\n totalClasses: number;\n smrtClasses: number;\n stiClasses: number;\n maxInheritanceDepth: number;\n fileCount: number;\n parseTimeMs: number;\n } {\n const resolverStats = this.resolver.getStats();\n\n return {\n ...resolverStats,\n fileCount: this.scanResults?.fileCount || 0,\n parseTimeMs: this.scanResults?.totalParseTimeMs || 0,\n };\n }\n\n /**\n * Discover files to scan using fast-glob\n */\n private async discoverFiles(): Promise<string[]> {\n const patterns = this.options.include;\n\n const files = await fg(patterns, {\n cwd: this.options.cwd,\n ignore: this.options.exclude,\n absolute: true,\n onlyFiles: true,\n });\n\n return files;\n }\n\n /**\n * Parse a single file with timing\n */\n private async parseFileWithTiming(filePath: string): Promise<FileScanResult> {\n // parseFile is synchronous but we wrap it for potential future async\n return parseFile(filePath);\n }\n}\n\n/**\n * Convenience wrapper that creates an {@link OxcScanner} for `dir` and runs\n * both scan phases in a single call.\n *\n * @param dir - Directory to scan (resolved to an absolute path automatically).\n * @param options - Scanner options, excluding `cwd` which is set from `dir`.\n * See {@link OxcScannerOptions}.\n * @returns An object with `results` ({@link ScanResults}) and `resolved`\n * ({@link ResolvedClassDefinition}[]).\n *\n * @example\n * ```typescript\n * import { scanDirectory } from '@happyvertical/smrt-scanner';\n *\n * const { resolved } = await scanDirectory('src/', {\n * include: ['**\\/*.ts'],\n * exclude: ['**\\/*.test.ts'],\n * });\n * console.log(`Found ${resolved.length} SMRT classes`);\n * ```\n *\n * @see {@link OxcScanner} for the full class API with more control.\n */\nexport async function scanDirectory(\n dir: string,\n options: Omit<OxcScannerOptions, 'cwd'> = {},\n): Promise<{\n results: ScanResults;\n resolved: ResolvedClassDefinition[];\n}> {\n const scanner = new OxcScanner({\n ...options,\n cwd: resolve(dir),\n });\n\n return scanner.scanAndResolve();\n}\n"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { readFileSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { resolve, dirname } from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
|
-
import { O as OxcScanner, M as ManifestAdapter } from "./chunks/scanner-
|
|
5
|
+
import { O as OxcScanner, M as ManifestAdapter } from "./chunks/scanner-BBNdy6xM.js";
|
|
6
6
|
function parseArgs(args) {
|
|
7
7
|
const options = {
|
|
8
8
|
directory: process.cwd(),
|
package/dist/index.d.ts
CHANGED
|
@@ -45,11 +45,12 @@ declare interface ClassDeclaration extends BaseNode {
|
|
|
45
45
|
id: Identifier | null;
|
|
46
46
|
superClass: Expression | null;
|
|
47
47
|
superTypeParameters?: TSTypeParameterInstantiation;
|
|
48
|
+
superTypeArguments?: TSTypeParameterInstantiation;
|
|
48
49
|
body: ClassBody;
|
|
49
50
|
decorators?: Decorator[];
|
|
50
51
|
}
|
|
51
52
|
|
|
52
|
-
declare type ClassElement = PropertyDefinition | MethodDefinition_2
|
|
53
|
+
declare type ClassElement = PropertyDefinition | MethodDefinition_2;
|
|
53
54
|
|
|
54
55
|
declare interface Decorator extends BaseNode {
|
|
55
56
|
type: 'Decorator';
|
|
@@ -73,7 +74,7 @@ declare interface ExportSpecifier extends BaseNode {
|
|
|
73
74
|
exported: Identifier;
|
|
74
75
|
}
|
|
75
76
|
|
|
76
|
-
declare type Expression = Identifier | Literal | CallExpression | MemberExpression | ObjectExpression | ArrayExpression | NewExpression |
|
|
77
|
+
declare type Expression = Identifier | Literal | CallExpression | MemberExpression | ObjectExpression | ArrayExpression | NewExpression | UnaryExpression;
|
|
77
78
|
|
|
78
79
|
/**
|
|
79
80
|
* Describes a pre-loaded manifest from an installed SMRT package, used by
|
|
@@ -101,14 +102,14 @@ export declare interface ExternalManifest {
|
|
|
101
102
|
declare interface FieldDefinition {
|
|
102
103
|
type: 'text' | 'decimal' | 'boolean' | 'integer' | 'datetime' | 'json' | 'foreignKey' | 'crossPackageRef' | 'oneToMany' | 'manyToMany' | 'meta';
|
|
103
104
|
required?: boolean;
|
|
104
|
-
default?:
|
|
105
|
+
default?: unknown;
|
|
105
106
|
min?: number;
|
|
106
107
|
max?: number;
|
|
107
108
|
maxLength?: number;
|
|
108
109
|
minLength?: number;
|
|
109
110
|
related?: string;
|
|
110
111
|
description?: string;
|
|
111
|
-
_meta?: Record<string,
|
|
112
|
+
_meta?: Record<string, unknown>;
|
|
112
113
|
transient?: boolean;
|
|
113
114
|
/** Sensitive value — excluded from public serialization + where filtering. */
|
|
114
115
|
sensitive?: boolean;
|
|
@@ -654,7 +655,7 @@ declare interface MethodDefinition {
|
|
|
654
655
|
name: string;
|
|
655
656
|
type: string;
|
|
656
657
|
optional: boolean;
|
|
657
|
-
default?:
|
|
658
|
+
default?: unknown;
|
|
658
659
|
}>;
|
|
659
660
|
returnType: string;
|
|
660
661
|
description?: string;
|
|
@@ -941,7 +942,7 @@ export declare function parseFile(filePath: string): FileScanResult;
|
|
|
941
942
|
*/
|
|
942
943
|
export declare function parseSource(sourceText: string, filename?: string): FileScanResult;
|
|
943
944
|
|
|
944
|
-
declare type Pattern = Identifier | AssignmentPattern | RestElement | ObjectPattern | ArrayPattern
|
|
945
|
+
declare type Pattern = Identifier | AssignmentPattern | RestElement | ObjectPattern | ArrayPattern;
|
|
945
946
|
|
|
946
947
|
declare interface Position {
|
|
947
948
|
line: number;
|
|
@@ -1227,7 +1228,7 @@ declare interface SmartObjectDefinition {
|
|
|
1227
1228
|
decoratorConfig: SmartObjectConfig;
|
|
1228
1229
|
extends?: string;
|
|
1229
1230
|
extendsTypeArg?: string;
|
|
1230
|
-
staticProperties?: Record<string,
|
|
1231
|
+
staticProperties?: Record<string, unknown>;
|
|
1231
1232
|
}
|
|
1232
1233
|
|
|
1233
1234
|
declare interface SmartObjectManifest {
|
|
@@ -1250,7 +1251,7 @@ declare interface SpreadElement extends BaseNode {
|
|
|
1250
1251
|
argument: Expression;
|
|
1251
1252
|
}
|
|
1252
1253
|
|
|
1253
|
-
declare type Statement = ClassDeclaration | ExportNamedDeclaration | ExportDefaultDeclaration | ImportDeclaration |
|
|
1254
|
+
declare type Statement = ClassDeclaration | ExportNamedDeclaration | ExportDefaultDeclaration | ImportDeclaration | TSTypeAliasDeclaration | TSEnumDeclaration;
|
|
1254
1255
|
|
|
1255
1256
|
declare interface TSAnyKeyword extends BaseNode {
|
|
1256
1257
|
type: 'TSAnyKeyword';
|
|
@@ -1265,12 +1266,38 @@ declare interface TSBooleanKeyword extends BaseNode {
|
|
|
1265
1266
|
type: 'TSBooleanKeyword';
|
|
1266
1267
|
}
|
|
1267
1268
|
|
|
1269
|
+
declare interface TSEnumBody extends BaseNode {
|
|
1270
|
+
type: 'TSEnumBody';
|
|
1271
|
+
members: TSEnumMember[];
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1274
|
+
declare interface TSEnumDeclaration extends BaseNode {
|
|
1275
|
+
type: 'TSEnumDeclaration';
|
|
1276
|
+
id: Identifier;
|
|
1277
|
+
body?: TSEnumBody;
|
|
1278
|
+
members?: TSEnumMember[];
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
declare interface TSEnumMember extends BaseNode {
|
|
1282
|
+
type: 'TSEnumMember';
|
|
1283
|
+
initializer?: Expression;
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
declare interface TSFunctionType extends BaseNode {
|
|
1287
|
+
type: 'TSFunctionType';
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1268
1290
|
declare interface TSIndexSignature extends BaseNode {
|
|
1269
1291
|
type: 'TSIndexSignature';
|
|
1270
1292
|
parameters: Identifier[];
|
|
1271
1293
|
typeAnnotation?: TSTypeAnnotation;
|
|
1272
1294
|
}
|
|
1273
1295
|
|
|
1296
|
+
declare interface TSLiteralType extends BaseNode {
|
|
1297
|
+
type: 'TSLiteralType';
|
|
1298
|
+
literal?: Literal;
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1274
1301
|
declare interface TSMethodSignature extends BaseNode {
|
|
1275
1302
|
type: 'TSMethodSignature';
|
|
1276
1303
|
key: Expression;
|
|
@@ -1304,14 +1331,20 @@ declare interface TSStringKeyword extends BaseNode {
|
|
|
1304
1331
|
type: 'TSStringKeyword';
|
|
1305
1332
|
}
|
|
1306
1333
|
|
|
1307
|
-
declare type TSType = TSStringKeyword | TSNumberKeyword | TSBooleanKeyword | TSAnyKeyword | TSVoidKeyword | TSNullKeyword | TSUndefinedKeyword | TSTypeReference | TSArrayType | TSUnionType | TSTypeLiteral |
|
|
1334
|
+
declare type TSType = TSStringKeyword | TSNumberKeyword | TSBooleanKeyword | TSAnyKeyword | TSVoidKeyword | TSNullKeyword | TSUndefinedKeyword | TSTypeReference | TSArrayType | TSUnionType | TSTypeLiteral | TSLiteralType | TSFunctionType;
|
|
1335
|
+
|
|
1336
|
+
declare interface TSTypeAliasDeclaration extends BaseNode {
|
|
1337
|
+
type: 'TSTypeAliasDeclaration';
|
|
1338
|
+
id: Identifier;
|
|
1339
|
+
typeAnnotation: TSType;
|
|
1340
|
+
}
|
|
1308
1341
|
|
|
1309
1342
|
declare interface TSTypeAnnotation extends BaseNode {
|
|
1310
1343
|
type: 'TSTypeAnnotation';
|
|
1311
1344
|
typeAnnotation: TSType;
|
|
1312
1345
|
}
|
|
1313
1346
|
|
|
1314
|
-
declare type TSTypeElement = TSPropertySignature | TSMethodSignature | TSIndexSignature
|
|
1347
|
+
declare type TSTypeElement = TSPropertySignature | TSMethodSignature | TSIndexSignature;
|
|
1315
1348
|
|
|
1316
1349
|
declare interface TSTypeLiteral extends BaseNode {
|
|
1317
1350
|
type: 'TSTypeLiteral';
|
|
@@ -1327,6 +1360,7 @@ declare interface TSTypeReference extends BaseNode {
|
|
|
1327
1360
|
type: 'TSTypeReference';
|
|
1328
1361
|
typeName: Identifier | TSQualifiedName;
|
|
1329
1362
|
typeParameters?: TSTypeParameterInstantiation;
|
|
1363
|
+
typeArguments?: TSTypeParameterInstantiation;
|
|
1330
1364
|
}
|
|
1331
1365
|
|
|
1332
1366
|
declare interface TSUndefinedKeyword extends BaseNode {
|
|
@@ -1342,6 +1376,12 @@ declare interface TSVoidKeyword extends BaseNode {
|
|
|
1342
1376
|
type: 'TSVoidKeyword';
|
|
1343
1377
|
}
|
|
1344
1378
|
|
|
1379
|
+
declare interface UnaryExpression extends BaseNode {
|
|
1380
|
+
type: 'UnaryExpression';
|
|
1381
|
+
operator: string;
|
|
1382
|
+
argument: Expression;
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1345
1385
|
/**
|
|
1346
1386
|
* Verify that `dist/manifest.json` contains every `@smrt()` object declared in
|
|
1347
1387
|
* the package source. See module docs for the rationale and guarantees.
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { O as OxcScanner, M as ManifestAdapter } from "./chunks/scanner-
|
|
2
|
-
import { I, e, p, a } from "./chunks/scanner-
|
|
1
|
+
import { O as OxcScanner, M as ManifestAdapter } from "./chunks/scanner-BBNdy6xM.js";
|
|
2
|
+
import { I, e, p, a } from "./chunks/scanner-BBNdy6xM.js";
|
|
3
3
|
import { existsSync, readFileSync } from "node:fs";
|
|
4
4
|
import { resolve, basename } from "node:path";
|
|
5
5
|
const DEFAULT_INCLUDE = ["src/**/*.ts"];
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scanner-3K_xuVXN.js","sources":["../../src/inheritance-resolver.ts","../../src/oxc-parser.ts","../../src/manifest-adapter.ts","../../src/scanner.ts"],"sourcesContent":["/**\n * Inheritance Resolver\n *\n * Resolves class inheritance chains using in-memory class map.\n * Handles STI (Single Table Inheritance) detection and field merging.\n */\n\nimport type {\n ExternalManifest,\n RawClassDefinition,\n RawFieldDefinition,\n ResolvedClassDefinition,\n} from './types.js';\n\n/**\n * Framework base classes that are always recognized.\n *\n * Hardcoded list — every framework abstract base class that consuming\n * packages can subclass without needing `@smrt()` must appear here, or\n * the scanner will silently drop undecorated subclasses from the manifest.\n *\n * `SmrtJunction`, `SmrtHierarchical`, and `SmrtPolymorphicAssociation` are\n * stopgap entries pending a manifest-driven base-class detection scheme —\n * core would export its abstract bases in its manifest and dependents would\n * resolve through them via the existing cross-package chain walker (see\n * `findClassDefinition`). After tracing the wiring at R3 kickoff\n * (2026-05-18), generalization was deferred: new `SmartObjectManifest →\n * ExternalManifest` adapter, new vite-plugin scan-path failure modes,\n * new sync-I/O surface — large cost for ~two saved lines per future\n * abstract base. R4 added the third base and re-confirmed the call: a new\n * abstract base is still two lines here + two in\n * `FRAMEWORK_ABSTRACT_BASE_NAMES`, far cheaper than the generalization's\n * new failure surface. Extend this list instead.\n */\nconst FRAMEWORK_BASE_CLASSES = new Set([\n 'SmrtObject',\n 'SmrtClass',\n 'SmrtCollection',\n 'SmrtJunction',\n 'SmrtHierarchical',\n 'SmrtPolymorphicAssociation',\n]);\n\n/**\n * Resolves class inheritance chains and STI hierarchies from raw OXC scan output.\n *\n * After {@link OxcScanner} parses files, `InheritanceResolver` builds a\n * class map from the raw definitions and walks each class's `extends` chain\n * to produce fully-resolved {@link ResolvedClassDefinition} objects.\n *\n * Key responsibilities:\n * - Walking extends chains across local classes and external package manifests.\n * - Detecting which classes participate in STI (Single Table Inheritance).\n * - Merging fields from ancestor classes for STI subclasses (base fields first).\n * - Caching resolved chains to avoid repeated traversals.\n *\n * Framework base classes (`SmrtObject`, `SmrtClass`, `SmrtCollection`) are\n * recognized without needing to appear in source files.\n *\n * @example\n * ```typescript\n * import { InheritanceResolver } from '@happyvertical/smrt-scanner';\n *\n * const resolver = new InheritanceResolver({ baseClasses: ['MyBaseClass'] });\n * resolver.addClasses(rawClasses);\n * const resolved = resolver.resolveAll();\n * ```\n *\n * @see {@link OxcScanner} which owns and drives this resolver internally.\n */\nexport class InheritanceResolver {\n /** Map of className -> RawClassDefinition */\n private classMap: Map<string, RawClassDefinition> = new Map();\n\n /** External package manifests for cross-package resolution */\n private externalManifests: Map<string, ExternalManifest> = new Map();\n\n /** Known base classes (user-provided) */\n private knownBaseClasses: Set<string>;\n\n /** Cache of resolved inheritance chains */\n private chainCache: Map<string, string[]> = new Map();\n\n /**\n * Create a new `InheritanceResolver`.\n *\n * @param options.baseClasses - Additional class names to treat as known\n * framework base classes (beyond the built-in `SmrtObject`, `SmrtClass`,\n * and `SmrtCollection`).\n * @param options.externalManifests - Pre-loaded external package manifests\n * keyed by package name, used for cross-package parent class resolution.\n */\n constructor(\n options: {\n baseClasses?: string[];\n externalManifests?: Map<string, ExternalManifest>;\n } = {},\n ) {\n this.knownBaseClasses = new Set([\n ...FRAMEWORK_BASE_CLASSES,\n ...(options.baseClasses || []),\n ]);\n this.externalManifests = options.externalManifests || new Map();\n }\n\n /**\n * Register raw class definitions from a scan pass.\n *\n * Adds each class to the internal class map by `className`. Calling this\n * clears the inheritance chain cache so subsequent calls to\n * {@link resolveAll} or {@link resolveInheritanceChain} reflect the new\n * classes.\n *\n * @param classes - Array of {@link RawClassDefinition} objects from\n * {@link ScanResults.classes}.\n */\n addClasses(classes: RawClassDefinition[]): void {\n for (const classDef of classes) {\n this.classMap.set(classDef.className, classDef);\n }\n // Clear cache when classes are added\n this.chainCache.clear();\n }\n\n /**\n * Register an external package manifest for cross-package base class resolution.\n *\n * Clears the chain cache after registration so re-resolution picks up the\n * new definitions.\n *\n * @param manifest - External package manifest providing class definitions\n * that may appear as base classes in the local project.\n *\n * @see {@link ExternalManifest}\n */\n addExternalManifest(manifest: ExternalManifest): void {\n this.externalManifests.set(manifest.packageName, manifest);\n this.chainCache.clear();\n }\n\n /**\n * Resolve all registered classes and return fully-resolved definitions.\n *\n * A class is included in the output if it either:\n * 1. Has an `@smrt()` decorator, or\n * 2. Directly or transitively extends a framework base class\n * (`SmrtObject`, `SmrtClass`, `SmrtCollection`) — this captures\n * collection classes such as `class MeetingCollection extends\n * SmrtCollection<Meeting>` that do not carry `@smrt()` themselves.\n *\n * @returns An array of {@link ResolvedClassDefinition} — one entry per\n * eligible class, with inheritance chain, STI metadata, and merged fields\n * populated.\n *\n * @see {@link resolve} to resolve a single class definition.\n */\n resolveAll(): ResolvedClassDefinition[] {\n const resolved: ResolvedClassDefinition[] = [];\n\n for (const classDef of this.classMap.values()) {\n // Include classes with @smrt() decorator\n // OR classes that extend framework base classes\n const extendsFrameworkBase = this.extendsFrameworkBase(classDef);\n if (!classDef.hasSmartDecorator && !extendsFrameworkBase) continue;\n\n const resolvedClass = this.resolve(classDef);\n resolved.push(resolvedClass);\n }\n\n return resolved;\n }\n\n /**\n * Check if a class extends a framework base class\n * (SmrtObject, SmrtClass, or SmrtCollection)\n */\n private extendsFrameworkBase(classDef: RawClassDefinition): boolean {\n // Direct extension of framework base\n if (\n classDef.extendsClause &&\n this.knownBaseClasses.has(classDef.extendsClause)\n ) {\n return true;\n }\n\n // Walk inheritance chain to check indirect extension\n const chain = this.resolveInheritanceChain(classDef.className);\n return chain.some((className) => this.knownBaseClasses.has(className));\n }\n\n /**\n * Resolve a single raw class definition into a fully-resolved definition.\n *\n * Computes the inheritance chain, determines the effective table strategy,\n * detects STI membership, and merges ancestor fields for STI classes.\n *\n * @param classDef - The raw class definition to resolve.\n * @returns A {@link ResolvedClassDefinition} with all inherited metadata\n * applied. The `packageName` field is left as `null` and must be set by\n * the caller (e.g. {@link ManifestAdapter}).\n *\n * @see {@link resolveAll} to resolve every registered class at once.\n */\n resolve(classDef: RawClassDefinition): ResolvedClassDefinition {\n const inheritanceChain = this.resolveInheritanceChain(classDef.className);\n const stiBase = this.findSTIBase(inheritanceChain);\n const effectiveTableStrategy = this.determineTableStrategy(\n classDef,\n inheritanceChain,\n );\n const isFrameworkBase = this.knownBaseClasses.has(classDef.className);\n const isSTI = effectiveTableStrategy === 'sti';\n\n // Merge fields for STI classes. For non-STI classes, the\n // ManifestGenerator in core selectively merges fields from framework\n // abstract bases (e.g. `SmrtHierarchical.parentId`) — see\n // `FRAMEWORK_ABSTRACT_BASE_NAMES` in\n // `packages/core/src/scanner/manifest-generator.ts`. Doing that merge\n // here too would compound with subtly different field shapes and\n // regress universal-baseline expectations in `fieldsFromClass`.\n const allFields = isSTI\n ? this.mergeFieldsForSTI(inheritanceChain)\n : classDef.fields;\n\n return {\n ...classDef,\n inheritanceChain,\n stiBase,\n effectiveTableStrategy,\n isSTI,\n isFrameworkBase,\n allFields,\n packageName: null, // Will be set by manifest adapter\n };\n }\n\n /**\n * Resolve the full inheritance chain for a named class, from the root base\n * class down to the named class itself.\n *\n * Results are memoised in an internal cache that is cleared whenever\n * {@link addClasses} or {@link addExternalManifest} is called.\n *\n * @param className - Name of the class to resolve.\n * @returns An ordered array of class names starting from the furthest\n * ancestor and ending with `className`.\n *\n * @example\n * ```typescript\n * // Given: class Article extends Content, class Content extends SmrtObject\n * resolver.resolveInheritanceChain('Article');\n * // => ['SmrtObject', 'Content', 'Article']\n * ```\n */\n resolveInheritanceChain(className: string): string[] {\n // Check cache\n const cached = this.chainCache.get(className);\n if (cached) return cached;\n\n const chain: string[] = [];\n const visited = new Set<string>();\n let current: string | null = className;\n\n while (current && !visited.has(current)) {\n visited.add(current);\n chain.unshift(current);\n\n // Check if this is a framework base class\n if (this.knownBaseClasses.has(current)) {\n break;\n }\n\n // Find parent class\n const classDef = this.findClassDefinition(current);\n current = classDef?.extendsClause || null;\n }\n\n // Cache result\n this.chainCache.set(className, chain);\n\n return chain;\n }\n\n /**\n * Look up a class definition by name, searching in priority order:\n * 1. Local classes added via {@link addClasses}.\n * 2. External package manifests added via {@link addExternalManifest}.\n * 3. Built-in framework base classes (`SmrtObject`, `SmrtClass`,\n * `SmrtCollection`) — returns a minimal stub definition so chain walking\n * can terminate cleanly.\n *\n * @param className - Class name to look up.\n * @returns The {@link RawClassDefinition} if found, or `null` if the class\n * is unknown to the resolver.\n */\n findClassDefinition(className: string): RawClassDefinition | null {\n // 1. Check local classes\n const local = this.classMap.get(className);\n if (local) return local;\n\n // 2. Check external manifests\n for (const manifest of this.externalManifests.values()) {\n const external = manifest.classes.get(className);\n if (external) return external;\n }\n\n // 3. Check if it's a known base class\n if (this.knownBaseClasses.has(className)) {\n // Return a minimal definition for framework bases\n return {\n className,\n filePath: '',\n extendsClause: null,\n extendsTypeArg: null,\n decoratorConfig: null,\n hasSmartDecorator: false,\n fields: [],\n methods: [],\n startLine: 0,\n endLine: 0,\n };\n }\n\n return null;\n }\n\n /**\n * Find the STI root class in a resolved inheritance chain.\n *\n * Walks the chain from base to leaf and returns the name of the first class\n * whose `@smrt()` decorator explicitly declares `tableStrategy: 'sti'`.\n *\n * @param chain - Ordered inheritance chain (base → leaf) as returned by\n * {@link resolveInheritanceChain}.\n * @returns The class name of the STI root, or `null` if no class in the\n * chain uses `tableStrategy: 'sti'`.\n */\n findSTIBase(chain: string[]): string | null {\n for (const className of chain) {\n const classDef = this.findClassDefinition(className);\n if (classDef?.decoratorConfig?.tableStrategy === 'sti') {\n return className;\n }\n }\n return null;\n }\n\n /**\n * Determine the effective table strategy (`'sti'` or `'cti'`) for a class.\n *\n * Resolution order:\n * 1. The class's own `@smrt({ tableStrategy })` declaration, if present.\n * 2. The nearest ancestor that declares `tableStrategy: 'sti'` — STI is\n * inherited automatically by all subclasses.\n * 3. Defaults to `'cti'` if no STI ancestor is found.\n *\n * @param classDef - Raw class definition whose strategy is being determined.\n * @param chain - Pre-resolved inheritance chain for `classDef` (base → leaf).\n * @returns `'sti'` or `'cti'`.\n */\n determineTableStrategy(\n classDef: RawClassDefinition,\n chain: string[],\n ): 'sti' | 'cti' {\n // Check if this class explicitly declares a strategy\n if (classDef.decoratorConfig?.tableStrategy) {\n return classDef.decoratorConfig.tableStrategy;\n }\n\n // Check ancestors for STI\n for (const className of chain) {\n if (className === classDef.className) continue;\n\n const ancestorDef = this.findClassDefinition(className);\n if (ancestorDef?.decoratorConfig?.tableStrategy === 'sti') {\n return 'sti';\n }\n }\n\n return 'cti';\n }\n\n /**\n * Merge fields from all classes in an STI inheritance chain.\n *\n * Iterates from the root base class to the leaf class so that base class\n * fields appear first in the returned array. If a field name is declared in\n * both an ancestor and a descendant, the ancestor's definition takes\n * precedence (first-seen wins), preserving the base-class column layout.\n *\n * @param chain - Ordered inheritance chain (base → leaf) as returned by\n * {@link resolveInheritanceChain}.\n * @returns A deduplicated, ordered array of {@link RawFieldDefinition}\n * covering every field in the STI hierarchy.\n */\n mergeFieldsForSTI(chain: string[]): RawFieldDefinition[] {\n const allFields: RawFieldDefinition[] = [];\n const seenNames = new Set<string>();\n\n for (const className of chain) {\n const classDef = this.findClassDefinition(className);\n if (!classDef) continue;\n\n for (const field of classDef.fields) {\n // Skip if already seen (child overrides parent)\n if (seenNames.has(field.name)) continue;\n\n seenNames.add(field.name);\n allFields.push(field);\n }\n }\n\n return allFields;\n }\n\n /**\n * Return all known descendants of a class.\n *\n * Useful for STI schema generation where the base table must accommodate\n * columns from every subclass.\n *\n * @param className - The ancestor class name to search from.\n * @returns An array of class names (local classes only) whose resolved\n * inheritance chain includes `className`. Does not include `className`\n * itself.\n */\n getDescendants(className: string): string[] {\n const descendants: string[] = [];\n\n for (const [name] of this.classMap) {\n if (name === className) continue;\n\n const chain = this.resolveInheritanceChain(name);\n if (chain.includes(className)) {\n descendants.push(name);\n }\n }\n\n return descendants;\n }\n\n /**\n * Check whether a class participates in an STI hierarchy.\n *\n * @param className - Name of the class to check.\n * @returns `true` if any class in the resolved inheritance chain declares\n * `tableStrategy: 'sti'`, `false` otherwise.\n */\n isSTIClass(className: string): boolean {\n const chain = this.resolveInheritanceChain(className);\n return this.findSTIBase(chain) !== null;\n }\n\n /**\n * Return aggregate statistics about the classes registered with this resolver.\n *\n * @returns An object with:\n * - `totalClasses` — total number of classes in the class map.\n * - `smrtClasses` — classes that carry `@smrt()`.\n * - `stiClasses` — `@smrt()` classes in an STI hierarchy.\n * - `maxInheritanceDepth` — length of the deepest inheritance chain among\n * `@smrt()` classes.\n */\n getStats(): {\n totalClasses: number;\n smrtClasses: number;\n stiClasses: number;\n maxInheritanceDepth: number;\n } {\n let smrtClasses = 0;\n let stiClasses = 0;\n let maxInheritanceDepth = 0;\n\n for (const classDef of this.classMap.values()) {\n if (classDef.hasSmartDecorator) {\n smrtClasses++;\n\n const chain = this.resolveInheritanceChain(classDef.className);\n maxInheritanceDepth = Math.max(maxInheritanceDepth, chain.length);\n\n if (this.findSTIBase(chain)) {\n stiClasses++;\n }\n }\n }\n\n return {\n totalClasses: this.classMap.size,\n smrtClasses,\n stiClasses,\n maxInheritanceDepth,\n };\n }\n}\n","/**\n * OXC-based TypeScript parser for SMRT class extraction\n *\n * Uses oxc-parser for high-performance syntactic parsing of TypeScript files.\n * Extracts @smrt() decorated classes with their fields, methods, and inheritance.\n *\n * @see https://oxc.rs/docs/guide/usage/parser.html\n */\n\nimport { readFileSync } from 'node:fs';\nimport { parseSync } from 'oxc-parser';\nimport type {\n FileScanResult,\n RawClassDefinition,\n RawDecorator,\n RawDecoratorConfig,\n RawFieldDefinition,\n RawMethodDefinition,\n RawParameterDefinition,\n ScanError,\n} from './types.js';\n\n/**\n * Get file extension for oxc-parser lang option\n */\nfunction getLangFromFilename(filename: string): 'ts' | 'tsx' | 'js' | 'jsx' {\n if (filename.endsWith('.tsx')) return 'tsx';\n if (filename.endsWith('.ts')) return 'ts';\n if (filename.endsWith('.jsx')) return 'jsx';\n return 'js';\n}\n\n/**\n * Extract line/column from offset in source text\n * Note: oxc-parser v0.108+ removed magicString, so we compute manually\n * @internal Exported for testing\n */\nexport function getLineColumn(\n sourceText: string,\n offset: number,\n): { line: number; column: number } | undefined {\n if (offset < 0 || offset > sourceText.length) {\n return undefined;\n }\n\n let line = 1;\n let lastNewlinePos = -1;\n\n for (let i = 0; i < offset; i++) {\n if (sourceText[i] === '\\n') {\n line++;\n lastNewlinePos = i;\n }\n }\n\n return {\n line,\n column: offset - lastNewlinePos, // 1-based column\n };\n}\n\n// ============================================================================\n// AST Node Types (TS-ESTree format from oxc-parser)\n// ============================================================================\n\ninterface Position {\n line: number;\n column: number;\n}\n\ninterface SourceLocation {\n start: Position;\n end: Position;\n}\n\ninterface BaseNode {\n type: string;\n loc?: SourceLocation;\n range?: [number, number];\n start?: number;\n end?: number;\n}\n\n/**\n * Get source range from an AST node.\n * oxc-parser v0.108+ uses start/end instead of range.\n */\nfunction getRange(node: BaseNode): [number, number] | null {\n if (node.range) return node.range;\n if (node.start !== undefined && node.end !== undefined)\n return [node.start, node.end];\n return null;\n}\n\n/**\n * Slice source text from an AST node's range.\n */\nfunction sliceSource(node: BaseNode, sourceText: string): string | null {\n const range = getRange(node);\n return range ? sourceText.slice(range[0], range[1]) : null;\n}\n\ninterface Program extends BaseNode {\n type: 'Program';\n body: Statement[];\n comments?: Comment[];\n}\n\ninterface Comment extends BaseNode {\n type: 'Line' | 'Block';\n value: string;\n}\n\ninterface ImportDeclaration extends BaseNode {\n type: 'ImportDeclaration';\n specifiers?: ImportSpecifierLike[];\n source: Literal;\n}\n\ntype ImportSpecifierLike =\n | ImportSpecifier\n | ImportNamespaceSpecifier\n | ImportDefaultSpecifier;\n\ninterface ImportSpecifier extends BaseNode {\n type: 'ImportSpecifier';\n imported: Identifier;\n local: Identifier;\n}\n\ninterface ImportNamespaceSpecifier extends BaseNode {\n type: 'ImportNamespaceSpecifier';\n local: Identifier;\n}\n\ninterface ImportDefaultSpecifier extends BaseNode {\n type: 'ImportDefaultSpecifier';\n local: Identifier;\n}\n\ntype Statement =\n | ClassDeclaration\n | ExportNamedDeclaration\n | ExportDefaultDeclaration\n | ImportDeclaration\n | any;\n\ninterface ClassDeclaration extends BaseNode {\n type: 'ClassDeclaration';\n id: Identifier | null;\n superClass: Expression | null;\n superTypeParameters?: TSTypeParameterInstantiation;\n body: ClassBody;\n decorators?: Decorator[];\n}\n\ninterface ClassBody extends BaseNode {\n type: 'ClassBody';\n body: ClassElement[];\n}\n\ntype ClassElement = PropertyDefinition | MethodDefinition | any;\n\ninterface PropertyDefinition extends BaseNode {\n type: 'PropertyDefinition';\n key: Expression;\n value: Expression | null;\n computed: boolean;\n static: boolean;\n readonly?: boolean;\n optional?: boolean;\n accessibility?: 'public' | 'private' | 'protected';\n typeAnnotation?: TSTypeAnnotation;\n decorators?: Decorator[];\n}\n\ninterface MethodDefinition extends BaseNode {\n type: 'MethodDefinition';\n key: Expression;\n value: FunctionExpression;\n kind: 'constructor' | 'method' | 'get' | 'set';\n computed: boolean;\n static: boolean;\n accessibility?: 'public' | 'private' | 'protected';\n}\n\ninterface FunctionExpression extends BaseNode {\n type: 'FunctionExpression';\n async: boolean;\n params: Pattern[];\n returnType?: TSTypeAnnotation;\n body: BlockStatement;\n}\n\ninterface BlockStatement extends BaseNode {\n type: 'BlockStatement';\n body: Statement[];\n}\n\ntype Pattern =\n | Identifier\n | AssignmentPattern\n | RestElement\n | ObjectPattern\n | ArrayPattern\n | any;\n\ninterface Identifier extends BaseNode {\n type: 'Identifier';\n name: string;\n typeAnnotation?: TSTypeAnnotation;\n optional?: boolean;\n}\n\ninterface AssignmentPattern extends BaseNode {\n type: 'AssignmentPattern';\n left: Pattern;\n right: Expression;\n}\n\ninterface RestElement extends BaseNode {\n type: 'RestElement';\n argument: Pattern;\n typeAnnotation?: TSTypeAnnotation;\n}\n\ninterface ObjectPattern extends BaseNode {\n type: 'ObjectPattern';\n properties: (Property | RestElement)[];\n typeAnnotation?: TSTypeAnnotation;\n}\n\ninterface ArrayPattern extends BaseNode {\n type: 'ArrayPattern';\n elements: (Pattern | null)[];\n typeAnnotation?: TSTypeAnnotation;\n}\n\ninterface Property extends BaseNode {\n type: 'Property';\n key: Expression;\n value: Expression | Pattern;\n kind: 'init' | 'get' | 'set';\n method: boolean;\n shorthand: boolean;\n computed: boolean;\n}\n\ntype Expression =\n | Identifier\n | Literal\n | CallExpression\n | MemberExpression\n | ObjectExpression\n | ArrayExpression\n | NewExpression\n | any;\n\ninterface Literal extends BaseNode {\n type: 'Literal';\n value: string | number | boolean | null | RegExp | bigint;\n raw?: string;\n}\n\ninterface CallExpression extends BaseNode {\n type: 'CallExpression';\n callee: Expression;\n arguments: Expression[];\n typeParameters?: TSTypeParameterInstantiation;\n}\n\ninterface MemberExpression extends BaseNode {\n type: 'MemberExpression';\n object: Expression;\n property: Expression;\n computed: boolean;\n}\n\ninterface ObjectExpression extends BaseNode {\n type: 'ObjectExpression';\n properties: (Property | SpreadElement)[];\n}\n\ninterface SpreadElement extends BaseNode {\n type: 'SpreadElement';\n argument: Expression;\n}\n\ninterface ArrayExpression extends BaseNode {\n type: 'ArrayExpression';\n elements: (Expression | SpreadElement | null)[];\n}\n\ninterface NewExpression extends BaseNode {\n type: 'NewExpression';\n callee: Expression;\n arguments: Expression[];\n}\n\ninterface Decorator extends BaseNode {\n type: 'Decorator';\n expression: Expression;\n}\n\ninterface ExportNamedDeclaration extends BaseNode {\n type: 'ExportNamedDeclaration';\n declaration: Statement | null;\n specifiers: ExportSpecifier[];\n}\n\ninterface ExportDefaultDeclaration extends BaseNode {\n type: 'ExportDefaultDeclaration';\n declaration: Statement | Expression;\n}\n\ninterface ExportSpecifier extends BaseNode {\n type: 'ExportSpecifier';\n local: Identifier;\n exported: Identifier;\n}\n\ninterface TSTypeAnnotation extends BaseNode {\n type: 'TSTypeAnnotation';\n typeAnnotation: TSType;\n}\n\ntype TSType =\n | TSStringKeyword\n | TSNumberKeyword\n | TSBooleanKeyword\n | TSAnyKeyword\n | TSVoidKeyword\n | TSNullKeyword\n | TSUndefinedKeyword\n | TSTypeReference\n | TSArrayType\n | TSUnionType\n | TSTypeLiteral\n | any;\n\ninterface TSStringKeyword extends BaseNode {\n type: 'TSStringKeyword';\n}\n\ninterface TSNumberKeyword extends BaseNode {\n type: 'TSNumberKeyword';\n}\n\ninterface TSBooleanKeyword extends BaseNode {\n type: 'TSBooleanKeyword';\n}\n\ninterface TSAnyKeyword extends BaseNode {\n type: 'TSAnyKeyword';\n}\n\ninterface TSVoidKeyword extends BaseNode {\n type: 'TSVoidKeyword';\n}\n\ninterface TSNullKeyword extends BaseNode {\n type: 'TSNullKeyword';\n}\n\ninterface TSUndefinedKeyword extends BaseNode {\n type: 'TSUndefinedKeyword';\n}\n\ninterface TSTypeReference extends BaseNode {\n type: 'TSTypeReference';\n typeName: Identifier | TSQualifiedName;\n typeParameters?: TSTypeParameterInstantiation;\n}\n\ninterface TSQualifiedName extends BaseNode {\n type: 'TSQualifiedName';\n left: Identifier | TSQualifiedName;\n right: Identifier;\n}\n\ninterface TSArrayType extends BaseNode {\n type: 'TSArrayType';\n elementType: TSType;\n}\n\ninterface TSUnionType extends BaseNode {\n type: 'TSUnionType';\n types: TSType[];\n}\n\ninterface TSTypeLiteral extends BaseNode {\n type: 'TSTypeLiteral';\n members: TSTypeElement[];\n}\n\ntype TSTypeElement =\n | TSPropertySignature\n | TSMethodSignature\n | TSIndexSignature\n | any;\n\ninterface TSPropertySignature extends BaseNode {\n type: 'TSPropertySignature';\n key: Expression;\n typeAnnotation?: TSTypeAnnotation;\n optional?: boolean;\n readonly?: boolean;\n}\n\ninterface TSMethodSignature extends BaseNode {\n type: 'TSMethodSignature';\n key: Expression;\n params: Pattern[];\n returnType?: TSTypeAnnotation;\n}\n\ninterface TSIndexSignature extends BaseNode {\n type: 'TSIndexSignature';\n parameters: Identifier[];\n typeAnnotation?: TSTypeAnnotation;\n}\n\ninterface TSTypeParameterInstantiation extends BaseNode {\n type: 'TSTypeParameterInstantiation';\n params: TSType[];\n}\n\n// ============================================================================\n// Parser Implementation\n// ============================================================================\n\n/**\n * Parse a single TypeScript file and extract SMRT class definitions.\n *\n * Reads the file from disk, runs oxc-parser on it, and returns all class\n * definitions found, any parse errors, accumulated type aliases, and\n * `@happyvertical/smrt-*` import metadata.\n *\n * @param filePath - Absolute path to the `.ts` or `.tsx` file to parse.\n * @returns A {@link FileScanResult} containing classes, errors, type aliases,\n * SMRT imports, and timing information for the file.\n *\n * @example\n * ```typescript\n * import { parseFile } from '@happyvertical/smrt-scanner';\n *\n * const result = parseFile('/project/src/models/Product.ts');\n * console.log(result.classes.map((c) => c.className));\n * // ['Product', 'ProductCollection']\n * ```\n *\n * @see {@link parseSource} to parse a source string directly (e.g. in tests).\n */\nexport function parseFile(filePath: string): FileScanResult {\n const startTime = performance.now();\n const errors: ScanError[] = [];\n const classes: RawClassDefinition[] = [];\n let typeAliases: Record<string, string> = {};\n let smrtImports: Map<string, Set<string>> | undefined;\n\n try {\n const sourceText = readFileSync(filePath, 'utf-8');\n const result = parseSync(filePath, sourceText, {\n lang: getLangFromFilename(filePath),\n preserveParens: false,\n });\n\n // Collect parse errors\n if (result.errors && result.errors.length > 0) {\n for (const error of result.errors) {\n const loc = error.labels?.[0]\n ? getLineColumn(sourceText, error.labels[0].start)\n : undefined;\n errors.push({\n message: error.message || 'Parse error',\n filePath,\n line: loc?.line,\n column: loc?.column,\n severity: error.severity === 'Error' ? 'error' : 'warning',\n });\n }\n }\n\n // Extract classes from AST\n const program = result.program as Program;\n if (program?.body) {\n const importAliases = extractImportAliases(program.body);\n typeAliases = extractTypeAliases(program.body);\n smrtImports = extractSmrtImports(program.body);\n for (const node of program.body) {\n const extracted = extractClassFromNode(\n node,\n filePath,\n sourceText,\n importAliases,\n );\n if (extracted) {\n classes.push(extracted);\n }\n }\n }\n } catch (error) {\n errors.push({\n message: error instanceof Error ? error.message : String(error),\n filePath,\n severity: 'error',\n });\n }\n\n const result2: FileScanResult = {\n filePath,\n classes,\n errors,\n parseTimeMs: performance.now() - startTime,\n typeAliases,\n };\n if (smrtImports && smrtImports.size > 0) {\n result2.smrtImports = smrtImports;\n }\n return result2;\n}\n\n/**\n * Parse TypeScript source text directly and extract SMRT class definitions.\n *\n * Identical to {@link parseFile} but accepts a source string instead of a\n * file path. Primarily used in tests and tooling that constructs source\n * programmatically.\n *\n * @param sourceText - Raw TypeScript source code to parse.\n * @param filename - Virtual filename used to determine the parser language\n * mode (`.ts`, `.tsx`, `.js`, `.jsx`) and to populate `filePath` fields in\n * the result. Defaults to `'test.ts'`.\n * @returns A {@link FileScanResult} containing classes, errors, type aliases,\n * and SMRT import metadata extracted from the source text.\n *\n * @example\n * ```typescript\n * import { parseSource } from '@happyvertical/smrt-scanner';\n *\n * const src = `\n * import { smrt } from '@happyvertical/smrt-core';\n * @smrt()\n * export class Widget extends SmrtObject {\n * label: string = '';\n * }\n * `;\n * const result = parseSource(src, 'Widget.ts');\n * console.log(result.classes[0].className); // 'Widget'\n * ```\n *\n * @see {@link parseFile} to parse a file from disk.\n */\nexport function parseSource(\n sourceText: string,\n filename = 'test.ts',\n): FileScanResult {\n const startTime = performance.now();\n const errors: ScanError[] = [];\n const classes: RawClassDefinition[] = [];\n let typeAliases: Record<string, string> = {};\n let smrtImports: Map<string, Set<string>> | undefined;\n\n try {\n const result = parseSync(filename, sourceText, {\n lang: getLangFromFilename(filename),\n preserveParens: false,\n });\n\n if (result.errors && result.errors.length > 0) {\n for (const error of result.errors) {\n const loc = error.labels?.[0]\n ? getLineColumn(sourceText, error.labels[0].start)\n : undefined;\n errors.push({\n message: error.message || 'Parse error',\n filePath: filename,\n line: loc?.line,\n column: loc?.column,\n severity: error.severity === 'Error' ? 'error' : 'warning',\n });\n }\n }\n\n const program = result.program as Program;\n if (program?.body) {\n const importAliases = extractImportAliases(program.body);\n typeAliases = extractTypeAliases(program.body);\n smrtImports = extractSmrtImports(program.body);\n for (const node of program.body) {\n const extracted = extractClassFromNode(\n node,\n filename,\n sourceText,\n importAliases,\n );\n if (extracted) {\n classes.push(extracted);\n }\n }\n }\n } catch (error) {\n errors.push({\n message: error instanceof Error ? error.message : String(error),\n filePath: filename,\n severity: 'error',\n });\n }\n\n const result2: FileScanResult = {\n filePath: filename,\n classes,\n errors,\n parseTimeMs: performance.now() - startTime,\n typeAliases,\n };\n if (smrtImports && smrtImports.size > 0) {\n result2.smrtImports = smrtImports;\n }\n return result2;\n}\n\n// ============================================================================\n// AST Extraction Helpers\n// ============================================================================\n\n/**\n * Property keys that must never be assigned onto a plain object built from\n * parsed source. Assigning `obj['__proto__'] = value` mutates the object's\n * prototype rather than adding an own property, which is a prototype-pollution\n * vector. `constructor` / `prototype` are blocked for defense-in-depth.\n *\n * Scanner input is developer-authored source consumed at build time (trusted),\n * so this is a hardening guard, not a fix for a remotely reachable bug: a class\n * field, decorator-config property, or type alias literally named `__proto__`\n * would otherwise silently corrupt the metadata object it is collected into.\n */\nconst FORBIDDEN_OBJECT_KEYS = new Set([\n '__proto__',\n 'constructor',\n 'prototype',\n]);\n\n/**\n * Whether a key is safe to assign as an own property on a plain object built\n * from parsed AST. See {@link FORBIDDEN_OBJECT_KEYS}.\n *\n * @internal Exported for testing.\n */\nexport function isSafeObjectKey(key: string): boolean {\n return !FORBIDDEN_OBJECT_KEYS.has(key);\n}\n\n/**\n * Extract import aliases from program body.\n * Maps local alias names to their original imported names.\n * e.g., `import { Performer as PerformerBase }` → Map { \"PerformerBase\" → \"Performer\" }\n */\nfunction extractImportAliases(body: Statement[]): Map<string, string> {\n const aliases = new Map<string, string>();\n for (const node of body) {\n if (node.type === 'ImportDeclaration' && node.specifiers) {\n for (const spec of node.specifiers) {\n if (spec.type === 'ImportSpecifier' && spec.imported && spec.local) {\n const original = spec.imported.name;\n const local = spec.local.name;\n if (original !== local) {\n aliases.set(local, original);\n }\n }\n }\n }\n }\n return aliases;\n}\n\n/**\n * Extract `@happyvertical/smrt-*` import declarations from an OXC program body.\n *\n * Scans the top-level AST statements for `ImportDeclaration` nodes whose\n * module specifier begins with `@happyvertical/smrt-` and collects the\n * PascalCase identifiers being imported. The result is used for tree-shaking:\n * only externally imported SMRT classes that appear in project source are\n * included in the generated manifest.\n *\n * Handles all import forms:\n * - Side-effect imports — `import '@happyvertical/smrt-messages'` (recorded as `'*'`)\n * - Named imports — `import { Person, Organization } from '@happyvertical/smrt-profiles'`\n * - Renamed named imports — `import { Person as PersonBase } from '...'` (records original name `Person`)\n * - Namespace imports — `import * as Profiles from '@happyvertical/smrt-profiles'` (recorded as `'*'`)\n * - Default imports — `import SomeClass from '@happyvertical/smrt-profiles'`\n *\n * Only PascalCase identifiers are recorded; utility function names (lowercase)\n * are ignored.\n *\n * @param body - The top-level statement array from the OXC-parsed `Program` node.\n * @returns A `Map` keyed by package name (e.g. `'@happyvertical/smrt-profiles'`)\n * whose values are `Set`s of the imported PascalCase class names (or `'*'`\n * for namespace imports).\n *\n * @example\n * ```typescript\n * import { parseSource, extractSmrtImports } from '@happyvertical/smrt-scanner';\n * import { parseSync } from 'oxc-parser';\n *\n * const src = `import { Person, Organization } from '@happyvertical/smrt-profiles';`;\n * const { program } = parseSync('file.ts', src, { lang: 'ts' });\n * const imports = extractSmrtImports(program.body);\n * // Map { '@happyvertical/smrt-profiles' => Set { 'Person', 'Organization' } }\n * ```\n *\n * @internal Exported for testing; use {@link OxcScanner.scanSmrtImports} for\n * production use cases.\n */\nexport function extractSmrtImports(\n body: Statement[],\n): Map<string, Set<string>> {\n const imports = new Map<string, Set<string>>();\n\n for (const node of body) {\n if (node.type !== 'ImportDeclaration') continue;\n\n // Get module specifier string\n const source = node.source;\n if (!source || !source.value) continue;\n\n const moduleName = source.value;\n\n // Only process @happyvertical/smrt-* packages\n if (!moduleName.startsWith('@happyvertical/smrt-')) continue;\n\n // Get or create the set for this package\n if (!imports.has(moduleName)) {\n imports.set(moduleName, new Set());\n }\n const classSet = imports.get(moduleName)!;\n\n if (!node.specifiers || node.specifiers.length === 0) {\n classSet.add('*');\n continue;\n }\n\n for (const spec of node.specifiers) {\n if (spec.type === 'ImportSpecifier' && spec.imported && spec.local) {\n // Named import: use original (imported) name, not local alias\n const importedName = spec.imported.name;\n // Only include PascalCase names (likely classes)\n if (/^[A-Z][A-Za-z0-9]*$/.test(importedName)) {\n classSet.add(importedName);\n }\n } else if (spec.type === 'ImportNamespaceSpecifier') {\n // Namespace import: import * as X from '...'\n classSet.add('*');\n } else if (spec.type === 'ImportDefaultSpecifier' && spec.local) {\n // Default import: import SomeClass from '...'\n const defaultName = spec.local.name;\n if (/^[A-Z][A-Za-z0-9]*$/.test(defaultName)) {\n classSet.add(defaultName);\n }\n }\n }\n }\n\n return imports;\n}\n\n/**\n * Extract type alias declarations from program body.\n * Maps alias names to their resolved type strings.\n * e.g., `type Status = 'active' | 'inactive'` → { Status: \"'active' | 'inactive'\" }\n * @internal Exported for testing\n */\nexport function extractTypeAliases(body: Statement[]): Record<string, string> {\n const aliases: Record<string, string> = {};\n for (const node of body) {\n if (node.type === 'TSTypeAliasDeclaration') {\n const name = node.id?.name;\n const resolved = node.typeAnnotation\n ? extractTypeName(node.typeAnnotation)\n : null;\n if (name && resolved && isSafeObjectKey(name)) aliases[name] = resolved;\n }\n // Also check `export type X = ...` (ExportNamedDeclaration wrapping)\n if (\n node.type === 'ExportNamedDeclaration' &&\n node.declaration?.type === 'TSTypeAliasDeclaration'\n ) {\n const decl = node.declaration;\n const name = decl.id?.name;\n const resolved = decl.typeAnnotation\n ? extractTypeName(decl.typeAnnotation)\n : null;\n if (name && resolved && isSafeObjectKey(name)) aliases[name] = resolved;\n }\n\n // Extract enum declarations as string union types\n // e.g., enum Status { PENDING = 'pending', ACTIVE = 'active' }\n // → Status: \"'pending' | 'active'\"\n const enumDecl =\n node.type === 'TSEnumDeclaration'\n ? node\n : node.type === 'ExportNamedDeclaration' &&\n node.declaration?.type === 'TSEnumDeclaration'\n ? node.declaration\n : null;\n if (enumDecl) {\n const name = enumDecl.id?.name;\n // OXC wraps members in a TSEnumBody node: enumDecl.body.members\n const members = enumDecl.body?.members ?? enumDecl.members;\n if (name && isSafeObjectKey(name) && members?.length > 0) {\n const values = members\n .map((m: any) => {\n if (m.initializer?.type === 'Literal') {\n const val = m.initializer.value;\n if (typeof val === 'string') return `'${val}'`;\n if (typeof val === 'number') return String(val);\n }\n return null;\n })\n .filter(Boolean);\n\n if (values.length > 0) {\n // All string values → string union, all numeric → number union\n const allStrings = values.every((v: string) => v.startsWith(\"'\"));\n if (allStrings) {\n aliases[name] = values.join(' | ');\n }\n }\n }\n }\n }\n return aliases;\n}\n\n/**\n * Extract class definition from an AST node\n */\nfunction extractClassFromNode(\n node: Statement,\n filePath: string,\n sourceText: string,\n importAliases: Map<string, string>,\n): RawClassDefinition | null {\n // Handle export declarations\n if (node.type === 'ExportNamedDeclaration' && node.declaration) {\n return extractClassFromNode(\n node.declaration,\n filePath,\n sourceText,\n importAliases,\n );\n }\n if (node.type === 'ExportDefaultDeclaration' && node.declaration) {\n return extractClassFromNode(\n node.declaration as Statement,\n filePath,\n sourceText,\n importAliases,\n );\n }\n\n // Handle class declaration\n if (node.type === 'ClassDeclaration') {\n return extractClassDeclaration(node, filePath, sourceText, importAliases);\n }\n\n return null;\n}\n\n/**\n * Extract class declaration details\n */\nfunction extractClassDeclaration(\n node: ClassDeclaration,\n filePath: string,\n sourceText: string,\n importAliases: Map<string, string>,\n): RawClassDefinition {\n const className = node.id?.name || 'AnonymousClass';\n\n // Extract decorators\n const decorators = node.decorators || [];\n const smrtDecorator = decorators.find((d) => isSmrtDecorator(d));\n const tenantScopedDecorator = decorators.find((d) =>\n isNamedDecorator(d, 'TenantScoped'),\n );\n const hasSmartDecorator = !!smrtDecorator;\n const smrtConfig = smrtDecorator\n ? extractDecoratorConfig(smrtDecorator, sourceText)\n : null;\n const decoratorConfig = tenantScopedDecorator\n ? {\n ...(smrtConfig ?? {}),\n tenantScoped: extractDecoratorConfig(tenantScopedDecorator, sourceText),\n }\n : smrtConfig;\n\n // Extract extends clause\n const { extendsClause, extendsTypeArg } = extractExtendsClause(\n node,\n importAliases,\n );\n\n // Extract fields and methods\n const fields: RawFieldDefinition[] = [];\n const methods: RawMethodDefinition[] = [];\n\n for (const member of node.body.body) {\n if (member.type === 'PropertyDefinition') {\n const field = extractPropertyDefinition(member, sourceText);\n if (field) {\n fields.push(field);\n }\n } else if (member.type === 'MethodDefinition') {\n const method = extractMethodDefinition(member, sourceText);\n if (method) {\n methods.push(method);\n }\n }\n }\n\n return {\n className,\n filePath,\n extendsClause,\n extendsTypeArg,\n decoratorConfig,\n hasSmartDecorator,\n fields,\n methods,\n startLine: node.loc?.start.line || 1,\n endLine: node.loc?.end.line || 1,\n };\n}\n\n/**\n * Check if a decorator is @smrt()\n */\nfunction isSmrtDecorator(decorator: Decorator): boolean {\n return isNamedDecorator(decorator, 'smrt');\n}\n\nfunction isNamedDecorator(decorator: Decorator, name: string): boolean {\n const expr = decorator.expression;\n\n // @decoratorName() - CallExpression\n if (expr.type === 'CallExpression') {\n const callee = expr.callee;\n if (callee.type === 'Identifier' && callee.name === name) {\n return true;\n }\n }\n\n // @decoratorName - Identifier (no parentheses)\n if (expr.type === 'Identifier' && expr.name === name) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Extract @smrt() decorator configuration\n */\nfunction extractDecoratorConfig(\n decorator: Decorator,\n sourceText: string,\n): RawDecoratorConfig | null {\n const expr = decorator.expression;\n\n if (expr.type === 'CallExpression' && expr.arguments.length > 0) {\n const arg = expr.arguments[0];\n if (arg.type === 'ObjectExpression') {\n return extractObjectLiteral(arg, sourceText) as RawDecoratorConfig;\n }\n }\n\n // @smrt() with no config or @smrt\n return {};\n}\n\n/**\n * Extract object literal to plain object\n */\nfunction extractObjectLiteral(\n node: ObjectExpression,\n sourceText: string,\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const prop of node.properties) {\n if (prop.type === 'Property' && !prop.computed) {\n const key = getPropertyKey(prop.key);\n // Skip prototype-pollution keys (__proto__/constructor/prototype) so a\n // decorator-config property of that name cannot mutate the metadata\n // object's prototype.\n if (key && isSafeObjectKey(key)) {\n result[key] = extractValue(prop.value, sourceText);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Get property key as string\n */\nfunction getPropertyKey(node: Expression): string | null {\n if (node.type === 'Identifier') {\n return node.name;\n }\n if (node.type === 'Literal' && typeof node.value === 'string') {\n return node.value;\n }\n return null;\n}\n\n/**\n * Extract value from expression\n */\nfunction extractValue(node: Expression, sourceText: string): unknown {\n switch (node.type) {\n case 'Literal':\n return node.value;\n\n case 'Identifier':\n // Handle special identifiers\n if (node.name === 'undefined') return undefined;\n if (node.name === 'null') return null;\n if (node.name === 'true') return true;\n if (node.name === 'false') return false;\n return node.name; // Return as string for class references\n\n case 'ArrayExpression':\n return node.elements\n .filter(\n (el: Expression | SpreadElement | null): el is Expression =>\n el !== null &&\n typeof el === 'object' &&\n 'type' in el &&\n el.type !== 'SpreadElement',\n )\n .map((el: Expression) => extractValue(el, sourceText));\n\n case 'ObjectExpression':\n return extractObjectLiteral(node, sourceText);\n\n case 'UnaryExpression':\n if (node.operator === '-' && node.argument?.type === 'Literal') {\n const value = node.argument.value;\n if (typeof value === 'number') {\n return -value;\n }\n }\n break;\n\n case 'CallExpression':\n case 'NewExpression': {\n // Return the raw source for complex expressions\n const src = sliceSource(node, sourceText);\n if (src) return src;\n break;\n }\n }\n\n // For complex expressions, return raw source if available\n const rawSrc = sliceSource(node, sourceText);\n if (rawSrc) return rawSrc;\n\n return undefined;\n}\n\n/**\n * Extract extends clause information\n */\nfunction extractExtendsClause(\n node: ClassDeclaration,\n importAliases: Map<string, string>,\n): {\n extendsClause: string | null;\n extendsTypeArg: string | null;\n} {\n if (!node.superClass) {\n return { extendsClause: null, extendsTypeArg: null };\n }\n\n let extendsClause: string | null = null;\n let extendsTypeArg: string | null = null;\n\n // Get class name\n if (node.superClass.type === 'Identifier') {\n extendsClause = node.superClass.name;\n } else if (node.superClass.type === 'MemberExpression') {\n // Handle Namespace.Class\n extendsClause = getMemberExpressionString(node.superClass);\n }\n\n // Resolve import aliases (e.g., import { Performer as PerformerBase })\n if (extendsClause && importAliases.has(extendsClause)) {\n extendsClause = importAliases.get(extendsClause)!;\n }\n\n // Get type argument (e.g., Meeting from SmrtCollection<Meeting>)\n // Note: oxc-parser v0.108+ renamed superTypeParameters to superTypeArguments\n const params =\n (node as any).superTypeArguments?.params ||\n node.superTypeParameters?.params;\n if (params && params.length > 0) {\n const typeParam = params[0];\n extendsTypeArg = extractTypeName(typeParam);\n }\n\n return { extendsClause, extendsTypeArg };\n}\n\n/**\n * Get member expression as dotted string\n */\nfunction getMemberExpressionString(node: MemberExpression): string {\n const parts: string[] = [];\n\n let current: Expression = node;\n while (current.type === 'MemberExpression') {\n if (current.property.type === 'Identifier') {\n parts.unshift(current.property.name);\n }\n current = current.object;\n }\n\n if (current.type === 'Identifier') {\n parts.unshift(current.name);\n }\n\n return parts.join('.');\n}\n\n/**\n * Reconstruct call expression string from AST\n * e.g., foreignKey(Customer) or decimal({ required: true })\n */\nfunction reconstructCallExpression(\n node: CallExpression,\n sourceText: string,\n): string | null {\n // Try range first\n const src = sliceSource(node, sourceText);\n if (src) return src;\n\n // Reconstruct from AST\n let callee = '';\n if (node.callee.type === 'Identifier') {\n callee = node.callee.name;\n } else if (node.callee.type === 'MemberExpression') {\n callee = getMemberExpressionString(node.callee);\n } else {\n return null;\n }\n\n // Reconstruct arguments\n const args: string[] = [];\n for (const arg of node.arguments) {\n const argSrc = sliceSource(arg, sourceText);\n if (argSrc) {\n args.push(argSrc);\n } else if (arg.type === 'Identifier') {\n args.push(arg.name);\n } else if (arg.type === 'Literal') {\n args.push(arg.raw || String(arg.value));\n } else if (arg.type === 'ObjectExpression') {\n // Simplified object reconstruction\n const objStr = reconstructObjectExpression(arg, sourceText);\n if (objStr) args.push(objStr);\n } else {\n // Skip complex arguments\n args.push('...');\n }\n }\n\n return `${callee}(${args.join(', ')})`;\n}\n\n/**\n * Reconstruct object expression string from AST\n */\nfunction reconstructObjectExpression(\n node: ObjectExpression,\n sourceText: string,\n): string | null {\n const src = sliceSource(node, sourceText);\n if (src) return src;\n\n const props: string[] = [];\n for (const prop of node.properties) {\n if (prop.type === 'SpreadElement') continue;\n if (prop.type === 'Property') {\n let key = '';\n if (prop.key.type === 'Identifier') {\n key = prop.key.name;\n } else if (prop.key.type === 'Literal') {\n key = String(prop.key.value);\n }\n if (!key) continue;\n\n let value = '';\n const valSrc = sliceSource(prop.value, sourceText);\n if (valSrc) {\n value = valSrc;\n } else if (prop.value.type === 'ObjectExpression') {\n // Recursively reconstruct nested objects (e.g., uiSlots.sources)\n value =\n reconstructObjectExpression(\n prop.value as ObjectExpression,\n sourceText,\n ) || '';\n } else if (prop.value.type === 'ArrayExpression') {\n value =\n reconstructArrayExpression(\n prop.value as ArrayExpression,\n sourceText,\n ) || '';\n } else if (prop.value.type === 'Identifier') {\n value = prop.value.name;\n } else if (prop.value.type === 'Literal') {\n value = prop.value.raw || String(prop.value.value);\n }\n\n if (value) {\n props.push(`${key}: ${value}`);\n }\n }\n }\n\n return `{ ${props.join(', ')} }`;\n}\n\n/**\n * Reconstruct array expression string from AST\n */\nfunction reconstructArrayExpression(\n node: ArrayExpression,\n sourceText: string,\n): string | null {\n const src = sliceSource(node, sourceText);\n if (src) return src;\n\n const elements: string[] = [];\n for (const el of node.elements) {\n if (!el) continue;\n if (el.type === 'SpreadElement') {\n elements.push('...');\n } else {\n const elSrc = sliceSource(el, sourceText);\n if (elSrc) {\n elements.push(elSrc);\n } else if (el.type === 'Identifier') {\n elements.push(el.name);\n } else if (el.type === 'Literal') {\n elements.push(el.raw || String(el.value));\n } else if (el.type === 'ObjectExpression') {\n const objStr = reconstructObjectExpression(\n el as ObjectExpression,\n sourceText,\n );\n if (objStr) elements.push(objStr);\n }\n }\n }\n\n return `[${elements.join(', ')}]`;\n}\n\n/**\n * Extract type name from TSType\n */\nfunction extractTypeName(type: TSType): string | null {\n switch (type.type) {\n case 'TSTypeReference': {\n let baseName: string | null = null;\n if (type.typeName.type === 'Identifier') {\n baseName = type.typeName.name;\n } else if (type.typeName.type === 'TSQualifiedName') {\n baseName = getQualifiedName(type.typeName);\n }\n\n // Include type parameters (e.g., Promise<any>, Map<string, number>)\n // Note: oxc-parser v0.108+ renamed typeParameters to typeArguments\n const typeParams =\n (type as any).typeArguments?.params || type.typeParameters?.params;\n if (baseName && typeParams?.length) {\n const typeArgs = typeParams\n .map((p: TSType) => extractTypeName(p))\n .filter(Boolean);\n if (typeArgs.length > 0) {\n return `${baseName}<${typeArgs.join(', ')}>`;\n }\n }\n return baseName;\n }\n\n case 'TSStringKeyword':\n return 'string';\n case 'TSNumberKeyword':\n return 'number';\n case 'TSBooleanKeyword':\n return 'boolean';\n case 'TSAnyKeyword':\n return 'any';\n case 'TSVoidKeyword':\n return 'void';\n case 'TSNullKeyword':\n return 'null';\n case 'TSUndefinedKeyword':\n return 'undefined';\n\n case 'TSLiteralType': {\n const literal = (type as any).literal;\n if (!literal) return null;\n // oxc-parser uses generic 'Literal' node type — distinguish by value type\n if (typeof literal.value === 'string') return `'${literal.value}'`;\n if (typeof literal.value === 'number') return String(literal.value);\n if (typeof literal.value === 'boolean') return String(literal.value);\n return null;\n }\n\n case 'TSArrayType': {\n const elementType = extractTypeName(type.elementType);\n return elementType ? `${elementType}[]` : null;\n }\n\n case 'TSUnionType': {\n const types = type.types\n .map((t: TSType) => extractTypeName(t))\n .filter(Boolean);\n return types.join(' | ');\n }\n\n // Inline object type literal: { subject?: string; from?: string; body?: string }\n // Maps to 'object' which the ManifestAdapter resolves as json\n case 'TSTypeLiteral':\n return 'object';\n case 'TSFunctionType':\n return 'Function';\n }\n\n return null;\n}\n\n/**\n * Get qualified name as string\n */\nfunction getQualifiedName(node: TSQualifiedName): string {\n const parts: string[] = [];\n\n let current: TSQualifiedName | Identifier = node;\n while (current.type === 'TSQualifiedName') {\n parts.unshift(current.right.name);\n current = current.left;\n }\n\n if (current.type === 'Identifier') {\n parts.unshift(current.name);\n }\n\n return parts.join('.');\n}\n\n/**\n * Extract property definition\n */\nfunction extractPropertyDefinition(\n node: PropertyDefinition,\n sourceText: string,\n): RawFieldDefinition | null {\n // Skip computed properties\n if (node.computed) return null;\n\n const name = getPropertyKey(node.key);\n if (!name) return null;\n // Reject prototype-polluting field names before they become manifest map keys\n // (a field literally named `__proto__`/`constructor`/`prototype`). The\n // type-alias/enum/object-literal extractors already gate on this; field\n // definitions must too (review #1559).\n if (!isSafeObjectKey(name)) return null;\n\n // Get type annotation\n const typeAnnotation = node.typeAnnotation\n ? extractTypeName(node.typeAnnotation.typeAnnotation)\n : null;\n\n // Get initializer\n let initializer: string | null = null;\n let hasDecimalPoint = false;\n let numericValue: number | null = null;\n\n if (node.value) {\n // Check for numeric literal with decimal point. Unwrap a leading unary\n // minus first: a negative initializer (`= -5`, `= -1.5`) parses as a\n // `UnaryExpression{ operator: '-', argument: Literal }`, not a bare\n // `Literal`, so without this the 0-vs-0.0 heuristic mis-infers negatives as\n // `integer` and drops the default. Mirrors the `extractValue` pattern above.\n if (\n node.value.type === 'UnaryExpression' &&\n node.value.operator === '-' &&\n node.value.argument?.type === 'Literal' &&\n typeof node.value.argument.value === 'number'\n ) {\n numericValue = -node.value.argument.value;\n // Check the inner literal's raw string for a decimal point (0.0 vs 0).\n if (node.value.argument.raw) {\n hasDecimalPoint = node.value.argument.raw.includes('.');\n }\n } else if (\n node.value.type === 'Literal' &&\n typeof node.value.value === 'number'\n ) {\n numericValue = node.value.value;\n // Check raw string for decimal point (0.0 vs 0)\n if (node.value.raw) {\n hasDecimalPoint = node.value.raw.includes('.');\n }\n }\n\n // Get raw initializer string - try range first for accurate source text\n const valueSrc = sliceSource(node.value, sourceText);\n if (valueSrc) {\n initializer = valueSrc;\n } else if (node.value.type === 'Literal' && node.value.raw) {\n // Fall back to raw property for literals\n initializer = node.value.raw;\n } else if (node.value.type === 'Literal') {\n // Convert literal value to string\n const val = node.value.value;\n if (typeof val === 'string') {\n initializer = `'${val}'`;\n } else if (val !== null && val !== undefined) {\n initializer = String(val);\n }\n } else if (\n node.value.type === 'CallExpression' ||\n node.value.type === 'NewExpression'\n ) {\n // Reconstruct call expression string from AST\n initializer = reconstructCallExpression(\n node.value as CallExpression,\n sourceText,\n );\n } else if (node.value.type === 'ArrayExpression') {\n // Reconstruct array expression\n initializer = reconstructArrayExpression(node.value, sourceText);\n } else if (node.value.type === 'ObjectExpression') {\n // Reconstruct object expression (e.g., static uiSlots = { ... })\n initializer = reconstructObjectExpression(\n node.value as ObjectExpression,\n sourceText,\n );\n }\n }\n\n // Extract decorators\n const decorators: RawDecorator[] = [];\n if (node.decorators) {\n for (const dec of node.decorators) {\n const extracted = extractFieldDecorator(dec, sourceText);\n if (extracted) {\n decorators.push(extracted);\n }\n }\n }\n\n return {\n name,\n typeAnnotation,\n initializer,\n hasDecimalPoint,\n numericValue,\n decorators,\n optional: node.optional || false,\n isStatic: node.static || false,\n readonly: node.readonly || false,\n accessibility: node.accessibility || 'public',\n line: node.loc?.start.line || 0,\n };\n}\n\n/**\n * Extract field decorator\n */\nfunction extractFieldDecorator(\n decorator: Decorator,\n sourceText: string,\n): RawDecorator | null {\n const expr = decorator.expression;\n\n let name: string | null = null;\n const args: string[] = [];\n\n if (expr.type === 'CallExpression') {\n if (expr.callee.type === 'Identifier') {\n name = expr.callee.name;\n }\n // Extract arguments as strings\n for (const arg of expr.arguments) {\n const argSrc = sliceSource(arg, sourceText);\n if (argSrc) args.push(argSrc);\n }\n } else if (expr.type === 'Identifier') {\n name = expr.name;\n }\n\n if (!name) return null;\n\n return { name, arguments: args };\n}\n\n/**\n * Extract method definition\n */\nfunction extractMethodDefinition(\n node: MethodDefinition,\n sourceText: string,\n): RawMethodDefinition | null {\n // Skip constructors, getters, setters\n if (node.kind !== 'method') return null;\n\n const name = getPropertyKey(node.key);\n if (!name) return null;\n\n const func = node.value;\n\n // Extract parameters\n const parameters: RawParameterDefinition[] = [];\n for (const param of func.params) {\n const extracted = extractParameter(param, sourceText);\n if (extracted) {\n parameters.push(extracted);\n }\n }\n\n // Extract return type\n const returnType = func.returnType\n ? extractTypeName(func.returnType.typeAnnotation)\n : null;\n\n return {\n name,\n async: func.async,\n isStatic: node.static,\n accessibility: node.accessibility || 'public',\n parameters,\n returnType,\n description: null, // TODO: Extract JSDoc\n line: node.loc?.start.line || 0,\n };\n}\n\n/**\n * Extract parameter definition\n */\nfunction extractParameter(\n param: Pattern,\n sourceText: string,\n): RawParameterDefinition | null {\n // Handle assignment pattern (default value)\n if (param.type === 'AssignmentPattern') {\n const left = param.left;\n if (left.type === 'Identifier') {\n return {\n name: left.name,\n type: left.typeAnnotation\n ? extractTypeName(left.typeAnnotation.typeAnnotation)\n : null,\n optional: true,\n defaultValue: sliceSource(param.right, sourceText),\n };\n }\n // Handle destructured parameter with default\n if (left.type === 'ObjectPattern' || left.type === 'ArrayPattern') {\n return {\n name: 'options',\n type: left.typeAnnotation\n ? extractTypeName(left.typeAnnotation.typeAnnotation)\n : 'any',\n optional: true,\n defaultValue: sliceSource(param.right, sourceText),\n };\n }\n return null;\n }\n\n // Handle rest parameter\n if (param.type === 'RestElement') {\n const arg = param.argument;\n if (arg.type === 'Identifier') {\n return {\n name: `...${arg.name}`,\n type: param.typeAnnotation\n ? extractTypeName(param.typeAnnotation.typeAnnotation)\n : null,\n optional: true,\n defaultValue: null,\n };\n }\n return null;\n }\n\n // Handle simple identifier\n if (param.type === 'Identifier') {\n return {\n name: param.name,\n type: param.typeAnnotation\n ? extractTypeName(param.typeAnnotation.typeAnnotation)\n : null,\n optional: param.optional || false,\n defaultValue: null,\n };\n }\n\n // Handle object pattern (destructured)\n if (param.type === 'ObjectPattern') {\n return {\n name: 'options',\n type: param.typeAnnotation\n ? extractTypeName(param.typeAnnotation.typeAnnotation)\n : 'any',\n optional: false,\n defaultValue: null,\n };\n }\n\n return null;\n}\n","/**\n * Manifest Adapter\n *\n * Converts OXC scanner output to smrt-core manifest format.\n * Ensures compatibility with existing manifest consumers.\n */\n\nimport { isSafeObjectKey } from './oxc-parser.js';\nimport type {\n FieldTypeInference,\n InferredFieldType,\n RawFieldDefinition,\n RawMethodDefinition,\n ResolvedClassDefinition,\n} from './types.js';\n\n// ============================================================================\n// smrt-core compatible types (copied to avoid circular dependency)\n// ============================================================================\n\n/**\n * Qualified class name format: \"@package/name:ClassName\"\n * Uniquely identifies classes across packages.\n */\ntype QualifiedClassName = `${string}:${string}`;\n\ninterface FieldDefinition {\n type:\n | 'text'\n | 'decimal'\n | 'boolean'\n | 'integer'\n | 'datetime'\n | 'json'\n | 'foreignKey'\n | 'crossPackageRef'\n | 'oneToMany'\n | 'manyToMany'\n | 'meta';\n required?: boolean;\n default?: any;\n min?: number;\n max?: number;\n maxLength?: number;\n minLength?: number;\n related?: string;\n description?: string;\n _meta?: Record<string, any>;\n transient?: boolean;\n /** Sensitive value — excluded from public serialization + where filtering. */\n sensitive?: boolean;\n /** Read-only over generated write surfaces — stripped from create/update bodies. */\n readonly?: boolean;\n}\n\ntype FieldDecoratorOptions = {\n type?: FieldDefinition['type'];\n required?: boolean;\n nullable?: boolean;\n default?: any;\n min?: number;\n max?: number;\n maxLength?: number;\n minLength?: number;\n related?: string;\n /** oneToMany explicit inverse foreign-key field on the target class */\n foreignKey?: string;\n description?: string;\n transient?: boolean;\n unique?: boolean;\n /** crossPackageRef opt-in save-time validation */\n validate?: boolean;\n /** manyToMany junction table name */\n through?: string;\n /** manyToMany override of the source-side join column */\n sourceKey?: string;\n /** manyToMany override of the target-side join column */\n targetKey?: string;\n /** meta opt-in JSON-path index */\n indexed?: boolean;\n /** sensitive value — excluded from public serialization + where filtering */\n sensitive?: boolean;\n /** read-only over generated write surfaces */\n readonly?: boolean;\n [key: string]: unknown;\n};\n\ninterface MethodDefinition {\n name: string;\n async: boolean;\n parameters: Array<{\n name: string;\n type: string;\n optional: boolean;\n default?: any;\n }>;\n returnType: string;\n description?: string;\n isStatic: boolean;\n isPublic: boolean;\n}\n\ninterface SmartObjectConfig {\n tableStrategy?: 'sti' | 'cti';\n idType?: 'uuid' | 'text';\n features?: Record<\n string,\n {\n defaultEnabled: boolean;\n label?: string;\n description?: string;\n metadata?: Record<string, unknown>;\n }\n >;\n api?: {\n include?: string[];\n exclude?: string[];\n };\n cli?:\n | boolean\n | {\n include?: string[];\n exclude?: string[];\n skipApiCheck?: boolean;\n http?: boolean;\n };\n mcp?: {\n include?: string[];\n exclude?: string[];\n };\n [key: string]: unknown;\n}\n\ninterface SmartObjectDefinition {\n name: string;\n className: string;\n qualifiedName?: QualifiedClassName; // NEW: @package/name:ClassName for namespace isolation (Issue #713)\n collection: string;\n filePath: string;\n packageName?: string;\n packageVersion?: string;\n importPath?: string;\n modulePath?: string;\n exportName?: string;\n collectionExportName?: string;\n fields: Record<string, FieldDefinition>;\n methods: Record<string, MethodDefinition>;\n decoratorConfig: SmartObjectConfig;\n extends?: string;\n extendsTypeArg?: string;\n staticProperties?: Record<string, any>;\n}\n\ninterface SmartObjectManifest {\n version: string;\n timestamp: number;\n packageName?: string;\n packageVersion?: string;\n objects: Record<string, SmartObjectDefinition>;\n moduleType?: string;\n smrtDependencies?: string[];\n}\n\n// ============================================================================\n// Utilities\n// ============================================================================\n\n/**\n * Property keys that must never appear as own properties on a manifest object.\n * Object literals authored as `{ constructor: ... }` or `{ prototype: ... }`\n * produce real own keys; spreading such a parsed object into a manifest\n * `_meta` / `staticProperties` entry (or assigning it under a class field name)\n * would carry a prototype-pollution gadget into the emitted JSON.\n */\n/**\n * Recursively strip prototype-pollution keys (via the shared\n * {@link isSafeObjectKey} guard — single source of truth with oxc-parser) from a\n * value parsed out of source. Returns a new plain object/array; primitives and\n * built-in objects pass through unchanged.\n */\nfunction sanitizeParsed(value: unknown, seen = new WeakSet<object>()): unknown {\n if (value === null || typeof value !== 'object') return value;\n\n const isArray = Array.isArray(value);\n // Preserve built-ins (Date, RegExp, Map, …) intact. They carry no\n // attacker-controlled own keys, and iterating their enumerable keys would\n // silently turn e.g. `@field({ default: new Date() })` into `{}` (review #1559).\n const proto = Object.getPrototypeOf(value);\n if (!isArray && proto !== Object.prototype && proto !== null) return value;\n\n // Cycle guard: a cyclic literal (e.g. an IIFE returning a self-referential\n // object) would otherwise recurse forever and hang the build (review #1559).\n if (seen.has(value as object)) return undefined;\n seen.add(value as object);\n\n if (isArray) {\n return (value as unknown[]).map((item) => sanitizeParsed(item, seen));\n }\n const clean: Record<string, unknown> = {};\n for (const key of Object.keys(value as Record<string, unknown>)) {\n if (!isSafeObjectKey(key)) continue;\n clean[key] = sanitizeParsed((value as Record<string, unknown>)[key], seen);\n }\n return clean;\n}\n\n/**\n * Parse a JavaScript literal (object or array) from source text.\n *\n * Uses the Function constructor to evaluate literal syntax at build time.\n * This is intentional — AST-based extraction can't handle computed keys,\n * template literals, or spread syntax that may appear in static initializers.\n *\n * The parsed result is run through {@link sanitizeParsed} to strip\n * prototype-pollution keys (`__proto__` / `constructor` / `prototype`) before\n * it is merged into a manifest object.\n *\n * WARNING: This executes the source text. It is only safe when scanning\n * your own trusted codebase at build time. Never run the scanner against\n * untrusted third-party code.\n */\nfunction parseLiteralInitializer(\n source: string,\n): Record<string, any> | any[] | null {\n const trimmed = source?.trim();\n if (!trimmed || (!trimmed.startsWith('{') && !trimmed.startsWith('[')))\n return null;\n try {\n // Use indirect eval via Function to parse the object/array literal\n // This runs at build time only, on trusted source code from our own codebase\n // The existing pattern (unchanged) uses Function constructor for object literal parsing\n // eslint-disable-next-line no-new-func\n const parsed = new Function(`return (${source})`)() as\n | Record<string, any>\n | any[];\n return sanitizeParsed(parsed) as Record<string, any> | any[];\n } catch {\n return null;\n }\n}\n\n/**\n * Strip surrounding quotes from a raw source string.\n * sliceSource() returns raw source text which includes quotes for string\n * literals (e.g., \"'TestProfile'\" or '\"TestProfile\"').\n */\nfunction stripQuotes(value: string | undefined): string | undefined {\n if (!value) return value;\n const match = value.match(/^(['\"`])(.+)\\1$/);\n return match ? match[2] : value;\n}\n\n// ============================================================================\n// Manifest Adapter\n// ============================================================================\n\n/**\n * Create a qualified name for a class (namespace isolation - Issue #713)\n * Format: @package/name:ClassName\n */\nfunction createQualifiedName(\n packageName: string,\n className: string,\n): QualifiedClassName {\n return `${packageName}:${className}` as QualifiedClassName;\n}\n\n/**\n * Converts OXC scanner output into the smrt-core `SmartObjectManifest` format\n * consumed by code generators, the Vitest plugin, and the SMRT CLI.\n *\n * The adapter handles field type inference (applying the `0` vs `0.0` integer /\n * decimal heuristic), decorator interpretation (`@foreignKey`, `@oneToMany`,\n * `@manyToMany`, `@field`), type alias resolution, STI `Meta<T>` unwrapping,\n * static property capture (`uiSlots`, `adminRoutes`), and qualified name\n * generation for namespace isolation across packages.\n *\n * @example\n * ```typescript\n * import { OxcScanner, ManifestAdapter } from '@happyvertical/smrt-scanner';\n *\n * const scanner = new OxcScanner({ cwd: process.cwd() });\n * const { results, resolved } = await scanner.scanAndResolve();\n *\n * const adapter = new ManifestAdapter();\n * const manifest = adapter.toManifest(resolved, {\n * packageName: '@my-org/my-package',\n * packageVersion: '1.0.0',\n * typeAliases: results.typeAliases,\n * });\n * ```\n *\n * @see {@link OxcScanner} for producing the `ResolvedClassDefinition[]` input.\n * @see {@link ResolvedClassDefinition} for the shape of each input element.\n */\nexport class ManifestAdapter {\n private typeAliases: Record<string, string> = {};\n private _aliasDepth?: number;\n\n /**\n * Convert an array of resolved class definitions into a `SmartObjectManifest`.\n *\n * Each class is converted to a `SmartObjectDefinition` via\n * {@link toSmartObjectDefinition} and stored under its qualified name key\n * (e.g. `@my-org/my-package:MyClass`) when `packageName` is provided, or\n * under its lowercased class name otherwise.\n *\n * @param resolved - Resolved class definitions from {@link OxcScanner.resolve}\n * or {@link OxcScanner.scanAndResolve}.\n * @param options.packageName - npm package name used to generate qualified\n * class names for namespace isolation across multi-package projects.\n * @param options.packageVersion - Package version recorded in the manifest\n * metadata.\n * @param options.typeAliases - Map of type alias names to their resolved type\n * strings (from {@link ScanResults.typeAliases}). Used to resolve custom\n * types like `type Status = 'active' | 'inactive'` during field inference.\n * @returns A complete `SmartObjectManifest` ready for serialisation.\n *\n * @example\n * ```typescript\n * const manifest = adapter.toManifest(resolved, {\n * packageName: '@my-org/my-package',\n * packageVersion: '1.0.0',\n * typeAliases: results.typeAliases,\n * });\n * fs.writeFileSync('manifest.json', JSON.stringify(manifest, null, 2));\n * ```\n */\n toManifest(\n resolved: ResolvedClassDefinition[],\n options: {\n packageName?: string;\n packageVersion?: string;\n typeAliases?: Record<string, string>;\n } = {},\n ): SmartObjectManifest {\n this.typeAliases = options.typeAliases || {};\n const objects: Record<string, SmartObjectDefinition> = {};\n\n for (const classDef of resolved) {\n const definition = this.toSmartObjectDefinition(classDef, options);\n\n // Use qualified name as key if packageName is available (Issue #713)\n // This enables namespace isolation for multi-package scenarios\n const manifestKey =\n definition.qualifiedName || definition.name.toLowerCase();\n objects[manifestKey] = definition;\n }\n\n return {\n version: '1.0.0',\n timestamp: Date.now(),\n packageName: options.packageName,\n packageVersion: options.packageVersion,\n objects,\n moduleType: 'smrt',\n };\n }\n\n /**\n * Convert a single resolved class definition to a `SmartObjectDefinition`.\n *\n * Handles:\n * - Static property capture (`uiSlots`, `adminRoutes`) with child-wins\n * semantics for overridden statics.\n * - Field conversion (non-static public fields only) via {@link convertField}.\n * - Method conversion (public instance/static methods) via {@link convertMethod}.\n * - Collection name pluralisation.\n * - Qualified name generation when `packageName` is supplied.\n *\n * @param classDef - A fully-resolved class definition.\n * @param options.packageName - Package name used to build the qualified class\n * name (`@pkg:ClassName`).\n * @param options.packageVersion - Package version (informational, stored in\n * the definition).\n * @returns A `SmartObjectDefinition` ready to be stored in a manifest.\n *\n * @see {@link toManifest} for the bulk conversion entry point.\n */\n toSmartObjectDefinition(\n classDef: ResolvedClassDefinition,\n options: { packageName?: string; packageVersion?: string } = {},\n ): SmartObjectDefinition {\n // Extract static properties (e.g., uiSlots, adminRoutes on Agent subclasses)\n // Use own fields (classDef.fields) not allFields — static properties use\n // child-wins semantics (static override), not parent-wins like STI columns.\n // Fall back to allFields for inherited static props not redeclared by child.\n let staticProperties: Record<string, any> | undefined;\n const knownStaticProps = ['uiSlots', 'adminRoutes', 'signalSubscriptions'];\n const ownStaticNames = new Set<string>();\n // First pass: own fields (child overrides win)\n for (const field of classDef.fields) {\n if (\n field.isStatic &&\n knownStaticProps.includes(field.name) &&\n field.initializer\n ) {\n try {\n const parsed = parseLiteralInitializer(field.initializer);\n if (parsed) {\n if (!staticProperties) staticProperties = {};\n staticProperties[field.name] = parsed;\n ownStaticNames.add(field.name);\n }\n } catch {\n // Failed to parse static property initializer — skip\n }\n }\n }\n // Second pass: inherited fields for any static props not overridden\n for (const field of classDef.allFields) {\n if (\n field.isStatic &&\n knownStaticProps.includes(field.name) &&\n field.initializer\n ) {\n if (ownStaticNames.has(field.name)) continue;\n try {\n const parsed = parseLiteralInitializer(field.initializer);\n if (parsed) {\n if (!staticProperties) staticProperties = {};\n staticProperties[field.name] = parsed;\n }\n } catch {\n // Failed to parse static property initializer — skip\n }\n }\n }\n\n // Convert fields (skip static fields — they're not database columns)\n const fields: Record<string, FieldDefinition> = {};\n for (const field of classDef.allFields) {\n if (field.isStatic) continue;\n const converted = this.convertField(field);\n if (converted) {\n fields[field.name] = converted;\n }\n }\n\n // Convert methods\n const methods: Record<string, MethodDefinition> = {};\n for (const method of classDef.methods) {\n const converted = this.convertMethod(method);\n if (converted) {\n methods[method.name] = converted;\n }\n }\n\n // Generate collection name (pluralize)\n const collection = this.pluralize(classDef.className);\n\n // Determine package name (prefer option, then classDef value)\n const packageName = options.packageName || classDef.packageName;\n\n // Generate qualified name if packageName is available (Issue #713)\n // Format: @package/name:ClassName for namespace isolation\n const qualifiedName = packageName\n ? createQualifiedName(packageName, classDef.className)\n : undefined;\n\n return {\n name: classDef.className.toLowerCase(),\n className: classDef.className,\n qualifiedName,\n collection,\n filePath: classDef.filePath,\n packageName: packageName || undefined,\n fields,\n methods,\n decoratorConfig: (classDef.decoratorConfig || {}) as SmartObjectConfig,\n extends: classDef.extendsClause || undefined,\n extendsTypeArg: classDef.extendsTypeArg || undefined,\n exportName: classDef.className,\n collectionExportName: `${classDef.className}Collection`,\n staticProperties,\n };\n }\n\n /**\n * Framework internal fields that should NOT be included in manifests\n * These are SmrtObject internals used by the framework, not user-defined fields\n */\n private static readonly FRAMEWORK_INTERNAL_FIELDS = new Set([\n '_tableName',\n 'options',\n '_loadedRelationships',\n '_db',\n '_ai',\n '_fs',\n '_isInitialized',\n '_errors',\n '_warnings',\n ]);\n\n /**\n * Convert a single raw field definition to a manifest `FieldDefinition`.\n *\n * Returns `null` for fields that should be omitted from the manifest:\n * - `private` or `protected` fields.\n * - Framework-internal fields (`_tableName`, `_db`, `_ai`, etc.).\n *\n * Delegates type inference to {@link inferFieldType} and applies additional\n * post-processing:\n * - Marks fields with `Function` type annotation as `transient`.\n * - Marks fields with `@field({ transient: true })` decorator as `transient`.\n * - Populates `_meta.underlyingType` for STI `Meta<T>` fields.\n *\n * @param field - Raw field definition from a scanned class.\n * @returns A `FieldDefinition` for the manifest, or `null` if the field\n * should be excluded.\n *\n * @see {@link inferFieldType} for the type inference logic.\n */\n convertField(field: RawFieldDefinition): FieldDefinition | null {\n // Skip private/protected fields\n if (field.accessibility !== 'public') {\n return null;\n }\n\n // Skip framework internal fields (SmrtObject internals)\n if (ManifestAdapter.FRAMEWORK_INTERNAL_FIELDS.has(field.name)) {\n return null;\n }\n\n // Check if field is a function type (automatically transient)\n const isFunctionType = field.typeAnnotation === 'Function';\n const fieldDecoratorOptions = this.extractFieldDecoratorOptions(field);\n\n const inference = this.inferFieldType(field);\n\n const definition: FieldDefinition = {\n type: inference.type as FieldDefinition['type'],\n required: inference.required,\n };\n\n if (inference.related) {\n definition.related = inference.related;\n }\n\n if (inference.defaultValue !== undefined) {\n definition.default = inference.defaultValue;\n }\n\n // Apply generic @field({...}) options to preserve manifest metadata used by\n // schema generation and runtime decorator merging.\n if (fieldDecoratorOptions.type) {\n definition.type = fieldDecoratorOptions.type;\n }\n\n if (fieldDecoratorOptions.nullable === true) {\n definition.required = false;\n } else if (fieldDecoratorOptions.required !== undefined) {\n definition.required = fieldDecoratorOptions.required;\n }\n\n if (fieldDecoratorOptions.default !== undefined) {\n definition.default = fieldDecoratorOptions.default;\n }\n\n if (fieldDecoratorOptions.related !== undefined) {\n definition.related = fieldDecoratorOptions.related;\n }\n\n if (fieldDecoratorOptions.description !== undefined) {\n definition.description = fieldDecoratorOptions.description;\n }\n\n if (fieldDecoratorOptions.min !== undefined) {\n definition.min = fieldDecoratorOptions.min;\n }\n\n if (fieldDecoratorOptions.max !== undefined) {\n definition.max = fieldDecoratorOptions.max;\n }\n\n if (fieldDecoratorOptions.minLength !== undefined) {\n definition.minLength = fieldDecoratorOptions.minLength;\n }\n\n if (fieldDecoratorOptions.maxLength !== undefined) {\n definition.maxLength = fieldDecoratorOptions.maxLength;\n }\n\n if (Object.keys(fieldDecoratorOptions).length > 0) {\n definition._meta = {\n ...definition._meta,\n ...fieldDecoratorOptions,\n };\n\n if (definition._meta?.type) {\n delete definition._meta.type;\n }\n\n if (definition.related !== undefined && definition._meta?.related) {\n delete definition._meta.related;\n }\n }\n\n // Carry through decorator-derived _meta (validate, through, indexed, etc.)\n if (inference._meta && Object.keys(inference._meta).length > 0) {\n definition._meta = {\n ...definition._meta,\n ...inference._meta,\n };\n }\n\n // For meta fields, store the underlying type for hydration coercion\n if (inference.underlyingType) {\n definition._meta = {\n ...definition._meta,\n underlyingType: inference.underlyingType,\n };\n }\n\n // Mark function type fields as transient (not persisted to database)\n if (isFunctionType) {\n definition.transient = true;\n }\n\n if (fieldDecoratorOptions.transient === true) {\n definition.transient = true;\n }\n\n // Promote security markers to first-class manifest metadata (also retained\n // in `_meta` via the spread above). Honored by `toPublicJSON()` and the\n // collection `where` builder at runtime.\n if (fieldDecoratorOptions.sensitive === true) {\n definition.sensitive = true;\n }\n\n if (fieldDecoratorOptions.readonly === true) {\n definition.readonly = true;\n }\n\n return definition;\n }\n\n /**\n * Infer the SMRT field type and required flag from a raw field definition.\n *\n * Inference is attempted in the following priority order:\n * 1. **Field helper call in initializer** — currently always returns `null`\n * (field helpers removed); reserved for future use.\n * 2. **Decorator** — `@foreignKey`, `@oneToMany`, `@manyToMany`, `@field({ type })`.\n * 3. **Type annotation** — `string` → `text`, `number` with `0` vs `0.0`\n * heuristic → `integer` / `decimal`, `boolean`, `Date` → `datetime`,\n * arrays → `json`, `Record<>` / `object` → `json`, union types with\n * `null`, inline string/number literal unions, `Meta<T>` wrapper,\n * and type alias resolution (up to depth 5).\n * 4. **Numeric literal without annotation** — `version = 1` → `integer`.\n * 5. **Boolean literal without annotation** — `isRead = false` → `boolean`.\n * 6. **Default** — falls back to `text`.\n *\n * @param field - The raw field definition to analyse.\n * @returns A {@link FieldTypeInference} describing the inferred type,\n * required flag, default value, related class name (for relationships),\n * and the inference source for debugging.\n *\n * @see {@link FieldTypeInference} for the result shape.\n * @see {@link InferredFieldType} for valid type values.\n */\n inferFieldType(field: RawFieldDefinition): FieldTypeInference {\n // 1. Check for field helper calls in initializer\n if (field.initializer) {\n const helperResult = this.inferFromHelper(field.initializer);\n if (helperResult) {\n return helperResult;\n }\n }\n\n // 2. Check decorators\n for (const decorator of field.decorators) {\n const decoratorResult = this.inferFromDecorator(decorator, field);\n if (decoratorResult) {\n return decoratorResult;\n }\n }\n\n // 3. Use type annotation with 0 vs 0.0 heuristic\n if (field.typeAnnotation) {\n return this.inferFromAnnotation(field);\n }\n\n // 3.5. Infer from numeric literal without type annotation\n // Handles cases like `version = 1` where there's no `: number` annotation\n if (field.numericValue !== null) {\n const fieldType: InferredFieldType = field.hasDecimalPoint\n ? 'decimal'\n : 'integer';\n return {\n type: fieldType,\n required: !field.optional,\n defaultValue: field.numericValue,\n source: 'heuristic',\n };\n }\n\n // 3.6. Infer from boolean literal without type annotation\n // Handles cases like `isRead = false` where there's no `: boolean` annotation\n if (field.initializer === 'true' || field.initializer === 'false') {\n return {\n type: 'boolean',\n required: !field.optional,\n defaultValue: field.initializer === 'true',\n source: 'heuristic',\n };\n }\n\n // 4. Default to text\n // A field is only required if it has no default value AND is not optional (?)\n // Fields with initializers (default values) should NOT be required\n const hasDefaultValue = field.initializer !== null;\n return {\n type: 'text',\n required: !field.optional && !hasDefaultValue,\n source: 'default',\n };\n }\n\n /**\n * Infer type from field helper call (removed)\n *\n * Field helpers have been removed in favor of decorators and TypeScript types:\n * - Use TypeScript types: name: string = '', price: number = 0.0\n * - Use @field() decorator for constraints: @field({ required: true })\n * - Use @foreignKey(), @oneToMany(), @manyToMany() decorators for relationships\n */\n private inferFromHelper(_initializer: string): FieldTypeInference | null {\n return null;\n }\n\n /**\n * Infer type from field decorator\n */\n private inferFromDecorator(\n decorator: {\n name: string;\n arguments: string[];\n },\n field: RawFieldDefinition,\n ): FieldTypeInference | null {\n // @field decorator with type config\n if (decorator.name === 'field' && decorator.arguments.length > 0) {\n const fieldOptions = this.parseFieldDecoratorOptions(\n decorator.arguments[0],\n );\n const type = this.normalizeFieldType(fieldOptions?.type);\n\n if (type) {\n const hasDefaultValue =\n field.initializer !== null || fieldOptions?.default !== undefined;\n let required = !field.optional && !hasDefaultValue;\n\n if (fieldOptions?.nullable === true) {\n required = false;\n } else if (fieldOptions?.required !== undefined) {\n required = fieldOptions.required;\n }\n\n return {\n type,\n required,\n defaultValue: fieldOptions?.default,\n related:\n typeof fieldOptions?.related === 'string'\n ? fieldOptions.related\n : undefined,\n source: 'decorator',\n };\n }\n }\n\n // @meta({ indexed?, required?, nullable?, ... }) decorator — flags the\n // field as STI meta storage AND preserves opt-in options like `indexed`\n // so the manifest-only schema path can emit the JSON-path index.\n if (decorator.name === 'meta') {\n const parsedOptions = this.parseFieldDecoratorOptions(\n decorator.arguments[0],\n );\n const hasDefaultValue = field.initializer !== null;\n const meta: Record<string, unknown> = {};\n if (parsedOptions?.indexed !== undefined)\n meta.indexed = parsedOptions.indexed;\n if (parsedOptions?.nullable !== undefined)\n meta.nullable = parsedOptions.nullable;\n return {\n type: 'meta',\n required:\n parsedOptions?.required !== undefined\n ? Boolean(parsedOptions.required)\n : !field.optional && !hasDefaultValue,\n defaultValue:\n parsedOptions?.default !== undefined\n ? parsedOptions.default\n : undefined,\n ...(Object.keys(meta).length > 0 ? { _meta: meta } : {}),\n source: 'decorator',\n };\n }\n\n // @foreignKey(RelatedClass) decorator\n if (decorator.name === 'foreignKey') {\n // First argument is the related class name\n // Strip surrounding quotes — sliceSource() returns raw source text\n // which includes quotes for string literals (e.g., \"'TestProfile'\")\n const relatedClass = stripQuotes(decorator.arguments[0]?.trim());\n const parsedOptions = this.parseFieldDecoratorOptions(\n decorator.arguments[1],\n );\n const meta: Record<string, unknown> = {};\n const META_KEYS = [\n 'required',\n 'nullable',\n 'unique',\n 'description',\n 'default',\n ] as const;\n if (parsedOptions) {\n for (const key of META_KEYS) {\n if (parsedOptions[key] !== undefined) {\n meta[key] = parsedOptions[key];\n }\n }\n }\n // Respect TypeScript optional marker (?) - fixes #846\n const hasDefaultValue = field.initializer !== null;\n return {\n type: 'foreignKey',\n related: relatedClass || undefined,\n required:\n parsedOptions?.required !== undefined\n ? Boolean(parsedOptions.required)\n : !field.optional && !hasDefaultValue,\n defaultValue:\n parsedOptions?.default !== undefined\n ? parsedOptions.default\n : undefined,\n ...(Object.keys(meta).length > 0 ? { _meta: meta } : {}),\n source: 'decorator',\n };\n }\n\n // @tenantId({ nullable?, required?, autoFilter?, autoPopulate? }) decorator\n if (decorator.name === 'tenantId') {\n const parsedOptions = this.parseFieldDecoratorOptions(\n decorator.arguments[0],\n );\n const nullable = parsedOptions?.nullable === true;\n const required =\n parsedOptions?.required !== undefined\n ? Boolean(parsedOptions.required)\n : !nullable;\n\n return {\n type: 'text',\n required,\n _meta: {\n sqlType: 'UUID',\n ...(parsedOptions ?? {}),\n __tenancy: {\n isTenantIdField: true,\n autoFilter: parsedOptions?.autoFilter ?? true,\n required,\n autoPopulate: parsedOptions?.autoPopulate ?? true,\n nullable,\n },\n },\n source: 'decorator',\n };\n }\n\n // @crossPackageRef('@pkg:Class', { validate?, unique?, nullable?, default?, description? }) decorator\n if (decorator.name === 'crossPackageRef') {\n const qualifiedName = stripQuotes(decorator.arguments[0]?.trim());\n const hasDefaultValue = field.initializer !== null;\n // Preserve every standard field option from the second argument so\n // manifest-only consumers generate the same schema/constraints that\n // the runtime decorator would produce.\n const parsedOptions = this.parseFieldDecoratorOptions(\n decorator.arguments[1],\n );\n const meta: Record<string, unknown> = {};\n const META_KEYS = [\n 'validate',\n 'nullable',\n 'unique',\n 'description',\n 'default',\n 'indexed',\n 'idType',\n ] as const;\n if (parsedOptions) {\n for (const key of META_KEYS) {\n if (parsedOptions[key] !== undefined) {\n meta[key] = parsedOptions[key];\n }\n }\n }\n return {\n type: 'crossPackageRef',\n related: qualifiedName || undefined,\n required:\n parsedOptions?.required !== undefined\n ? Boolean(parsedOptions.required)\n : !field.optional && !hasDefaultValue,\n defaultValue:\n parsedOptions?.default !== undefined\n ? parsedOptions.default\n : undefined,\n ...(Object.keys(meta).length > 0 ? { _meta: meta } : {}),\n source: 'decorator',\n };\n }\n\n // @oneToMany(RelatedClass, { foreignKey? }) decorator\n if (decorator.name === 'oneToMany') {\n const relatedClass = stripQuotes(decorator.arguments[0]?.trim());\n // Preserve an explicit inverse `foreignKey` so manifest-only consumers\n // disambiguate the inverse side the same way the runtime decorator does\n // (needed when the target declares multiple FKs back to this class).\n const parsedOptions = this.parseFieldDecoratorOptions(\n decorator.arguments[1],\n );\n const meta: Record<string, unknown> = {};\n if (parsedOptions?.foreignKey !== undefined) {\n meta.foreignKey = parsedOptions.foreignKey;\n }\n return {\n type: 'oneToMany',\n related: relatedClass || undefined,\n required: false,\n ...(Object.keys(meta).length > 0 ? { _meta: meta } : {}),\n source: 'decorator',\n };\n }\n\n // @manyToMany(RelatedClass, { through?, sourceKey?, targetKey? }) decorator\n if (decorator.name === 'manyToMany') {\n const relatedClass = stripQuotes(decorator.arguments[0]?.trim());\n // Preserve junction-table coordinates so manifest-only consumers can\n // execute manyToMany loads without the decorator firing in-process.\n const parsedOptions = this.parseFieldDecoratorOptions(\n decorator.arguments[1],\n );\n const meta: Record<string, unknown> = {};\n if (parsedOptions?.through !== undefined)\n meta.through = parsedOptions.through;\n if (parsedOptions?.sourceKey !== undefined)\n meta.sourceKey = parsedOptions.sourceKey;\n if (parsedOptions?.targetKey !== undefined)\n meta.targetKey = parsedOptions.targetKey;\n return {\n type: 'manyToMany',\n related: relatedClass || undefined,\n required: false,\n ...(Object.keys(meta).length > 0 ? { _meta: meta } : {}),\n source: 'decorator',\n };\n }\n\n return null;\n }\n\n private extractFieldDecoratorOptions(\n field: RawFieldDefinition,\n ): FieldDecoratorOptions {\n for (const decorator of field.decorators) {\n if (decorator.name !== 'field') continue;\n\n const parsed = this.parseFieldDecoratorOptions(decorator.arguments[0]);\n if (parsed) {\n return parsed;\n }\n }\n\n return {};\n }\n\n private parseFieldDecoratorOptions(\n rawArgument: string | undefined,\n ): FieldDecoratorOptions | null {\n if (!rawArgument) return null;\n\n const parsed = parseLiteralInitializer(rawArgument);\n if (!parsed || Array.isArray(parsed) || typeof parsed !== 'object') {\n return null;\n }\n\n return parsed as FieldDecoratorOptions;\n }\n\n private normalizeFieldType(\n value: unknown,\n ): FieldDefinition['type'] | undefined {\n switch (value) {\n case 'text':\n case 'decimal':\n case 'boolean':\n case 'integer':\n case 'datetime':\n case 'json':\n case 'foreignKey':\n case 'crossPackageRef':\n case 'oneToMany':\n case 'manyToMany':\n case 'meta':\n return value;\n default:\n return undefined;\n }\n }\n\n /**\n * Infer type from TypeScript type annotation\n */\n private inferFromAnnotation(field: RawFieldDefinition): FieldTypeInference {\n const type = field.typeAnnotation;\n\n // A field is only required if it has no default value AND is not optional (?)\n // Fields with initializers (default values) should NOT be required\n // This matches the behavior of the legacy TypeScript scanner\n const hasDefaultValue = field.initializer !== null;\n const isRequired = !field.optional && !hasDefaultValue;\n\n // Meta<T> wrapper for STI child fields\n // Extract the inner type T and mark as meta field\n if (type?.startsWith('Meta<') && type.endsWith('>')) {\n const innerType = type.slice(5, -1); // Extract type inside Meta<...>\n\n // Recursively infer the underlying type\n const underlyingInference = this.inferFromAnnotation({\n ...field,\n typeAnnotation: innerType,\n });\n\n return {\n type: 'meta',\n required: isRequired,\n defaultValue: underlyingInference.defaultValue,\n source: 'annotation',\n // Store underlying type for hydration coercion\n underlyingType: underlyingInference.type,\n };\n }\n\n // String types\n if (type === 'string') {\n return {\n type: 'text',\n required: isRequired,\n defaultValue: this.parseDefaultValue(field.initializer, 'string'),\n source: 'annotation',\n };\n }\n\n // Number with 0 vs 0.0 heuristic\n if (type === 'number') {\n const fieldType: InferredFieldType = field.hasDecimalPoint\n ? 'decimal'\n : 'integer';\n\n return {\n type: fieldType,\n required: isRequired,\n defaultValue: field.numericValue ?? undefined,\n source: 'heuristic',\n };\n }\n\n // Boolean\n if (type === 'boolean') {\n return {\n type: 'boolean',\n required: isRequired,\n defaultValue: this.parseDefaultValue(field.initializer, 'boolean'),\n source: 'annotation',\n };\n }\n\n // Date\n if (type === 'Date') {\n return {\n type: 'datetime',\n required: isRequired,\n source: 'annotation',\n };\n }\n\n // Arrays → JSON\n if (type?.endsWith('[]')) {\n return {\n type: 'json',\n required: isRequired,\n defaultValue: [],\n source: 'annotation',\n };\n }\n\n // Record/object → JSON\n if (type?.startsWith('Record<') || type === 'object') {\n return {\n type: 'json',\n required: isRequired,\n defaultValue: {},\n source: 'annotation',\n };\n }\n\n // Union types with null/undefined → nullable or optional\n if (\n type?.includes(' | null') ||\n type?.includes('null | ') ||\n type?.includes(' | undefined') ||\n type?.includes('undefined | ')\n ) {\n const baseType = type\n .replace(/\\s*\\|\\s*null/g, '')\n .replace(/\\s*\\|\\s*undefined/g, '')\n .replace(/\\bnull\\s*\\|\\s*/g, '')\n .replace(/\\bundefined\\s*\\|\\s*/g, '')\n .trim();\n const inference = this.inferFromAnnotation({\n ...field,\n typeAnnotation: baseType,\n optional: true,\n });\n return inference;\n }\n\n // Inline string literal union: 'pending' | 'ready' | 'archived'\n if (type && /^'[^']*'(\\s*\\|\\s*'[^']*')+$/.test(type)) {\n return {\n type: 'text',\n required: isRequired,\n defaultValue: this.parseDefaultValue(field.initializer, 'string'),\n source: 'annotation',\n };\n }\n\n // Inline number literal union: 1 | 2 | 3 (supports negatives: -1 | 0 | 1)\n if (type && /^-?\\d+(\\s*\\|\\s*-?\\d+)+$/.test(type)) {\n return {\n type: 'integer',\n required: isRequired,\n defaultValue: field.numericValue ?? undefined,\n source: 'annotation',\n };\n }\n\n // Type alias resolution: look up single-identifier types in typeAliases\n // Guard against circular aliases (e.g., type A = B; type B = A) with depth limit\n if (\n type &&\n !type.includes(' ') &&\n !type.includes('<') &&\n this.typeAliases[type] &&\n (this._aliasDepth ?? 0) < 5\n ) {\n const resolved = this.typeAliases[type];\n this._aliasDepth = (this._aliasDepth ?? 0) + 1;\n try {\n return this.inferFromAnnotation({ ...field, typeAnnotation: resolved });\n } finally {\n this._aliasDepth = (this._aliasDepth ?? 0) - 1;\n }\n }\n\n // String initializer heuristic: if initializer is a quoted string, infer text\n if (field.initializer?.match(/^(['\"]).*\\1$/)) {\n return {\n type: 'text',\n required: isRequired,\n defaultValue: this.parseDefaultValue(field.initializer, 'string'),\n source: 'heuristic',\n };\n }\n\n // Default to json for unknown/complex types\n // Matches the TS scanner behavior: custom interfaces, type aliases,\n // and other non-primitive types are stored as JSON\n return {\n type: 'json',\n required: isRequired,\n source: 'default',\n };\n }\n\n /**\n * Parse default value from initializer string\n */\n private parseDefaultValue(\n initializer: string | null,\n expectedType: 'string' | 'boolean' | 'number',\n ): any {\n if (!initializer) return undefined;\n\n switch (expectedType) {\n case 'string': {\n // Match quoted strings (backreference ensures same quote type)\n const stringMatch = initializer.match(/^(['\"`])(.*)\\1$/s);\n if (stringMatch) {\n return stringMatch[2];\n }\n break;\n }\n\n case 'boolean':\n if (initializer === 'true') return true;\n if (initializer === 'false') return false;\n break;\n\n case 'number': {\n const num = parseFloat(initializer);\n if (!Number.isNaN(num)) return num;\n break;\n }\n }\n\n return undefined;\n }\n\n /**\n * Convert a raw method definition to a manifest `MethodDefinition`.\n *\n * Returns `null` for `private` or `protected` methods, which are excluded\n * from the manifest. Parameters are mapped to the manifest parameter shape\n * and default values are parsed via `parseDefaultValue`.\n *\n * @param method - Raw method definition from a scanned class.\n * @returns A manifest-compatible `MethodDefinition`, or `null` if the method\n * should be excluded.\n */\n convertMethod(method: RawMethodDefinition): MethodDefinition | null {\n // Skip private/protected methods\n if (method.accessibility !== 'public') {\n return null;\n }\n\n return {\n name: method.name,\n async: method.async,\n parameters: method.parameters.map((p) => ({\n name: p.name,\n type: p.type || 'any',\n optional: p.optional,\n default: p.defaultValue\n ? this.parseDefaultValue(p.defaultValue, 'string')\n : undefined,\n })),\n returnType: method.returnType || 'any',\n description: method.description || undefined,\n isStatic: method.isStatic,\n isPublic: true,\n };\n }\n\n /**\n * Simple pluralization for collection names.\n *\n * This produces the manifest's `collection` label only; the authoritative DDL\n * table name is derived independently by core (`classnameToTablename` →\n * the `pluralize` library), so this needs to stay self-consistent rather than\n * cover every irregular plural. Note the `y → ies` rule fires only after a\n * consonant, so vowel+y words pluralise correctly (`Day` → `days`, not\n * `daies`).\n */\n private pluralize(name: string): string {\n // Lowercase the name first for consistent collection/table names\n const lower = name.toLowerCase();\n // Consonant + y → ies (City → cities); vowel + y → +s (Day → days).\n if (/[^aeiou]y$/.test(lower)) {\n return `${lower.slice(0, -1)}ies`;\n }\n if (lower.endsWith('s') || lower.endsWith('x') || lower.endsWith('z')) {\n return `${lower}es`;\n }\n if (lower.endsWith('ch') || lower.endsWith('sh')) {\n return `${lower}es`;\n }\n return `${lower}s`;\n }\n}\n","/**\n * OXC Scanner\n *\n * High-level scanner that orchestrates OXC parsing and inheritance resolution.\n * Provides a simple API for scanning TypeScript files for SMRT classes.\n */\n\nimport { resolve } from 'node:path';\nimport fg from 'fast-glob';\nimport { InheritanceResolver } from './inheritance-resolver.js';\nimport { parseFile } from './oxc-parser.js';\nimport type {\n ExternalManifest,\n FileScanResult,\n OxcScannerOptions,\n ResolvedClassDefinition,\n ScanResults,\n} from './types.js';\n\n/**\n * Default glob patterns for scanning\n */\nconst DEFAULT_INCLUDE = ['**/*.ts', '**/*.tsx'];\nconst DEFAULT_EXCLUDE = [\n '**/node_modules/**',\n '**/dist/**',\n '**/build/**',\n '**/*.d.ts',\n '**/*.test.ts',\n '**/*.spec.ts',\n '**/__tests__/**',\n];\n\n/**\n * High-performance TypeScript scanner that discovers `@smrt()`-decorated\n * classes in a project's source files.\n *\n * Orchestrates the two-phase scan pipeline:\n * 1. **Phase 1 — Parse** (`scan()`): uses OXC (Rust) to parse TypeScript files\n * in parallel and extract raw class, field, method, and decorator metadata.\n * 2. **Phase 2 — Resolve** (`resolve()`): walks inheritance chains, detects STI\n * hierarchies, and merges fields from ancestor classes.\n *\n * The common path is {@link scanAndResolve} which runs both phases in sequence.\n *\n * @example\n * ```typescript\n * import { OxcScanner } from '@happyvertical/smrt-scanner';\n *\n * const scanner = new OxcScanner({\n * cwd: process.cwd(),\n * include: ['src/**\\/*.ts'],\n * exclude: ['**\\/*.test.ts'],\n * });\n *\n * const { results, resolved } = await scanner.scanAndResolve();\n * console.log(`Found ${resolved.length} SMRT classes in ${results.fileCount} files`);\n * ```\n *\n * @see {@link OxcScannerOptions} for all available configuration options.\n * @see {@link scanDirectory} for a one-liner convenience wrapper.\n */\nexport class OxcScanner {\n private options: Required<OxcScannerOptions>;\n private resolver: InheritanceResolver;\n private scanResults: ScanResults | null = null;\n\n /**\n * Create a new `OxcScanner` with the given options.\n *\n * All options are optional. By default the scanner targets every `.ts` and\n * `.tsx` file under `process.cwd()`, excluding `node_modules`, `dist`,\n * `build`, declaration files, and test files.\n *\n * @param options - Scanner configuration. See {@link OxcScannerOptions}.\n */\n constructor(options: OxcScannerOptions = {}) {\n this.options = {\n include: options.include || DEFAULT_INCLUDE,\n exclude: options.exclude || DEFAULT_EXCLUDE,\n cwd: options.cwd || process.cwd(),\n tsconfig: options.tsconfig || '',\n followImports: options.followImports ?? false,\n baseClasses: options.baseClasses || [],\n includePrivateMethods: options.includePrivateMethods ?? false,\n includeStaticMethods: options.includeStaticMethods ?? true,\n externalManifests: options.externalManifests || new Map(),\n };\n\n this.resolver = new InheritanceResolver({\n baseClasses: this.options.baseClasses,\n externalManifests: this.options.externalManifests,\n });\n }\n\n /**\n * Phase 1 — Discover and parse TypeScript files using OXC.\n *\n * Uses `fast-glob` to enumerate matching files and then parses them in\n * parallel with OXC (Rust). The raw class definitions are registered with\n * the internal {@link InheritanceResolver} for use in the subsequent\n * {@link resolve} call.\n *\n * @returns A {@link ScanResults} object containing all classes found, any\n * parse errors, accumulated type aliases, SMRT import metadata, and\n * aggregate timing information.\n *\n * @example\n * ```typescript\n * const scanner = new OxcScanner({ cwd: '/project' });\n * const results = await scanner.scan();\n * console.log(`Parsed ${results.fileCount} files in ${results.totalParseTimeMs.toFixed(1)}ms`);\n * ```\n */\n async scan(): Promise<ScanResults> {\n const startTime = performance.now();\n\n // Discover files\n const files = await this.discoverFiles();\n\n // Parse files in parallel\n const fileResults = await Promise.all(\n files.map((filePath) => this.parseFileWithTiming(filePath)),\n );\n\n // Collect results\n const results: ScanResults = {\n files: fileResults,\n classes: [],\n errors: [],\n totalParseTimeMs: performance.now() - startTime,\n fileCount: files.length,\n typeAliases: {},\n };\n\n // Flatten classes, errors, and type aliases\n for (const file of fileResults) {\n for (const classDef of file.classes) {\n results.classes.push(classDef);\n }\n for (const error of file.errors) {\n results.errors.push(error);\n }\n Object.assign(results.typeAliases, file.typeAliases);\n }\n\n // Add classes to resolver\n this.resolver.addClasses(results.classes);\n\n this.scanResults = results;\n return results;\n }\n\n /**\n * Phase 2 — Resolve inheritance chains for all scanned classes.\n *\n * Must be called after {@link scan}. Walks each class's extends chain,\n * detects STI hierarchies, merges ancestor fields for STI subclasses, and\n * marks framework base classes.\n *\n * @returns An array of {@link ResolvedClassDefinition} objects — one for\n * every class that either carries `@smrt()` or extends a framework base\n * class (`SmrtObject`, `SmrtClass`, `SmrtCollection`).\n *\n * @throws {Error} If called before {@link scan}.\n *\n * @see {@link scanAndResolve} to run both phases in one call.\n */\n resolve(): ResolvedClassDefinition[] {\n if (!this.scanResults) {\n throw new Error('Must call scan() before resolve()');\n }\n\n return this.resolver.resolveAll();\n }\n\n /**\n * Run both scan phases in a single call.\n *\n * Equivalent to calling `await scanner.scan()` followed by\n * `scanner.resolve()`. This is the most common entry point for callers\n * that want the fully-resolved manifest-ready data in one step.\n *\n * @returns An object with:\n * - `results` — raw {@link ScanResults} from Phase 1.\n * - `resolved` — array of {@link ResolvedClassDefinition} from Phase 2.\n *\n * @example\n * ```typescript\n * const scanner = new OxcScanner({ cwd: '/project/src' });\n * const { results, resolved } = await scanner.scanAndResolve();\n * // resolved is ready to pass to ManifestAdapter.toManifest()\n * ```\n *\n * @see {@link ManifestAdapter} to convert `resolved` into a manifest JSON.\n */\n async scanAndResolve(): Promise<{\n results: ScanResults;\n resolved: ResolvedClassDefinition[];\n }> {\n const results = await this.scan();\n const resolved = this.resolve();\n\n return { results, resolved };\n }\n\n /**\n * Register an external package manifest for cross-package base class resolution.\n *\n * When a project class extends a class defined in an installed SMRT package,\n * the resolver needs access to that package's class definitions to walk the\n * full inheritance chain. Call this method with each external package's\n * {@link ExternalManifest} before calling {@link scan} or {@link resolve}.\n *\n * @param manifest - The external manifest to register, including `packageName`,\n * `packageVersion`, and a `classes` map keyed by class name.\n *\n * @see {@link ExternalManifest}\n */\n addExternalManifest(manifest: ExternalManifest): void {\n this.resolver.addExternalManifest(manifest);\n }\n\n /**\n * Scan all discovered files for @happyvertical/smrt-* imports.\n * Returns a map of package name → Set of imported class names.\n *\n * Used for tree-shaking: only external objects that are actually imported\n * in the project's source files will be included in the manifest.\n *\n * Must be called after scan() or as part of scanAndResolve().\n *\n * @example\n * ```typescript\n * const scanner = new OxcScanner({ cwd: process.cwd() });\n * await scanner.scan();\n * const imports = scanner.scanSmrtImports();\n * // Map { '@happyvertical/smrt-profiles' => Set { 'Person', 'Organization' } }\n * ```\n */\n scanSmrtImports(): Map<string, Set<string>> {\n if (!this.scanResults) {\n throw new Error('Must call scan() before scanSmrtImports()');\n }\n\n const merged = new Map<string, Set<string>>();\n\n for (const file of this.scanResults.files) {\n if (file.smrtImports) {\n for (const [pkg, classes] of file.smrtImports) {\n if (!merged.has(pkg)) {\n merged.set(pkg, new Set());\n }\n const mergedSet = merged.get(pkg)!;\n for (const cls of classes) {\n mergedSet.add(cls);\n }\n }\n }\n }\n\n return merged;\n }\n\n /**\n * Return aggregate statistics about the last scan.\n *\n * Can be called after {@link scan} has completed. Returns counts useful for\n * diagnostics and the `--stats` CLI flag.\n *\n * @returns An object with:\n * - `totalClasses` — total class declarations seen (including non-SMRT).\n * - `smrtClasses` — classes with `@smrt()` decorator.\n * - `stiClasses` — SMRT classes participating in an STI hierarchy.\n * - `maxInheritanceDepth` — length of the deepest inheritance chain.\n * - `fileCount` — number of files scanned.\n * - `parseTimeMs` — total wall-clock parse time in milliseconds.\n */\n getStats(): {\n totalClasses: number;\n smrtClasses: number;\n stiClasses: number;\n maxInheritanceDepth: number;\n fileCount: number;\n parseTimeMs: number;\n } {\n const resolverStats = this.resolver.getStats();\n\n return {\n ...resolverStats,\n fileCount: this.scanResults?.fileCount || 0,\n parseTimeMs: this.scanResults?.totalParseTimeMs || 0,\n };\n }\n\n /**\n * Discover files to scan using fast-glob\n */\n private async discoverFiles(): Promise<string[]> {\n const patterns = this.options.include;\n\n const files = await fg(patterns, {\n cwd: this.options.cwd,\n ignore: this.options.exclude,\n absolute: true,\n onlyFiles: true,\n });\n\n return files;\n }\n\n /**\n * Parse a single file with timing\n */\n private async parseFileWithTiming(filePath: string): Promise<FileScanResult> {\n // parseFile is synchronous but we wrap it for potential future async\n return parseFile(filePath);\n }\n}\n\n/**\n * Convenience wrapper that creates an {@link OxcScanner} for `dir` and runs\n * both scan phases in a single call.\n *\n * @param dir - Directory to scan (resolved to an absolute path automatically).\n * @param options - Scanner options, excluding `cwd` which is set from `dir`.\n * See {@link OxcScannerOptions}.\n * @returns An object with `results` ({@link ScanResults}) and `resolved`\n * ({@link ResolvedClassDefinition}[]).\n *\n * @example\n * ```typescript\n * import { scanDirectory } from '@happyvertical/smrt-scanner';\n *\n * const { resolved } = await scanDirectory('src/', {\n * include: ['**\\/*.ts'],\n * exclude: ['**\\/*.test.ts'],\n * });\n * console.log(`Found ${resolved.length} SMRT classes`);\n * ```\n *\n * @see {@link OxcScanner} for the full class API with more control.\n */\nexport async function scanDirectory(\n dir: string,\n options: Omit<OxcScannerOptions, 'cwd'> = {},\n): Promise<{\n results: ScanResults;\n resolved: ResolvedClassDefinition[];\n}> {\n const scanner = new OxcScanner({\n ...options,\n cwd: resolve(dir),\n });\n\n return scanner.scanAndResolve();\n}\n"],"names":[],"mappings":"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"}
|