@happyvertical/smrt-core 0.52.0 → 0.53.1
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.
- package/AGENTS.md +1 -0
- package/README.md +8 -2
- package/agents/model-moves.md +114 -0
- package/agents/object-runtime.md +3 -1
- package/agents/run-once.md +16 -7
- package/dist/cascade.d.ts.map +1 -1
- package/dist/cascade.js +4 -2
- package/dist/cascade.js.map +1 -1
- package/dist/generators/preflight-route.d.ts.map +1 -1
- package/dist/generators/preflight-route.js +1 -1
- package/dist/generators/preflight-route.js.map +1 -1
- package/dist/knowledge.d.ts.map +1 -1
- package/dist/knowledge.js +3 -0
- package/dist/knowledge.js.map +1 -1
- package/dist/manifest/static-manifest.js +1 -1
- package/dist/manifest/static-manifest.js.map +1 -1
- package/dist/manifest/store.js +1 -1
- package/dist/manifest.json +1 -1
- package/dist/migrations/index.d.ts +1 -0
- package/dist/migrations/index.d.ts.map +1 -1
- package/dist/migrations/index.js +2 -1
- package/dist/migrations/qualified-name-aliases.d.ts +134 -0
- package/dist/migrations/qualified-name-aliases.d.ts.map +1 -0
- package/dist/migrations/qualified-name-aliases.js +294 -0
- package/dist/migrations/qualified-name-aliases.js.map +1 -0
- package/dist/migrations.js +2 -1
- package/dist/polymorphic-association.d.ts +18 -0
- package/dist/polymorphic-association.d.ts.map +1 -1
- package/dist/polymorphic-association.js +27 -2
- package/dist/polymorphic-association.js.map +1 -1
- package/dist/registry/class-registration.d.ts.map +1 -1
- package/dist/registry/class-registration.js +27 -4
- package/dist/registry/class-registration.js.map +1 -1
- package/dist/registry/name-resolver.d.ts +8 -2
- package/dist/registry/name-resolver.d.ts.map +1 -1
- package/dist/registry/name-resolver.js +17 -8
- package/dist/registry/name-resolver.js.map +1 -1
- package/dist/registry/qualified-name-aliases.d.ts +109 -0
- package/dist/registry/qualified-name-aliases.d.ts.map +1 -0
- package/dist/registry/qualified-name-aliases.js +286 -0
- package/dist/registry/qualified-name-aliases.js.map +1 -0
- package/dist/registry/relationship-graph.d.ts.map +1 -1
- package/dist/registry/relationship-graph.js +1 -1
- package/dist/registry/relationship-graph.js.map +1 -1
- package/dist/registry/types.d.ts +26 -0
- package/dist/registry/types.d.ts.map +1 -1
- package/dist/registry.d.ts +59 -2
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +115 -6
- package/dist/registry.js.map +1 -1
- package/dist/scanner/manifest-generator.d.ts +11 -0
- package/dist/scanner/manifest-generator.d.ts.map +1 -1
- package/dist/scanner/manifest-generator.js +36 -1
- package/dist/scanner/manifest-generator.js.map +1 -1
- package/dist/schema/conflict-target.js +8 -1
- package/dist/schema/conflict-target.js.map +1 -1
- package/dist/scripts/browser-plain-json-regression.mjs +4 -1
- package/dist/smrt-knowledge.json +15 -9
- package/dist/utils/qualified-names.d.ts +11 -0
- package/dist/utils/qualified-names.d.ts.map +1 -1
- package/dist/utils/qualified-names.js +21 -1
- package/dist/utils/qualified-names.js.map +1 -1
- package/package.json +11 -11
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"polymorphic-association.js","names":[],"sources":["../src/polymorphic-association.ts"],"sourcesContent":["/**\n * SmrtPolymorphicAssociation — base class for polymorphic association rows.\n *\n * A polymorphic association links an owner row to an arbitrary target\n * SmrtObject identified by a `(metaType, metaId)` pair — `metaType` being the\n * target's qualified class name (e.g. `@happyvertical/smrt-content:Article`)\n * and `metaId` its row id. Pair that with a `role` discriminator and a\n * `sortOrder`, and one join table can reference many different target types\n * without a typed foreign key per type.\n *\n * Subclasses add their own \"owner\" side and decorate with `@smrt()`:\n *\n * ```typescript\n * @smrt({ conflictColumns: ['asset_id', 'meta_type', 'meta_id', 'role'] })\n * export class AssetAssociation extends SmrtPolymorphicAssociation {\n * @foreignKey('Asset', { required: true })\n * assetId = '';\n * }\n *\n * const target = await association.hydrate(); // resolves metaType + loads metaId\n * ```\n *\n * Convention: `metaId` is intentionally a bare string, NOT a typed\n * `@foreignKey` / `@crossPackageRef` — it is polymorphic, so there is no\n * single target table to point at. `metaType` carries the type information\n * instead, resolved at runtime via `ObjectRegistry`.\n *\n * This is an abstract framework base in the same family as\n * `SmrtHierarchical` and `SmrtJunction`: it has no `@smrt()` decorator and no\n * table of its own. Its columns are merged into each concrete subclass's\n * manifest by the scanner's `FRAMEWORK_BASE_CLASSES` /\n * `FRAMEWORK_ABSTRACT_BASE_NAMES` wiring. Keep those two lists in sync when\n * touching this class.\n *\n * @example\n * ```typescript\n * @smrt({ conflictColumns: ['owner_id', 'meta_type', 'meta_id', 'role'] })\n * export class CommentAssociation extends SmrtPolymorphicAssociation {\n * @foreignKey('Comment', { required: true })\n * ownerId = '';\n * }\n * ```\n */\n\nimport { field } from './decorators/index';\nimport { SmrtObject, type SmrtObjectOptions } from './object';\nimport { ObjectRegistry } from './registry';\n\n/**\n * Options accepted by `SmrtPolymorphicAssociation` (and its subclasses)\n * covering the polymorphic right side of the join.\n */\nexport interface SmrtPolymorphicAssociationOptions extends SmrtObjectOptions {\n /** Target class name or qualified name (e.g. `'Article'` or `'@pkg:Article'`). */\n metaType?: string;\n /** Target object id. */\n metaId?: string;\n /** Association role (e.g. `'hero'`, `'thumbnail'`, `'attachment'`). */\n role?: string;\n /** Sort order within a role. */\n sortOrder?: number;\n}\n\nexport class SmrtPolymorphicAssociation extends SmrtObject {\n /**\n * Internal marker so the scanner can recognize this framework abstract base\n * even when consumers haven't built its package. Mirrors\n * `SmrtHierarchical._isHierarchicalBase` and `SmrtJunction._isJunctionBase`.\n * Don't rename without also updating the scanner's `FRAMEWORK_BASE_CLASSES`\n * set in `packages/scanner/src/inheritance-resolver.ts` and\n * `FRAMEWORK_ABSTRACT_BASE_NAMES` in\n * `packages/core/src/scanner/manifest-generator.ts`.\n */\n static readonly _isPolymorphicAssociationBase = true as const;\n\n /** Target class name or qualified name (e.g. `'Article'` or `'@pkg:Article'`). */\n @field({ required: true })\n metaType = '';\n\n /**\n * Target object id. Bare string by design — polymorphic, not a typed\n * `@foreignKey` / `@crossPackageRef`, because there is no single target\n * table to point at.\n */\n @field({ required: true })\n metaId = '';\n\n /** Role of this association (e.g. `'hero'`, `'thumbnail'`, `'attachment'`). */\n @field({ required: true })\n role = 'default';\n\n /** Sort order for ordering targets within a role. */\n @field()\n sortOrder: number = 0;\n\n constructor(options: SmrtPolymorphicAssociationOptions = {}) {\n super(options);\n if (options.metaType) this.metaType = options.metaType;\n if (options.metaId) this.metaId = options.metaId;\n if (options.role) this.role = options.role;\n if (options.sortOrder !== undefined) this.sortOrder = options.sortOrder;\n }\n\n /**\n * Resolve and load the target object this association points at.\n *\n * Resolves `metaType` to its registered class via\n * `ObjectRegistry.getClassByQualifiedName` (falling back to a simple-name\n * lookup for legacy/unqualified values), then loads the `metaId` row through\n * the target's collection. Going through the collection means STI targets\n * are rehydrated as their concrete subclass and a missing row yields `null`.\n *\n * When the type isn't registered yet, a lazy external-package load is\n * attempted so a qualified `metaType` still hydrates even if nothing has\n * imported the target class. Once resolved, the load goes through the\n * target's collection by its qualified name — genuine failures (DB/init\n * errors) surface rather than being masked as \"no target\".\n *\n * Returns `null` when `metaType`/`metaId` are unset, the type can't be\n * resolved to a registered/loadable class, or the target row no longer\n * exists. The target shares this association's database connection via\n * `this.options`.\n *\n * Prefer qualified `metaType` values (`@pkg:Class`): a bare simple name\n * resolves to the first registered match, and an ambiguous unqualified name\n * that has to be lazily loaded surfaces a `ConfigurationError` rather than\n * guessing.\n *\n * @typeParam T - Expected target type for the caller's convenience cast.\n */\n async hydrate<T extends SmrtObject = SmrtObject>(): Promise<T | null> {\n if (!this.metaType || !this.metaId) return null;\n\n // Prefer the qualified-name lookup; fall back to a simple-name lookup for\n // legacy/unqualified values.\n let registered =\n ObjectRegistry.getClassByQualifiedName(this.metaType) ??\n ObjectRegistry.getClass(this.metaType);\n\n // Not registered yet — try a lazy external-package load, then re-resolve.\n // Branch on the boolean: a `false` result means the type genuinely isn't\n // installed (→ null), while real loader failures (e.g. an ambiguous\n // unqualified name throwing ConfigurationError) propagate instead of being\n // masked as \"no target\".\n if (!registered) {\n const loaded = await ObjectRegistry.tryLoadFromExternalPackage(\n this.metaType,\n );\n if (!loaded) return null;\n registered =\n ObjectRegistry.getClassByQualifiedName(this.metaType) ??\n ObjectRegistry.getClass(this.metaType);\n }\n\n if (!registered) return null;\n\n // Resolve via the canonical (qualified) name so the lookup is\n // unambiguous. getCollection is deliberately NOT wrapped in a catch:\n // real DB/init failures must surface, not be reported as a missing row.\n const collection = await ObjectRegistry.getCollection<SmrtObject>(\n registered.qualifiedName ?? registered.name,\n this.options,\n );\n\n const target = await collection.get({ id: this.metaId });\n return target as T | null;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+DA,IAAa,6BAAb,cAAgD,WAAW;;;;;;;;;;CAUzD,OAAgB,gCAAgC;;CAGhD,WACW;;;;;;CAOX,SACS;;CAGT,OACO;;CAGP,YACoB;CAEpB,YAAY,UAA6C,CAAC,GAAG;EAC3D,MAAM,OAAO;EACb,IAAI,QAAQ,UAAU,KAAK,WAAW,QAAQ;EAC9C,IAAI,QAAQ,QAAQ,KAAK,SAAS,QAAQ;EAC1C,IAAI,QAAQ,MAAM,KAAK,OAAO,QAAQ;EACtC,IAAI,QAAQ,cAAc,KAAA,GAAW,KAAK,YAAY,QAAQ;CAChE;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BA,MAAM,UAAgE;EACpE,IAAI,CAAC,KAAK,YAAY,CAAC,KAAK,QAAQ,OAAO;EAI3C,IAAI,aACF,eAAe,wBAAwB,KAAK,QAAQ,KACpD,eAAe,SAAS,KAAK,QAAQ;EAOvC,IAAI,CAAC,YAAY;GAIf,IAAI,CAAC,MAHgB,eAAe,2BAClC,KAAK,QACP,GACa,OAAO;GACpB,aACE,eAAe,wBAAwB,KAAK,QAAQ,KACpD,eAAe,SAAS,KAAK,QAAQ;EACzC;EAEA,IAAI,CAAC,YAAY,OAAO;EAWxB,OAAO,OADc,MALI,eAAe,cACtC,WAAW,iBAAiB,WAAW,MACvC,KAAK,OACP,EAAA,CAEgC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC;CAEzD;AACF;WA3FG,MAAM,EAAE,UAAU,KAAK,CAAC,GAAA,kBAAA,eAAA,MAAA,CAAA,GAAA,2BAAA,WAAA,YAAA,KAAA,CAAA;WAQxB,MAAM,EAAE,UAAU,KAAK,CAAC,GAAA,kBAAA,eAAA,MAAA,CAAA,GAAA,2BAAA,WAAA,UAAA,KAAA,CAAA;WAIxB,MAAM,EAAE,UAAU,KAAK,CAAC,GAAA,kBAAA,eAAA,MAAA,CAAA,GAAA,2BAAA,WAAA,QAAA,KAAA,CAAA;WAIxB,MAAM,GAAA,kBAAA,eAAA,MAAA,CAAA,GAAA,2BAAA,WAAA,aAAA,KAAA,CAAA"}
|
|
1
|
+
{"version":3,"file":"polymorphic-association.js","names":[],"sources":["../src/polymorphic-association.ts"],"sourcesContent":["/**\n * SmrtPolymorphicAssociation — base class for polymorphic association rows.\n *\n * A polymorphic association links an owner row to an arbitrary target\n * SmrtObject identified by a `(metaType, metaId)` pair — `metaType` being the\n * target's qualified class name (e.g. `@happyvertical/smrt-content:Article`)\n * and `metaId` its row id. Pair that with a `role` discriminator and a\n * `sortOrder`, and one join table can reference many different target types\n * without a typed foreign key per type.\n *\n * Subclasses add their own \"owner\" side and decorate with `@smrt()`:\n *\n * ```typescript\n * @smrt({ conflictColumns: ['asset_id', 'meta_type', 'meta_id', 'role'] })\n * export class AssetAssociation extends SmrtPolymorphicAssociation {\n * @foreignKey('Asset', { required: true })\n * assetId = '';\n * }\n *\n * const target = await association.hydrate(); // resolves metaType + loads metaId\n * ```\n *\n * Convention: `metaId` is intentionally a bare string, NOT a typed\n * `@foreignKey` / `@crossPackageRef` — it is polymorphic, so there is no\n * single target table to point at. `metaType` carries the type information\n * instead, resolved at runtime via `ObjectRegistry`.\n *\n * This is an abstract framework base in the same family as\n * `SmrtHierarchical` and `SmrtJunction`: it has no `@smrt()` decorator and no\n * table of its own. Its columns are merged into each concrete subclass's\n * manifest by the scanner's `FRAMEWORK_BASE_CLASSES` /\n * `FRAMEWORK_ABSTRACT_BASE_NAMES` wiring. Keep those two lists in sync when\n * touching this class.\n *\n * @example\n * ```typescript\n * @smrt({ conflictColumns: ['owner_id', 'meta_type', 'meta_id', 'role'] })\n * export class CommentAssociation extends SmrtPolymorphicAssociation {\n * @foreignKey('Comment', { required: true })\n * ownerId = '';\n * }\n * ```\n */\n\nimport { field } from './decorators/index';\nimport { SmrtObject, type SmrtObjectOptions } from './object';\nimport { ObjectRegistry } from './registry';\n\n/**\n * Options accepted by `SmrtPolymorphicAssociation` (and its subclasses)\n * covering the polymorphic right side of the join.\n */\nexport interface SmrtPolymorphicAssociationOptions extends SmrtObjectOptions {\n /** Target class name or qualified name (e.g. `'Article'` or `'@pkg:Article'`). */\n metaType?: string;\n /** Target object id. */\n metaId?: string;\n /** Association role (e.g. `'hero'`, `'thumbnail'`, `'attachment'`). */\n role?: string;\n /** Sort order within a role. */\n sortOrder?: number;\n}\n\nexport class SmrtPolymorphicAssociation extends SmrtObject {\n /**\n * Internal marker so the scanner can recognize this framework abstract base\n * even when consumers haven't built its package. Mirrors\n * `SmrtHierarchical._isHierarchicalBase` and `SmrtJunction._isJunctionBase`.\n * Don't rename without also updating the scanner's `FRAMEWORK_BASE_CLASSES`\n * set in `packages/scanner/src/inheritance-resolver.ts` and\n * `FRAMEWORK_ABSTRACT_BASE_NAMES` in\n * `packages/core/src/scanner/manifest-generator.ts`.\n */\n static readonly _isPolymorphicAssociationBase = true as const;\n\n /** Target class name or qualified name (e.g. `'Article'` or `'@pkg:Article'`). */\n @field({ required: true })\n metaType = '';\n\n /**\n * Target object id. Bare string by design — polymorphic, not a typed\n * `@foreignKey` / `@crossPackageRef`, because there is no single target\n * table to point at.\n */\n @field({ required: true })\n metaId = '';\n\n /** Role of this association (e.g. `'hero'`, `'thumbnail'`, `'attachment'`). */\n @field({ required: true })\n role = 'default';\n\n /** Sort order for ordering targets within a role. */\n @field()\n sortOrder: number = 0;\n\n constructor(options: SmrtPolymorphicAssociationOptions = {}) {\n super(options);\n if (options.metaType) this.metaType = options.metaType;\n if (options.metaId) this.metaId = options.metaId;\n if (options.role) this.role = options.role;\n if (options.sortOrder !== undefined) this.sortOrder = options.sortOrder;\n }\n\n /**\n * Store `metaType` under its target's CURRENT qualified name before every\n * save (#3338). A deprecated name declared in the target's\n * `previousQualifiedNames` is rewritten first, so new rows — and any legacy\n * row that is loaded and saved again — never perpetuate it. A target known\n * only from an installed manifest is lazily loaded first; names that\n * resolve to no class at all are stored as given.\n *\n * This runs in the first save-preparation hook rather than a `save()`\n * override: a public override would be scanned into every subclass's\n * manifest as a `save` method.\n */\n protected override async validateBeforeSave(): Promise<void> {\n if (this.metaType) {\n // Async: a target known only from its (new owner's) manifest is\n // lazily loaded first, so an old name never slips through unresolved.\n const current = await ObjectRegistry.resolveQualifiedNameAsync(\n this.metaType,\n { source: 'SmrtPolymorphicAssociation.save' },\n );\n if (current && current !== this.metaType) this.metaType = current;\n }\n await super.validateBeforeSave();\n }\n\n /**\n * Resolve and load the target object this association points at.\n *\n * Resolves `metaType` to its registered class via\n * `ObjectRegistry.getClassByQualifiedName` (falling back to a simple-name\n * lookup for legacy/unqualified values), then loads the `metaId` row through\n * the target's collection. Going through the collection means STI targets\n * are rehydrated as their concrete subclass and a missing row yields `null`.\n *\n * When the type isn't registered yet, a lazy external-package load is\n * attempted so a qualified `metaType` still hydrates even if nothing has\n * imported the target class. Once resolved, the load goes through the\n * target's collection by its qualified name — genuine failures (DB/init\n * errors) surface rather than being masked as \"no target\".\n *\n * Returns `null` when `metaType`/`metaId` are unset, the type can't be\n * resolved to a registered/loadable class, or the target row no longer\n * exists. The target shares this association's database connection via\n * `this.options`.\n *\n * A `metaType` written under a class's former qualified name (declared in\n * its `previousQualifiedNames`, e.g. after the class moved package)\n * resolves to the class, eagerly or through the lazy manifest alias index,\n * with a one-time deprecation warning (#3338).\n *\n * Prefer qualified `metaType` values (`@pkg:Class`): a bare simple name\n * resolves to the first registered match, and an ambiguous unqualified name\n * that has to be lazily loaded surfaces a `ConfigurationError` rather than\n * guessing.\n *\n * @typeParam T - Expected target type for the caller's convenience cast.\n */\n async hydrate<T extends SmrtObject = SmrtObject>(): Promise<T | null> {\n if (!this.metaType || !this.metaId) return null;\n\n // Prefer the qualified-name lookup; fall back to a simple-name lookup for\n // legacy/unqualified values.\n const lookup = { source: 'SmrtPolymorphicAssociation.hydrate' };\n let registered =\n ObjectRegistry.getClassByQualifiedName(this.metaType, lookup) ??\n ObjectRegistry.getClass(this.metaType);\n\n // Not registered yet — try a lazy external-package load, then re-resolve.\n // Branch on the boolean: a `false` result means the type genuinely isn't\n // installed (→ null), while real loader failures (e.g. an ambiguous\n // unqualified name throwing ConfigurationError) propagate instead of being\n // masked as \"no target\".\n if (!registered) {\n const loaded = await ObjectRegistry.tryLoadFromExternalPackage(\n this.metaType,\n );\n if (!loaded) return null;\n registered =\n ObjectRegistry.getClassByQualifiedName(this.metaType, lookup) ??\n ObjectRegistry.getClass(this.metaType);\n }\n\n if (!registered) return null;\n\n // Resolve via the canonical (qualified) name so the lookup is\n // unambiguous. getCollection is deliberately NOT wrapped in a catch:\n // real DB/init failures must surface, not be reported as a missing row.\n const collection = await ObjectRegistry.getCollection<SmrtObject>(\n registered.qualifiedName ?? registered.name,\n this.options,\n );\n\n const target = await collection.get({ id: this.metaId });\n return target as T | null;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+DA,IAAa,6BAAb,cAAgD,WAAW;;;;;;;;;;CAUzD,OAAgB,gCAAgC;;CAGhD,WACW;;;;;;CAOX,SACS;;CAGT,OACO;;CAGP,YACoB;CAEpB,YAAY,UAA6C,CAAC,GAAG;EAC3D,MAAM,OAAO;EACb,IAAI,QAAQ,UAAU,KAAK,WAAW,QAAQ;EAC9C,IAAI,QAAQ,QAAQ,KAAK,SAAS,QAAQ;EAC1C,IAAI,QAAQ,MAAM,KAAK,OAAO,QAAQ;EACtC,IAAI,QAAQ,cAAc,KAAA,GAAW,KAAK,YAAY,QAAQ;CAChE;;;;;;;;;;;;;CAcA,MAAyB,qBAAoC;EAC3D,IAAI,KAAK,UAAU;GAGjB,MAAM,UAAU,MAAM,eAAe,0BACnC,KAAK,UACL,EAAE,QAAQ,kCAAkC,CAC9C;GACA,IAAI,WAAW,YAAY,KAAK,UAAU,KAAK,WAAW;EAC5D;EACA,MAAM,MAAM,mBAAmB;CACjC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkCA,MAAM,UAAgE;EACpE,IAAI,CAAC,KAAK,YAAY,CAAC,KAAK,QAAQ,OAAO;EAI3C,MAAM,SAAS,EAAE,QAAQ,qCAAqC;EAC9D,IAAI,aACF,eAAe,wBAAwB,KAAK,UAAU,MAAM,KAC5D,eAAe,SAAS,KAAK,QAAQ;EAOvC,IAAI,CAAC,YAAY;GAIf,IAAI,CAAC,MAHgB,eAAe,2BAClC,KAAK,QACP,GACa,OAAO;GACpB,aACE,eAAe,wBAAwB,KAAK,UAAU,MAAM,KAC5D,eAAe,SAAS,KAAK,QAAQ;EACzC;EAEA,IAAI,CAAC,YAAY,OAAO;EAWxB,OAAO,OADc,MALI,eAAe,cACtC,WAAW,iBAAiB,WAAW,MACvC,KAAK,OACP,EAAA,CAEgC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC;CAEzD;AACF;WA1HG,MAAM,EAAE,UAAU,KAAK,CAAC,GAAA,kBAAA,eAAA,MAAA,CAAA,GAAA,2BAAA,WAAA,YAAA,KAAA,CAAA;WAQxB,MAAM,EAAE,UAAU,KAAK,CAAC,GAAA,kBAAA,eAAA,MAAA,CAAA,GAAA,2BAAA,WAAA,UAAA,KAAA,CAAA;WAIxB,MAAM,EAAE,UAAU,KAAK,CAAC,GAAA,kBAAA,eAAA,MAAA,CAAA,GAAA,2BAAA,WAAA,QAAA,KAAA,CAAA;WAIxB,MAAM,GAAA,kBAAA,eAAA,MAAA,CAAA,GAAA,2BAAA,WAAA,aAAA,KAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"class-registration.d.ts","sourceRoot":"","sources":["../../src/registry/class-registration.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAuBH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,KAAK,EAKV,qBAAqB,EAGtB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"class-registration.d.ts","sourceRoot":"","sources":["../../src/registry/class-registration.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAuBH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,KAAK,EAKV,qBAAqB,EAGtB,MAAM,qBAAqB,CAAC;AA4C7B,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EACf,iBAAiB,EAElB,MAAM,YAAY,CAAC;AAkDpB;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAS3E;AA4BD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB,OAAO,CAeT;AA4nBD;;;;GAIG;AACH,wBAAgB,QAAQ,CACtB,IAAI,EAAE,OAAO,UAAU,EACvB,MAAM,GAAE,iBAAsB,GAC7B,IAAI,CAON;AAmiCD,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,MAAM,EAMlB,qBAAqB,EAAE,WAAW,CAAC,eAAe,CAAC,uBAAuB,CAAC,CAAC,GAC3E,IAAI,CAeN;AA+BD,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,EACpC,kBAAkB,EAAE,eAAe,CAAC,oBAAoB,CAAC,GAAG,SAAS,GACpE,IAAI,CAyCN;AAoHD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,eAAe,EACzB,gBAAgB,CAAC,EAAE;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,GACA,IAAI,CA4CN;AAkLD,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,qBAAqB,EAChC,mBAAmB,CAAC,EAAE,MAAM,GAC3B,IAAI,CAQN"}
|
|
@@ -6,6 +6,7 @@ import { createQualifiedName, isQualifiedName, parseQualifiedName } from "../uti
|
|
|
6
6
|
import { getClasses, getCollections, getConstructorFieldDecorators, getConstructorIndex, getConstructorTenantScopedDeclarations, getInheritanceCache, getLegacyFieldDecorators, getSourceFileFromStack, getStiSiblingsLoaded, verboseLog } from "./shared-state.js";
|
|
7
7
|
import { cloneManifestSchemaColumns, findWorkspaceRootSync, getLocalTestManifestCache, getManifestCache, getNodeBuiltins, getStaticManifestCache, getTestManifestCache } from "../manifest/store.js";
|
|
8
8
|
import { discoverManifestSync, discoverSTISiblingsSync, getPackageName, lookupInManifest, readProjectManifestSync } from "../manifest/manifest-loader.js";
|
|
9
|
+
import { assertQualifiedNameAliasesAvailable } from "./qualified-name-aliases.js";
|
|
9
10
|
import { findClass, findClassesByName, getCanonicalClassName, hasClassCaseInsensitive, qualifyExtendsName } from "./name-resolver.js";
|
|
10
11
|
import { buildInheritanceChain } from "./inheritance-resolver.js";
|
|
11
12
|
import { compileValidators } from "./validator.js";
|
|
@@ -293,6 +294,13 @@ function applyManifestCollisionPolicy(args) {
|
|
|
293
294
|
verboseLog(`[registry] ${decision.scenario}: '${args.name}' replaces '${args.existingKey}' (${decision.reason})`);
|
|
294
295
|
return "continue";
|
|
295
296
|
case "merge-manifest":
|
|
297
|
+
assertQualifiedNameAliasesAvailable(args.registrationKey, {
|
|
298
|
+
...args.existing,
|
|
299
|
+
config: {
|
|
300
|
+
...args.objectDef.decoratorConfig || {},
|
|
301
|
+
...args.existing.config
|
|
302
|
+
}
|
|
303
|
+
}, args.existing);
|
|
296
304
|
mergeManifestIntoExistingRegistration(args.existing, args.objectDef, args.packageName);
|
|
297
305
|
if (args.registrationKey !== args.existingKey) {
|
|
298
306
|
getClasses().set(args.registrationKey, args.existing);
|
|
@@ -438,6 +446,17 @@ function registerUntracked(ctor, config = {}) {
|
|
|
438
446
|
name: existing.name,
|
|
439
447
|
qualifiedName: existing.qualifiedName
|
|
440
448
|
};
|
|
449
|
+
assertQualifiedNameAliasesAvailable(nextKey, {
|
|
450
|
+
...existing,
|
|
451
|
+
name,
|
|
452
|
+
packageName: nextPackageName,
|
|
453
|
+
qualifiedName: nextPackageName ? createQualifiedName(nextPackageName, name) : void 0,
|
|
454
|
+
constructor: ctor,
|
|
455
|
+
config: {
|
|
456
|
+
...existing.config,
|
|
457
|
+
...config
|
|
458
|
+
}
|
|
459
|
+
}, existing);
|
|
441
460
|
existing.name = name;
|
|
442
461
|
existing.packageName = nextPackageName;
|
|
443
462
|
bumpRegistryGeneration();
|
|
@@ -760,7 +779,7 @@ function registerUntracked(ctor, config = {}) {
|
|
|
760
779
|
const qualifiedName = packageName ? createQualifiedName(packageName, name) : void 0;
|
|
761
780
|
const visibility = config.visibility || manifestEntry?.visibility || "public";
|
|
762
781
|
const registrationKey = qualifiedName || name;
|
|
763
|
-
|
|
782
|
+
const registration = {
|
|
764
783
|
name,
|
|
765
784
|
qualifiedName,
|
|
766
785
|
constructor: ctor,
|
|
@@ -780,7 +799,9 @@ function registerUntracked(ctor, config = {}) {
|
|
|
780
799
|
tenantScopedConfig,
|
|
781
800
|
tenantScopedConfigSource,
|
|
782
801
|
visibility
|
|
783
|
-
}
|
|
802
|
+
};
|
|
803
|
+
assertQualifiedNameAliasesAvailable(registrationKey, registration);
|
|
804
|
+
getClasses().set(registrationKey, registration);
|
|
784
805
|
getConstructorIndex().set(ctor, registrationKey);
|
|
785
806
|
setSmrtQualifiedName(ctor, qualifiedName);
|
|
786
807
|
verboseLog(`🎯 Registered smrt object: ${name} (key: ${registrationKey}) with schema for ${schema.tableName} and ${(validators?.length || 0) + (validationRules?.length || 0)} validators/rules`);
|
|
@@ -1140,7 +1161,7 @@ function registerFromManifestUntracked(name, objectDef, manifestPackageName) {
|
|
|
1140
1161
|
const qualifiedName = qualifiedNameEarly;
|
|
1141
1162
|
const visibility = objectDef.visibility || config.visibility || "public";
|
|
1142
1163
|
const tenantScopedConfig = normalizeTenantScopedConfig(config.tenantScoped);
|
|
1143
|
-
|
|
1164
|
+
const registration = {
|
|
1144
1165
|
name: simpleClassName,
|
|
1145
1166
|
qualifiedName,
|
|
1146
1167
|
constructor: stubConstructor,
|
|
@@ -1158,7 +1179,9 @@ function registerFromManifestUntracked(name, objectDef, manifestPackageName) {
|
|
|
1158
1179
|
extends: qualifiedExtends,
|
|
1159
1180
|
extendsTypeArg: objectDef.extendsTypeArg,
|
|
1160
1181
|
visibility
|
|
1161
|
-
}
|
|
1182
|
+
};
|
|
1183
|
+
assertQualifiedNameAliasesAvailable(registrationKey, registration);
|
|
1184
|
+
getClasses().set(registrationKey, registration);
|
|
1162
1185
|
setSmrtQualifiedName(stubConstructor, qualifiedName);
|
|
1163
1186
|
verboseLog(`📦 Registered ${simpleClassName} from manifest (key: ${registrationKey}, ${fields.size} fields, ${methods.size} methods)`);
|
|
1164
1187
|
const collection = objectDef.collection;
|