@happyvertical/smrt-profiles 0.57.15 → 0.57.16

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.
Files changed (45) hide show
  1. package/dist/chunks/{ApiKey-CVmlf3V6.js → ApiKey-9YuYcpWy.js} +3 -3
  2. package/dist/chunks/{ApiKey-CVmlf3V6.js.map → ApiKey-9YuYcpWy.js.map} +1 -1
  3. package/dist/chunks/{ApiKeyCollection-CiiDNFdD.js → ApiKeyCollection-BrJT9vo_.js} +3 -3
  4. package/dist/chunks/{ApiKeyCollection-CiiDNFdD.js.map → ApiKeyCollection-BrJT9vo_.js.map} +1 -1
  5. package/dist/chunks/{AuditLogCollection-WDHL-_AF.js → AuditLogCollection-BBbvr8Qc.js} +2 -2
  6. package/dist/chunks/{AuditLogCollection-WDHL-_AF.js.map → AuditLogCollection-BBbvr8Qc.js.map} +1 -1
  7. package/dist/chunks/{NostrIdentity-AC8fAdxe.js → NostrIdentity-RJaATTCt.js} +20 -9
  8. package/dist/chunks/{NostrIdentity-AC8fAdxe.js.map → NostrIdentity-RJaATTCt.js.map} +1 -1
  9. package/dist/chunks/{NostrIdentityCollection-CctlECpX.js → NostrIdentityCollection-BPNgPOBE.js} +2 -2
  10. package/dist/chunks/{NostrIdentityCollection-CctlECpX.js.map → NostrIdentityCollection-BPNgPOBE.js.map} +1 -1
  11. package/dist/chunks/{OidcIdentity-BUblgQLs.js → OidcIdentity-MVVO3MfG.js} +3 -3
  12. package/dist/chunks/{OidcIdentity-BUblgQLs.js.map → OidcIdentity-MVVO3MfG.js.map} +1 -1
  13. package/dist/chunks/{OidcIdentityCollection-ClOyaHeF.js → OidcIdentityCollection-s4mp3n62.js} +3 -3
  14. package/dist/chunks/{OidcIdentityCollection-ClOyaHeF.js.map → OidcIdentityCollection-s4mp3n62.js.map} +1 -1
  15. package/dist/chunks/{ProfileAssetCollection-CRMcjLJ-.js → ProfileAssetCollection-BuVAdOiv.js} +3 -3
  16. package/dist/chunks/{ProfileAssetCollection-CRMcjLJ-.js.map → ProfileAssetCollection-BuVAdOiv.js.map} +1 -1
  17. package/dist/chunks/{ProfileCollection-C4INKh7Y.js → ProfileCollection-CMS9dFc0.js} +26 -26
  18. package/dist/chunks/{ProfileCollection-C4INKh7Y.js.map → ProfileCollection-CMS9dFc0.js.map} +1 -1
  19. package/dist/chunks/{ProfileLinkCollection-DFfZRsgv.js → ProfileLinkCollection-ChK9iEBp.js} +3 -3
  20. package/dist/chunks/{ProfileLinkCollection-DFfZRsgv.js.map → ProfileLinkCollection-ChK9iEBp.js.map} +1 -1
  21. package/dist/chunks/{ProfileMetadataCollection-BIYKy4Y3.js → ProfileMetadataCollection-CAgJyjze.js} +2 -2
  22. package/dist/chunks/{ProfileMetadataCollection-BIYKy4Y3.js.map → ProfileMetadataCollection-CAgJyjze.js.map} +1 -1
  23. package/dist/chunks/{ProfileMetafieldCollection-Buz7gzag.js → ProfileMetafieldCollection-19ae6Lpf.js} +2 -2
  24. package/dist/chunks/{ProfileMetafieldCollection-Buz7gzag.js.map → ProfileMetafieldCollection-19ae6Lpf.js.map} +1 -1
  25. package/dist/chunks/{ProfileRelationshipCollection-C4g_QLI4.js → ProfileRelationshipCollection-BFSlTQ7J.js} +5 -5
  26. package/dist/chunks/{ProfileRelationshipCollection-C4g_QLI4.js.map → ProfileRelationshipCollection-BFSlTQ7J.js.map} +1 -1
  27. package/dist/chunks/{ProfileRelationshipTermCollection-C9J7mC7P.js → ProfileRelationshipTermCollection-OluL8BGP.js} +2 -2
  28. package/dist/chunks/{ProfileRelationshipTermCollection-C9J7mC7P.js.map → ProfileRelationshipTermCollection-OluL8BGP.js.map} +1 -1
  29. package/dist/chunks/{ProfileRelationshipType-U7IwF6Wf.js → ProfileRelationshipType-Cevy-vaF.js} +2 -2
  30. package/dist/chunks/{ProfileRelationshipType-U7IwF6Wf.js.map → ProfileRelationshipType-Cevy-vaF.js.map} +1 -1
  31. package/dist/chunks/{ProfileRelationshipTypeCollection-_n22WqTb.js → ProfileRelationshipTypeCollection-BRBpX00F.js} +3 -3
  32. package/dist/chunks/{ProfileRelationshipTypeCollection-_n22WqTb.js.map → ProfileRelationshipTypeCollection-BRBpX00F.js.map} +1 -1
  33. package/dist/chunks/{ProfileTypeCollection-B7kwi1mU.js → ProfileTypeCollection-B7m698Bl.js} +3 -3
  34. package/dist/chunks/{ProfileTypeCollection-B7kwi1mU.js.map → ProfileTypeCollection-B7m698Bl.js.map} +1 -1
  35. package/dist/chunks/{oidcProvisioningPrimitives-DNP9EZlU.js → oidcProvisioningPrimitives-Dl9qIcYS.js} +5 -5
  36. package/dist/chunks/{oidcProvisioningPrimitives-DNP9EZlU.js.map → oidcProvisioningPrimitives-Dl9qIcYS.js.map} +1 -1
  37. package/dist/chunks/{resolveIdentity-CkyqvctR.js → resolveIdentity-CR5p_g7K.js} +16 -16
  38. package/dist/chunks/{resolveIdentity-CkyqvctR.js.map → resolveIdentity-CR5p_g7K.js.map} +1 -1
  39. package/dist/index.js +24 -24
  40. package/dist/index.js.map +1 -1
  41. package/dist/internal/oidc-provisioning.js +2 -2
  42. package/dist/manifest.json +1 -1
  43. package/dist/smrt-knowledge.json +4 -4
  44. package/dist/utils.js +4 -4
  45. package/package.json +7 -7
@@ -1,4 +1,4 @@
1
- import { y as __exportAll } from "./NostrIdentity-AC8fAdxe.js";
1
+ import { y as __exportAll } from "./NostrIdentity-RJaATTCt.js";
2
2
  import { SmrtCollection, SmrtObject, field, foreignKey, smrt } from "@happyvertical/smrt-core";
3
3
  import { TenantScoped, tenantId } from "@happyvertical/smrt-tenancy";
4
4
  //#region src/models/ProfileMetadata.ts
@@ -111,4 +111,4 @@ var ProfileMetadataCollection = class extends SmrtCollection {
111
111
  //#endregion
112
112
  export { ProfileMetadataCollection_exports as n, ProfileMetadata as r, ProfileMetadataCollection as t };
113
113
 
114
- //# sourceMappingURL=ProfileMetadataCollection-BIYKy4Y3.js.map
114
+ //# sourceMappingURL=ProfileMetadataCollection-CAgJyjze.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileMetadataCollection-BIYKy4Y3.js","names":[],"sources":["../../src/models/ProfileMetadata.ts","../../src/collections/ProfileMetadataCollection.ts"],"sourcesContent":["/**\n * ProfileMetadata model - Stores metadata values for profiles\n *\n * Links profiles to metafield definitions with actual values.\n * Uses UUID primary key with foreign keys to Profile and ProfileMetafield.\n */\n\nimport {\n field,\n foreignKey,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\n\nexport interface ProfileMetadataOptions extends SmrtObjectOptions {\n profileId?: string;\n metafieldId?: string;\n value?: string;\n tenantId?: string | null;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get'] },\n cli: { skipApiCheck: true },\n})\nexport class ProfileMetadata extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-profiles\";\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n // id: UUID (auto-generated by SmrtObject)\n @foreignKey('Profile', { required: true })\n profileId?: string; // References Profile.id\n\n @foreignKey('ProfileMetafield', { required: true })\n metafieldId?: string; // References ProfileMetafield.id\n\n @field({ required: true })\n value: string = ''; // The metadata value (stored as text)\n\n constructor(options: ProfileMetadataOptions = {}) {\n super(options);\n if (options.profileId !== undefined) this.profileId = options.profileId;\n if (options.metafieldId !== undefined)\n this.metafieldId = options.metafieldId;\n if (options.value) this.value = options.value;\n // The class-field initializer above runs after super(), so an explicit\n // tenant must be re-applied here or it is silently dropped.\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n }\n\n /**\n * Validate this metadata value against the metafield's validation schema\n *\n * @returns True if valid, throws error if invalid\n */\n async validate(): Promise<boolean> {\n const metafield = await this.loadRelated('metafieldId');\n if (!metafield) {\n throw new Error('Metafield not found');\n }\n\n return await metafield.validateValue(this.value);\n }\n\n /**\n * Get the metafield slug for this metadata\n *\n * @returns The slug of the metafield\n */\n async getMetafieldSlug(): Promise<string> {\n const metafield = await this.loadRelated('metafieldId');\n return metafield?.slug || '';\n }\n}\n","/**\n * ProfileMetadataCollection - Collection manager for ProfileMetadata objects\n *\n * Provides querying and batch operations for profile metadata.\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { ProfileMetadata } from '../models/ProfileMetadata';\n\nexport class ProfileMetadataCollection extends SmrtCollection<ProfileMetadata> {\n static readonly _itemClass = ProfileMetadata;\n\n /**\n * Get all metadata for a profile\n *\n * @param profileId - The profile UUID\n * @returns Array of ProfileMetadata instances\n */\n async getByProfile(profileId: string): Promise<ProfileMetadata[]> {\n return await this.list({ where: { profileId } });\n }\n\n /**\n * Get metadata as key-value object for a profile\n *\n * @param profileId - The profile UUID\n * @returns Object with metafield slugs as keys\n */\n async getMetadataObject(profileId: string): Promise<Record<string, string>> {\n const metadata = await this.getByProfile(profileId);\n const result: Record<string, string> = {};\n\n for (const item of metadata) {\n const slug = await item.getMetafieldSlug();\n if (slug) {\n result[slug] = item.value;\n }\n }\n\n return result;\n }\n\n /**\n * Find all profiles with a specific metadata key-value pair\n *\n * @param metafieldId - The metafield UUID\n * @param value - The value to match\n * @returns Array of profile UUIDs\n */\n async findProfilesByMetadata(\n metafieldId: string,\n value: unknown,\n ): Promise<string[]> {\n const matches = await this.list({\n where: { metafieldId, value: String(value) },\n });\n\n return matches\n .map((m) => m.profileId)\n .filter((id) => typeof id === 'string') as string[];\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AA8BO,IAAM,kBAAN,cAA8B,WAAW;CAE9C,WAA0B;CAI1B;CAGA;CAGA,QAAgB;CAEhB,YAAY,UAAkC,CAAC,GAAG;EAChD,MAAM,OAAO;EACb,IAAI,QAAQ,cAAc,KAAA,GAAW,KAAK,YAAY,QAAQ;EAC9D,IAAI,QAAQ,gBAAgB,KAAA,GAC1B,KAAK,cAAc,QAAQ;EAC7B,IAAI,QAAQ,OAAO,KAAK,QAAQ,QAAQ;EAGxC,IAAI,QAAQ,aAAa,KAAA,GAAW,KAAK,WAAW,QAAQ;CAC9D;;;;;;CAOA,MAAM,WAA6B;EACjC,MAAM,YAAY,MAAM,KAAK,YAAY,aAAa;EACtD,IAAI,CAAC,WACH,MAAM,IAAI,MAAM,qBAAqB;EAGvC,OAAO,MAAM,UAAU,cAAc,KAAK,KAAK;CACjD;;;;;;CAOA,MAAM,mBAAoC;EAExC,QAAO,MADiB,KAAK,YAAY,aAAa,EAAA,EACpC,QAAQ;CAC5B;AACF;AAhDkD,cAArC,iBAA4C,mBAAkB,8BAAA;AAEzE,gBAAA,CADC,SAAS,EAAE,UAAU,KAAK,CAAC,CAAA,GADjB,gBAEX,WAAA,YAAA,CAAA;AAIA,gBAAA,CADC,WAAW,WAAW,EAAE,UAAU,KAAK,CAAC,CAAA,GAL9B,gBAMX,WAAA,aAAA,CAAA;AAGA,gBAAA,CADC,WAAW,oBAAoB,EAAE,UAAU,KAAK,CAAC,CAAA,GARvC,gBASX,WAAA,eAAA,CAAA;AAGA,gBAAA,CADC,MAAM,EAAE,UAAU,KAAK,CAAC,CAAA,GAXd,gBAYX,WAAA,SAAA,CAAA;AAZW,kBAAN,gBAAA,CAPN,aAAa,EAAE,MAAM,WAAW,CAAC,GACjC,KAAK;CACJ,eAAe;CACf,KAAK,EAAE,SAAS;EAAC;EAAQ;EAAO;EAAU;EAAU;CAAQ,EAAE;CAC9D,KAAK,EAAE,SAAS,CAAC,QAAQ,KAAK,EAAE;CAChC,KAAK,EAAE,cAAc,KAAK;AAC5B,CAAC,CAAA,GACY,eAAA;;;;ACrBN,IAAM,4BAAN,cAAwC,eAAgC;CAC7E,OAAgB,aAAa;;;;;;;CAQ7B,MAAM,aAAa,WAA+C;EAChE,OAAO,MAAM,KAAK,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;CACjD;;;;;;;CAQA,MAAM,kBAAkB,WAAoD;EAC1E,MAAM,WAAW,MAAM,KAAK,aAAa,SAAS;EAClD,MAAM,SAAiC,CAAC;EAExC,KAAA,MAAW,QAAQ,UAAU;GAC3B,MAAM,OAAO,MAAM,KAAK,iBAAiB;GACzC,IAAI,MACF,OAAO,QAAQ,KAAK;EAExB;EAEA,OAAO;CACT;;;;;;;;CASA,MAAM,uBACJ,aACA,OACmB;EAKnB,QAAO,MAJe,KAAK,KAAK,EAC9B,OAAO;GAAE;GAAa,OAAO,OAAO,KAAK;EAAE,EAC7C,CAAC,EAAA,CAGE,KAAK,MAAM,EAAE,SAAS,CAAA,CACtB,QAAQ,OAAO,OAAO,OAAO,QAAQ;CAC1C;AACF"}
1
+ {"version":3,"file":"ProfileMetadataCollection-CAgJyjze.js","names":[],"sources":["../../src/models/ProfileMetadata.ts","../../src/collections/ProfileMetadataCollection.ts"],"sourcesContent":["/**\n * ProfileMetadata model - Stores metadata values for profiles\n *\n * Links profiles to metafield definitions with actual values.\n * Uses UUID primary key with foreign keys to Profile and ProfileMetafield.\n */\n\nimport {\n field,\n foreignKey,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\n\nexport interface ProfileMetadataOptions extends SmrtObjectOptions {\n profileId?: string;\n metafieldId?: string;\n value?: string;\n tenantId?: string | null;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get'] },\n cli: { skipApiCheck: true },\n})\nexport class ProfileMetadata extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-profiles\";\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n // id: UUID (auto-generated by SmrtObject)\n @foreignKey('Profile', { required: true })\n profileId?: string; // References Profile.id\n\n @foreignKey('ProfileMetafield', { required: true })\n metafieldId?: string; // References ProfileMetafield.id\n\n @field({ required: true })\n value: string = ''; // The metadata value (stored as text)\n\n constructor(options: ProfileMetadataOptions = {}) {\n super(options);\n if (options.profileId !== undefined) this.profileId = options.profileId;\n if (options.metafieldId !== undefined)\n this.metafieldId = options.metafieldId;\n if (options.value) this.value = options.value;\n // The class-field initializer above runs after super(), so an explicit\n // tenant must be re-applied here or it is silently dropped.\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n }\n\n /**\n * Validate this metadata value against the metafield's validation schema\n *\n * @returns True if valid, throws error if invalid\n */\n async validate(): Promise<boolean> {\n const metafield = await this.loadRelated('metafieldId');\n if (!metafield) {\n throw new Error('Metafield not found');\n }\n\n return await metafield.validateValue(this.value);\n }\n\n /**\n * Get the metafield slug for this metadata\n *\n * @returns The slug of the metafield\n */\n async getMetafieldSlug(): Promise<string> {\n const metafield = await this.loadRelated('metafieldId');\n return metafield?.slug || '';\n }\n}\n","/**\n * ProfileMetadataCollection - Collection manager for ProfileMetadata objects\n *\n * Provides querying and batch operations for profile metadata.\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { ProfileMetadata } from '../models/ProfileMetadata';\n\nexport class ProfileMetadataCollection extends SmrtCollection<ProfileMetadata> {\n static readonly _itemClass = ProfileMetadata;\n\n /**\n * Get all metadata for a profile\n *\n * @param profileId - The profile UUID\n * @returns Array of ProfileMetadata instances\n */\n async getByProfile(profileId: string): Promise<ProfileMetadata[]> {\n return await this.list({ where: { profileId } });\n }\n\n /**\n * Get metadata as key-value object for a profile\n *\n * @param profileId - The profile UUID\n * @returns Object with metafield slugs as keys\n */\n async getMetadataObject(profileId: string): Promise<Record<string, string>> {\n const metadata = await this.getByProfile(profileId);\n const result: Record<string, string> = {};\n\n for (const item of metadata) {\n const slug = await item.getMetafieldSlug();\n if (slug) {\n result[slug] = item.value;\n }\n }\n\n return result;\n }\n\n /**\n * Find all profiles with a specific metadata key-value pair\n *\n * @param metafieldId - The metafield UUID\n * @param value - The value to match\n * @returns Array of profile UUIDs\n */\n async findProfilesByMetadata(\n metafieldId: string,\n value: unknown,\n ): Promise<string[]> {\n const matches = await this.list({\n where: { metafieldId, value: String(value) },\n });\n\n return matches\n .map((m) => m.profileId)\n .filter((id) => typeof id === 'string') as string[];\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AA8BO,IAAM,kBAAN,cAA8B,WAAW;CAE9C,WAA0B;CAI1B;CAGA;CAGA,QAAgB;CAEhB,YAAY,UAAkC,CAAC,GAAG;EAChD,MAAM,OAAO;EACb,IAAI,QAAQ,cAAc,KAAA,GAAW,KAAK,YAAY,QAAQ;EAC9D,IAAI,QAAQ,gBAAgB,KAAA,GAC1B,KAAK,cAAc,QAAQ;EAC7B,IAAI,QAAQ,OAAO,KAAK,QAAQ,QAAQ;EAGxC,IAAI,QAAQ,aAAa,KAAA,GAAW,KAAK,WAAW,QAAQ;CAC9D;;;;;;CAOA,MAAM,WAA6B;EACjC,MAAM,YAAY,MAAM,KAAK,YAAY,aAAa;EACtD,IAAI,CAAC,WACH,MAAM,IAAI,MAAM,qBAAqB;EAGvC,OAAO,MAAM,UAAU,cAAc,KAAK,KAAK;CACjD;;;;;;CAOA,MAAM,mBAAoC;EAExC,QAAO,MADiB,KAAK,YAAY,aAAa,EAAA,EACpC,QAAQ;CAC5B;AACF;AAhDkD,cAArC,iBAA4C,mBAAkB,8BAAA;AAEzE,gBAAA,CADC,SAAS,EAAE,UAAU,KAAK,CAAC,CAAA,GADjB,gBAEX,WAAA,YAAA,CAAA;AAIA,gBAAA,CADC,WAAW,WAAW,EAAE,UAAU,KAAK,CAAC,CAAA,GAL9B,gBAMX,WAAA,aAAA,CAAA;AAGA,gBAAA,CADC,WAAW,oBAAoB,EAAE,UAAU,KAAK,CAAC,CAAA,GARvC,gBASX,WAAA,eAAA,CAAA;AAGA,gBAAA,CADC,MAAM,EAAE,UAAU,KAAK,CAAC,CAAA,GAXd,gBAYX,WAAA,SAAA,CAAA;AAZW,kBAAN,gBAAA,CAPN,aAAa,EAAE,MAAM,WAAW,CAAC,GACjC,KAAK;CACJ,eAAe;CACf,KAAK,EAAE,SAAS;EAAC;EAAQ;EAAO;EAAU;EAAU;CAAQ,EAAE;CAC9D,KAAK,EAAE,SAAS,CAAC,QAAQ,KAAK,EAAE;CAChC,KAAK,EAAE,cAAc,KAAK;AAC5B,CAAC,CAAA,GACY,eAAA;;;;ACrBN,IAAM,4BAAN,cAAwC,eAAgC;CAC7E,OAAgB,aAAa;;;;;;;CAQ7B,MAAM,aAAa,WAA+C;EAChE,OAAO,MAAM,KAAK,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;CACjD;;;;;;;CAQA,MAAM,kBAAkB,WAAoD;EAC1E,MAAM,WAAW,MAAM,KAAK,aAAa,SAAS;EAClD,MAAM,SAAiC,CAAC;EAExC,KAAA,MAAW,QAAQ,UAAU;GAC3B,MAAM,OAAO,MAAM,KAAK,iBAAiB;GACzC,IAAI,MACF,OAAO,QAAQ,KAAK;EAExB;EAEA,OAAO;CACT;;;;;;;;CASA,MAAM,uBACJ,aACA,OACmB;EAKnB,QAAO,MAJe,KAAK,KAAK,EAC9B,OAAO;GAAE;GAAa,OAAO,OAAO,KAAK;EAAE,EAC7C,CAAC,EAAA,CAGE,KAAK,MAAM,EAAE,SAAS,CAAA,CACtB,QAAQ,OAAO,OAAO,OAAO,QAAQ;CAC1C;AACF"}
@@ -1,4 +1,4 @@
1
- import { y as __exportAll } from "./NostrIdentity-AC8fAdxe.js";
1
+ import { y as __exportAll } from "./NostrIdentity-RJaATTCt.js";
2
2
  import { SmrtCollection, SmrtObject, field, smrt } from "@happyvertical/smrt-core";
3
3
  import { TenantScoped, tenantId } from "@happyvertical/smrt-tenancy";
4
4
  //#region src/models/ProfileMetafield.ts
@@ -148,4 +148,4 @@ var ProfileMetafieldCollection = class extends SmrtCollection {
148
148
  //#endregion
149
149
  export { ProfileMetafieldCollection_exports as n, ProfileMetafield as r, ProfileMetafieldCollection as t };
150
150
 
151
- //# sourceMappingURL=ProfileMetafieldCollection-Buz7gzag.js.map
151
+ //# sourceMappingURL=ProfileMetafieldCollection-19ae6Lpf.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileMetafieldCollection-Buz7gzag.js","names":[],"sources":["../../src/models/ProfileMetafield.ts","../../src/collections/ProfileMetafieldCollection.ts"],"sourcesContent":["/**\n * ProfileMetafield model - Controlled vocabulary for metadata fields\n *\n * Defines allowed metadata keys with validation rules.\n * Uses UUID primary key with unique slug for human-readable lookups.\n */\n\nimport {\n field,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type { ValidationSchema, ValidatorFunction } from '../types';\n\nexport interface ProfileMetafieldOptions extends SmrtObjectOptions {\n slug?: string;\n name?: string;\n description?: string;\n validation?: ValidationSchema;\n tenantId?: string | null;\n}\n\n/**\n * Extend globalThis to include custom validators registry.\n * Using globalThis ensures all module instances share the same validators,\n * which is critical in monorepos where the same package can be loaded\n * from different paths (e.g., pnpm store vs workspace symlink).\n *\n * @see https://github.com/happyvertical/smrt/issues/543\n */\ndeclare global {\n // eslint-disable-next-line no-var\n var __smrtProfileMetafieldValidators:\n | Map<string, ValidatorFunction>\n | undefined;\n}\n\n/**\n * Get the custom validators Map from globalThis\n */\nfunction getCustomValidators(): Map<string, ValidatorFunction> {\n if (!globalThis.__smrtProfileMetafieldValidators) {\n globalThis.__smrtProfileMetafieldValidators = new Map<\n string,\n ValidatorFunction\n >();\n }\n return globalThis.__smrtProfileMetafieldValidators;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get'] },\n cli: { skipApiCheck: true },\n})\nexport class ProfileMetafield extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-profiles\";\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n // id: UUID (auto-generated by SmrtObject)\n // slug is inherited from SmrtObject (auto-generated from name)\n @field({ required: true })\n name: string = '';\n\n description?: string;\n\n validation?: ValidationSchema; // Validation schema as JSON\n\n constructor(options: ProfileMetafieldOptions = {}) {\n super(options);\n if (options.name) this.name = options.name;\n if (options.description !== undefined)\n this.description = options.description;\n if (options.validation !== undefined) this.validation = options.validation;\n // The class-field initializer above runs after super(), so an explicit\n // tenant must be re-applied here or it is silently dropped.\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n }\n\n /**\n * Convenience method for slug-based lookup\n *\n * @param slug - The slug to search for\n * @returns ProfileMetafield instance or null if not found\n */\n static async getBySlug(_slug: string): Promise<ProfileMetafield | null> {\n // Will be auto-implemented by SMRT\n return null;\n }\n\n /**\n * Register a custom validator function\n *\n * @param name - Name of the validator (used in validation.custom field)\n * @param validator - The validator function\n */\n static registerValidator(name: string, validator: ValidatorFunction): void {\n getCustomValidators().set(name, validator);\n }\n\n /**\n * Get a registered custom validator\n *\n * @param name - Name of the validator\n * @returns The validator function or undefined\n */\n static getValidator(name: string): ValidatorFunction | undefined {\n return getCustomValidators().get(name);\n }\n\n /**\n * Validate a value against this metafield's validation schema\n *\n * @param value - The value to validate\n * @returns True if valid, throws ValidationError if invalid\n */\n async validateValue(value: unknown): Promise<boolean> {\n if (!this.validation) return true;\n\n const schema = this.validation;\n\n // Type validation\n if (schema.type) {\n const actualType = typeof value;\n const expectedType = schema.type;\n\n if (expectedType === 'number' && actualType !== 'number') {\n throw new Error(\n schema.message || `Expected ${expectedType}, got ${actualType}`,\n );\n }\n if (expectedType === 'string' && actualType !== 'string') {\n throw new Error(\n schema.message || `Expected ${expectedType}, got ${actualType}`,\n );\n }\n if (expectedType === 'boolean' && actualType !== 'boolean') {\n throw new Error(\n schema.message || `Expected ${expectedType}, got ${actualType}`,\n );\n }\n }\n\n // String validations\n if (schema.pattern && typeof value === 'string') {\n const regex = new RegExp(schema.pattern);\n if (!regex.test(value)) {\n throw new Error(schema.message || 'Pattern validation failed');\n }\n }\n\n if (schema.minLength && typeof value === 'string') {\n if (value.length < schema.minLength) {\n throw new Error(\n schema.message ||\n `Minimum length is ${schema.minLength}, got ${value.length}`,\n );\n }\n }\n\n if (schema.maxLength && typeof value === 'string') {\n if (value.length > schema.maxLength) {\n throw new Error(\n schema.message ||\n `Maximum length is ${schema.maxLength}, got ${value.length}`,\n );\n }\n }\n\n // Numeric validations\n if (schema.min !== undefined && typeof value === 'number') {\n if (value < schema.min) {\n throw new Error(\n schema.message || `Value must be at least ${schema.min}`,\n );\n }\n }\n\n if (schema.max !== undefined && typeof value === 'number') {\n if (value > schema.max) {\n throw new Error(\n schema.message || `Value must be at most ${schema.max}`,\n );\n }\n }\n\n // Custom validator\n if (schema.custom) {\n const validator = ProfileMetafield.getValidator(schema.custom);\n if (!validator) {\n throw new Error(`Custom validator '${schema.custom}' not registered`);\n }\n\n const result = await validator(value);\n if (!result) {\n throw new Error(schema.message || 'Custom validation failed');\n }\n }\n\n return true;\n }\n}\n","/**\n * ProfileMetafieldCollection - Collection manager for ProfileMetafield objects\n *\n * Provides querying for profile metafield lookup table.\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { ProfileMetafield } from '../models/ProfileMetafield';\nimport type { ValidationSchema } from '../types';\n\nexport class ProfileMetafieldCollection extends SmrtCollection<ProfileMetafield> {\n static readonly _itemClass = ProfileMetafield;\n\n /**\n * Get metafield by slug\n *\n * @param slug - The slug to search for\n * @returns ProfileMetafield instance or null\n */\n async getBySlug(slug: string): Promise<ProfileMetafield | null> {\n return await this.get({ slug });\n }\n\n /**\n * Get or create a metafield by slug\n *\n * @param slug - The slug to search for\n * @param defaults - Default values if creating\n * @returns ProfileMetafield instance\n */\n async getOrCreateBySlug(\n slug: string,\n defaults: {\n name: string;\n description?: string;\n validation?: ValidationSchema;\n },\n ): Promise<ProfileMetafield> {\n const existing = await this.getBySlug(slug);\n if (existing) return existing;\n\n const metafield = await this.create({ slug, ...defaults });\n await metafield.save();\n return metafield;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ProfileMetafieldCollection-19ae6Lpf.js","names":[],"sources":["../../src/models/ProfileMetafield.ts","../../src/collections/ProfileMetafieldCollection.ts"],"sourcesContent":["/**\n * ProfileMetafield model - Controlled vocabulary for metadata fields\n *\n * Defines allowed metadata keys with validation rules.\n * Uses UUID primary key with unique slug for human-readable lookups.\n */\n\nimport {\n field,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type { ValidationSchema, ValidatorFunction } from '../types';\n\nexport interface ProfileMetafieldOptions extends SmrtObjectOptions {\n slug?: string;\n name?: string;\n description?: string;\n validation?: ValidationSchema;\n tenantId?: string | null;\n}\n\n/**\n * Extend globalThis to include custom validators registry.\n * Using globalThis ensures all module instances share the same validators,\n * which is critical in monorepos where the same package can be loaded\n * from different paths (e.g., pnpm store vs workspace symlink).\n *\n * @see https://github.com/happyvertical/smrt/issues/543\n */\ndeclare global {\n // eslint-disable-next-line no-var\n var __smrtProfileMetafieldValidators:\n | Map<string, ValidatorFunction>\n | undefined;\n}\n\n/**\n * Get the custom validators Map from globalThis\n */\nfunction getCustomValidators(): Map<string, ValidatorFunction> {\n if (!globalThis.__smrtProfileMetafieldValidators) {\n globalThis.__smrtProfileMetafieldValidators = new Map<\n string,\n ValidatorFunction\n >();\n }\n return globalThis.__smrtProfileMetafieldValidators;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get'] },\n cli: { skipApiCheck: true },\n})\nexport class ProfileMetafield extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-profiles\";\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n // id: UUID (auto-generated by SmrtObject)\n // slug is inherited from SmrtObject (auto-generated from name)\n @field({ required: true })\n name: string = '';\n\n description?: string;\n\n validation?: ValidationSchema; // Validation schema as JSON\n\n constructor(options: ProfileMetafieldOptions = {}) {\n super(options);\n if (options.name) this.name = options.name;\n if (options.description !== undefined)\n this.description = options.description;\n if (options.validation !== undefined) this.validation = options.validation;\n // The class-field initializer above runs after super(), so an explicit\n // tenant must be re-applied here or it is silently dropped.\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n }\n\n /**\n * Convenience method for slug-based lookup\n *\n * @param slug - The slug to search for\n * @returns ProfileMetafield instance or null if not found\n */\n static async getBySlug(_slug: string): Promise<ProfileMetafield | null> {\n // Will be auto-implemented by SMRT\n return null;\n }\n\n /**\n * Register a custom validator function\n *\n * @param name - Name of the validator (used in validation.custom field)\n * @param validator - The validator function\n */\n static registerValidator(name: string, validator: ValidatorFunction): void {\n getCustomValidators().set(name, validator);\n }\n\n /**\n * Get a registered custom validator\n *\n * @param name - Name of the validator\n * @returns The validator function or undefined\n */\n static getValidator(name: string): ValidatorFunction | undefined {\n return getCustomValidators().get(name);\n }\n\n /**\n * Validate a value against this metafield's validation schema\n *\n * @param value - The value to validate\n * @returns True if valid, throws ValidationError if invalid\n */\n async validateValue(value: unknown): Promise<boolean> {\n if (!this.validation) return true;\n\n const schema = this.validation;\n\n // Type validation\n if (schema.type) {\n const actualType = typeof value;\n const expectedType = schema.type;\n\n if (expectedType === 'number' && actualType !== 'number') {\n throw new Error(\n schema.message || `Expected ${expectedType}, got ${actualType}`,\n );\n }\n if (expectedType === 'string' && actualType !== 'string') {\n throw new Error(\n schema.message || `Expected ${expectedType}, got ${actualType}`,\n );\n }\n if (expectedType === 'boolean' && actualType !== 'boolean') {\n throw new Error(\n schema.message || `Expected ${expectedType}, got ${actualType}`,\n );\n }\n }\n\n // String validations\n if (schema.pattern && typeof value === 'string') {\n const regex = new RegExp(schema.pattern);\n if (!regex.test(value)) {\n throw new Error(schema.message || 'Pattern validation failed');\n }\n }\n\n if (schema.minLength && typeof value === 'string') {\n if (value.length < schema.minLength) {\n throw new Error(\n schema.message ||\n `Minimum length is ${schema.minLength}, got ${value.length}`,\n );\n }\n }\n\n if (schema.maxLength && typeof value === 'string') {\n if (value.length > schema.maxLength) {\n throw new Error(\n schema.message ||\n `Maximum length is ${schema.maxLength}, got ${value.length}`,\n );\n }\n }\n\n // Numeric validations\n if (schema.min !== undefined && typeof value === 'number') {\n if (value < schema.min) {\n throw new Error(\n schema.message || `Value must be at least ${schema.min}`,\n );\n }\n }\n\n if (schema.max !== undefined && typeof value === 'number') {\n if (value > schema.max) {\n throw new Error(\n schema.message || `Value must be at most ${schema.max}`,\n );\n }\n }\n\n // Custom validator\n if (schema.custom) {\n const validator = ProfileMetafield.getValidator(schema.custom);\n if (!validator) {\n throw new Error(`Custom validator '${schema.custom}' not registered`);\n }\n\n const result = await validator(value);\n if (!result) {\n throw new Error(schema.message || 'Custom validation failed');\n }\n }\n\n return true;\n }\n}\n","/**\n * ProfileMetafieldCollection - Collection manager for ProfileMetafield objects\n *\n * Provides querying for profile metafield lookup table.\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { ProfileMetafield } from '../models/ProfileMetafield';\nimport type { ValidationSchema } from '../types';\n\nexport class ProfileMetafieldCollection extends SmrtCollection<ProfileMetafield> {\n static readonly _itemClass = ProfileMetafield;\n\n /**\n * Get metafield by slug\n *\n * @param slug - The slug to search for\n * @returns ProfileMetafield instance or null\n */\n async getBySlug(slug: string): Promise<ProfileMetafield | null> {\n return await this.get({ slug });\n }\n\n /**\n * Get or create a metafield by slug\n *\n * @param slug - The slug to search for\n * @param defaults - Default values if creating\n * @returns ProfileMetafield instance\n */\n async getOrCreateBySlug(\n slug: string,\n defaults: {\n name: string;\n description?: string;\n validation?: ValidationSchema;\n },\n ): Promise<ProfileMetafield> {\n const existing = await this.getBySlug(slug);\n if (existing) return existing;\n\n const metafield = await this.create({ slug, ...defaults });\n await metafield.save();\n return metafield;\n }\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { y as __exportAll } from "./NostrIdentity-AC8fAdxe.js";
1
+ import { y as __exportAll } from "./NostrIdentity-RJaATTCt.js";
2
2
  import { SmrtCollection, SmrtObject, foreignKey, oneToMany, smrt } from "@happyvertical/smrt-core";
3
3
  import { TenantScoped, tenantId } from "@happyvertical/smrt-tenancy";
4
4
  //#region src/models/ProfileRelationship.ts
@@ -48,7 +48,7 @@ var ProfileRelationship = class extends SmrtObject {
48
48
  async addTerm(startedAt, endedAt) {
49
49
  if (!this.id) throw new Error("ProfileRelationship.addTerm requires a persisted relationship (missing id)");
50
50
  const relationshipId = this.id;
51
- const { ProfileRelationshipTermCollection } = await import("./ProfileRelationshipTermCollection-C9J7mC7P.js").then((n) => n.n);
51
+ const { ProfileRelationshipTermCollection } = await import("./ProfileRelationshipTermCollection-OluL8BGP.js").then((n) => n.n);
52
52
  await (await (await ProfileRelationshipTermCollection.create(this.options)).create({
53
53
  relationshipId,
54
54
  startedAt,
@@ -70,7 +70,7 @@ var ProfileRelationship = class extends SmrtObject {
70
70
  * @returns Array of ProfileRelationshipTerm instances
71
71
  */
72
72
  async getTerms() {
73
- const { ProfileRelationshipTermCollection } = await import("./ProfileRelationshipTermCollection-C9J7mC7P.js").then((n) => n.n);
73
+ const { ProfileRelationshipTermCollection } = await import("./ProfileRelationshipTermCollection-OluL8BGP.js").then((n) => n.n);
74
74
  return await (await ProfileRelationshipTermCollection.create(this.options)).getByRelationship(this.id);
75
75
  }
76
76
  /**
@@ -79,7 +79,7 @@ var ProfileRelationship = class extends SmrtObject {
79
79
  * @returns Current term or null if none active
80
80
  */
81
81
  async getActiveTerm() {
82
- const { ProfileRelationshipTermCollection } = await import("./ProfileRelationshipTermCollection-C9J7mC7P.js").then((n) => n.n);
82
+ const { ProfileRelationshipTermCollection } = await import("./ProfileRelationshipTermCollection-OluL8BGP.js").then((n) => n.n);
83
83
  return await (await ProfileRelationshipTermCollection.create(this.options)).getActiveTerm(this.id);
84
84
  }
85
85
  };
@@ -164,4 +164,4 @@ var ProfileRelationshipCollection = class extends SmrtCollection {
164
164
  //#endregion
165
165
  export { ProfileRelationshipCollection_exports as n, ProfileRelationship as r, ProfileRelationshipCollection as t };
166
166
 
167
- //# sourceMappingURL=ProfileRelationshipCollection-C4g_QLI4.js.map
167
+ //# sourceMappingURL=ProfileRelationshipCollection-BFSlTQ7J.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileRelationshipCollection-C4g_QLI4.js","names":[],"sources":["../../src/models/ProfileRelationship.ts","../../src/collections/ProfileRelationshipCollection.ts"],"sourcesContent":["/**\n * ProfileRelationship model - Connects two profiles with a relationship type\n *\n * Represents directional or reciprocal relationships between profiles.\n * Uses UUID primary key with foreign keys to profiles and relationship type.\n */\n\nimport {\n foreignKey,\n oneToMany,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type { ProfileRelationshipTerm } from './ProfileRelationshipTerm';\n\nexport interface ProfileRelationshipOptions extends SmrtObjectOptions {\n fromProfileId?: string;\n toProfileId?: string;\n typeId?: string;\n contextProfileId?: string;\n tenantId?: string | null;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get', 'create', 'delete'] },\n mcp: { include: ['list', 'get'] },\n cli: { skipApiCheck: true },\n})\nexport class ProfileRelationship extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-profiles\";\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n // id: UUID (auto-generated by SmrtObject)\n @foreignKey('Profile', { required: true })\n fromProfileId?: string; // Origin profile\n\n @foreignKey('Profile', { required: true })\n toProfileId?: string; // Target profile\n\n @foreignKey('ProfileRelationshipType', { required: true })\n typeId?: string; // Relationship type\n\n @foreignKey('Profile')\n contextProfileId?: string; // Optional tertiary context\n\n // Relationships\n @oneToMany('ProfileRelationshipTerm')\n terms: ProfileRelationshipTerm[] = [];\n\n constructor(options: ProfileRelationshipOptions = {}) {\n super(options);\n if (options.fromProfileId !== undefined)\n this.fromProfileId = options.fromProfileId;\n if (options.toProfileId !== undefined)\n this.toProfileId = options.toProfileId;\n if (options.typeId !== undefined) this.typeId = options.typeId;\n if (options.contextProfileId !== undefined)\n this.contextProfileId = options.contextProfileId;\n }\n\n /**\n * Get the relationship type slug\n *\n * @returns The slug of the relationship type\n */\n async getTypeSlug(): Promise<string> {\n const type = await this.loadRelated('typeId');\n return type?.slug || '';\n }\n\n /**\n * Add a term (time period) to this relationship\n *\n * @param startedAt - Start date of the term\n * @param endedAt - Optional end date of the term\n */\n async addTerm(startedAt: Date, endedAt?: Date): Promise<void> {\n if (!this.id) {\n throw new Error(\n 'ProfileRelationship.addTerm requires a persisted relationship (missing id)',\n );\n }\n const relationshipId = this.id;\n\n const { ProfileRelationshipTermCollection } = await import(\n '../collections/ProfileRelationshipTermCollection'\n );\n\n const termCollection = await ProfileRelationshipTermCollection.create(\n this.options,\n );\n\n const term = await termCollection.create({\n relationshipId,\n startedAt,\n endedAt,\n });\n\n await term.save();\n }\n\n /**\n * End the current active term\n *\n * @param endedAt - End date for the term\n */\n async endCurrentTerm(endedAt: Date): Promise<void> {\n const activeTerm = await this.getActiveTerm();\n if (activeTerm) {\n await activeTerm.end(endedAt);\n }\n }\n\n /**\n * Get all terms for this relationship\n *\n * @returns Array of ProfileRelationshipTerm instances\n */\n async getTerms(): Promise<ProfileRelationshipTerm[]> {\n const { ProfileRelationshipTermCollection } = await import(\n '../collections/ProfileRelationshipTermCollection'\n );\n\n const termCollection = await ProfileRelationshipTermCollection.create(\n this.options,\n );\n\n return await termCollection.getByRelationship(this.id as string);\n }\n\n /**\n * Get the active term (no end date)\n *\n * @returns Current term or null if none active\n */\n async getActiveTerm(): Promise<ProfileRelationshipTerm | null> {\n const { ProfileRelationshipTermCollection } = await import(\n '../collections/ProfileRelationshipTermCollection'\n );\n\n const termCollection = await ProfileRelationshipTermCollection.create(\n this.options,\n );\n\n return await termCollection.getActiveTerm(this.id as string);\n }\n}\n","/**\n * ProfileRelationshipCollection - Collection manager for ProfileRelationship objects\n *\n * Provides querying for relationships between profiles.\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { ProfileRelationship } from '../models/ProfileRelationship';\n\nexport class ProfileRelationshipCollection extends SmrtCollection<ProfileRelationship> {\n static readonly _itemClass = ProfileRelationship;\n\n /**\n * Get all relationships from a profile\n *\n * @param fromProfileId - The origin profile UUID\n * @param typeId - Optional filter by relationship type UUID\n * @returns Array of ProfileRelationship instances\n */\n async getFromProfile(\n fromProfileId: string,\n typeId?: string,\n ): Promise<ProfileRelationship[]> {\n const where: Record<string, unknown> = { fromProfileId };\n if (typeId) where.typeId = typeId;\n\n return await this.list({ where });\n }\n\n /**\n * Get all relationships to a profile\n *\n * @param toProfileId - The target profile UUID\n * @param typeId - Optional filter by relationship type UUID\n * @returns Array of ProfileRelationship instances\n */\n async getToProfile(\n toProfileId: string,\n typeId?: string,\n ): Promise<ProfileRelationship[]> {\n const where: Record<string, unknown> = { toProfileId };\n if (typeId) where.typeId = typeId;\n\n return await this.list({ where });\n }\n\n /**\n * Get all relationships for a profile (both directions)\n *\n * @param profileId - The profile UUID\n * @param typeId - Optional filter by relationship type UUID\n * @returns Array of ProfileRelationship instances\n */\n async getForProfile(\n profileId: string,\n typeId?: string,\n ): Promise<ProfileRelationship[]> {\n const fromRelationships = await this.getFromProfile(profileId, typeId);\n const toRelationships = await this.getToProfile(profileId, typeId);\n\n return [...fromRelationships, ...toRelationships];\n }\n\n /**\n * Check if a relationship exists between two profiles\n *\n * @param fromProfileId - The origin profile UUID\n * @param toProfileId - The target profile UUID\n * @param typeId - The relationship type UUID\n * @returns True if relationship exists\n */\n async exists(\n fromProfileId: string,\n toProfileId: string,\n typeId: string,\n ): Promise<boolean> {\n const matches = await this.list({\n where: { fromProfileId, toProfileId, typeId },\n limit: 1,\n });\n\n return matches.length > 0;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAgCO,IAAM,sBAAN,cAAkC,WAAW;CAElD,WAA0B;CAI1B;CAGA;CAGA;CAGA;CAIA,QAAmC,CAAC;CAEpC,YAAY,UAAsC,CAAC,GAAG;EACpD,MAAM,OAAO;EACb,IAAI,QAAQ,kBAAkB,KAAA,GAC5B,KAAK,gBAAgB,QAAQ;EAC/B,IAAI,QAAQ,gBAAgB,KAAA,GAC1B,KAAK,cAAc,QAAQ;EAC7B,IAAI,QAAQ,WAAW,KAAA,GAAW,KAAK,SAAS,QAAQ;EACxD,IAAI,QAAQ,qBAAqB,KAAA,GAC/B,KAAK,mBAAmB,QAAQ;CACpC;;;;;;CAOA,MAAM,cAA+B;EAEnC,QAAO,MADY,KAAK,YAAY,QAAQ,EAAA,EAC/B,QAAQ;CACvB;;;;;;;CAQA,MAAM,QAAQ,WAAiB,SAA+B;EAC5D,IAAI,CAAC,KAAK,IACR,MAAM,IAAI,MACR,4EACF;EAEF,MAAM,iBAAiB,KAAK;EAE5B,MAAM,EAAE,sCAAsC,MAAM,OAClD,kDAAA,CAAA,MAAA,MAAA,EAAA,CAAA;EAaF,OAAM,OANa,MAJU,kCAAkC,OAC7D,KAAK,OACP,EAAA,CAEkC,OAAO;GACvC;GACA;GACA;EACF,CAAC,EAAA,CAEU,KAAK;CAClB;;;;;;CAOA,MAAM,eAAe,SAA8B;EACjD,MAAM,aAAa,MAAM,KAAK,cAAc;EAC5C,IAAI,YACF,MAAM,WAAW,IAAI,OAAO;CAEhC;;;;;;CAOA,MAAM,WAA+C;EACnD,MAAM,EAAE,sCAAsC,MAAM,OAClD,kDAAA,CAAA,MAAA,MAAA,EAAA,CAAA;EAOF,OAAO,OAAM,MAJgB,kCAAkC,OAC7D,KAAK,OACP,EAAA,CAE4B,kBAAkB,KAAK,EAAY;CACjE;;;;;;CAOA,MAAM,gBAAyD;EAC7D,MAAM,EAAE,sCAAsC,MAAM,OAClD,kDAAA,CAAA,MAAA,MAAA,EAAA,CAAA;EAOF,OAAO,OAAM,MAJgB,kCAAkC,OAC7D,KAAK,OACP,EAAA,CAE4B,cAAc,KAAK,EAAY;CAC7D;AACF;AAtHsD,cAAzC,qBAAgD,mBAAkB,8BAAA;AAE7E,gBAAA,CADC,SAAS,EAAE,UAAU,KAAK,CAAC,CAAA,GADjB,oBAEX,WAAA,YAAA,CAAA;AAIA,gBAAA,CADC,WAAW,WAAW,EAAE,UAAU,KAAK,CAAC,CAAA,GAL9B,oBAMX,WAAA,iBAAA,CAAA;AAGA,gBAAA,CADC,WAAW,WAAW,EAAE,UAAU,KAAK,CAAC,CAAA,GAR9B,oBASX,WAAA,eAAA,CAAA;AAGA,gBAAA,CADC,WAAW,2BAA2B,EAAE,UAAU,KAAK,CAAC,CAAA,GAX9C,oBAYX,WAAA,UAAA,CAAA;AAGA,gBAAA,CADC,WAAW,SAAS,CAAA,GAdV,oBAeX,WAAA,oBAAA,CAAA;AAIA,gBAAA,CADC,UAAU,yBAAyB,CAAA,GAlBzB,oBAmBX,WAAA,SAAA,CAAA;AAnBW,sBAAN,gBAAA,CAPN,aAAa,EAAE,MAAM,WAAW,CAAC,GACjC,KAAK;CACJ,eAAe;CACf,KAAK,EAAE,SAAS;EAAC;EAAQ;EAAO;EAAU;CAAQ,EAAE;CACpD,KAAK,EAAE,SAAS,CAAC,QAAQ,KAAK,EAAE;CAChC,KAAK,EAAE,cAAc,KAAK;AAC5B,CAAC,CAAA,GACY,mBAAA;;;;ACvBN,IAAM,gCAAN,cAA4C,eAAoC;CACrF,OAAgB,aAAa;;;;;;;;CAS7B,MAAM,eACJ,eACA,QACgC;EAChC,MAAM,QAAiC,EAAE,cAAc;EACvD,IAAI,QAAQ,MAAM,SAAS;EAE3B,OAAO,MAAM,KAAK,KAAK,EAAE,MAAM,CAAC;CAClC;;;;;;;;CASA,MAAM,aACJ,aACA,QACgC;EAChC,MAAM,QAAiC,EAAE,YAAY;EACrD,IAAI,QAAQ,MAAM,SAAS;EAE3B,OAAO,MAAM,KAAK,KAAK,EAAE,MAAM,CAAC;CAClC;;;;;;;;CASA,MAAM,cACJ,WACA,QACgC;EAChC,MAAM,oBAAoB,MAAM,KAAK,eAAe,WAAW,MAAM;EACrE,MAAM,kBAAkB,MAAM,KAAK,aAAa,WAAW,MAAM;EAEjE,OAAO,CAAC,GAAG,mBAAmB,GAAG,eAAe;CAClD;;;;;;;;;CAUA,MAAM,OACJ,eACA,aACA,QACkB;EAMlB,QAAO,MALe,KAAK,KAAK;GAC9B,OAAO;IAAE;IAAe;IAAa;GAAO;GAC5C,OAAO;EACT,CAAC,EAAA,CAEc,SAAS;CAC1B;AACF"}
1
+ {"version":3,"file":"ProfileRelationshipCollection-BFSlTQ7J.js","names":[],"sources":["../../src/models/ProfileRelationship.ts","../../src/collections/ProfileRelationshipCollection.ts"],"sourcesContent":["/**\n * ProfileRelationship model - Connects two profiles with a relationship type\n *\n * Represents directional or reciprocal relationships between profiles.\n * Uses UUID primary key with foreign keys to profiles and relationship type.\n */\n\nimport {\n foreignKey,\n oneToMany,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type { ProfileRelationshipTerm } from './ProfileRelationshipTerm';\n\nexport interface ProfileRelationshipOptions extends SmrtObjectOptions {\n fromProfileId?: string;\n toProfileId?: string;\n typeId?: string;\n contextProfileId?: string;\n tenantId?: string | null;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get', 'create', 'delete'] },\n mcp: { include: ['list', 'get'] },\n cli: { skipApiCheck: true },\n})\nexport class ProfileRelationship extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-profiles\";\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n // id: UUID (auto-generated by SmrtObject)\n @foreignKey('Profile', { required: true })\n fromProfileId?: string; // Origin profile\n\n @foreignKey('Profile', { required: true })\n toProfileId?: string; // Target profile\n\n @foreignKey('ProfileRelationshipType', { required: true })\n typeId?: string; // Relationship type\n\n @foreignKey('Profile')\n contextProfileId?: string; // Optional tertiary context\n\n // Relationships\n @oneToMany('ProfileRelationshipTerm')\n terms: ProfileRelationshipTerm[] = [];\n\n constructor(options: ProfileRelationshipOptions = {}) {\n super(options);\n if (options.fromProfileId !== undefined)\n this.fromProfileId = options.fromProfileId;\n if (options.toProfileId !== undefined)\n this.toProfileId = options.toProfileId;\n if (options.typeId !== undefined) this.typeId = options.typeId;\n if (options.contextProfileId !== undefined)\n this.contextProfileId = options.contextProfileId;\n }\n\n /**\n * Get the relationship type slug\n *\n * @returns The slug of the relationship type\n */\n async getTypeSlug(): Promise<string> {\n const type = await this.loadRelated('typeId');\n return type?.slug || '';\n }\n\n /**\n * Add a term (time period) to this relationship\n *\n * @param startedAt - Start date of the term\n * @param endedAt - Optional end date of the term\n */\n async addTerm(startedAt: Date, endedAt?: Date): Promise<void> {\n if (!this.id) {\n throw new Error(\n 'ProfileRelationship.addTerm requires a persisted relationship (missing id)',\n );\n }\n const relationshipId = this.id;\n\n const { ProfileRelationshipTermCollection } = await import(\n '../collections/ProfileRelationshipTermCollection'\n );\n\n const termCollection = await ProfileRelationshipTermCollection.create(\n this.options,\n );\n\n const term = await termCollection.create({\n relationshipId,\n startedAt,\n endedAt,\n });\n\n await term.save();\n }\n\n /**\n * End the current active term\n *\n * @param endedAt - End date for the term\n */\n async endCurrentTerm(endedAt: Date): Promise<void> {\n const activeTerm = await this.getActiveTerm();\n if (activeTerm) {\n await activeTerm.end(endedAt);\n }\n }\n\n /**\n * Get all terms for this relationship\n *\n * @returns Array of ProfileRelationshipTerm instances\n */\n async getTerms(): Promise<ProfileRelationshipTerm[]> {\n const { ProfileRelationshipTermCollection } = await import(\n '../collections/ProfileRelationshipTermCollection'\n );\n\n const termCollection = await ProfileRelationshipTermCollection.create(\n this.options,\n );\n\n return await termCollection.getByRelationship(this.id as string);\n }\n\n /**\n * Get the active term (no end date)\n *\n * @returns Current term or null if none active\n */\n async getActiveTerm(): Promise<ProfileRelationshipTerm | null> {\n const { ProfileRelationshipTermCollection } = await import(\n '../collections/ProfileRelationshipTermCollection'\n );\n\n const termCollection = await ProfileRelationshipTermCollection.create(\n this.options,\n );\n\n return await termCollection.getActiveTerm(this.id as string);\n }\n}\n","/**\n * ProfileRelationshipCollection - Collection manager for ProfileRelationship objects\n *\n * Provides querying for relationships between profiles.\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { ProfileRelationship } from '../models/ProfileRelationship';\n\nexport class ProfileRelationshipCollection extends SmrtCollection<ProfileRelationship> {\n static readonly _itemClass = ProfileRelationship;\n\n /**\n * Get all relationships from a profile\n *\n * @param fromProfileId - The origin profile UUID\n * @param typeId - Optional filter by relationship type UUID\n * @returns Array of ProfileRelationship instances\n */\n async getFromProfile(\n fromProfileId: string,\n typeId?: string,\n ): Promise<ProfileRelationship[]> {\n const where: Record<string, unknown> = { fromProfileId };\n if (typeId) where.typeId = typeId;\n\n return await this.list({ where });\n }\n\n /**\n * Get all relationships to a profile\n *\n * @param toProfileId - The target profile UUID\n * @param typeId - Optional filter by relationship type UUID\n * @returns Array of ProfileRelationship instances\n */\n async getToProfile(\n toProfileId: string,\n typeId?: string,\n ): Promise<ProfileRelationship[]> {\n const where: Record<string, unknown> = { toProfileId };\n if (typeId) where.typeId = typeId;\n\n return await this.list({ where });\n }\n\n /**\n * Get all relationships for a profile (both directions)\n *\n * @param profileId - The profile UUID\n * @param typeId - Optional filter by relationship type UUID\n * @returns Array of ProfileRelationship instances\n */\n async getForProfile(\n profileId: string,\n typeId?: string,\n ): Promise<ProfileRelationship[]> {\n const fromRelationships = await this.getFromProfile(profileId, typeId);\n const toRelationships = await this.getToProfile(profileId, typeId);\n\n return [...fromRelationships, ...toRelationships];\n }\n\n /**\n * Check if a relationship exists between two profiles\n *\n * @param fromProfileId - The origin profile UUID\n * @param toProfileId - The target profile UUID\n * @param typeId - The relationship type UUID\n * @returns True if relationship exists\n */\n async exists(\n fromProfileId: string,\n toProfileId: string,\n typeId: string,\n ): Promise<boolean> {\n const matches = await this.list({\n where: { fromProfileId, toProfileId, typeId },\n limit: 1,\n });\n\n return matches.length > 0;\n }\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { y as __exportAll } from "./NostrIdentity-AC8fAdxe.js";
1
+ import { y as __exportAll } from "./NostrIdentity-RJaATTCt.js";
2
2
  import { SmrtCollection, SmrtObject, field, foreignKey, smrt } from "@happyvertical/smrt-core";
3
3
  //#region src/models/ProfileRelationshipTerm.ts
4
4
  var __defProp = Object.defineProperty;
@@ -110,4 +110,4 @@ var ProfileRelationshipTermCollection = class extends SmrtCollection {
110
110
  //#endregion
111
111
  export { ProfileRelationshipTermCollection_exports as n, ProfileRelationshipTerm as r, ProfileRelationshipTermCollection as t };
112
112
 
113
- //# sourceMappingURL=ProfileRelationshipTermCollection-C9J7mC7P.js.map
113
+ //# sourceMappingURL=ProfileRelationshipTermCollection-OluL8BGP.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileRelationshipTermCollection-C9J7mC7P.js","names":[],"sources":["../../src/models/ProfileRelationshipTerm.ts","../../src/collections/ProfileRelationshipTermCollection.ts"],"sourcesContent":["/**\n * ProfileRelationshipTerm model - Temporal data for relationships\n *\n * Defines the duration or terms of a specific relationship.\n * Uses UUID primary key with foreign key to ProfileRelationship.\n */\n\nimport {\n field,\n foreignKey,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\n\nexport interface ProfileRelationshipTermOptions extends SmrtObjectOptions {\n relationshipId?: string;\n startedAt?: Date;\n endedAt?: Date;\n}\n\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get'] },\n cli: { skipApiCheck: true },\n})\nexport class ProfileRelationshipTerm extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-profiles\";\n // id: UUID (auto-generated by SmrtObject)\n @foreignKey('ProfileRelationship', { required: true })\n relationshipId?: string; // References ProfileRelationship.id\n\n @field({ required: true })\n startedAt: Date = new Date(); // Start date of the term\n\n endedAt?: Date; // Optional end date\n\n constructor(options: ProfileRelationshipTermOptions = {}) {\n super(options);\n if (options.relationshipId !== undefined)\n this.relationshipId = options.relationshipId;\n if (options.startedAt) this.startedAt = options.startedAt;\n if (options.endedAt !== undefined) this.endedAt = options.endedAt;\n }\n\n /**\n * Check if this term is currently active\n *\n * @returns True if active (no end date or end date in future)\n */\n isActive(): boolean {\n if (!this.endedAt) return true;\n return this.endedAt > new Date();\n }\n\n /**\n * End this term\n *\n * @param endedAt - End date for the term (defaults to now)\n */\n async end(endedAt: Date = new Date()): Promise<void> {\n this.endedAt = endedAt;\n await this.save();\n }\n\n /**\n * Get the duration of this term in days\n *\n * @returns Duration in days\n */\n getDurationDays(): number {\n const endValue = this.endedAt || new Date();\n const diffMs = endValue.getTime() - this.startedAt.getTime();\n return Math.floor(diffMs / (1000 * 60 * 60 * 24));\n }\n}\n","/**\n * ProfileRelationshipTermCollection - Collection manager for ProfileRelationshipTerm objects\n *\n * Provides querying for relationship terms (temporal data).\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { ProfileRelationshipTerm } from '../models/ProfileRelationshipTerm';\n\nexport class ProfileRelationshipTermCollection extends SmrtCollection<ProfileRelationshipTerm> {\n static readonly _itemClass = ProfileRelationshipTerm;\n\n /**\n * Get all terms for a relationship\n *\n * @param relationshipId - The relationship UUID\n * @returns Array of ProfileRelationshipTerm instances\n */\n async getByRelationship(\n relationshipId: string,\n ): Promise<ProfileRelationshipTerm[]> {\n return await this.list({\n where: { relationshipId },\n orderBy: ['startedAt DESC'],\n });\n }\n\n /**\n * Get the active term for a relationship (no end date or future end date)\n *\n * @param relationshipId - The relationship UUID\n * @returns Active term or null\n */\n async getActiveTerm(\n relationshipId: string,\n ): Promise<ProfileRelationshipTerm | null> {\n const terms = await this.getByRelationship(relationshipId);\n\n for (const term of terms) {\n if (term.isActive()) {\n return term;\n }\n }\n\n return null;\n }\n\n /**\n * Get all historical (ended) terms for a relationship\n *\n * @param relationshipId - The relationship UUID\n * @returns Array of ended ProfileRelationshipTerm instances\n */\n async getHistoricalTerms(\n relationshipId: string,\n ): Promise<ProfileRelationshipTerm[]> {\n const terms = await this.getByRelationship(relationshipId);\n return terms.filter((term) => !term.isActive());\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA2BO,IAAM,0BAAN,cAAsC,WAAW;CAGtD;CAGA,4BAAkB,IAAI,KAAK;CAE3B;CAEA,YAAY,UAA0C,CAAC,GAAG;EACxD,MAAM,OAAO;EACb,IAAI,QAAQ,mBAAmB,KAAA,GAC7B,KAAK,iBAAiB,QAAQ;EAChC,IAAI,QAAQ,WAAW,KAAK,YAAY,QAAQ;EAChD,IAAI,QAAQ,YAAY,KAAA,GAAW,KAAK,UAAU,QAAQ;CAC5D;;;;;;CAOA,WAAoB;EAClB,IAAI,CAAC,KAAK,SAAS,OAAO;EAC1B,OAAO,KAAK,0BAAU,IAAI,KAAK;CACjC;;;;;;CAOA,MAAM,IAAI,0BAAgB,IAAI,KAAK,GAAkB;EACnD,KAAK,UAAU;EACf,MAAM,KAAK,KAAK;CAClB;;;;;;CAOA,kBAA0B;EAExB,MAAM,UADW,KAAK,2BAAW,IAAI,KAAK,EAAA,CAClB,QAAQ,IAAI,KAAK,UAAU,QAAQ;EAC3D,OAAO,KAAK,MAAM,UAAU,MAAO,KAAK,KAAK,GAAG;CAClD;AACF;AAhD0D,cAA7C,yBAAoD,mBAAkB,8BAAA;AAGjF,gBAAA,CADC,WAAW,uBAAuB,EAAE,UAAU,KAAK,CAAC,CAAA,GAF1C,wBAGX,WAAA,kBAAA,CAAA;AAGA,gBAAA,CADC,MAAM,EAAE,UAAU,KAAK,CAAC,CAAA,GALd,wBAMX,WAAA,aAAA,CAAA;AANW,0BAAN,gBAAA,CANN,KAAK;CACJ,eAAe;CACf,KAAK,EAAE,SAAS;EAAC;EAAQ;EAAO;EAAU;EAAU;CAAQ,EAAE;CAC9D,KAAK,EAAE,SAAS,CAAC,QAAQ,KAAK,EAAE;CAChC,KAAK,EAAE,cAAc,KAAK;AAC5B,CAAC,CAAA,GACY,uBAAA;;;;AClBN,IAAM,oCAAN,cAAgD,eAAwC;CAC7F,OAAgB,aAAa;;;;;;;CAQ7B,MAAM,kBACJ,gBACoC;EACpC,OAAO,MAAM,KAAK,KAAK;GACrB,OAAO,EAAE,eAAe;GACxB,SAAS,CAAC,gBAAgB;EAC5B,CAAC;CACH;;;;;;;CAQA,MAAM,cACJ,gBACyC;EACzC,MAAM,QAAQ,MAAM,KAAK,kBAAkB,cAAc;EAEzD,KAAA,MAAW,QAAQ,OACjB,IAAI,KAAK,SAAS,GAChB,OAAO;EAIX,OAAO;CACT;;;;;;;CAQA,MAAM,mBACJ,gBACoC;EAEpC,QAAO,MADa,KAAK,kBAAkB,cAAc,EAAA,CAC5C,QAAQ,SAAS,CAAC,KAAK,SAAS,CAAC;CAChD;AACF"}
1
+ {"version":3,"file":"ProfileRelationshipTermCollection-OluL8BGP.js","names":[],"sources":["../../src/models/ProfileRelationshipTerm.ts","../../src/collections/ProfileRelationshipTermCollection.ts"],"sourcesContent":["/**\n * ProfileRelationshipTerm model - Temporal data for relationships\n *\n * Defines the duration or terms of a specific relationship.\n * Uses UUID primary key with foreign key to ProfileRelationship.\n */\n\nimport {\n field,\n foreignKey,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\n\nexport interface ProfileRelationshipTermOptions extends SmrtObjectOptions {\n relationshipId?: string;\n startedAt?: Date;\n endedAt?: Date;\n}\n\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get', 'create', 'update', 'delete'] },\n mcp: { include: ['list', 'get'] },\n cli: { skipApiCheck: true },\n})\nexport class ProfileRelationshipTerm extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-profiles\";\n // id: UUID (auto-generated by SmrtObject)\n @foreignKey('ProfileRelationship', { required: true })\n relationshipId?: string; // References ProfileRelationship.id\n\n @field({ required: true })\n startedAt: Date = new Date(); // Start date of the term\n\n endedAt?: Date; // Optional end date\n\n constructor(options: ProfileRelationshipTermOptions = {}) {\n super(options);\n if (options.relationshipId !== undefined)\n this.relationshipId = options.relationshipId;\n if (options.startedAt) this.startedAt = options.startedAt;\n if (options.endedAt !== undefined) this.endedAt = options.endedAt;\n }\n\n /**\n * Check if this term is currently active\n *\n * @returns True if active (no end date or end date in future)\n */\n isActive(): boolean {\n if (!this.endedAt) return true;\n return this.endedAt > new Date();\n }\n\n /**\n * End this term\n *\n * @param endedAt - End date for the term (defaults to now)\n */\n async end(endedAt: Date = new Date()): Promise<void> {\n this.endedAt = endedAt;\n await this.save();\n }\n\n /**\n * Get the duration of this term in days\n *\n * @returns Duration in days\n */\n getDurationDays(): number {\n const endValue = this.endedAt || new Date();\n const diffMs = endValue.getTime() - this.startedAt.getTime();\n return Math.floor(diffMs / (1000 * 60 * 60 * 24));\n }\n}\n","/**\n * ProfileRelationshipTermCollection - Collection manager for ProfileRelationshipTerm objects\n *\n * Provides querying for relationship terms (temporal data).\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { ProfileRelationshipTerm } from '../models/ProfileRelationshipTerm';\n\nexport class ProfileRelationshipTermCollection extends SmrtCollection<ProfileRelationshipTerm> {\n static readonly _itemClass = ProfileRelationshipTerm;\n\n /**\n * Get all terms for a relationship\n *\n * @param relationshipId - The relationship UUID\n * @returns Array of ProfileRelationshipTerm instances\n */\n async getByRelationship(\n relationshipId: string,\n ): Promise<ProfileRelationshipTerm[]> {\n return await this.list({\n where: { relationshipId },\n orderBy: ['startedAt DESC'],\n });\n }\n\n /**\n * Get the active term for a relationship (no end date or future end date)\n *\n * @param relationshipId - The relationship UUID\n * @returns Active term or null\n */\n async getActiveTerm(\n relationshipId: string,\n ): Promise<ProfileRelationshipTerm | null> {\n const terms = await this.getByRelationship(relationshipId);\n\n for (const term of terms) {\n if (term.isActive()) {\n return term;\n }\n }\n\n return null;\n }\n\n /**\n * Get all historical (ended) terms for a relationship\n *\n * @param relationshipId - The relationship UUID\n * @returns Array of ended ProfileRelationshipTerm instances\n */\n async getHistoricalTerms(\n relationshipId: string,\n ): Promise<ProfileRelationshipTerm[]> {\n const terms = await this.getByRelationship(relationshipId);\n return terms.filter((term) => !term.isActive());\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA2BO,IAAM,0BAAN,cAAsC,WAAW;CAGtD;CAGA,4BAAkB,IAAI,KAAK;CAE3B;CAEA,YAAY,UAA0C,CAAC,GAAG;EACxD,MAAM,OAAO;EACb,IAAI,QAAQ,mBAAmB,KAAA,GAC7B,KAAK,iBAAiB,QAAQ;EAChC,IAAI,QAAQ,WAAW,KAAK,YAAY,QAAQ;EAChD,IAAI,QAAQ,YAAY,KAAA,GAAW,KAAK,UAAU,QAAQ;CAC5D;;;;;;CAOA,WAAoB;EAClB,IAAI,CAAC,KAAK,SAAS,OAAO;EAC1B,OAAO,KAAK,0BAAU,IAAI,KAAK;CACjC;;;;;;CAOA,MAAM,IAAI,0BAAgB,IAAI,KAAK,GAAkB;EACnD,KAAK,UAAU;EACf,MAAM,KAAK,KAAK;CAClB;;;;;;CAOA,kBAA0B;EAExB,MAAM,UADW,KAAK,2BAAW,IAAI,KAAK,EAAA,CAClB,QAAQ,IAAI,KAAK,UAAU,QAAQ;EAC3D,OAAO,KAAK,MAAM,UAAU,MAAO,KAAK,KAAK,GAAG;CAClD;AACF;AAhD0D,cAA7C,yBAAoD,mBAAkB,8BAAA;AAGjF,gBAAA,CADC,WAAW,uBAAuB,EAAE,UAAU,KAAK,CAAC,CAAA,GAF1C,wBAGX,WAAA,kBAAA,CAAA;AAGA,gBAAA,CADC,MAAM,EAAE,UAAU,KAAK,CAAC,CAAA,GALd,wBAMX,WAAA,aAAA,CAAA;AANW,0BAAN,gBAAA,CANN,KAAK;CACJ,eAAe;CACf,KAAK,EAAE,SAAS;EAAC;EAAQ;EAAO;EAAU;EAAU;CAAQ,EAAE;CAC9D,KAAK,EAAE,SAAS,CAAC,QAAQ,KAAK,EAAE;CAChC,KAAK,EAAE,cAAc,KAAK;AAC5B,CAAC,CAAA,GACY,uBAAA;;;;AClBN,IAAM,oCAAN,cAAgD,eAAwC;CAC7F,OAAgB,aAAa;;;;;;;CAQ7B,MAAM,kBACJ,gBACoC;EACpC,OAAO,MAAM,KAAK,KAAK;GACrB,OAAO,EAAE,eAAe;GACxB,SAAS,CAAC,gBAAgB;EAC5B,CAAC;CACH;;;;;;;CAQA,MAAM,cACJ,gBACyC;EACzC,MAAM,QAAQ,MAAM,KAAK,kBAAkB,cAAc;EAEzD,KAAA,MAAW,QAAQ,OACjB,IAAI,KAAK,SAAS,GAChB,OAAO;EAIX,OAAO;CACT;;;;;;;CAQA,MAAM,mBACJ,gBACoC;EAEpC,QAAO,MADa,KAAK,kBAAkB,cAAc,EAAA,CAC5C,QAAQ,SAAS,CAAC,KAAK,SAAS,CAAC;CAChD;AACF"}
@@ -1,4 +1,4 @@
1
- import { y as __exportAll } from "./NostrIdentity-AC8fAdxe.js";
1
+ import { y as __exportAll } from "./NostrIdentity-RJaATTCt.js";
2
2
  import { SmrtObject, field, smrt } from "@happyvertical/smrt-core";
3
3
  //#region src/models/ProfileRelationshipType.ts
4
4
  var ProfileRelationshipType_exports = /* @__PURE__ */ __exportAll({ ProfileRelationshipType: () => ProfileRelationshipType });
@@ -103,4 +103,4 @@ ProfileRelationshipType = __decorateClass([smrt({
103
103
  //#endregion
104
104
  export { ProfileRelationshipType_exports as n, ProfileRelationshipType as t };
105
105
 
106
- //# sourceMappingURL=ProfileRelationshipType-U7IwF6Wf.js.map
106
+ //# sourceMappingURL=ProfileRelationshipType-Cevy-vaF.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileRelationshipType-U7IwF6Wf.js","names":[],"sources":["../../src/models/ProfileRelationshipType.ts"],"sourcesContent":["/**\n * ProfileRelationshipType model - Lookup table for relationship types\n *\n * Defines the kinds of relationships that can exist between profiles.\n * Uses UUID primary key with unique slug for human-readable lookups.\n */\n\nimport {\n field,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport type { ReciprocalHandler } from '../types';\n\nexport interface ProfileRelationshipTypeOptions extends SmrtObjectOptions {\n slug?: string;\n name?: string;\n reciprocal?: boolean;\n}\n\n/**\n * Extend globalThis to include reciprocal handlers registry.\n * Using globalThis ensures all module instances share the same handlers,\n * which is critical in monorepos where the same package can be loaded\n * from different paths (e.g., pnpm store vs workspace symlink).\n *\n * @see https://github.com/happyvertical/smrt/issues/543\n */\ndeclare global {\n // eslint-disable-next-line no-var\n var __smrtProfileRelationshipHandlers:\n | Map<string, ReciprocalHandler>\n | undefined;\n // eslint-disable-next-line no-var\n var __smrtProfileRelationshipHandlersInitialized: boolean | undefined;\n}\n\n/**\n * Get the reciprocal handlers Map from globalThis\n */\nfunction getReciprocalHandlers(): Map<string, ReciprocalHandler> {\n if (!globalThis.__smrtProfileRelationshipHandlers) {\n globalThis.__smrtProfileRelationshipHandlers = new Map<\n string,\n ReciprocalHandler\n >();\n }\n return globalThis.__smrtProfileRelationshipHandlers;\n}\n\n/**\n * Default handlers for common reciprocal relationship patterns\n */\nconst DEFAULT_HANDLERS: Record<string, ReciprocalHandler> = {\n // Symmetric relationships (same type in both directions)\n friend: async (from, to, context) => {\n await to.addRelationship(from, 'friend', context);\n },\n\n spouse: async (from, to) => {\n await to.addRelationship(from, 'spouse');\n },\n\n partner: async (from, to, context) => {\n await to.addRelationship(from, 'partner', context);\n },\n\n colleague: async (from, to, context) => {\n await to.addRelationship(from, 'colleague', context);\n },\n\n sibling: async (from, to) => {\n await to.addRelationship(from, 'sibling');\n },\n};\n\n// Register default handlers (only once across all module instances)\nif (!globalThis.__smrtProfileRelationshipHandlersInitialized) {\n globalThis.__smrtProfileRelationshipHandlersInitialized = true;\n for (const [slug, handler] of Object.entries(DEFAULT_HANDLERS)) {\n getReciprocalHandlers().set(slug, handler);\n }\n}\n\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get'] },\n cli: { skipApiCheck: true },\n})\nexport class ProfileRelationshipType extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-profiles\";\n // id: UUID (auto-generated by SmrtObject)\n // slug is inherited from SmrtObject (auto-generated from name)\n @field({ required: true })\n name: string = '';\n\n reciprocal: boolean = true; // True for two-way relationships\n\n constructor(options: ProfileRelationshipTypeOptions = {}) {\n super(options);\n if (options.name) this.name = options.name;\n if (options.reciprocal !== undefined) this.reciprocal = options.reciprocal;\n }\n\n /**\n * Convenience method for slug-based lookup\n *\n * @param slug - The slug to search for\n * @returns ProfileRelationshipType instance or null if not found\n */\n static async getBySlug(\n _slug: string,\n ): Promise<ProfileRelationshipType | null> {\n // Will be auto-implemented by SMRT\n return null;\n }\n\n /**\n * Register a custom reciprocal handler for a relationship type\n *\n * @param slug - The relationship type slug\n * @param handler - The handler function to execute when creating reciprocal relationship\n */\n static registerReciprocalHandler(\n slug: string,\n handler: ReciprocalHandler,\n ): void {\n getReciprocalHandlers().set(slug, handler);\n }\n\n /**\n * Get the reciprocal handler for a relationship type\n *\n * @param slug - The relationship type slug\n * @returns The handler function or undefined\n */\n static getReciprocalHandler(slug: string): ReciprocalHandler | undefined {\n return getReciprocalHandlers().get(slug);\n }\n\n /**\n * Check if a relationship type is reciprocal\n *\n * @param slug - The relationship type slug\n * @returns True if reciprocal, false otherwise\n */\n static async isReciprocal(slug: string): Promise<boolean> {\n const type = await ProfileRelationshipType.getBySlug(slug);\n return type?.reciprocal || false;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAyCA,SAAS,wBAAwD;CAC/D,IAAI,CAAC,WAAW,mCACd,WAAW,oDAAoC,IAAI,IAGjD;CAEJ,OAAO,WAAW;AACpB;AAKA,IAAM,mBAAsD;CAE1D,QAAQ,OAAO,MAAM,IAAI,YAAY;EACnC,MAAM,GAAG,gBAAgB,MAAM,UAAU,OAAO;CAClD;CAEA,QAAQ,OAAO,MAAM,OAAO;EAC1B,MAAM,GAAG,gBAAgB,MAAM,QAAQ;CACzC;CAEA,SAAS,OAAO,MAAM,IAAI,YAAY;EACpC,MAAM,GAAG,gBAAgB,MAAM,WAAW,OAAO;CACnD;CAEA,WAAW,OAAO,MAAM,IAAI,YAAY;EACtC,MAAM,GAAG,gBAAgB,MAAM,aAAa,OAAO;CACrD;CAEA,SAAS,OAAO,MAAM,OAAO;EAC3B,MAAM,GAAG,gBAAgB,MAAM,SAAS;CAC1C;AACF;AAGA,IAAI,CAAC,WAAW,8CAA8C;CAC5D,WAAW,+CAA+C;CAC1D,KAAA,MAAW,CAAC,MAAM,YAAY,OAAO,QAAQ,gBAAgB,GAC3D,sBAAsB,CAAA,CAAE,IAAI,MAAM,OAAO;AAE7C;AAQO,IAAM,0BAAN,cAAsC,WAAW;CAItD,OAAe;CAEf,aAAsB;CAEtB,YAAY,UAA0C,CAAC,GAAG;EACxD,MAAM,OAAO;EACb,IAAI,QAAQ,MAAM,KAAK,OAAO,QAAQ;EACtC,IAAI,QAAQ,eAAe,KAAA,GAAW,KAAK,aAAa,QAAQ;CAClE;;;;;;;CAQA,aAAa,UACX,OACyC;EAEzC,OAAO;CACT;;;;;;;CAQA,OAAO,0BACL,MACA,SACM;EACN,sBAAsB,CAAA,CAAE,IAAI,MAAM,OAAO;CAC3C;;;;;;;CAQA,OAAO,qBAAqB,MAA6C;EACvE,OAAO,sBAAsB,CAAA,CAAE,IAAI,IAAI;CACzC;;;;;;;CAQA,aAAa,aAAa,MAAgC;EAExD,QAAO,MADY,wBAAwB,UAAU,IAAI,EAAA,EAC5C,cAAc;CAC7B;AACF;AA5D0D,cAA7C,yBAAoD,mBAAkB,8BAAA;AAIjF,gBAAA,CADC,MAAM,EAAE,UAAU,KAAK,CAAC,CAAA,GAHd,wBAIX,WAAA,QAAA,CAAA;AAJW,0BAAN,gBAAA,CANN,KAAK;CACJ,eAAe;CACf,KAAK,EAAE,SAAS;EAAC;EAAQ;EAAO;EAAU;CAAQ,EAAE;CACpD,KAAK,EAAE,SAAS,CAAC,QAAQ,KAAK,EAAE;CAChC,KAAK,EAAE,cAAc,KAAK;AAC5B,CAAC,CAAA,GACY,uBAAA"}
1
+ {"version":3,"file":"ProfileRelationshipType-Cevy-vaF.js","names":[],"sources":["../../src/models/ProfileRelationshipType.ts"],"sourcesContent":["/**\n * ProfileRelationshipType model - Lookup table for relationship types\n *\n * Defines the kinds of relationships that can exist between profiles.\n * Uses UUID primary key with unique slug for human-readable lookups.\n */\n\nimport {\n field,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport type { ReciprocalHandler } from '../types';\n\nexport interface ProfileRelationshipTypeOptions extends SmrtObjectOptions {\n slug?: string;\n name?: string;\n reciprocal?: boolean;\n}\n\n/**\n * Extend globalThis to include reciprocal handlers registry.\n * Using globalThis ensures all module instances share the same handlers,\n * which is critical in monorepos where the same package can be loaded\n * from different paths (e.g., pnpm store vs workspace symlink).\n *\n * @see https://github.com/happyvertical/smrt/issues/543\n */\ndeclare global {\n // eslint-disable-next-line no-var\n var __smrtProfileRelationshipHandlers:\n | Map<string, ReciprocalHandler>\n | undefined;\n // eslint-disable-next-line no-var\n var __smrtProfileRelationshipHandlersInitialized: boolean | undefined;\n}\n\n/**\n * Get the reciprocal handlers Map from globalThis\n */\nfunction getReciprocalHandlers(): Map<string, ReciprocalHandler> {\n if (!globalThis.__smrtProfileRelationshipHandlers) {\n globalThis.__smrtProfileRelationshipHandlers = new Map<\n string,\n ReciprocalHandler\n >();\n }\n return globalThis.__smrtProfileRelationshipHandlers;\n}\n\n/**\n * Default handlers for common reciprocal relationship patterns\n */\nconst DEFAULT_HANDLERS: Record<string, ReciprocalHandler> = {\n // Symmetric relationships (same type in both directions)\n friend: async (from, to, context) => {\n await to.addRelationship(from, 'friend', context);\n },\n\n spouse: async (from, to) => {\n await to.addRelationship(from, 'spouse');\n },\n\n partner: async (from, to, context) => {\n await to.addRelationship(from, 'partner', context);\n },\n\n colleague: async (from, to, context) => {\n await to.addRelationship(from, 'colleague', context);\n },\n\n sibling: async (from, to) => {\n await to.addRelationship(from, 'sibling');\n },\n};\n\n// Register default handlers (only once across all module instances)\nif (!globalThis.__smrtProfileRelationshipHandlersInitialized) {\n globalThis.__smrtProfileRelationshipHandlersInitialized = true;\n for (const [slug, handler] of Object.entries(DEFAULT_HANDLERS)) {\n getReciprocalHandlers().set(slug, handler);\n }\n}\n\n@smrt({\n tableStrategy: 'sti',\n api: { include: ['list', 'get', 'create', 'update'] },\n mcp: { include: ['list', 'get'] },\n cli: { skipApiCheck: true },\n})\nexport class ProfileRelationshipType extends SmrtObject { static __smrtPackage__ = \"@happyvertical/smrt-profiles\";\n // id: UUID (auto-generated by SmrtObject)\n // slug is inherited from SmrtObject (auto-generated from name)\n @field({ required: true })\n name: string = '';\n\n reciprocal: boolean = true; // True for two-way relationships\n\n constructor(options: ProfileRelationshipTypeOptions = {}) {\n super(options);\n if (options.name) this.name = options.name;\n if (options.reciprocal !== undefined) this.reciprocal = options.reciprocal;\n }\n\n /**\n * Convenience method for slug-based lookup\n *\n * @param slug - The slug to search for\n * @returns ProfileRelationshipType instance or null if not found\n */\n static async getBySlug(\n _slug: string,\n ): Promise<ProfileRelationshipType | null> {\n // Will be auto-implemented by SMRT\n return null;\n }\n\n /**\n * Register a custom reciprocal handler for a relationship type\n *\n * @param slug - The relationship type slug\n * @param handler - The handler function to execute when creating reciprocal relationship\n */\n static registerReciprocalHandler(\n slug: string,\n handler: ReciprocalHandler,\n ): void {\n getReciprocalHandlers().set(slug, handler);\n }\n\n /**\n * Get the reciprocal handler for a relationship type\n *\n * @param slug - The relationship type slug\n * @returns The handler function or undefined\n */\n static getReciprocalHandler(slug: string): ReciprocalHandler | undefined {\n return getReciprocalHandlers().get(slug);\n }\n\n /**\n * Check if a relationship type is reciprocal\n *\n * @param slug - The relationship type slug\n * @returns True if reciprocal, false otherwise\n */\n static async isReciprocal(slug: string): Promise<boolean> {\n const type = await ProfileRelationshipType.getBySlug(slug);\n return type?.reciprocal || false;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAyCA,SAAS,wBAAwD;CAC/D,IAAI,CAAC,WAAW,mCACd,WAAW,oDAAoC,IAAI,IAGjD;CAEJ,OAAO,WAAW;AACpB;AAKA,IAAM,mBAAsD;CAE1D,QAAQ,OAAO,MAAM,IAAI,YAAY;EACnC,MAAM,GAAG,gBAAgB,MAAM,UAAU,OAAO;CAClD;CAEA,QAAQ,OAAO,MAAM,OAAO;EAC1B,MAAM,GAAG,gBAAgB,MAAM,QAAQ;CACzC;CAEA,SAAS,OAAO,MAAM,IAAI,YAAY;EACpC,MAAM,GAAG,gBAAgB,MAAM,WAAW,OAAO;CACnD;CAEA,WAAW,OAAO,MAAM,IAAI,YAAY;EACtC,MAAM,GAAG,gBAAgB,MAAM,aAAa,OAAO;CACrD;CAEA,SAAS,OAAO,MAAM,OAAO;EAC3B,MAAM,GAAG,gBAAgB,MAAM,SAAS;CAC1C;AACF;AAGA,IAAI,CAAC,WAAW,8CAA8C;CAC5D,WAAW,+CAA+C;CAC1D,KAAA,MAAW,CAAC,MAAM,YAAY,OAAO,QAAQ,gBAAgB,GAC3D,sBAAsB,CAAA,CAAE,IAAI,MAAM,OAAO;AAE7C;AAQO,IAAM,0BAAN,cAAsC,WAAW;CAItD,OAAe;CAEf,aAAsB;CAEtB,YAAY,UAA0C,CAAC,GAAG;EACxD,MAAM,OAAO;EACb,IAAI,QAAQ,MAAM,KAAK,OAAO,QAAQ;EACtC,IAAI,QAAQ,eAAe,KAAA,GAAW,KAAK,aAAa,QAAQ;CAClE;;;;;;;CAQA,aAAa,UACX,OACyC;EAEzC,OAAO;CACT;;;;;;;CAQA,OAAO,0BACL,MACA,SACM;EACN,sBAAsB,CAAA,CAAE,IAAI,MAAM,OAAO;CAC3C;;;;;;;CAQA,OAAO,qBAAqB,MAA6C;EACvE,OAAO,sBAAsB,CAAA,CAAE,IAAI,IAAI;CACzC;;;;;;;CAQA,aAAa,aAAa,MAAgC;EAExD,QAAO,MADY,wBAAwB,UAAU,IAAI,EAAA,EAC5C,cAAc;CAC7B;AACF;AA5D0D,cAA7C,yBAAoD,mBAAkB,8BAAA;AAIjF,gBAAA,CADC,MAAM,EAAE,UAAU,KAAK,CAAC,CAAA,GAHd,wBAIX,WAAA,QAAA,CAAA;AAJW,0BAAN,gBAAA,CANN,KAAK;CACJ,eAAe;CACf,KAAK,EAAE,SAAS;EAAC;EAAQ;EAAO;EAAU;CAAQ,EAAE;CACpD,KAAK,EAAE,SAAS,CAAC,QAAQ,KAAK,EAAE;CAChC,KAAK,EAAE,cAAc,KAAK;AAC5B,CAAC,CAAA,GACY,uBAAA"}
@@ -1,5 +1,5 @@
1
- import { y as __exportAll } from "./NostrIdentity-AC8fAdxe.js";
2
- import { t as ProfileRelationshipType } from "./ProfileRelationshipType-U7IwF6Wf.js";
1
+ import { y as __exportAll } from "./NostrIdentity-RJaATTCt.js";
2
+ import { t as ProfileRelationshipType } from "./ProfileRelationshipType-Cevy-vaF.js";
3
3
  import { SmrtCollection } from "@happyvertical/smrt-core";
4
4
  //#region src/collections/ProfileRelationshipTypeCollection.ts
5
5
  var ProfileRelationshipTypeCollection_exports = /* @__PURE__ */ __exportAll({ ProfileRelationshipTypeCollection: () => ProfileRelationshipTypeCollection });
@@ -51,4 +51,4 @@ var ProfileRelationshipTypeCollection = class extends SmrtCollection {
51
51
  //#endregion
52
52
  export { ProfileRelationshipTypeCollection_exports as n, ProfileRelationshipTypeCollection as t };
53
53
 
54
- //# sourceMappingURL=ProfileRelationshipTypeCollection-_n22WqTb.js.map
54
+ //# sourceMappingURL=ProfileRelationshipTypeCollection-BRBpX00F.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileRelationshipTypeCollection-_n22WqTb.js","names":[],"sources":["../../src/collections/ProfileRelationshipTypeCollection.ts"],"sourcesContent":["/**\n * ProfileRelationshipTypeCollection - Collection manager for ProfileRelationshipType objects\n *\n * Provides querying for relationship type lookup table.\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { ProfileRelationshipType } from '../models/ProfileRelationshipType';\n\nexport class ProfileRelationshipTypeCollection extends SmrtCollection<ProfileRelationshipType> {\n static readonly _itemClass = ProfileRelationshipType;\n\n /**\n * Get relationship type by slug\n *\n * @param slug - The slug to search for\n * @returns ProfileRelationshipType instance or null\n */\n async getBySlug(slug: string): Promise<ProfileRelationshipType | null> {\n return await this.get({ slug });\n }\n\n /**\n * Get or create a relationship type by slug\n *\n * @param slug - The slug to search for\n * @param defaults - Default values if creating\n * @returns ProfileRelationshipType instance\n */\n async getOrCreateBySlug(\n slug: string,\n defaults: { name: string; reciprocal?: boolean },\n ): Promise<ProfileRelationshipType> {\n const existing = await this.getBySlug(slug);\n if (existing) return existing;\n\n const relationshipType = await this.create({ slug, ...defaults });\n await relationshipType.save();\n return relationshipType;\n }\n\n /**\n * Get all reciprocal relationship types\n *\n * @returns Array of reciprocal ProfileRelationshipType instances\n */\n async getReciprocal(): Promise<ProfileRelationshipType[]> {\n return await this.list({ where: { reciprocal: true } });\n }\n\n /**\n * Get all directional (non-reciprocal) relationship types\n *\n * @returns Array of directional ProfileRelationshipType instances\n */\n async getDirectional(): Promise<ProfileRelationshipType[]> {\n return await this.list({ where: { reciprocal: false } });\n }\n}\n"],"mappings":";;;;;AASO,IAAM,oCAAN,cAAgD,eAAwC;CAC7F,OAAgB,aAAa;;;;;;;CAQ7B,MAAM,UAAU,MAAuD;EACrE,OAAO,MAAM,KAAK,IAAI,EAAE,KAAK,CAAC;CAChC;;;;;;;;CASA,MAAM,kBACJ,MACA,UACkC;EAClC,MAAM,WAAW,MAAM,KAAK,UAAU,IAAI;EAC1C,IAAI,UAAU,OAAO;EAErB,MAAM,mBAAmB,MAAM,KAAK,OAAO;GAAE;GAAM,GAAG;EAAS,CAAC;EAChE,MAAM,iBAAiB,KAAK;EAC5B,OAAO;CACT;;;;;;CAOA,MAAM,gBAAoD;EACxD,OAAO,MAAM,KAAK,KAAK,EAAE,OAAO,EAAE,YAAY,KAAK,EAAE,CAAC;CACxD;;;;;;CAOA,MAAM,iBAAqD;EACzD,OAAO,MAAM,KAAK,KAAK,EAAE,OAAO,EAAE,YAAY,MAAM,EAAE,CAAC;CACzD;AACF"}
1
+ {"version":3,"file":"ProfileRelationshipTypeCollection-BRBpX00F.js","names":[],"sources":["../../src/collections/ProfileRelationshipTypeCollection.ts"],"sourcesContent":["/**\n * ProfileRelationshipTypeCollection - Collection manager for ProfileRelationshipType objects\n *\n * Provides querying for relationship type lookup table.\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { ProfileRelationshipType } from '../models/ProfileRelationshipType';\n\nexport class ProfileRelationshipTypeCollection extends SmrtCollection<ProfileRelationshipType> {\n static readonly _itemClass = ProfileRelationshipType;\n\n /**\n * Get relationship type by slug\n *\n * @param slug - The slug to search for\n * @returns ProfileRelationshipType instance or null\n */\n async getBySlug(slug: string): Promise<ProfileRelationshipType | null> {\n return await this.get({ slug });\n }\n\n /**\n * Get or create a relationship type by slug\n *\n * @param slug - The slug to search for\n * @param defaults - Default values if creating\n * @returns ProfileRelationshipType instance\n */\n async getOrCreateBySlug(\n slug: string,\n defaults: { name: string; reciprocal?: boolean },\n ): Promise<ProfileRelationshipType> {\n const existing = await this.getBySlug(slug);\n if (existing) return existing;\n\n const relationshipType = await this.create({ slug, ...defaults });\n await relationshipType.save();\n return relationshipType;\n }\n\n /**\n * Get all reciprocal relationship types\n *\n * @returns Array of reciprocal ProfileRelationshipType instances\n */\n async getReciprocal(): Promise<ProfileRelationshipType[]> {\n return await this.list({ where: { reciprocal: true } });\n }\n\n /**\n * Get all directional (non-reciprocal) relationship types\n *\n * @returns Array of directional ProfileRelationshipType instances\n */\n async getDirectional(): Promise<ProfileRelationshipType[]> {\n return await this.list({ where: { reciprocal: false } });\n }\n}\n"],"mappings":";;;;;AASO,IAAM,oCAAN,cAAgD,eAAwC;CAC7F,OAAgB,aAAa;;;;;;;CAQ7B,MAAM,UAAU,MAAuD;EACrE,OAAO,MAAM,KAAK,IAAI,EAAE,KAAK,CAAC;CAChC;;;;;;;;CASA,MAAM,kBACJ,MACA,UACkC;EAClC,MAAM,WAAW,MAAM,KAAK,UAAU,IAAI;EAC1C,IAAI,UAAU,OAAO;EAErB,MAAM,mBAAmB,MAAM,KAAK,OAAO;GAAE;GAAM,GAAG;EAAS,CAAC;EAChE,MAAM,iBAAiB,KAAK;EAC5B,OAAO;CACT;;;;;;CAOA,MAAM,gBAAoD;EACxD,OAAO,MAAM,KAAK,KAAK,EAAE,OAAO,EAAE,YAAY,KAAK,EAAE,CAAC;CACxD;;;;;;CAOA,MAAM,iBAAqD;EACzD,OAAO,MAAM,KAAK,KAAK,EAAE,OAAO,EAAE,YAAY,MAAM,EAAE,CAAC;CACzD;AACF"}
@@ -1,5 +1,5 @@
1
- import { y as __exportAll } from "./NostrIdentity-AC8fAdxe.js";
2
- import { m as ProfileType } from "./ProfileCollection-C4INKh7Y.js";
1
+ import { y as __exportAll } from "./NostrIdentity-RJaATTCt.js";
2
+ import { m as ProfileType } from "./ProfileCollection-CMS9dFc0.js";
3
3
  import { SmrtCollection } from "@happyvertical/smrt-core";
4
4
  import { isSystemContext, withTenantGlobalRead } from "@happyvertical/smrt-tenancy";
5
5
  //#region src/collections/ProfileTypeCollection.ts
@@ -97,4 +97,4 @@ var ProfileTypeCollection = class extends SmrtCollection {
97
97
  //#endregion
98
98
  export { ProfileTypeCollection_exports as n, ProfileTypeCollection as t };
99
99
 
100
- //# sourceMappingURL=ProfileTypeCollection-B7kwi1mU.js.map
100
+ //# sourceMappingURL=ProfileTypeCollection-B7m698Bl.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileTypeCollection-B7kwi1mU.js","names":[],"sources":["../../src/collections/ProfileTypeCollection.ts"],"sourcesContent":["/**\n * ProfileTypeCollection - Collection manager for ProfileType objects\n *\n * Provides querying for profile type lookup table.\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport {\n isSystemContext,\n withTenantGlobalRead,\n} from '@happyvertical/smrt-tenancy';\nimport { ProfileType } from '../models/ProfileType';\n\nfunction isPostgresUrl(url: string | undefined): boolean {\n return /^postgres(?:ql)?:/iu.test(url ?? '');\n}\n\nexport class ProfileTypeCollection extends SmrtCollection<ProfileType> {\n static readonly _itemClass = ProfileType;\n\n /**\n * Get profile type by slug\n *\n * @param slug - The slug to search for\n * @returns ProfileType instance or null\n */\n async getBySlug(slug: string): Promise<ProfileType | null> {\n return await this.get({ slug });\n }\n\n /**\n * Resolve one profile type available to a tenant.\n *\n * Profile types may be tenant-owned or global lookup rows. A normal point\n * read under an active tenant context intentionally cannot see a global\n * row, so this uses the bounded tenant-plus-globals list capability. The\n * capability preserves the active actor and fails closed when the requested\n * tenant differs from the active tenant context.\n */\n async getAvailableById(\n id: string,\n tenantId: string,\n ): Promise<ProfileType | null> {\n const rows = await withTenantGlobalRead(tenantId, () =>\n this.list({ where: { id }, limit: 1 }),\n );\n return rows[0] ?? null;\n }\n\n /**\n * Get or create a profile type by slug\n *\n * @param slug - The slug to search for\n * @param defaults - Default values if creating\n * @returns ProfileType instance\n */\n async getOrCreateBySlug(\n slug: string,\n defaults: { name: string; description?: string },\n ): Promise<ProfileType> {\n const existing = await this.getBySlug(slug);\n if (existing) return existing;\n\n const profileType = await this.create({ slug, ...defaults });\n await profileType.save();\n return profileType;\n }\n\n /**\n * Atomically create or load a global ProfileType from trusted system code.\n *\n * This intentionally bypasses tenant auto-population and therefore refuses\n * to run outside an explicit `withSystemContext()` boundary.\n */\n async getOrCreateGlobalBySlug(\n slug: string,\n defaults: { name: string; description?: string },\n ): Promise<ProfileType> {\n if (!isSystemContext()) {\n throw new Error(\n 'Global ProfileType creation requires an explicit system context.',\n );\n }\n\n const existing = await this.loadGlobalBySlug(slug);\n if (existing) return existing;\n\n // A plain SMRT create is an upsert and may replace the winning row's id\n // when two first-login transactions race. Keep the canonical id stable by\n // using a cross-adapter insert-if-absent and then hydrating the winner.\n //\n // The table's unique key is `(tenant_id, slug, context, _meta_type)` since\n // smrt#2360, and a global row's NULL tenant never conflicts at the\n // database level (NULLs are distinct in a unique index), so a raw\n // `ON CONFLICT (…) DO NOTHING` can no longer arbitrate this race. Serialize\n // the global create per slug instead: PostgreSQL through a\n // transaction-scoped advisory lock (the arbiter the SDK's null-aware\n // upsert uses too); the embedded engines through the provisioning\n // coordinator's in-process lock plus their single-writer transactions.\n const insertIfAbsent = async (db: typeof this.db): Promise<void> => {\n if (isPostgresUrl(db.url)) {\n await db.query(\n 'SELECT pg_advisory_xact_lock(hashtext(?), hashtext(?))',\n '@happyvertical/smrt-profiles:profile_types:global',\n slug,\n );\n }\n await db.query(\n `INSERT INTO profile_types\n (id, slug, context, _meta_type, tenant_id, name, description)\n SELECT ?, ?, '', '@happyvertical/smrt-profiles:ProfileType', NULL, ?, ?\n WHERE NOT EXISTS (\n SELECT 1 FROM profile_types\n WHERE slug = ?\n AND context = ''\n AND _meta_type = '@happyvertical/smrt-profiles:ProfileType'\n AND tenant_id IS NULL\n )`,\n crypto.randomUUID(),\n slug,\n defaults.name,\n defaults.description ?? null,\n slug,\n );\n };\n\n // A transaction-scoped advisory lock only spans both statements when they\n // run on one transaction. On PostgreSQL, any handle that is NOT already\n // transaction-bound may route each query to a different pooled connection\n // — a root adapter (`beginTransaction` present) and equally a view\n // wrapper (only `transaction()` present) — so open a transaction for the\n // pair on every such handle. A transaction-bound handle (fingerprint: it\n // carries `commit`) already keeps both statements on one client and must\n // not nest. Embedded engines run directly: a nested root transaction\n // would deadlock their single-writer adapters, and the provisioning\n // coordinator's in-process lock already serializes them.\n const isTransactionBound =\n typeof (this.db as { commit?: unknown }).commit === 'function';\n if (\n isPostgresUrl(this.db.url) &&\n !isTransactionBound &&\n typeof this.db.transaction === 'function'\n ) {\n await this.db.transaction((tx) => insertIfAbsent(tx));\n } else {\n await insertIfAbsent(this.db);\n }\n const profileType = await this.loadGlobalBySlug(slug);\n if (!profileType) {\n throw new Error(\n `Global ProfileType '${slug}' could not be created or loaded.`,\n );\n }\n return profileType;\n }\n\n private async loadGlobalBySlug(slug: string): Promise<ProfileType | null> {\n const result = await this.db.query(\n `SELECT CAST(id AS VARCHAR) AS id\n FROM profile_types\n WHERE slug = ?\n AND context = ''\n AND _meta_type = '@happyvertical/smrt-profiles:ProfileType'\n AND tenant_id IS NULL\n LIMIT 1`,\n slug,\n );\n const id = result.rows[0]?.id;\n if (typeof id !== 'string') return null;\n const profileType = await this.get({ id });\n // @happyvertical/sql 0.88 exposes native DuckDB UUID result values as an\n // internal object. The cast above is the portable identity boundary for\n // this lookup; retain it on the hydrated object used by provisioning.\n if (profileType) profileType.id = id;\n return profileType;\n }\n}\n"],"mappings":";;;;;;AAaA,SAAS,cAAc,KAAkC;CACvD,OAAO,sBAAsB,KAAK,OAAO,EAAE;AAC7C;AAEO,IAAM,wBAAN,cAAoC,eAA4B;CACrE,OAAgB,aAAa;;;;;;;CAQ7B,MAAM,UAAU,MAA2C;EACzD,OAAO,MAAM,KAAK,IAAI,EAAE,KAAK,CAAC;CAChC;;;;;;;;;;CAWA,MAAM,iBACJ,IACA,UAC6B;EAI7B,QAAO,MAHY,qBAAqB,gBACtC,KAAK,KAAK;GAAE,OAAO,EAAE,GAAG;GAAG,OAAO;EAAE,CAAC,CACvC,EAAA,CACY,MAAM;CACpB;;;;;;;;CASA,MAAM,kBACJ,MACA,UACsB;EACtB,MAAM,WAAW,MAAM,KAAK,UAAU,IAAI;EAC1C,IAAI,UAAU,OAAO;EAErB,MAAM,cAAc,MAAM,KAAK,OAAO;GAAE;GAAM,GAAG;EAAS,CAAC;EAC3D,MAAM,YAAY,KAAK;EACvB,OAAO;CACT;;;;;;;CAQA,MAAM,wBACJ,MACA,UACsB;EACtB,IAAI,CAAC,gBAAgB,GACnB,MAAM,IAAI,MACR,kEACF;EAGF,MAAM,WAAW,MAAM,KAAK,iBAAiB,IAAI;EACjD,IAAI,UAAU,OAAO;EAcrB,MAAM,iBAAiB,OAAO,OAAsC;GAClE,IAAI,cAAc,GAAG,GAAG,GACtB,MAAM,GAAG,MACP,0DACA,qDACA,IACF;GAEF,MAAM,GAAG,MACP;;;;;;;;;aAUA,OAAO,WAAW,GAClB,MACA,SAAS,MACT,SAAS,eAAe,MACxB,IACF;EACF;EAYA,MAAM,qBACJ,OAAQ,KAAK,GAA4B,WAAW;EACtD,IACE,cAAc,KAAK,GAAG,GAAG,KACzB,CAAC,sBACD,OAAO,KAAK,GAAG,gBAAgB,YAE/B,MAAM,KAAK,GAAG,aAAa,OAAO,eAAe,EAAE,CAAC;OAEpD,MAAM,eAAe,KAAK,EAAE;EAE9B,MAAM,cAAc,MAAM,KAAK,iBAAiB,IAAI;EACpD,IAAI,CAAC,aACH,MAAM,IAAI,MACR,uBAAuB,KAAI,kCAC7B;EAEF,OAAO;CACT;CAEA,MAAc,iBAAiB,MAA2C;EAWxE,MAAM,MAAK,MAVU,KAAK,GAAG,MAC3B;;;;;;iBAOA,IACF,EAAA,CACkB,KAAK,EAAC,EAAG;EAC3B,IAAI,OAAO,OAAO,UAAU,OAAO;EACnC,MAAM,cAAc,MAAM,KAAK,IAAI,EAAE,GAAG,CAAC;EAIzC,IAAI,aAAa,YAAY,KAAK;EAClC,OAAO;CACT;AACF"}
1
+ {"version":3,"file":"ProfileTypeCollection-B7m698Bl.js","names":[],"sources":["../../src/collections/ProfileTypeCollection.ts"],"sourcesContent":["/**\n * ProfileTypeCollection - Collection manager for ProfileType objects\n *\n * Provides querying for profile type lookup table.\n */\n\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport {\n isSystemContext,\n withTenantGlobalRead,\n} from '@happyvertical/smrt-tenancy';\nimport { ProfileType } from '../models/ProfileType';\n\nfunction isPostgresUrl(url: string | undefined): boolean {\n return /^postgres(?:ql)?:/iu.test(url ?? '');\n}\n\nexport class ProfileTypeCollection extends SmrtCollection<ProfileType> {\n static readonly _itemClass = ProfileType;\n\n /**\n * Get profile type by slug\n *\n * @param slug - The slug to search for\n * @returns ProfileType instance or null\n */\n async getBySlug(slug: string): Promise<ProfileType | null> {\n return await this.get({ slug });\n }\n\n /**\n * Resolve one profile type available to a tenant.\n *\n * Profile types may be tenant-owned or global lookup rows. A normal point\n * read under an active tenant context intentionally cannot see a global\n * row, so this uses the bounded tenant-plus-globals list capability. The\n * capability preserves the active actor and fails closed when the requested\n * tenant differs from the active tenant context.\n */\n async getAvailableById(\n id: string,\n tenantId: string,\n ): Promise<ProfileType | null> {\n const rows = await withTenantGlobalRead(tenantId, () =>\n this.list({ where: { id }, limit: 1 }),\n );\n return rows[0] ?? null;\n }\n\n /**\n * Get or create a profile type by slug\n *\n * @param slug - The slug to search for\n * @param defaults - Default values if creating\n * @returns ProfileType instance\n */\n async getOrCreateBySlug(\n slug: string,\n defaults: { name: string; description?: string },\n ): Promise<ProfileType> {\n const existing = await this.getBySlug(slug);\n if (existing) return existing;\n\n const profileType = await this.create({ slug, ...defaults });\n await profileType.save();\n return profileType;\n }\n\n /**\n * Atomically create or load a global ProfileType from trusted system code.\n *\n * This intentionally bypasses tenant auto-population and therefore refuses\n * to run outside an explicit `withSystemContext()` boundary.\n */\n async getOrCreateGlobalBySlug(\n slug: string,\n defaults: { name: string; description?: string },\n ): Promise<ProfileType> {\n if (!isSystemContext()) {\n throw new Error(\n 'Global ProfileType creation requires an explicit system context.',\n );\n }\n\n const existing = await this.loadGlobalBySlug(slug);\n if (existing) return existing;\n\n // A plain SMRT create is an upsert and may replace the winning row's id\n // when two first-login transactions race. Keep the canonical id stable by\n // using a cross-adapter insert-if-absent and then hydrating the winner.\n //\n // The table's unique key is `(tenant_id, slug, context, _meta_type)` since\n // smrt#2360, and a global row's NULL tenant never conflicts at the\n // database level (NULLs are distinct in a unique index), so a raw\n // `ON CONFLICT (…) DO NOTHING` can no longer arbitrate this race. Serialize\n // the global create per slug instead: PostgreSQL through a\n // transaction-scoped advisory lock (the arbiter the SDK's null-aware\n // upsert uses too); the embedded engines through the provisioning\n // coordinator's in-process lock plus their single-writer transactions.\n const insertIfAbsent = async (db: typeof this.db): Promise<void> => {\n if (isPostgresUrl(db.url)) {\n await db.query(\n 'SELECT pg_advisory_xact_lock(hashtext(?), hashtext(?))',\n '@happyvertical/smrt-profiles:profile_types:global',\n slug,\n );\n }\n await db.query(\n `INSERT INTO profile_types\n (id, slug, context, _meta_type, tenant_id, name, description)\n SELECT ?, ?, '', '@happyvertical/smrt-profiles:ProfileType', NULL, ?, ?\n WHERE NOT EXISTS (\n SELECT 1 FROM profile_types\n WHERE slug = ?\n AND context = ''\n AND _meta_type = '@happyvertical/smrt-profiles:ProfileType'\n AND tenant_id IS NULL\n )`,\n crypto.randomUUID(),\n slug,\n defaults.name,\n defaults.description ?? null,\n slug,\n );\n };\n\n // A transaction-scoped advisory lock only spans both statements when they\n // run on one transaction. On PostgreSQL, any handle that is NOT already\n // transaction-bound may route each query to a different pooled connection\n // — a root adapter (`beginTransaction` present) and equally a view\n // wrapper (only `transaction()` present) — so open a transaction for the\n // pair on every such handle. A transaction-bound handle (fingerprint: it\n // carries `commit`) already keeps both statements on one client and must\n // not nest. Embedded engines run directly: a nested root transaction\n // would deadlock their single-writer adapters, and the provisioning\n // coordinator's in-process lock already serializes them.\n const isTransactionBound =\n typeof (this.db as { commit?: unknown }).commit === 'function';\n if (\n isPostgresUrl(this.db.url) &&\n !isTransactionBound &&\n typeof this.db.transaction === 'function'\n ) {\n await this.db.transaction((tx) => insertIfAbsent(tx));\n } else {\n await insertIfAbsent(this.db);\n }\n const profileType = await this.loadGlobalBySlug(slug);\n if (!profileType) {\n throw new Error(\n `Global ProfileType '${slug}' could not be created or loaded.`,\n );\n }\n return profileType;\n }\n\n private async loadGlobalBySlug(slug: string): Promise<ProfileType | null> {\n const result = await this.db.query(\n `SELECT CAST(id AS VARCHAR) AS id\n FROM profile_types\n WHERE slug = ?\n AND context = ''\n AND _meta_type = '@happyvertical/smrt-profiles:ProfileType'\n AND tenant_id IS NULL\n LIMIT 1`,\n slug,\n );\n const id = result.rows[0]?.id;\n if (typeof id !== 'string') return null;\n const profileType = await this.get({ id });\n // @happyvertical/sql 0.88 exposes native DuckDB UUID result values as an\n // internal object. The cast above is the portable identity boundary for\n // this lookup; retain it on the hydrated object used by provisioning.\n if (profileType) profileType.id = id;\n return profileType;\n }\n}\n"],"mappings":";;;;;;AAaA,SAAS,cAAc,KAAkC;CACvD,OAAO,sBAAsB,KAAK,OAAO,EAAE;AAC7C;AAEO,IAAM,wBAAN,cAAoC,eAA4B;CACrE,OAAgB,aAAa;;;;;;;CAQ7B,MAAM,UAAU,MAA2C;EACzD,OAAO,MAAM,KAAK,IAAI,EAAE,KAAK,CAAC;CAChC;;;;;;;;;;CAWA,MAAM,iBACJ,IACA,UAC6B;EAI7B,QAAO,MAHY,qBAAqB,gBACtC,KAAK,KAAK;GAAE,OAAO,EAAE,GAAG;GAAG,OAAO;EAAE,CAAC,CACvC,EAAA,CACY,MAAM;CACpB;;;;;;;;CASA,MAAM,kBACJ,MACA,UACsB;EACtB,MAAM,WAAW,MAAM,KAAK,UAAU,IAAI;EAC1C,IAAI,UAAU,OAAO;EAErB,MAAM,cAAc,MAAM,KAAK,OAAO;GAAE;GAAM,GAAG;EAAS,CAAC;EAC3D,MAAM,YAAY,KAAK;EACvB,OAAO;CACT;;;;;;;CAQA,MAAM,wBACJ,MACA,UACsB;EACtB,IAAI,CAAC,gBAAgB,GACnB,MAAM,IAAI,MACR,kEACF;EAGF,MAAM,WAAW,MAAM,KAAK,iBAAiB,IAAI;EACjD,IAAI,UAAU,OAAO;EAcrB,MAAM,iBAAiB,OAAO,OAAsC;GAClE,IAAI,cAAc,GAAG,GAAG,GACtB,MAAM,GAAG,MACP,0DACA,qDACA,IACF;GAEF,MAAM,GAAG,MACP;;;;;;;;;aAUA,OAAO,WAAW,GAClB,MACA,SAAS,MACT,SAAS,eAAe,MACxB,IACF;EACF;EAYA,MAAM,qBACJ,OAAQ,KAAK,GAA4B,WAAW;EACtD,IACE,cAAc,KAAK,GAAG,GAAG,KACzB,CAAC,sBACD,OAAO,KAAK,GAAG,gBAAgB,YAE/B,MAAM,KAAK,GAAG,aAAa,OAAO,eAAe,EAAE,CAAC;OAEpD,MAAM,eAAe,KAAK,EAAE;EAE9B,MAAM,cAAc,MAAM,KAAK,iBAAiB,IAAI;EACpD,IAAI,CAAC,aACH,MAAM,IAAI,MACR,uBAAuB,KAAI,kCAC7B;EAEF,OAAO;CACT;CAEA,MAAc,iBAAiB,MAA2C;EAWxE,MAAM,MAAK,MAVU,KAAK,GAAG,MAC3B;;;;;;iBAOA,IACF,EAAA,CACkB,KAAK,EAAC,EAAG;EAC3B,IAAI,OAAO,OAAO,UAAU,OAAO;EACnC,MAAM,cAAc,MAAM,KAAK,IAAI,EAAE,GAAG,CAAC;EAIzC,IAAI,aAAa,YAAY,KAAK;EAClC,OAAO;CACT;AACF"}
@@ -1,7 +1,7 @@
1
- import { y as __exportAll } from "./NostrIdentity-AC8fAdxe.js";
2
- import { a as Profile, f as saveOidcRaceArbiter, n as ProfileCollection } from "./ProfileCollection-C4INKh7Y.js";
3
- import { t as ProfileTypeCollection } from "./ProfileTypeCollection-B7kwi1mU.js";
4
- import { t as OidcIdentity } from "./OidcIdentity-BUblgQLs.js";
1
+ import { y as __exportAll } from "./NostrIdentity-RJaATTCt.js";
2
+ import { a as Profile, f as saveOidcRaceArbiter, n as ProfileCollection } from "./ProfileCollection-CMS9dFc0.js";
3
+ import { t as ProfileTypeCollection } from "./ProfileTypeCollection-B7m698Bl.js";
4
+ import { t as OidcIdentity } from "./OidcIdentity-MVVO3MfG.js";
5
5
  import { smrt } from "@happyvertical/smrt-core";
6
6
  //#region src/models/ProfileTypes.ts
7
7
  var ProfileTypes_exports = /* @__PURE__ */ __exportAll({
@@ -85,4 +85,4 @@ function requireProvisioningId(value, label) {
85
85
  //#endregion
86
86
  export { Person as a, Organization as i, insertOidcProvisioningIdentity as n, ProfileTypes_exports as o, Bot as r, createOidcProvisioningPerson as t };
87
87
 
88
- //# sourceMappingURL=oidcProvisioningPrimitives-DNP9EZlU.js.map
88
+ //# sourceMappingURL=oidcProvisioningPrimitives-Dl9qIcYS.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"oidcProvisioningPrimitives-DNP9EZlU.js","names":[],"sources":["../../src/models/ProfileTypes.ts","../../src/auth/oidcProvisioningPrimitives.ts"],"sourcesContent":["/**\n * Profile subclasses for STI (Single Table Inheritance)\n *\n * These classes inherit from Profile and automatically use the shared\n * profiles table with _meta_type discriminator.\n */\n\nimport { smrt } from '@happyvertical/smrt-core';\nimport { Profile, type ProfileOptions } from './Profile';\n\n/**\n * Person profile type\n *\n * Represents individual people/users.\n */\n@smrt({\n tableStrategy: 'sti',\n})\nexport class Person extends Profile { static __smrtPackage__ = \"@happyvertical/smrt-profiles\";\n constructor(options: ProfileOptions = {}) {\n super(options);\n // Person-specific initialization can go here\n }\n}\n\n/**\n * Organization profile type\n *\n * Represents companies, groups, institutions, and other organizational entities.\n */\n@smrt({\n tableStrategy: 'sti',\n})\nexport class Organization extends Profile { static __smrtPackage__ = \"@happyvertical/smrt-profiles\";\n constructor(options: ProfileOptions = {}) {\n super(options);\n // Organization-specific initialization can go here\n }\n}\n\n/**\n * Bot profile type\n *\n * Represents automated agents, bots, and AI entities.\n */\n@smrt({\n tableStrategy: 'sti',\n})\nexport class Bot extends Profile { static __smrtPackage__ = \"@happyvertical/smrt-profiles\";\n constructor(options: ProfileOptions = {}) {\n super(options);\n // Bot-specific initialization can go here\n }\n}\n","import type { getDatabase } from '@happyvertical/sql';\nimport { ProfileCollection } from '../collections/ProfileCollection';\nimport { ProfileTypeCollection } from '../collections/ProfileTypeCollection';\nimport { OidcIdentity } from '../models/OidcIdentity';\nimport type { Profile } from '../models/Profile';\nimport { Person } from '../models/ProfileTypes';\nimport { saveOidcRaceArbiter } from './oidcProvisioningCoordinator';\n\ntype DatabaseInterface = Awaited<ReturnType<typeof getDatabase>>;\n\nexport interface OidcProvisioningPersonInput {\n email?: string;\n name?: string;\n preferredUsername?: string;\n subject: string;\n}\n\nexport interface OidcProvisioningIdentityInput {\n email?: string;\n issuer: string;\n profileId: string;\n provider: string;\n subject: string;\n}\n\n/** Create and reserve a fresh global Person inside the caller's transaction. */\nexport async function createOidcProvisioningPerson(\n db: DatabaseInterface,\n input: OidcProvisioningPersonInput,\n): Promise<Profile> {\n const typeCollection = await ProfileTypeCollection.create({ db });\n const personType = await typeCollection.getOrCreateGlobalBySlug('person', {\n name: 'Person',\n description: 'Individual person profile',\n });\n const typeId = requireProvisioningId(personType.id, 'Person ProfileType');\n let profile: Profile = new Person({\n db,\n // OIDC display names are not identity keys. A per-profile slug keeps\n // SMRT's natural-key upsert from replacing an unrelated Person.\n slug: `oidc-${crypto.randomUUID()}`,\n tenantId: null,\n typeId,\n email: input.email ?? '',\n name: input.name || input.preferredUsername || input.subject,\n });\n await profile.initialize();\n await saveOidcRaceArbiter(() => profile.save());\n\n if (input.email) {\n const profiles = await ProfileCollection.create({ db });\n profile = await profiles.reserveCanonicalIdentityEmail(\n requireProvisioningId(profile.id, 'Created Profile'),\n input.email,\n );\n }\n return profile;\n}\n\n/** Insert the identity after the caller proves Profile ownership. */\nexport async function insertOidcProvisioningIdentity(\n db: DatabaseInterface,\n input: OidcProvisioningIdentityInput,\n): Promise<OidcIdentity> {\n const identity = new OidcIdentity({\n db,\n email: input.email ?? '',\n issuer: input.issuer,\n profileId: input.profileId,\n provider: input.provider,\n subject: input.subject,\n });\n await identity.initialize();\n await saveOidcRaceArbiter(() => identity.save());\n return identity;\n}\n\nfunction requireProvisioningId(value: unknown, label: string): string {\n if (typeof value !== 'string' || !value) {\n throw new Error(`${label} did not produce an id.`);\n }\n return value;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAkBO,IAAM,SAAN,cAAqB,QAAQ;CAClC,YAAY,UAA0B,CAAC,GAAG;EACxC,MAAM,OAAO;CAEf;AACF;AALsC,cAAzB,QAAgC,mBAAkB,8BAAA;AAAlD,SAAN,gBAAA,CAHN,KAAK,EACJ,eAAe,MACjB,CAAC,CAAA,GACY,MAAA;AAeN,IAAM,eAAN,cAA2B,QAAQ;CACxC,YAAY,UAA0B,CAAC,GAAG;EACxC,MAAM,OAAO;CAEf;AACF;AAL4C,cAA/B,cAAsC,mBAAkB,8BAAA;AAAxD,eAAN,gBAAA,CAHN,KAAK,EACJ,eAAe,MACjB,CAAC,CAAA,GACY,YAAA;AAeN,IAAM,MAAN,cAAkB,QAAQ;CAC/B,YAAY,UAA0B,CAAC,GAAG;EACxC,MAAM,OAAO;CAEf;AACF;AALmC,cAAtB,KAA6B,mBAAkB,8BAAA;AAA/C,MAAN,gBAAA,CAHN,KAAK,EACJ,eAAe,MACjB,CAAC,CAAA,GACY,GAAA;;;ACtBb,eAAsB,6BACpB,IACA,OACkB;CAMlB,MAAM,SAAS,uBAAsB,OAJZ,MADI,sBAAsB,OAAO,EAAE,GAAG,CAAC,EAAA,CACxB,wBAAwB,UAAU;EACxE,MAAM;EACN,aAAa;CACf,CAAC,EAAA,CAC+C,IAAI,oBAAoB;CACxE,IAAI,UAAmB,IAAI,OAAO;EAChC;EAGA,MAAM,QAAQ,OAAO,WAAW;EAChC,UAAU;EACV;EACA,OAAO,MAAM,SAAS;EACtB,MAAM,MAAM,QAAQ,MAAM,qBAAqB,MAAM;CACvD,CAAC;CACD,MAAM,QAAQ,WAAW;CACzB,MAAM,0BAA0B,QAAQ,KAAK,CAAC;CAE9C,IAAI,MAAM,OAER,UAAU,OAAM,MADO,kBAAkB,OAAO,EAAE,GAAG,CAAC,EAAA,CAC7B,8BACvB,sBAAsB,QAAQ,IAAI,iBAAiB,GACnD,MAAM,KACR;CAEF,OAAO;AACT;AAGA,eAAsB,+BACpB,IACA,OACuB;CACvB,MAAM,WAAW,IAAI,aAAa;EAChC;EACA,OAAO,MAAM,SAAS;EACtB,QAAQ,MAAM;EACd,WAAW,MAAM;EACjB,UAAU,MAAM;EAChB,SAAS,MAAM;CACjB,CAAC;CACD,MAAM,SAAS,WAAW;CAC1B,MAAM,0BAA0B,SAAS,KAAK,CAAC;CAC/C,OAAO;AACT;AAEA,SAAS,sBAAsB,OAAgB,OAAuB;CACpE,IAAI,OAAO,UAAU,YAAY,CAAC,OAChC,MAAM,IAAI,MAAM,GAAG,MAAK,wBAAyB;CAEnD,OAAO;AACT"}
1
+ {"version":3,"file":"oidcProvisioningPrimitives-Dl9qIcYS.js","names":[],"sources":["../../src/models/ProfileTypes.ts","../../src/auth/oidcProvisioningPrimitives.ts"],"sourcesContent":["/**\n * Profile subclasses for STI (Single Table Inheritance)\n *\n * These classes inherit from Profile and automatically use the shared\n * profiles table with _meta_type discriminator.\n */\n\nimport { smrt } from '@happyvertical/smrt-core';\nimport { Profile, type ProfileOptions } from './Profile';\n\n/**\n * Person profile type\n *\n * Represents individual people/users.\n */\n@smrt({\n tableStrategy: 'sti',\n})\nexport class Person extends Profile { static __smrtPackage__ = \"@happyvertical/smrt-profiles\";\n constructor(options: ProfileOptions = {}) {\n super(options);\n // Person-specific initialization can go here\n }\n}\n\n/**\n * Organization profile type\n *\n * Represents companies, groups, institutions, and other organizational entities.\n */\n@smrt({\n tableStrategy: 'sti',\n})\nexport class Organization extends Profile { static __smrtPackage__ = \"@happyvertical/smrt-profiles\";\n constructor(options: ProfileOptions = {}) {\n super(options);\n // Organization-specific initialization can go here\n }\n}\n\n/**\n * Bot profile type\n *\n * Represents automated agents, bots, and AI entities.\n */\n@smrt({\n tableStrategy: 'sti',\n})\nexport class Bot extends Profile { static __smrtPackage__ = \"@happyvertical/smrt-profiles\";\n constructor(options: ProfileOptions = {}) {\n super(options);\n // Bot-specific initialization can go here\n }\n}\n","import type { getDatabase } from '@happyvertical/sql';\nimport { ProfileCollection } from '../collections/ProfileCollection';\nimport { ProfileTypeCollection } from '../collections/ProfileTypeCollection';\nimport { OidcIdentity } from '../models/OidcIdentity';\nimport type { Profile } from '../models/Profile';\nimport { Person } from '../models/ProfileTypes';\nimport { saveOidcRaceArbiter } from './oidcProvisioningCoordinator';\n\ntype DatabaseInterface = Awaited<ReturnType<typeof getDatabase>>;\n\nexport interface OidcProvisioningPersonInput {\n email?: string;\n name?: string;\n preferredUsername?: string;\n subject: string;\n}\n\nexport interface OidcProvisioningIdentityInput {\n email?: string;\n issuer: string;\n profileId: string;\n provider: string;\n subject: string;\n}\n\n/** Create and reserve a fresh global Person inside the caller's transaction. */\nexport async function createOidcProvisioningPerson(\n db: DatabaseInterface,\n input: OidcProvisioningPersonInput,\n): Promise<Profile> {\n const typeCollection = await ProfileTypeCollection.create({ db });\n const personType = await typeCollection.getOrCreateGlobalBySlug('person', {\n name: 'Person',\n description: 'Individual person profile',\n });\n const typeId = requireProvisioningId(personType.id, 'Person ProfileType');\n let profile: Profile = new Person({\n db,\n // OIDC display names are not identity keys. A per-profile slug keeps\n // SMRT's natural-key upsert from replacing an unrelated Person.\n slug: `oidc-${crypto.randomUUID()}`,\n tenantId: null,\n typeId,\n email: input.email ?? '',\n name: input.name || input.preferredUsername || input.subject,\n });\n await profile.initialize();\n await saveOidcRaceArbiter(() => profile.save());\n\n if (input.email) {\n const profiles = await ProfileCollection.create({ db });\n profile = await profiles.reserveCanonicalIdentityEmail(\n requireProvisioningId(profile.id, 'Created Profile'),\n input.email,\n );\n }\n return profile;\n}\n\n/** Insert the identity after the caller proves Profile ownership. */\nexport async function insertOidcProvisioningIdentity(\n db: DatabaseInterface,\n input: OidcProvisioningIdentityInput,\n): Promise<OidcIdentity> {\n const identity = new OidcIdentity({\n db,\n email: input.email ?? '',\n issuer: input.issuer,\n profileId: input.profileId,\n provider: input.provider,\n subject: input.subject,\n });\n await identity.initialize();\n await saveOidcRaceArbiter(() => identity.save());\n return identity;\n}\n\nfunction requireProvisioningId(value: unknown, label: string): string {\n if (typeof value !== 'string' || !value) {\n throw new Error(`${label} did not produce an id.`);\n }\n return value;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAkBO,IAAM,SAAN,cAAqB,QAAQ;CAClC,YAAY,UAA0B,CAAC,GAAG;EACxC,MAAM,OAAO;CAEf;AACF;AALsC,cAAzB,QAAgC,mBAAkB,8BAAA;AAAlD,SAAN,gBAAA,CAHN,KAAK,EACJ,eAAe,MACjB,CAAC,CAAA,GACY,MAAA;AAeN,IAAM,eAAN,cAA2B,QAAQ;CACxC,YAAY,UAA0B,CAAC,GAAG;EACxC,MAAM,OAAO;CAEf;AACF;AAL4C,cAA/B,cAAsC,mBAAkB,8BAAA;AAAxD,eAAN,gBAAA,CAHN,KAAK,EACJ,eAAe,MACjB,CAAC,CAAA,GACY,YAAA;AAeN,IAAM,MAAN,cAAkB,QAAQ;CAC/B,YAAY,UAA0B,CAAC,GAAG;EACxC,MAAM,OAAO;CAEf;AACF;AALmC,cAAtB,KAA6B,mBAAkB,8BAAA;AAA/C,MAAN,gBAAA,CAHN,KAAK,EACJ,eAAe,MACjB,CAAC,CAAA,GACY,GAAA;;;ACtBb,eAAsB,6BACpB,IACA,OACkB;CAMlB,MAAM,SAAS,uBAAsB,OAJZ,MADI,sBAAsB,OAAO,EAAE,GAAG,CAAC,EAAA,CACxB,wBAAwB,UAAU;EACxE,MAAM;EACN,aAAa;CACf,CAAC,EAAA,CAC+C,IAAI,oBAAoB;CACxE,IAAI,UAAmB,IAAI,OAAO;EAChC;EAGA,MAAM,QAAQ,OAAO,WAAW;EAChC,UAAU;EACV;EACA,OAAO,MAAM,SAAS;EACtB,MAAM,MAAM,QAAQ,MAAM,qBAAqB,MAAM;CACvD,CAAC;CACD,MAAM,QAAQ,WAAW;CACzB,MAAM,0BAA0B,QAAQ,KAAK,CAAC;CAE9C,IAAI,MAAM,OAER,UAAU,OAAM,MADO,kBAAkB,OAAO,EAAE,GAAG,CAAC,EAAA,CAC7B,8BACvB,sBAAsB,QAAQ,IAAI,iBAAiB,GACnD,MAAM,KACR;CAEF,OAAO;AACT;AAGA,eAAsB,+BACpB,IACA,OACuB;CACvB,MAAM,WAAW,IAAI,aAAa;EAChC;EACA,OAAO,MAAM,SAAS;EACtB,QAAQ,MAAM;EACd,WAAW,MAAM;EACjB,UAAU,MAAM;EAChB,SAAS,MAAM;CACjB,CAAC;CACD,MAAM,SAAS,WAAW;CAC1B,MAAM,0BAA0B,SAAS,KAAK,CAAC;CAC/C,OAAO;AACT;AAEA,SAAS,sBAAsB,OAAgB,OAAuB;CACpE,IAAI,OAAO,UAAU,YAAY,CAAC,OAChC,MAAM,IAAI,MAAM,GAAG,MAAK,wBAAyB;CAEnD,OAAO;AACT"}
@@ -1,8 +1,8 @@
1
- import { _ as verifyAuthEvent, t as NostrIdentity, y as __exportAll } from "./NostrIdentity-AC8fAdxe.js";
2
- import { d as isOidcProvisioningRaceConflict, l as coordinateOidcProvisioning, p as normalizeIdentityEmail } from "./ProfileCollection-C4INKh7Y.js";
3
- import { t as ApiKey } from "./ApiKey-CVmlf3V6.js";
4
- import { t as OidcIdentity } from "./OidcIdentity-BUblgQLs.js";
5
- import { n as insertOidcProvisioningIdentity, t as createOidcProvisioningPerson } from "./oidcProvisioningPrimitives-DNP9EZlU.js";
1
+ import { _ as verifyAuthEvent, t as NostrIdentity, y as __exportAll } from "./NostrIdentity-RJaATTCt.js";
2
+ import { d as isOidcProvisioningRaceConflict, l as coordinateOidcProvisioning, p as normalizeIdentityEmail } from "./ProfileCollection-CMS9dFc0.js";
3
+ import { t as ApiKey } from "./ApiKey-9YuYcpWy.js";
4
+ import { t as OidcIdentity } from "./OidcIdentity-MVVO3MfG.js";
5
+ import { n as insertOidcProvisioningIdentity, t as createOidcProvisioningPerson } from "./oidcProvisioningPrimitives-Dl9qIcYS.js";
6
6
  import { resolveDatabase } from "@happyvertical/smrt-core";
7
7
  import { withSystemContext } from "@happyvertical/smrt-tenancy";
8
8
  //#region src/auth/resolveIdentity.ts
@@ -65,13 +65,13 @@ async function resolveIdentity(context) {
65
65
  };
66
66
  }
67
67
  async function findProfileByExternalId(provider, externalId, options) {
68
- const { OidcIdentityCollection } = await import("./OidcIdentityCollection-ClOyaHeF.js").then((n) => n.r);
68
+ const { OidcIdentityCollection } = await import("./OidcIdentityCollection-s4mp3n62.js").then((n) => n.r);
69
69
  const identities = await (await OidcIdentityCollection.create(options)).findByProvider(provider);
70
70
  for (const identity of identities) if (identity.subject === externalId || identity.email?.includes(externalId)) {
71
71
  const profile = await identity.getProfile();
72
72
  if (profile) return profile;
73
73
  }
74
- const { ProfileCollection } = await import("./ProfileCollection-C4INKh7Y.js").then((n) => n.r);
74
+ const { ProfileCollection } = await import("./ProfileCollection-CMS9dFc0.js").then((n) => n.r);
75
75
  const profiles = await (await ProfileCollection.create(options)).list({
76
76
  where: { email: `${externalId}@users.noreply.github.com` },
77
77
  limit: 1
@@ -92,7 +92,7 @@ async function reuseExistingOidcIdentityForProfile(profileId, claims, provider,
92
92
  createConcurrencyError: (cause) => new Error("Concurrent exact OIDC identity reuse did not converge.", cause === void 0 ? void 0 : { cause }),
93
93
  rebindRootResult: rebindOidcProfileResult,
94
94
  provision: (tx) => withSystemContext(async () => {
95
- const { OidcIdentityCollection } = await import("./OidcIdentityCollection-ClOyaHeF.js").then((n) => n.r);
95
+ const { OidcIdentityCollection } = await import("./OidcIdentityCollection-s4mp3n62.js").then((n) => n.r);
96
96
  const identity = await (await OidcIdentityCollection.create({ db: tx })).findBySubject(normalizedClaims.iss, normalizedClaims.sub);
97
97
  if (!identity) throw new Error("OidcIdentity.findOrCreate() no longer creates authentication links; use UserCollection.getOrCreateFromOidc() or createProfileFromOidc().");
98
98
  if (identity.profileId !== profileId) throw new Error(`OIDC identity ${normalizedClaims.iss} subject ${normalizedClaims.sub} belongs to a different Profile.`);
@@ -126,7 +126,7 @@ async function coordinateProfileOidcProvisioning(claims, provider, options) {
126
126
  });
127
127
  }
128
128
  async function provisionOidcProfile(claims, provider, options) {
129
- const { OidcIdentityCollection } = await import("./OidcIdentityCollection-ClOyaHeF.js").then((n) => n.r);
129
+ const { OidcIdentityCollection } = await import("./OidcIdentityCollection-s4mp3n62.js").then((n) => n.r);
130
130
  const existingIdentity = await (await OidcIdentityCollection.create(options)).findBySubject(claims.iss, claims.sub);
131
131
  if (existingIdentity) {
132
132
  const profile2 = await existingIdentity.getProfile();
@@ -141,7 +141,7 @@ async function provisionOidcProfile(claims, provider, options) {
141
141
  created: false
142
142
  };
143
143
  }
144
- const { ProfileCollection } = await import("./ProfileCollection-C4INKh7Y.js").then((n) => n.r);
144
+ const { ProfileCollection } = await import("./ProfileCollection-CMS9dFc0.js").then((n) => n.r);
145
145
  const profileCollection = await ProfileCollection.create(options);
146
146
  if (claims.email) {
147
147
  if (await profileCollection.findUniqueGlobalPersonByEmail(claims.email)) {
@@ -168,8 +168,8 @@ async function provisionOidcProfile(claims, provider, options) {
168
168
  };
169
169
  }
170
170
  async function rebindOidcProfileResult(result, rootDb) {
171
- const { OidcIdentityCollection } = await import("./OidcIdentityCollection-ClOyaHeF.js").then((n) => n.r);
172
- const { ProfileCollection } = await import("./ProfileCollection-C4INKh7Y.js").then((n) => n.r);
171
+ const { OidcIdentityCollection } = await import("./OidcIdentityCollection-s4mp3n62.js").then((n) => n.r);
172
+ const { ProfileCollection } = await import("./ProfileCollection-CMS9dFc0.js").then((n) => n.r);
173
173
  const profileId = requireOidcProfileId(result.profile.id);
174
174
  const identityId = requireOidcProfileId(result.oidcIdentity.id);
175
175
  const [profile, oidcIdentity] = await withSystemContext(async () => {
@@ -218,11 +218,11 @@ async function createProfileFromNostr(email, nostrData, options) {
218
218
  created: false
219
219
  };
220
220
  }
221
- const { Person } = await import("./oidcProvisioningPrimitives-DNP9EZlU.js").then((n) => n.o);
222
- const { ProfileTypeCollection } = await import("./ProfileTypeCollection-B7kwi1mU.js").then((n) => n.n);
221
+ const { Person } = await import("./oidcProvisioningPrimitives-Dl9qIcYS.js").then((n) => n.o);
222
+ const { ProfileTypeCollection } = await import("./ProfileTypeCollection-B7m698Bl.js").then((n) => n.n);
223
223
  let personType = await (await ProfileTypeCollection.create(options)).getBySlug("person");
224
224
  if (!personType) {
225
- const { ProfileType } = await import("./ProfileCollection-C4INKh7Y.js").then((n) => n.h);
225
+ const { ProfileType } = await import("./ProfileCollection-CMS9dFc0.js").then((n) => n.h);
226
226
  personType = new ProfileType({
227
227
  ...options,
228
228
  slug: "person",
@@ -261,4 +261,4 @@ async function createProfileFromNostr(email, nostrData, options) {
261
261
  //#endregion
262
262
  export { resolveIdentity_exports as i, createProfileFromOidc as n, resolveIdentity as r, createProfileFromNostr as t };
263
263
 
264
- //# sourceMappingURL=resolveIdentity-CkyqvctR.js.map
264
+ //# sourceMappingURL=resolveIdentity-CR5p_g7K.js.map