@happyvertical/smrt-profiles 0.35.2 → 0.35.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -68,7 +68,7 @@ let ProfileAssetCollection = class extends SmrtJunction {
68
68
  profileCollectionPromise = null;
69
69
  async getProfileCollection() {
70
70
  if (!this.profileCollectionPromise) {
71
- const { ProfileCollection } = await import("./ProfileCollection-DQD1uJEc.js").then((n) => n.d);
71
+ const { ProfileCollection } = await import("./ProfileCollection-M2PK8bp-.js").then((n) => n.d);
72
72
  this.profileCollectionPromise = ProfileCollection.create({ db: this.db });
73
73
  }
74
74
  return this.profileCollectionPromise;
@@ -119,4 +119,4 @@ export {
119
119
  ProfileAssetCollection as a,
120
120
  ProfileAssetCollection$1 as b
121
121
  };
122
- //# sourceMappingURL=ProfileAssetCollection-ChX4kLjN.js.map
122
+ //# sourceMappingURL=ProfileAssetCollection-CUM5QfuJ.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileAssetCollection-ChX4kLjN.js","sources":["../../src/models/ProfileAsset.ts","../../src/collections/ProfileAssetCollection.ts"],"sourcesContent":["import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport {\n crossPackageRef,\n field,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\n\nexport interface ProfileAssetOptions extends SmrtObjectOptions {\n profileId?: string;\n assetId?: string;\n relationship?: string;\n sortOrder?: number;\n tenantId?: string | null;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'profile_assets',\n conflictColumns: ['profile_id', 'asset_id', 'relationship'],\n api: false,\n mcp: false,\n cli: false,\n})\nexport class ProfileAsset extends SmrtObject {\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n @foreignKey('Profile', { required: true })\n profileId = '';\n\n @crossPackageRef('@happyvertical/smrt-assets:Asset', { required: true })\n assetId = '';\n\n @field({ required: true })\n relationship = 'attachment';\n\n @field()\n sortOrder = 0;\n\n constructor(options: ProfileAssetOptions = {}) {\n super(options);\n if (options.profileId) this.profileId = options.profileId;\n if (options.assetId) this.assetId = options.assetId;\n if (options.relationship) this.relationship = options.relationship;\n if (options.sortOrder !== undefined) this.sortOrder = options.sortOrder;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n }\n}\n","import type { Asset } from '@happyvertical/smrt-assets';\nimport {\n addOwnedAssetFromCollection,\n getOwnedAssetsFromCollection,\n removeOwnedAssetFromCollection,\n} from '@happyvertical/smrt-assets';\nimport type { SmrtCollectionOptions } from '@happyvertical/smrt-core';\nimport { SmrtJunction, smrt } from '@happyvertical/smrt-core';\nimport { ProfileAsset } from '../models/ProfileAsset';\nimport type { ProfileCollection } from './ProfileCollection';\n\nexport interface ProfileAssetCollectionOptions extends SmrtCollectionOptions {}\n\n@smrt({\n api: false,\n mcp: false,\n cli: false,\n})\nexport class ProfileAssetCollection extends SmrtJunction<ProfileAsset> {\n static readonly _itemClass = ProfileAsset;\n protected leftField = 'profileId';\n protected rightField = 'assetId';\n\n private profileCollectionPromise: Promise<ProfileCollection> | null = null;\n\n private async getProfileCollection(): Promise<ProfileCollection> {\n if (!this.profileCollectionPromise) {\n const { ProfileCollection } = await import('./ProfileCollection');\n this.profileCollectionPromise = ProfileCollection.create({ db: this.db });\n }\n\n return this.profileCollectionPromise;\n }\n\n async getAssets(profileId: string, relationship?: string): Promise<Asset[]> {\n return getOwnedAssetsFromCollection(\n await this.getProfileCollection(),\n profileId,\n relationship,\n );\n }\n\n async addAsset(\n profileId: string,\n asset: Asset,\n relationship = 'attachment',\n sortOrder = 0,\n ): Promise<void> {\n await addOwnedAssetFromCollection(\n await this.getProfileCollection(),\n 'Profile',\n profileId,\n asset,\n relationship,\n sortOrder,\n );\n }\n\n async removeAsset(\n profileId: string,\n assetId: string,\n relationship?: string,\n ): Promise<void> {\n await removeOwnedAssetFromCollection(\n await this.getProfileCollection(),\n 'Profile',\n profileId,\n assetId,\n relationship,\n );\n }\n}\n"],"names":["__decorateClass"],"mappings":";;;;;;;;;;;;;AA0BO,IAAM,eAAN,cAA2B,WAAW;AAAA,EAE3C,WAA0B;AAAA,EAG1B,YAAY;AAAA,EAGZ,UAAU;AAAA,EAGV,eAAe;AAAA,EAGf,YAAY;AAAA,EAEZ,YAAY,UAA+B,IAAI;AAC7C,UAAM,OAAO;AACb,QAAI,QAAQ,UAAW,MAAK,YAAY,QAAQ;AAChD,QAAI,QAAQ,QAAS,MAAK,UAAU,QAAQ;AAC5C,QAAI,QAAQ,aAAc,MAAK,eAAe,QAAQ;AACtD,QAAI,QAAQ,cAAc,OAAW,MAAK,YAAY,QAAQ;AAC9D,QAAI,QAAQ,aAAa,OAAW,MAAK,WAAW,QAAQ;AAAA,EAC9D;AACF;AAtBEA,kBAAA;AAAA,EADC,SAAS,EAAE,UAAU,KAAA,CAAM;AAAA,GADjB,aAEX,WAAA,YAAA,CAAA;AAGAA,kBAAA;AAAA,EADC,WAAW,WAAW,EAAE,UAAU,MAAM;AAAA,GAJ9B,aAKX,WAAA,aAAA,CAAA;AAGAA,kBAAA;AAAA,EADC,gBAAgB,oCAAoC,EAAE,UAAU,MAAM;AAAA,GAP5D,aAQX,WAAA,WAAA,CAAA;AAGAA,kBAAA;AAAA,EADC,MAAM,EAAE,UAAU,KAAA,CAAM;AAAA,GAVd,aAWX,WAAA,gBAAA,CAAA;AAGAA,kBAAA;AAAA,EADC,MAAA;AAAM,GAbI,aAcX,WAAA,aAAA,CAAA;AAdW,eAANA,kBAAA;AAAA,EARN,aAAa,EAAE,MAAM,YAAY;AAAA,EACjC,KAAK;AAAA,IACJ,WAAW;AAAA,IACX,iBAAiB,CAAC,cAAc,YAAY,cAAc;AAAA,IAC1D,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,EAAA,CACN;AAAA,GACY,YAAA;;;;;;;;;;;;ACRN,IAAM,yBAAN,cAAqC,aAA2B;AAAA,EAE3D,YAAY;AAAA,EACZ,aAAa;AAAA,EAEf,2BAA8D;AAAA,EAEtE,MAAc,uBAAmD;AAC/D,QAAI,CAAC,KAAK,0BAA0B;AAClC,YAAM,EAAE,kBAAA,IAAsB,MAAM,OAAO,iCAAqB,EAAA,KAAA,OAAA,EAAA,CAAA;AAChE,WAAK,2BAA2B,kBAAkB,OAAO,EAAE,IAAI,KAAK,IAAI;AAAA,IAC1E;AAEA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,UAAU,WAAmB,cAAyC;AAC1E,WAAO;AAAA,MACL,MAAM,KAAK,qBAAA;AAAA,MACX;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAAA,EAEA,MAAM,SACJ,WACA,OACA,eAAe,cACf,YAAY,GACG;AACf,UAAM;AAAA,MACJ,MAAM,KAAK,qBAAA;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAAA,EAEA,MAAM,YACJ,WACA,SACA,cACe;AACf,UAAM;AAAA,MACJ,MAAM,KAAK,qBAAA;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AACF;AApDE,cADW,wBACK,cAAa,YAAA;AADlB,yBAAN,gBAAA;AAAA,EALN,KAAK;AAAA,IACJ,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,EAAA,CACN;AAAA,GACY,sBAAA;;;;;;;"}
1
+ {"version":3,"file":"ProfileAssetCollection-CUM5QfuJ.js","sources":["../../src/models/ProfileAsset.ts","../../src/collections/ProfileAssetCollection.ts"],"sourcesContent":["import type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport {\n crossPackageRef,\n field,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\n\nexport interface ProfileAssetOptions extends SmrtObjectOptions {\n profileId?: string;\n assetId?: string;\n relationship?: string;\n sortOrder?: number;\n tenantId?: string | null;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableName: 'profile_assets',\n conflictColumns: ['profile_id', 'asset_id', 'relationship'],\n api: false,\n mcp: false,\n cli: false,\n})\nexport class ProfileAsset extends SmrtObject {\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n @foreignKey('Profile', { required: true })\n profileId = '';\n\n @crossPackageRef('@happyvertical/smrt-assets:Asset', { required: true })\n assetId = '';\n\n @field({ required: true })\n relationship = 'attachment';\n\n @field()\n sortOrder = 0;\n\n constructor(options: ProfileAssetOptions = {}) {\n super(options);\n if (options.profileId) this.profileId = options.profileId;\n if (options.assetId) this.assetId = options.assetId;\n if (options.relationship) this.relationship = options.relationship;\n if (options.sortOrder !== undefined) this.sortOrder = options.sortOrder;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n }\n}\n","import type { Asset } from '@happyvertical/smrt-assets';\nimport {\n addOwnedAssetFromCollection,\n getOwnedAssetsFromCollection,\n removeOwnedAssetFromCollection,\n} from '@happyvertical/smrt-assets';\nimport type { SmrtCollectionOptions } from '@happyvertical/smrt-core';\nimport { SmrtJunction, smrt } from '@happyvertical/smrt-core';\nimport { ProfileAsset } from '../models/ProfileAsset';\nimport type { ProfileCollection } from './ProfileCollection';\n\nexport interface ProfileAssetCollectionOptions extends SmrtCollectionOptions {}\n\n@smrt({\n api: false,\n mcp: false,\n cli: false,\n})\nexport class ProfileAssetCollection extends SmrtJunction<ProfileAsset> {\n static readonly _itemClass = ProfileAsset;\n protected leftField = 'profileId';\n protected rightField = 'assetId';\n\n private profileCollectionPromise: Promise<ProfileCollection> | null = null;\n\n private async getProfileCollection(): Promise<ProfileCollection> {\n if (!this.profileCollectionPromise) {\n const { ProfileCollection } = await import('./ProfileCollection');\n this.profileCollectionPromise = ProfileCollection.create({ db: this.db });\n }\n\n return this.profileCollectionPromise;\n }\n\n async getAssets(profileId: string, relationship?: string): Promise<Asset[]> {\n return getOwnedAssetsFromCollection(\n await this.getProfileCollection(),\n profileId,\n relationship,\n );\n }\n\n async addAsset(\n profileId: string,\n asset: Asset,\n relationship = 'attachment',\n sortOrder = 0,\n ): Promise<void> {\n await addOwnedAssetFromCollection(\n await this.getProfileCollection(),\n 'Profile',\n profileId,\n asset,\n relationship,\n sortOrder,\n );\n }\n\n async removeAsset(\n profileId: string,\n assetId: string,\n relationship?: string,\n ): Promise<void> {\n await removeOwnedAssetFromCollection(\n await this.getProfileCollection(),\n 'Profile',\n profileId,\n assetId,\n relationship,\n );\n }\n}\n"],"names":["__decorateClass"],"mappings":";;;;;;;;;;;;;AA0BO,IAAM,eAAN,cAA2B,WAAW;AAAA,EAE3C,WAA0B;AAAA,EAG1B,YAAY;AAAA,EAGZ,UAAU;AAAA,EAGV,eAAe;AAAA,EAGf,YAAY;AAAA,EAEZ,YAAY,UAA+B,IAAI;AAC7C,UAAM,OAAO;AACb,QAAI,QAAQ,UAAW,MAAK,YAAY,QAAQ;AAChD,QAAI,QAAQ,QAAS,MAAK,UAAU,QAAQ;AAC5C,QAAI,QAAQ,aAAc,MAAK,eAAe,QAAQ;AACtD,QAAI,QAAQ,cAAc,OAAW,MAAK,YAAY,QAAQ;AAC9D,QAAI,QAAQ,aAAa,OAAW,MAAK,WAAW,QAAQ;AAAA,EAC9D;AACF;AAtBEA,kBAAA;AAAA,EADC,SAAS,EAAE,UAAU,KAAA,CAAM;AAAA,GADjB,aAEX,WAAA,YAAA,CAAA;AAGAA,kBAAA;AAAA,EADC,WAAW,WAAW,EAAE,UAAU,MAAM;AAAA,GAJ9B,aAKX,WAAA,aAAA,CAAA;AAGAA,kBAAA;AAAA,EADC,gBAAgB,oCAAoC,EAAE,UAAU,MAAM;AAAA,GAP5D,aAQX,WAAA,WAAA,CAAA;AAGAA,kBAAA;AAAA,EADC,MAAM,EAAE,UAAU,KAAA,CAAM;AAAA,GAVd,aAWX,WAAA,gBAAA,CAAA;AAGAA,kBAAA;AAAA,EADC,MAAA;AAAM,GAbI,aAcX,WAAA,aAAA,CAAA;AAdW,eAANA,kBAAA;AAAA,EARN,aAAa,EAAE,MAAM,YAAY;AAAA,EACjC,KAAK;AAAA,IACJ,WAAW;AAAA,IACX,iBAAiB,CAAC,cAAc,YAAY,cAAc;AAAA,IAC1D,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,EAAA,CACN;AAAA,GACY,YAAA;;;;;;;;;;;;ACRN,IAAM,yBAAN,cAAqC,aAA2B;AAAA,EAE3D,YAAY;AAAA,EACZ,aAAa;AAAA,EAEf,2BAA8D;AAAA,EAEtE,MAAc,uBAAmD;AAC/D,QAAI,CAAC,KAAK,0BAA0B;AAClC,YAAM,EAAE,kBAAA,IAAsB,MAAM,OAAO,iCAAqB,EAAA,KAAA,OAAA,EAAA,CAAA;AAChE,WAAK,2BAA2B,kBAAkB,OAAO,EAAE,IAAI,KAAK,IAAI;AAAA,IAC1E;AAEA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,UAAU,WAAmB,cAAyC;AAC1E,WAAO;AAAA,MACL,MAAM,KAAK,qBAAA;AAAA,MACX;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAAA,EAEA,MAAM,SACJ,WACA,OACA,eAAe,cACf,YAAY,GACG;AACf,UAAM;AAAA,MACJ,MAAM,KAAK,qBAAA;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AAAA,EAEA,MAAM,YACJ,WACA,SACA,cACe;AACf,UAAM;AAAA,MACJ,MAAM,KAAK,qBAAA;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EAEJ;AACF;AApDE,cADW,wBACK,cAAa,YAAA;AADlB,yBAAN,gBAAA;AAAA,EALN,KAAK;AAAA,IACJ,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,EAAA,CACN;AAAA,GACY,sBAAA;;;;;;;"}
@@ -133,7 +133,9 @@ let Profile = class extends SmrtObject {
133
133
  async addMetadata(metafieldSlug, value) {
134
134
  const { ProfileMetafieldCollection } = await import("./ProfileMetafieldCollection-DMKhSHXX.js").then((n) => n.b);
135
135
  const { ProfileMetadataCollection } = await import("./ProfileMetadataCollection-DEhmljMY.js").then((n) => n.b);
136
- const metafieldCollection = await ProfileMetafieldCollection.create(this.options);
136
+ const metafieldCollection = await ProfileMetafieldCollection.create(
137
+ this.options
138
+ );
137
139
  const metafield = await metafieldCollection.getBySlug(metafieldSlug);
138
140
  if (!metafield) {
139
141
  throw new Error(`Metafield '${metafieldSlug}' not found`);
@@ -151,6 +153,11 @@ let Profile = class extends SmrtObject {
151
153
  metadata.value = String(value);
152
154
  await metadata.save();
153
155
  } else {
156
+ if (!this.id || !metafield.id) {
157
+ throw new Error(
158
+ "Profile.addMetadata requires a persisted profile and metafield (missing id)"
159
+ );
160
+ }
154
161
  const metadata = await metadataCollection.create({
155
162
  profileId: this.id,
156
163
  metafieldId: metafield.id,
@@ -189,7 +196,9 @@ let Profile = class extends SmrtObject {
189
196
  async removeMetadata(metafieldSlug) {
190
197
  const { ProfileMetafieldCollection } = await import("./ProfileMetafieldCollection-DMKhSHXX.js").then((n) => n.b);
191
198
  const { ProfileMetadataCollection } = await import("./ProfileMetadataCollection-DEhmljMY.js").then((n) => n.b);
192
- const metafieldCollection = await ProfileMetafieldCollection.create(this.options);
199
+ const metafieldCollection = await ProfileMetafieldCollection.create(
200
+ this.options
201
+ );
193
202
  const metafield = await metafieldCollection.getBySlug(metafieldSlug);
194
203
  if (!metafield) {
195
204
  throw new Error(`Metafield '${metafieldSlug}' not found`);
@@ -206,7 +215,7 @@ let Profile = class extends SmrtObject {
206
215
  }
207
216
  }
208
217
  async getProfileAssetCollection() {
209
- const { ProfileAssetCollection } = await import("./ProfileAssetCollection-ChX4kLjN.js").then((n) => n.b);
218
+ const { ProfileAssetCollection } = await import("./ProfileAssetCollection-CUM5QfuJ.js").then((n) => n.b);
210
219
  return ProfileAssetCollection.create({ db: this.db });
211
220
  }
212
221
  async getAssets(relationship) {
@@ -257,14 +266,16 @@ let Profile = class extends SmrtObject {
257
266
  */
258
267
  async addRelationship(toProfile, relationshipSlug, contextProfile) {
259
268
  const { ProfileRelationshipTypeCollection } = await import("./ProfileRelationshipTypeCollection-CF8YvLTV.js");
260
- const { ProfileRelationshipCollection } = await import("./ProfileRelationshipCollection-C0IM8UQR.js").then((n) => n.b);
269
+ const { ProfileRelationshipCollection } = await import("./ProfileRelationshipCollection-_TsY7MHL.js").then((n) => n.b);
261
270
  const { ProfileRelationshipType } = await import("./ProfileRelationshipType-BXBLldea.js");
262
271
  const relationshipTypeCollection = await ProfileRelationshipTypeCollection.create(this.options);
263
272
  const relationshipType = await relationshipTypeCollection.getBySlug(relationshipSlug);
264
273
  if (!relationshipType) {
265
274
  throw new Error(`Relationship type '${relationshipSlug}' not found`);
266
275
  }
267
- const relationshipCollection = await ProfileRelationshipCollection.create(this.options);
276
+ const relationshipCollection = await ProfileRelationshipCollection.create(
277
+ this.options
278
+ );
268
279
  const exists = await relationshipCollection.exists(
269
280
  this.id,
270
281
  toProfile.id,
@@ -272,10 +283,10 @@ let Profile = class extends SmrtObject {
272
283
  );
273
284
  if (!exists) {
274
285
  const relationship = await relationshipCollection.create({
275
- fromProfileId: this.id,
276
- toProfileId: toProfile.id,
277
- typeId: relationshipType.id,
278
- contextProfileId: contextProfile?.id
286
+ fromProfileId: this.id ?? void 0,
287
+ toProfileId: toProfile.id ?? void 0,
288
+ typeId: relationshipType.id ?? void 0,
289
+ contextProfileId: contextProfile?.id ?? void 0
279
290
  });
280
291
  await relationship.save();
281
292
  if (relationshipType.reciprocal) {
@@ -293,9 +304,11 @@ let Profile = class extends SmrtObject {
293
304
  * @returns Array of ProfileRelationship instances
294
305
  */
295
306
  async getRelationships(options) {
296
- const { ProfileRelationshipCollection } = await import("./ProfileRelationshipCollection-C0IM8UQR.js").then((n) => n.b);
307
+ const { ProfileRelationshipCollection } = await import("./ProfileRelationshipCollection-_TsY7MHL.js").then((n) => n.b);
297
308
  const { ProfileRelationshipTypeCollection } = await import("./ProfileRelationshipTypeCollection-CF8YvLTV.js");
298
- const relationshipCollection = await ProfileRelationshipCollection.create(this.options);
309
+ const relationshipCollection = await ProfileRelationshipCollection.create(
310
+ this.options
311
+ );
299
312
  const direction = options?.direction || "all";
300
313
  let typeId;
301
314
  if (options?.typeSlug) {
@@ -303,14 +316,23 @@ let Profile = class extends SmrtObject {
303
316
  const relationshipType = await relationshipTypeCollection.getBySlug(
304
317
  options.typeSlug
305
318
  );
306
- typeId = relationshipType?.id;
319
+ typeId = relationshipType?.id ?? void 0;
307
320
  }
308
321
  if (direction === "from") {
309
- return await relationshipCollection.getFromProfile(this.id, typeId);
322
+ return await relationshipCollection.getFromProfile(
323
+ this.id,
324
+ typeId
325
+ );
310
326
  } else if (direction === "to") {
311
- return await relationshipCollection.getToProfile(this.id, typeId);
327
+ return await relationshipCollection.getToProfile(
328
+ this.id,
329
+ typeId
330
+ );
312
331
  } else {
313
- return await relationshipCollection.getForProfile(this.id, typeId);
332
+ return await relationshipCollection.getForProfile(
333
+ this.id,
334
+ typeId
335
+ );
314
336
  }
315
337
  }
316
338
  /**
@@ -325,9 +347,7 @@ let Profile = class extends SmrtObject {
325
347
  typeSlug: relationshipSlug,
326
348
  direction: "all"
327
349
  });
328
- const profileCollection = await ProfileCollection2.create(
329
- this.options
330
- );
350
+ const profileCollection = await ProfileCollection2.create(this.options);
331
351
  const relatedProfiles = [];
332
352
  const seenIds = /* @__PURE__ */ new Set();
333
353
  for (const relationship of relationships) {
@@ -353,13 +373,15 @@ let Profile = class extends SmrtObject {
353
373
  */
354
374
  async removeRelationship(toProfile, relationshipSlug) {
355
375
  const { ProfileRelationshipTypeCollection } = await import("./ProfileRelationshipTypeCollection-CF8YvLTV.js");
356
- const { ProfileRelationshipCollection } = await import("./ProfileRelationshipCollection-C0IM8UQR.js").then((n) => n.b);
376
+ const { ProfileRelationshipCollection } = await import("./ProfileRelationshipCollection-_TsY7MHL.js").then((n) => n.b);
357
377
  const relationshipTypeCollection = await ProfileRelationshipTypeCollection.create(this.options);
358
378
  const relationshipType = await relationshipTypeCollection.getBySlug(relationshipSlug);
359
379
  if (!relationshipType) {
360
380
  throw new Error(`Relationship type '${relationshipSlug}' not found`);
361
381
  }
362
- const relationshipCollection = await ProfileRelationshipCollection.create(this.options);
382
+ const relationshipCollection = await ProfileRelationshipCollection.create(
383
+ this.options
384
+ );
363
385
  const relationships = await relationshipCollection.list({
364
386
  where: {
365
387
  fromProfileId: this.id,
@@ -501,10 +523,8 @@ let Profile = class extends SmrtObject {
501
523
  * @returns Array of OIDC identity records
502
524
  */
503
525
  async getOidcIdentities() {
504
- const { OidcIdentityCollection } = await import("./index-DHLYp075.js").then((n) => n.j);
505
- const collection = await OidcIdentityCollection.create(
506
- this.options
507
- );
526
+ const { OidcIdentityCollection } = await import("./index-B9lXQy7N.js").then((n) => n.j);
527
+ const collection = await OidcIdentityCollection.create(this.options);
508
528
  return await collection.findByProfile(this.id);
509
529
  }
510
530
  /**
@@ -514,10 +534,8 @@ let Profile = class extends SmrtObject {
514
534
  * @returns The linked OIDC identity record
515
535
  */
516
536
  async linkOidcIdentity(oidcData) {
517
- const { OidcIdentityCollection } = await import("./index-DHLYp075.js").then((n) => n.j);
518
- const collection = await OidcIdentityCollection.create(
519
- this.options
520
- );
537
+ const { OidcIdentityCollection } = await import("./index-B9lXQy7N.js").then((n) => n.j);
538
+ const collection = await OidcIdentityCollection.create(this.options);
521
539
  return await collection.linkToProfile(this, oidcData);
522
540
  }
523
541
  /**
@@ -527,9 +545,7 @@ let Profile = class extends SmrtObject {
527
545
  */
528
546
  async getNostrIdentities() {
529
547
  const { NostrIdentityCollection } = await import("./NostrIdentityCollection-DadQBHWy.js").then((n) => n.q);
530
- const collection = await NostrIdentityCollection.create(
531
- this.options
532
- );
548
+ const collection = await NostrIdentityCollection.create(this.options);
533
549
  return await collection.findByProfile(this.id);
534
550
  }
535
551
  /**
@@ -540,9 +556,7 @@ let Profile = class extends SmrtObject {
540
556
  */
541
557
  async linkNostrIdentity(nostrData) {
542
558
  const { NostrIdentityCollection } = await import("./NostrIdentityCollection-DadQBHWy.js").then((n) => n.q);
543
- const collection = await NostrIdentityCollection.create(
544
- this.options
545
- );
559
+ const collection = await NostrIdentityCollection.create(this.options);
546
560
  return await collection.linkToProfile(this, nostrData);
547
561
  }
548
562
  /**
@@ -783,4 +797,4 @@ export {
783
797
  promptMessageOptions as p,
784
798
  smrtProfilesGenerateBioPrompt as s
785
799
  };
786
- //# sourceMappingURL=ProfileCollection-DQD1uJEc.js.map
800
+ //# sourceMappingURL=ProfileCollection-M2PK8bp-.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProfileCollection-M2PK8bp-.js","sources":["../../src/prompts.ts","../../src/models/ProfileType.ts","../../src/models/Profile.ts","../../src/collections/ProfileCollection.ts"],"sourcesContent":["/**\n * Prompt registrations for the @happyvertical/smrt-profiles package.\n *\n * Prompts are registered at module-load time via `definePrompt()` so that\n * tenant-aware overrides can be applied at call time via `resolvePrompt()`.\n *\n * Mirrors the pattern used by `@happyvertical/smrt-content` (see\n * `content-prompts.ts`) and `@happyvertical/smrt-facts` (see `prompts.ts`).\n */\n\nimport {\n definePrompt,\n type ResolvedPromptAI,\n} from '@happyvertical/smrt-prompts';\n\n// Bio generation only uses non-PII profile fields (name + description).\n// Email is intentionally NOT passed to the AI provider — see review on PR\n// #1209 — to minimize PII exposure. If a downstream tenant needs email in\n// the bio, they can override the template via PromptOverride.\nexport const smrtProfilesGenerateBioPrompt = definePrompt({\n key: 'smrtProfiles.profile.generateBio',\n template: `Write a short, professional bio for this person.\n\nProfile name: {profileName}\nProfile description: {profileDescription}\n\nReturn only the bio text, with no commentary or surrounding quotation marks.`,\n editable: {\n template: true,\n profile: true,\n model: true,\n params: true,\n },\n});\n\nexport function promptMessageOptions(ai: ResolvedPromptAI) {\n return {\n ...(ai.params || {}),\n ...(ai.model ? { model: ai.model } : {}),\n ...(typeof ai.temperature === 'number'\n ? { temperature: ai.temperature }\n : {}),\n ...(typeof ai.maxTokens === 'number' ? { maxTokens: ai.maxTokens } : {}),\n };\n}\n","/**\n * ProfileType model - Lookup table defining profile types\n *\n * Represents the nature of a profile (e.g., 'human', 'org', 'robot').\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';\n\nexport interface ProfileTypeOptions extends SmrtObjectOptions {\n slug?: string;\n name?: string;\n description?: string;\n tenantId?: string | null;\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: true,\n})\nexport class ProfileType extends SmrtObject {\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 constructor(options: ProfileTypeOptions = {}) {\n super(options);\n if (options.name) this.name = options.name;\n if (options.description !== undefined)\n this.description = options.description;\n }\n\n /**\n * Convenience method for slug-based lookup\n *\n * @param slug - The slug to search for\n * @returns ProfileType instance or null if not found\n */\n static async getBySlug(_slug: string): Promise<ProfileType | null> {\n // Will be auto-implemented by SMRT\n return null;\n }\n}\n","/**\n * Profile model - Core entity representing any profile type\n *\n * Central table holding all primary entities with type, email, name, and description.\n * Uses UUID primary key with relationships to ProfileType for classification.\n */\n\nimport type { Asset } from '@happyvertical/smrt-assets';\nimport {\n assertValidOwnedAssetRelationship,\n assertValidOwnedAssetSortOrder,\n resolveOwnedAssetsById,\n} from '@happyvertical/smrt-assets';\n\nimport {\n field,\n foreignKey,\n oneToMany,\n SmrtObject,\n type SmrtObjectOptions,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { resolvePrompt } from '@happyvertical/smrt-prompts';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport {\n promptMessageOptions,\n smrtProfilesGenerateBioPrompt,\n} from '../prompts';\nimport type { ApiKey, GenerateKeyResult } from './ApiKey';\nimport type { AuditLog } from './AuditLog';\nimport type { NostrIdentity } from './NostrIdentity';\nimport type { OidcIdentity } from './OidcIdentity';\nimport type { ProfileMetadata } from './ProfileMetadata';\nimport type { ProfileRelationship } from './ProfileRelationship';\nimport { ProfileType } from './ProfileType';\n\nexport interface ProfileOptions extends SmrtObjectOptions {\n typeId?: string;\n email?: string;\n name?: string;\n description?: 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', 'create', 'update'] },\n cli: true,\n})\nexport class Profile extends SmrtObject {\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n // id: UUID (auto-generated by SmrtObject)\n @foreignKey('ProfileType', { required: true })\n typeId?: string; // References ProfileType.id\n\n @field({ unique: true })\n email?: string; // Optional email address\n\n @field({ required: true })\n name: string = ''; // Display name\n\n description?: string; // Short bio or description\n\n // Relationships (not stored as columns)\n @oneToMany('ProfileMetadata')\n metadata: ProfileMetadata[] = [];\n\n // ProfileRelationship declares multiple foreign keys back to Profile\n // (fromProfileId / toProfileId / contextProfileId), so each oneToMany names\n // its inverse side explicitly. This both disambiguates `loadRelatedMany`\n // and gives the R10-generated `getRelationshipsFrom()` / `getRelationshipsTo()`\n // accessors the correct inverse foreign key.\n @oneToMany('ProfileRelationship', { foreignKey: 'fromProfileId' })\n relationshipsFrom: ProfileRelationship[] = [];\n\n @oneToMany('ProfileRelationship', { foreignKey: 'toProfileId' })\n relationshipsTo: ProfileRelationship[] = [];\n\n constructor(options: ProfileOptions = {}) {\n super(options);\n if (options.typeId !== undefined) this.typeId = options.typeId;\n if (options.email !== undefined) this.email = options.email;\n if (options.name) this.name = options.name;\n if (options.description !== undefined)\n this.description = options.description;\n }\n\n /**\n * Get the profile type slug for this profile\n *\n * @returns The slug of the profile type\n */\n async getTypeSlug(): Promise<string> {\n const type = await this.loadRelated('typeId');\n return type?.slug || '';\n }\n\n /**\n * Set the profile type by slug\n *\n * @param slug - The slug of the profile type\n * @throws Error if profile type not found\n */\n async setTypeBySlug(slug: string): Promise<void> {\n const type = await ProfileType.getBySlug(slug);\n if (!type) throw new Error(`Profile type '${slug}' not found`);\n this.typeId = type.id as string;\n }\n\n /**\n * Add metadata to this profile\n *\n * @param metafieldSlug - The slug of the metafield\n * @param value - The value to set\n */\n async addMetadata(metafieldSlug: string, value: unknown): Promise<void> {\n const { ProfileMetafieldCollection } = await import(\n '../collections/ProfileMetafieldCollection'\n );\n const { ProfileMetadataCollection } = await import(\n '../collections/ProfileMetadataCollection'\n );\n\n // Get or create metafield collection\n const metafieldCollection = await ProfileMetafieldCollection.create(\n this.options,\n );\n\n // Find the metafield by slug\n const metafield = await metafieldCollection.getBySlug(metafieldSlug);\n if (!metafield) {\n throw new Error(`Metafield '${metafieldSlug}' not found`);\n }\n\n // Validate the value\n await metafield.validateValue(value);\n\n // Get or create metadata collection\n const metadataCollection = await ProfileMetadataCollection.create(\n this.options,\n );\n\n // Check if metadata already exists\n const existing = await metadataCollection.list({\n where: { profileId: this.id, metafieldId: metafield.id },\n limit: 1,\n });\n\n if (existing.length > 0) {\n // Update existing\n const metadata = existing[0];\n metadata.value = String(value);\n await metadata.save();\n } else {\n // Create new\n if (!this.id || !metafield.id) {\n throw new Error(\n 'Profile.addMetadata requires a persisted profile and metafield (missing id)',\n );\n }\n const metadata = await metadataCollection.create({\n profileId: this.id,\n metafieldId: metafield.id,\n value: String(value),\n });\n await metadata.save();\n }\n }\n\n /**\n * Get all metadata for this profile as key-value object\n *\n * @returns Object with metafield slugs as keys\n */\n async getMetadata(): Promise<Record<string, string>> {\n const { ProfileMetadataCollection } = await import(\n '../collections/ProfileMetadataCollection'\n );\n\n const metadataCollection = await ProfileMetadataCollection.create(\n this.options,\n );\n\n return await metadataCollection.getMetadataObject(this.id as string);\n }\n\n /**\n * Update multiple metadata values\n *\n * @param metadata - Object with metafield slugs as keys and values\n */\n async updateMetadata(metadata: Record<string, unknown>): Promise<void> {\n for (const [metafieldSlug, value] of Object.entries(metadata)) {\n await this.addMetadata(metafieldSlug, value);\n }\n }\n\n /**\n * Remove metadata by metafield slug\n *\n * @param metafieldSlug - The slug of the metafield to remove\n */\n async removeMetadata(metafieldSlug: string): Promise<void> {\n const { ProfileMetafieldCollection } = await import(\n '../collections/ProfileMetafieldCollection'\n );\n const { ProfileMetadataCollection } = await import(\n '../collections/ProfileMetadataCollection'\n );\n\n const metafieldCollection = await ProfileMetafieldCollection.create(\n this.options,\n );\n\n const metafield = await metafieldCollection.getBySlug(metafieldSlug);\n if (!metafield) {\n throw new Error(`Metafield '${metafieldSlug}' not found`);\n }\n\n const metadataCollection = await ProfileMetadataCollection.create(\n this.options,\n );\n\n const existing = await metadataCollection.list({\n where: { profileId: this.id, metafieldId: metafield.id },\n limit: 1,\n });\n\n if (existing.length > 0) {\n await existing[0].delete();\n }\n }\n\n private async getProfileAssetCollection() {\n const { ProfileAssetCollection } = await import(\n '../collections/ProfileAssetCollection'\n );\n return ProfileAssetCollection.create({ db: this.db });\n }\n async getAssets(relationship?: string): Promise<Asset[]> {\n if (!this.id) {\n return [];\n }\n\n const profileAssets = await this.getProfileAssetCollection();\n const linkedAssets = await profileAssets.byLeft(\n this.id,\n relationship ? { relationship } : {},\n );\n\n return resolveOwnedAssetsById(\n this.db,\n linkedAssets.map((link) => link.assetId),\n this.tenantId,\n );\n }\n\n async addAsset(\n asset: Asset,\n relationship = 'attachment',\n sortOrder = 0,\n ): Promise<void> {\n if (!this.id || !asset.id) {\n throw new Error('Cannot associate unsaved profile or asset');\n }\n\n assertValidOwnedAssetRelationship(relationship);\n assertValidOwnedAssetSortOrder(sortOrder);\n\n const profileAssets = await this.getProfileAssetCollection();\n await profileAssets.attach(this.id, asset.id, {\n relationship,\n sortOrder,\n tenantId: this.tenantId,\n });\n }\n\n async removeAsset(assetId: string, relationship?: string): Promise<void> {\n if (!this.id) {\n return;\n }\n\n const profileAssets = await this.getProfileAssetCollection();\n await profileAssets.detach(\n this.id,\n assetId,\n relationship ? { relationship } : {},\n );\n }\n\n /**\n * Add a relationship to another profile\n *\n * @param toProfile - The target profile\n * @param relationshipSlug - The type of relationship\n * @param contextProfile - Optional context profile for tertiary relationships\n */\n async addRelationship(\n toProfile: Profile,\n relationshipSlug: string,\n contextProfile?: Profile,\n ): Promise<void> {\n const { ProfileRelationshipTypeCollection } = await import(\n '../collections/ProfileRelationshipTypeCollection'\n );\n const { ProfileRelationshipCollection } = await import(\n '../collections/ProfileRelationshipCollection'\n );\n const { ProfileRelationshipType } = await import(\n './ProfileRelationshipType'\n );\n\n // Get relationship type\n const relationshipTypeCollection =\n await ProfileRelationshipTypeCollection.create(this.options);\n\n const relationshipType =\n await relationshipTypeCollection.getBySlug(relationshipSlug);\n if (!relationshipType) {\n throw new Error(`Relationship type '${relationshipSlug}' not found`);\n }\n\n // Check if relationship already exists\n const relationshipCollection = await ProfileRelationshipCollection.create(\n this.options,\n );\n\n const exists = await relationshipCollection.exists(\n this.id as string,\n toProfile.id as string,\n relationshipType.id as string,\n );\n\n if (!exists) {\n // Create the relationship\n const relationship = await relationshipCollection.create({\n fromProfileId: this.id ?? undefined,\n toProfileId: toProfile.id ?? undefined,\n typeId: relationshipType.id ?? undefined,\n contextProfileId: contextProfile?.id ?? undefined,\n });\n await relationship.save();\n\n // Handle reciprocal relationships. A reciprocal handler creates the\n // inverse edge by calling addRelationship() back on `toProfile`. Gating\n // this on `!exists` is what terminates the recursion: the inverse call\n // creates its own edge and re-enters, but by then the original edge\n // already exists, so the handler is skipped and the cycle stops. Firing\n // it unconditionally instead recurses forever (the bundled friend /\n // spouse / partner / colleague / sibling handlers all call back here).\n if (relationshipType.reciprocal) {\n const handler =\n ProfileRelationshipType.getReciprocalHandler(relationshipSlug);\n if (handler) {\n await handler(this, toProfile, contextProfile);\n }\n }\n }\n }\n\n /**\n * Get all relationships for this profile\n *\n * @param options - Filter options (typeSlug, direction)\n * @returns Array of ProfileRelationship instances\n */\n async getRelationships(options?: {\n typeSlug?: string;\n direction?: 'from' | 'to' | 'all';\n }): Promise<ProfileRelationship[]> {\n const { ProfileRelationshipCollection } = await import(\n '../collections/ProfileRelationshipCollection'\n );\n const { ProfileRelationshipTypeCollection } = await import(\n '../collections/ProfileRelationshipTypeCollection'\n );\n\n const relationshipCollection = await ProfileRelationshipCollection.create(\n this.options,\n );\n\n const direction = options?.direction || 'all';\n\n // Get type ID if typeSlug is provided\n let typeId: string | undefined;\n if (options?.typeSlug) {\n const relationshipTypeCollection =\n await ProfileRelationshipTypeCollection.create(this.options);\n\n const relationshipType = await relationshipTypeCollection.getBySlug(\n options.typeSlug,\n );\n typeId = relationshipType?.id ?? undefined;\n }\n\n // Fetch relationships based on direction\n if (direction === 'from') {\n return await relationshipCollection.getFromProfile(\n this.id as string,\n typeId,\n );\n } else if (direction === 'to') {\n return await relationshipCollection.getToProfile(\n this.id as string,\n typeId,\n );\n } else {\n return await relationshipCollection.getForProfile(\n this.id as string,\n typeId,\n );\n }\n }\n\n /**\n * Get related profiles\n *\n * @param relationshipSlug - Optional filter by relationship type slug\n * @returns Array of related Profile instances\n */\n async getRelatedProfiles(relationshipSlug?: string): Promise<Profile[]> {\n const { ProfileCollection } = await import(\n '../collections/ProfileCollection'\n );\n\n const relationships = await this.getRelationships({\n typeSlug: relationshipSlug,\n direction: 'all',\n });\n\n const profileCollection = await ProfileCollection.create(this.options);\n\n const relatedProfiles: Profile[] = [];\n const seenIds = new Set<string>();\n\n for (const relationship of relationships) {\n // Get the other profile (not this one)\n // Convert Field instances to strings for comparison\n const fromId = String(relationship.fromProfileId);\n const toId = String(relationship.toProfileId);\n const thisId = String(this.id);\n const otherId = fromId === thisId ? toId : fromId;\n\n if (!seenIds.has(otherId)) {\n seenIds.add(otherId);\n const profile = await profileCollection.get({ id: otherId });\n if (profile) {\n relatedProfiles.push(profile);\n }\n }\n }\n\n return relatedProfiles;\n }\n\n /**\n * Remove a relationship to another profile\n *\n * @param toProfile - The target profile\n * @param relationshipSlug - The type of relationship to remove\n */\n async removeRelationship(\n toProfile: Profile,\n relationshipSlug: string,\n ): Promise<void> {\n const { ProfileRelationshipTypeCollection } = await import(\n '../collections/ProfileRelationshipTypeCollection'\n );\n const { ProfileRelationshipCollection } = await import(\n '../collections/ProfileRelationshipCollection'\n );\n\n // Get relationship type\n const relationshipTypeCollection =\n await ProfileRelationshipTypeCollection.create(this.options);\n\n const relationshipType =\n await relationshipTypeCollection.getBySlug(relationshipSlug);\n if (!relationshipType) {\n throw new Error(`Relationship type '${relationshipSlug}' not found`);\n }\n\n // Find and delete the relationship\n const relationshipCollection = await ProfileRelationshipCollection.create(\n this.options,\n );\n\n const relationships = await relationshipCollection.list({\n where: {\n fromProfileId: this.id,\n toProfileId: toProfile.id,\n typeId: relationshipType.id,\n },\n });\n\n for (const relationship of relationships) {\n await relationship.delete();\n }\n\n // Handle reciprocal relationships - delete the inverse\n if (relationshipType.reciprocal) {\n const inverseRelationships = await relationshipCollection.list({\n where: {\n fromProfileId: toProfile.id,\n toProfileId: this.id,\n typeId: relationshipType.id,\n },\n });\n\n for (const relationship of inverseRelationships) {\n await relationship.delete();\n }\n }\n }\n\n /**\n * AI-powered: Generate a professional bio for this profile\n *\n * Uses the `smrtProfiles.profile.generateBio` prompt registered via\n * `@happyvertical/smrt-prompts`, allowing tenant- or instance-level\n * overrides of the template, model, and parameters at runtime.\n *\n * @returns Generated bio text\n */\n async generateBio(): Promise<string> {\n // Resolve `db` from either the canonical `db` option or its `persistence`\n // alias. SmrtClass maps `persistence → db` lazily during `initialize()`,\n // so on a freshly-constructed Profile that has not yet been initialized,\n // `this.options.db` may be undefined while `this.options.persistence` is\n // set. Falling back here ensures stored app- and tenant-level prompt\n // overrides in `_smrt_prompt_overrides` are honored on the first call —\n // before `getAiClient()` triggers full initialization further below.\n const db = this.options.db ?? this.options.persistence;\n\n const resolvedPrompt = await resolvePrompt(\n smrtProfilesGenerateBioPrompt.key,\n {\n db,\n tenantId: this.tenantId,\n variables: {\n profileName: this.name || '',\n profileDescription: this.description || '',\n },\n },\n );\n\n const ai = await this.getAiClient();\n const response = await ai.message(\n resolvedPrompt.text,\n promptMessageOptions(resolvedPrompt.ai),\n );\n\n return response.trim();\n }\n\n /**\n * AI-powered: Check if profile matches criteria\n *\n * @param criteria - Criteria to match against\n * @returns True if matches criteria\n */\n async matches(criteria: string): Promise<boolean> {\n return await this.is(criteria);\n }\n\n /**\n * Find profiles by metadata key-value pair\n *\n * @param metafieldSlug - The metafield slug to search\n * @param value - The value to match\n * @returns Array of matching profiles\n */\n static async findByMetadata(\n _metafieldSlug: string,\n _value: unknown,\n ): Promise<Profile[]> {\n // Will be auto-implemented by SMRT\n return [];\n }\n\n /**\n * Find profiles by type slug\n *\n * @param typeSlug - The profile type slug\n * @returns Array of matching profiles\n */\n static async findByType(_typeSlug: string): Promise<Profile[]> {\n // Will be auto-implemented by SMRT\n return [];\n }\n\n /**\n * Find related profiles for a given profile\n *\n * @param profileId - The profile UUID\n * @param relationshipSlug - Optional filter by relationship type\n * @returns Array of related profiles\n */\n static async findRelated(\n _profileId: string,\n _relationshipSlug?: string,\n ): Promise<Profile[]> {\n // Will be auto-implemented by SMRT\n return [];\n }\n\n /**\n * Search profiles by email\n *\n * @param email - The email to search for\n * @returns Profile or null if not found\n */\n static async searchByEmail(_email: string): Promise<Profile | null> {\n // Will be auto-implemented by SMRT\n return null;\n }\n\n // ========================\n // Auth-related methods\n // ========================\n\n /**\n * Get all API keys for this profile\n *\n * @returns Array of API keys\n */\n async getApiKeys(): Promise<ApiKey[]> {\n const { ApiKeyCollection } = await import(\n '../collections/ApiKeyCollection'\n );\n const collection = await ApiKeyCollection.create(this.options);\n return await collection.findByProfile(this.id as string);\n }\n\n /**\n * Get active (non-revoked, non-expired) API keys for this profile\n *\n * @returns Array of active API keys\n */\n async getActiveApiKeys(): Promise<ApiKey[]> {\n const { ApiKeyCollection } = await import(\n '../collections/ApiKeyCollection'\n );\n const collection = await ApiKeyCollection.create(this.options);\n return await collection.findActiveByProfile(this.id as string);\n }\n\n /**\n * Generate a new API key for this profile\n *\n * @param options - Key options (name, scopes, expiration)\n * @returns The generated key (plaintext) and ApiKey record\n */\n async generateApiKey(options: {\n name: string;\n scopes?: string[];\n expiresAt?: Date | null;\n }): Promise<GenerateKeyResult> {\n const { ApiKey } = await import('./ApiKey');\n return await ApiKey.generate(this, {\n ...options,\n db: this.options?.db,\n });\n }\n\n /**\n * Get all OIDC identities linked to this profile\n *\n * @returns Array of OIDC identity records\n */\n async getOidcIdentities(): Promise<OidcIdentity[]> {\n const { OidcIdentityCollection } = await import(\n '../collections/OidcIdentityCollection'\n );\n const collection = await OidcIdentityCollection.create(this.options);\n return await collection.findByProfile(this.id as string);\n }\n\n /**\n * Link a new OIDC identity to this profile\n *\n * @param oidcData - OIDC provider data\n * @returns The linked OIDC identity record\n */\n async linkOidcIdentity(oidcData: {\n provider: string;\n issuer: string;\n subject: string;\n email?: string;\n }): Promise<OidcIdentity> {\n const { OidcIdentityCollection } = await import(\n '../collections/OidcIdentityCollection'\n );\n const collection = await OidcIdentityCollection.create(this.options);\n return await collection.linkToProfile(this, oidcData);\n }\n\n /**\n * Get all Nostr identities linked to this profile\n *\n * @returns Array of Nostr identity records\n */\n async getNostrIdentities(): Promise<NostrIdentity[]> {\n const { NostrIdentityCollection } = await import(\n '../collections/NostrIdentityCollection'\n );\n const collection = await NostrIdentityCollection.create(this.options);\n return await collection.findByProfile(this.id as string);\n }\n\n /**\n * Link a new Nostr identity to this profile\n *\n * @param nostrData - Nostr identity data (encrypted keypair)\n * @returns The linked Nostr identity record\n */\n async linkNostrIdentity(nostrData: {\n pubkey: string;\n encryptedPrivkey: string;\n encryptionIv: string;\n encryptionTag: string;\n email: string;\n nip05Username?: string;\n }): Promise<NostrIdentity> {\n const { NostrIdentityCollection } = await import(\n '../collections/NostrIdentityCollection'\n );\n const collection = await NostrIdentityCollection.create(this.options);\n return await collection.linkToProfile(this, nostrData);\n }\n\n /**\n * Get audit logs for actions performed by this profile\n *\n * @param limit - Maximum number of logs to return\n * @returns Array of audit log entries\n */\n async getAuditLogs(limit: number = 50): Promise<AuditLog[]> {\n const { AuditLogCollection } = await import(\n '../collections/AuditLogCollection'\n );\n const collection = await AuditLogCollection.create(this.options);\n return await collection.getRecentActivity(this.id as string, limit);\n }\n\n /**\n * Record an audit log entry for an action by this profile\n *\n * @param options - Audit log options\n * @returns The created audit log entry\n */\n async recordAction(options: {\n action: string;\n resourceType: string;\n resourceId: string;\n source?: 'web' | 'cli' | 'ci' | 'webhook' | 'mcp';\n metadata?: Record<string, unknown>;\n onBehalfOf?: Profile | null;\n }): Promise<AuditLog> {\n const { AuditLogCollection } = await import(\n '../collections/AuditLogCollection'\n );\n const collection = await AuditLogCollection.create(this.options);\n return await collection.record({\n profile: this,\n ...options,\n });\n }\n}\n","/**\n * ProfileCollection - Collection manager for Profile objects\n *\n * Provides advanced querying and batch operations for Profile entities.\n */\n\nimport type { Asset } from '@happyvertical/smrt-assets';\nimport {\n addOwnedAssetFromCollection,\n getOwnedAssetsFromCollection,\n removeOwnedAssetFromCollection,\n} from '@happyvertical/smrt-assets';\nimport { SmrtCollection } from '@happyvertical/smrt-core';\nimport { queryGlobal, queryWithGlobals } from '@happyvertical/smrt-tenancy';\nimport { Profile } from '../models/Profile';\n\nexport class ProfileCollection extends SmrtCollection<Profile> {\n static readonly _itemClass = Profile;\n\n /**\n * Find a profile by email address\n *\n * @param email - The email address to search for\n * @returns The matching profile or null\n */\n async findByEmail(email: string): Promise<Profile | null> {\n const normalizedEmail = email.toLowerCase();\n const profiles = await this.list({\n where: { email: normalizedEmail },\n limit: 1,\n });\n return profiles.length > 0 ? profiles[0] : null;\n }\n\n /**\n * Find profiles by type slug\n *\n * @param typeSlug - The profile type slug to filter by\n * @returns Array of matching profiles\n */\n async findByType(typeSlug: string): Promise<Profile[]> {\n // Will use eager loading when available\n const allProfiles = await this.list({});\n\n const filtered: Profile[] = [];\n for (const profile of allProfiles) {\n const slug = await profile.getTypeSlug();\n if (slug === typeSlug) {\n filtered.push(profile);\n }\n }\n\n return filtered;\n }\n\n /**\n * Batch get metadata for multiple profiles\n *\n * @param profileIds - Array of profile UUIDs\n * @returns Map of profile ID to metadata object\n */\n async batchGetMetadata(\n profileIds: string[],\n ): Promise<Map<string, Record<string, string>>> {\n const result = new Map<string, Record<string, string>>();\n\n for (const profileId of profileIds) {\n const profile = await this.get({ id: profileId });\n if (profile) {\n const metadata = await profile.getMetadata();\n result.set(profileId, metadata);\n }\n }\n\n return result;\n }\n\n /**\n * Batch update metadata for multiple profiles\n *\n * @param updates - Array of { profileId, data } objects\n */\n async batchUpdateMetadata(\n updates: Array<{ profileId: string; data: Record<string, unknown> }>,\n ): Promise<void> {\n for (const update of updates) {\n const profile = await this.get({ id: update.profileId });\n if (profile) {\n await profile.updateMetadata(update.data);\n }\n }\n }\n\n /**\n * Find related profiles for a given profile\n *\n * @param profileId - The profile UUID\n * @param relationshipSlug - Optional filter by relationship type\n * @returns Array of related profiles\n */\n async findRelated(\n profileId: string,\n relationshipSlug?: string,\n ): Promise<Profile[]> {\n const profile = await this.get({ id: profileId });\n if (!profile) return [];\n\n return await profile.getRelatedProfiles(relationshipSlug);\n }\n\n async getAssets(profileId: string, relationship?: string): Promise<Asset[]> {\n return getOwnedAssetsFromCollection(this, profileId, relationship);\n }\n\n async addAsset(\n profileId: string,\n asset: Asset,\n relationship = 'attachment',\n sortOrder = 0,\n ): Promise<void> {\n await addOwnedAssetFromCollection(\n this,\n 'Profile',\n profileId,\n asset,\n relationship,\n sortOrder,\n );\n }\n\n async removeAsset(\n profileId: string,\n assetId: string,\n relationship?: string,\n ): Promise<void> {\n await removeOwnedAssetFromCollection(\n this,\n 'Profile',\n profileId,\n assetId,\n relationship,\n );\n }\n\n /**\n * Get the relationship network for a profile up to a maximum depth\n *\n * @param profileId - The starting profile UUID\n * @param options - Configuration options\n * @returns Map of profile ID to depth level\n */\n async getRelationshipNetwork(\n profileId: string,\n options: { maxDepth?: number } = {},\n ): Promise<Map<string, number>> {\n const maxDepth = options.maxDepth || 2;\n const network = new Map<string, number>();\n const visited = new Set<string>();\n const queue: Array<{ id: string; depth: number }> = [\n { id: profileId, depth: 0 },\n ];\n\n while (queue.length > 0) {\n const current = queue.shift();\n if (!current) {\n break;\n }\n\n if (visited.has(current.id) || current.depth > maxDepth) {\n continue;\n }\n\n visited.add(current.id);\n network.set(current.id, current.depth);\n\n if (current.depth < maxDepth) {\n const related = await this.findRelated(current.id);\n for (const profile of related) {\n if (profile.id && !visited.has(profile.id)) {\n queue.push({ id: profile.id, depth: current.depth + 1 });\n }\n }\n }\n }\n\n return network;\n }\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Tenant-scoped helper methods\n // ─────────────────────────────────────────────────────────────────────────────\n\n /**\n * Find all profiles belonging to a specific tenant\n *\n * @param tenantId - The tenant UUID to filter by\n * @returns Array of profiles for this tenant\n */\n async findByTenant(tenantId: string): Promise<Profile[]> {\n return this.list({ where: { tenantId } });\n }\n\n /**\n * Find all global profiles (no tenant association).\n *\n * Routes through the shared tenant-global helper so it does not throw under\n * an active tenant context (an explicit `tenant_id IS NULL` filter would be\n * flagged as an isolation violation). (#1600)\n *\n * @returns Array of profiles with null tenantId\n */\n async findGlobal(): Promise<Profile[]> {\n return queryGlobal<Profile>(this);\n }\n\n /**\n * Find profiles belonging to a tenant plus all global profiles.\n *\n * Fails closed if an active tenant context requests a different tenant's\n * rows; the admin/system path keeps the cross-tenant capability. (#1600)\n *\n * @param tenantId - The tenant UUID to include\n * @returns Array of tenant-specific and global profiles\n */\n async findWithGlobals(tenantId: string): Promise<Profile[]> {\n return queryWithGlobals<Profile>(this, tenantId, 'Profile.findWithGlobals');\n }\n}\n"],"names":["__decorateClass","ProfileCollection","tenantId"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileMetadataCollection-DEhmljMY.js","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: true,\n})\nexport class ProfileMetadata extends SmrtObject {\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 }\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, any>> {\n const metadata = await this.getByProfile(profileId);\n const result: Record<string, any> = {};\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: any,\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"],"names":[],"mappings":";;;;;;;;;;;;AA8BO,IAAM,kBAAN,cAA8B,WAAW;AAAA,EAE9C,WAA0B;AAAA,EAI1B;AAAA,EAGA;AAAA,EAGA,QAAgB;AAAA;AAAA,EAEhB,YAAY,UAAkC,IAAI;AAChD,UAAM,OAAO;AACb,QAAI,QAAQ,cAAc,OAAW,MAAK,YAAY,QAAQ;AAC9D,QAAI,QAAQ,gBAAgB;AAC1B,WAAK,cAAc,QAAQ;AAC7B,QAAI,QAAQ,MAAO,MAAK,QAAQ,QAAQ;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,WAA6B;AACjC,UAAM,YAAY,MAAM,KAAK,YAAY,aAAa;AACtD,QAAI,CAAC,WAAW;AACd,YAAM,IAAI,MAAM,qBAAqB;AAAA,IACvC;AAEA,WAAO,MAAM,UAAU,cAAc,KAAK,KAAK;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,mBAAoC;AACxC,UAAM,YAAY,MAAM,KAAK,YAAY,aAAa;AACtD,WAAO,WAAW,QAAQ;AAAA,EAC5B;AACF;AA3CE,gBAAA;AAAA,EADC,SAAS,EAAE,UAAU,KAAA,CAAM;AAAA,GADjB,gBAEX,WAAA,YAAA,CAAA;AAIA,gBAAA;AAAA,EADC,WAAW,WAAW,EAAE,UAAU,MAAM;AAAA,GAL9B,gBAMX,WAAA,aAAA,CAAA;AAGA,gBAAA;AAAA,EADC,WAAW,oBAAoB,EAAE,UAAU,MAAM;AAAA,GARvC,gBASX,WAAA,eAAA,CAAA;AAGA,gBAAA;AAAA,EADC,MAAM,EAAE,UAAU,KAAA,CAAM;AAAA,GAXd,gBAYX,WAAA,SAAA,CAAA;AAZW,kBAAN,gBAAA;AAAA,EAPN,aAAa,EAAE,MAAM,YAAY;AAAA,EACjC,KAAK;AAAA,IACJ,eAAe;AAAA,IACf,KAAK,EAAE,SAAS,CAAC,QAAQ,OAAO,UAAU,UAAU,QAAQ,EAAA;AAAA,IAC5D,KAAK,EAAE,SAAS,CAAC,QAAQ,KAAK,EAAA;AAAA,IAC9B,KAAK;AAAA,EAAA,CACN;AAAA,GACY,eAAA;ACrBN,MAAM,kCAAkC,eAAgC;AAAA,EAC7E,OAAgB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ7B,MAAM,aAAa,WAA+C;AAChE,WAAO,MAAM,KAAK,KAAK,EAAE,OAAO,EAAE,UAAA,GAAa;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,kBAAkB,WAAiD;AACvE,UAAM,WAAW,MAAM,KAAK,aAAa,SAAS;AAClD,UAAM,SAA8B,CAAA;AAEpC,eAAW,QAAQ,UAAU;AAC3B,YAAM,OAAO,MAAM,KAAK,iBAAA;AACxB,UAAI,MAAM;AACR,eAAO,IAAI,IAAI,KAAK;AAAA,MACtB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,uBACJ,aACA,OACmB;AACnB,UAAM,UAAU,MAAM,KAAK,KAAK;AAAA,MAC9B,OAAO,EAAE,aAAa,OAAO,OAAO,KAAK,EAAA;AAAA,IAAE,CAC5C;AAED,WAAO,QACJ,IAAI,CAAC,MAAM,EAAE,SAAS,EACtB,OAAO,CAAC,OAAO,OAAO,OAAO,QAAQ;AAAA,EAC1C;AACF;;;;;"}
1
+ {"version":3,"file":"ProfileMetadataCollection-DEhmljMY.js","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: true,\n})\nexport class ProfileMetadata extends SmrtObject {\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 }\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"],"names":[],"mappings":";;;;;;;;;;;;AA8BO,IAAM,kBAAN,cAA8B,WAAW;AAAA,EAE9C,WAA0B;AAAA,EAI1B;AAAA,EAGA;AAAA,EAGA,QAAgB;AAAA;AAAA,EAEhB,YAAY,UAAkC,IAAI;AAChD,UAAM,OAAO;AACb,QAAI,QAAQ,cAAc,OAAW,MAAK,YAAY,QAAQ;AAC9D,QAAI,QAAQ,gBAAgB;AAC1B,WAAK,cAAc,QAAQ;AAC7B,QAAI,QAAQ,MAAO,MAAK,QAAQ,QAAQ;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,WAA6B;AACjC,UAAM,YAAY,MAAM,KAAK,YAAY,aAAa;AACtD,QAAI,CAAC,WAAW;AACd,YAAM,IAAI,MAAM,qBAAqB;AAAA,IACvC;AAEA,WAAO,MAAM,UAAU,cAAc,KAAK,KAAK;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,mBAAoC;AACxC,UAAM,YAAY,MAAM,KAAK,YAAY,aAAa;AACtD,WAAO,WAAW,QAAQ;AAAA,EAC5B;AACF;AA3CE,gBAAA;AAAA,EADC,SAAS,EAAE,UAAU,KAAA,CAAM;AAAA,GADjB,gBAEX,WAAA,YAAA,CAAA;AAIA,gBAAA;AAAA,EADC,WAAW,WAAW,EAAE,UAAU,MAAM;AAAA,GAL9B,gBAMX,WAAA,aAAA,CAAA;AAGA,gBAAA;AAAA,EADC,WAAW,oBAAoB,EAAE,UAAU,MAAM;AAAA,GARvC,gBASX,WAAA,eAAA,CAAA;AAGA,gBAAA;AAAA,EADC,MAAM,EAAE,UAAU,KAAA,CAAM;AAAA,GAXd,gBAYX,WAAA,SAAA,CAAA;AAZW,kBAAN,gBAAA;AAAA,EAPN,aAAa,EAAE,MAAM,YAAY;AAAA,EACjC,KAAK;AAAA,IACJ,eAAe;AAAA,IACf,KAAK,EAAE,SAAS,CAAC,QAAQ,OAAO,UAAU,UAAU,QAAQ,EAAA;AAAA,IAC5D,KAAK,EAAE,SAAS,CAAC,QAAQ,KAAK,EAAA;AAAA,IAC9B,KAAK;AAAA,EAAA,CACN;AAAA,GACY,eAAA;ACrBN,MAAM,kCAAkC,eAAgC;AAAA,EAC7E,OAAgB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ7B,MAAM,aAAa,WAA+C;AAChE,WAAO,MAAM,KAAK,KAAK,EAAE,OAAO,EAAE,UAAA,GAAa;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,kBAAkB,WAAoD;AAC1E,UAAM,WAAW,MAAM,KAAK,aAAa,SAAS;AAClD,UAAM,SAAiC,CAAA;AAEvC,eAAW,QAAQ,UAAU;AAC3B,YAAM,OAAO,MAAM,KAAK,iBAAA;AACxB,UAAI,MAAM;AACR,eAAO,IAAI,IAAI,KAAK;AAAA,MACtB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,uBACJ,aACA,OACmB;AACnB,UAAM,UAAU,MAAM,KAAK,KAAK;AAAA,MAC9B,OAAO,EAAE,aAAa,OAAO,OAAO,KAAK,EAAA;AAAA,IAAE,CAC5C;AAED,WAAO,QACJ,IAAI,CAAC,MAAM,EAAE,SAAS,EACtB,OAAO,CAAC,OAAO,OAAO,OAAO,QAAQ;AAAA,EAC1C;AACF;;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileMetafieldCollection-DMKhSHXX.js","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: true,\n})\nexport class ProfileMetafield extends SmrtObject {\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?: Record<string, any>; // 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 }\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: any): Promise<boolean> {\n if (!this.validation) return true;\n\n const schema = this.validation as ValidationSchema;\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"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ProfileMetafieldCollection-DMKhSHXX.js","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: true,\n})\nexport class ProfileMetafield extends SmrtObject {\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 }\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"],"names":[],"mappings":";;;;;;;;;;;;AA0CA,SAAS,sBAAsD;AAC7D,MAAI,CAAC,WAAW,kCAAkC;AAChD,eAAW,uDAAuC,IAAA;AAAA,EAIpD;AACA,SAAO,WAAW;AACpB;AASO,IAAM,mBAAN,cAA+B,WAAW;AAAA,EAE/C,WAA0B;AAAA,EAK1B,OAAe;AAAA,EAEf;AAAA,EAEA;AAAA;AAAA,EAEA,YAAY,UAAmC,IAAI;AACjD,UAAM,OAAO;AACb,QAAI,QAAQ,KAAM,MAAK,OAAO,QAAQ;AACtC,QAAI,QAAQ,gBAAgB;AAC1B,WAAK,cAAc,QAAQ;AAC7B,QAAI,QAAQ,eAAe,OAAW,MAAK,aAAa,QAAQ;AAAA,EAClE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,aAAa,UAAU,OAAiD;AAEtE,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,kBAAkB,MAAc,WAAoC;AACzE,0BAAsB,IAAI,MAAM,SAAS;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,aAAa,MAA6C;AAC/D,WAAO,oBAAA,EAAsB,IAAI,IAAI;AAAA,EACvC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,cAAc,OAAkC;AACpD,QAAI,CAAC,KAAK,WAAY,QAAO;AAE7B,UAAM,SAAS,KAAK;AAGpB,QAAI,OAAO,MAAM;AACf,YAAM,aAAa,OAAO;AAC1B,YAAM,eAAe,OAAO;AAE5B,UAAI,iBAAiB,YAAY,eAAe,UAAU;AACxD,cAAM,IAAI;AAAA,UACR,OAAO,WAAW,YAAY,YAAY,SAAS,UAAU;AAAA,QAAA;AAAA,MAEjE;AACA,UAAI,iBAAiB,YAAY,eAAe,UAAU;AACxD,cAAM,IAAI;AAAA,UACR,OAAO,WAAW,YAAY,YAAY,SAAS,UAAU;AAAA,QAAA;AAAA,MAEjE;AACA,UAAI,iBAAiB,aAAa,eAAe,WAAW;AAC1D,cAAM,IAAI;AAAA,UACR,OAAO,WAAW,YAAY,YAAY,SAAS,UAAU;AAAA,QAAA;AAAA,MAEjE;AAAA,IACF;AAGA,QAAI,OAAO,WAAW,OAAO,UAAU,UAAU;AAC/C,YAAM,QAAQ,IAAI,OAAO,OAAO,OAAO;AACvC,UAAI,CAAC,MAAM,KAAK,KAAK,GAAG;AACtB,cAAM,IAAI,MAAM,OAAO,WAAW,2BAA2B;AAAA,MAC/D;AAAA,IACF;AAEA,QAAI,OAAO,aAAa,OAAO,UAAU,UAAU;AACjD,UAAI,MAAM,SAAS,OAAO,WAAW;AACnC,cAAM,IAAI;AAAA,UACR,OAAO,WACL,qBAAqB,OAAO,SAAS,SAAS,MAAM,MAAM;AAAA,QAAA;AAAA,MAEhE;AAAA,IACF;AAEA,QAAI,OAAO,aAAa,OAAO,UAAU,UAAU;AACjD,UAAI,MAAM,SAAS,OAAO,WAAW;AACnC,cAAM,IAAI;AAAA,UACR,OAAO,WACL,qBAAqB,OAAO,SAAS,SAAS,MAAM,MAAM;AAAA,QAAA;AAAA,MAEhE;AAAA,IACF;AAGA,QAAI,OAAO,QAAQ,UAAa,OAAO,UAAU,UAAU;AACzD,UAAI,QAAQ,OAAO,KAAK;AACtB,cAAM,IAAI;AAAA,UACR,OAAO,WAAW,0BAA0B,OAAO,GAAG;AAAA,QAAA;AAAA,MAE1D;AAAA,IACF;AAEA,QAAI,OAAO,QAAQ,UAAa,OAAO,UAAU,UAAU;AACzD,UAAI,QAAQ,OAAO,KAAK;AACtB,cAAM,IAAI;AAAA,UACR,OAAO,WAAW,yBAAyB,OAAO,GAAG;AAAA,QAAA;AAAA,MAEzD;AAAA,IACF;AAGA,QAAI,OAAO,QAAQ;AACjB,YAAM,YAAY,iBAAiB,aAAa,OAAO,MAAM;AAC7D,UAAI,CAAC,WAAW;AACd,cAAM,IAAI,MAAM,qBAAqB,OAAO,MAAM,kBAAkB;AAAA,MACtE;AAEA,YAAM,SAAS,MAAM,UAAU,KAAK;AACpC,UAAI,CAAC,QAAQ;AACX,cAAM,IAAI,MAAM,OAAO,WAAW,0BAA0B;AAAA,MAC9D;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AACF;AA7IE,gBAAA;AAAA,EADC,SAAS,EAAE,UAAU,KAAA,CAAM;AAAA,GADjB,iBAEX,WAAA,YAAA,CAAA;AAKA,gBAAA;AAAA,EADC,MAAM,EAAE,UAAU,KAAA,CAAM;AAAA,GANd,iBAOX,WAAA,QAAA,CAAA;AAPW,mBAAN,gBAAA;AAAA,EAPN,aAAa,EAAE,MAAM,YAAY;AAAA,EACjC,KAAK;AAAA,IACJ,eAAe;AAAA,IACf,KAAK,EAAE,SAAS,CAAC,QAAQ,OAAO,UAAU,QAAQ,EAAA;AAAA,IAClD,KAAK,EAAE,SAAS,CAAC,QAAQ,KAAK,EAAA;AAAA,IAC9B,KAAK;AAAA,EAAA,CACN;AAAA,GACY,gBAAA;ACjDN,MAAM,mCAAmC,eAAiC;AAAA,EAC/E,OAAgB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ7B,MAAM,UAAU,MAAgD;AAC9D,WAAO,MAAM,KAAK,IAAI,EAAE,MAAM;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,kBACJ,MACA,UAK2B;AAC3B,UAAM,WAAW,MAAM,KAAK,UAAU,IAAI;AAC1C,QAAI,SAAU,QAAO;AAErB,UAAM,YAAY,MAAM,KAAK,OAAO,EAAE,MAAM,GAAG,UAAU;AACzD,UAAM,UAAU,KAAA;AAChB,WAAO;AAAA,EACT;AACF;;;;;"}
@@ -43,10 +43,18 @@ let ProfileRelationship = class extends SmrtObject {
43
43
  * @param endedAt - Optional end date of the term
44
44
  */
45
45
  async addTerm(startedAt, endedAt) {
46
+ if (!this.id) {
47
+ throw new Error(
48
+ "ProfileRelationship.addTerm requires a persisted relationship (missing id)"
49
+ );
50
+ }
51
+ const relationshipId = this.id;
46
52
  const { ProfileRelationshipTermCollection } = await import("./ProfileRelationshipTermCollection-CXem_qT-.js").then((n) => n.b);
47
- const termCollection = await ProfileRelationshipTermCollection.create(this.options);
53
+ const termCollection = await ProfileRelationshipTermCollection.create(
54
+ this.options
55
+ );
48
56
  const term = await termCollection.create({
49
- relationshipId: this.id,
57
+ relationshipId,
50
58
  startedAt,
51
59
  endedAt
52
60
  });
@@ -70,7 +78,9 @@ let ProfileRelationship = class extends SmrtObject {
70
78
  */
71
79
  async getTerms() {
72
80
  const { ProfileRelationshipTermCollection } = await import("./ProfileRelationshipTermCollection-CXem_qT-.js").then((n) => n.b);
73
- const termCollection = await ProfileRelationshipTermCollection.create(this.options);
81
+ const termCollection = await ProfileRelationshipTermCollection.create(
82
+ this.options
83
+ );
74
84
  return await termCollection.getByRelationship(this.id);
75
85
  }
76
86
  /**
@@ -80,7 +90,9 @@ let ProfileRelationship = class extends SmrtObject {
80
90
  */
81
91
  async getActiveTerm() {
82
92
  const { ProfileRelationshipTermCollection } = await import("./ProfileRelationshipTermCollection-CXem_qT-.js").then((n) => n.b);
83
- const termCollection = await ProfileRelationshipTermCollection.create(this.options);
93
+ const termCollection = await ProfileRelationshipTermCollection.create(
94
+ this.options
95
+ );
84
96
  return await termCollection.getActiveTerm(this.id);
85
97
  }
86
98
  };
@@ -174,4 +186,4 @@ export {
174
186
  ProfileRelationshipCollection as a,
175
187
  ProfileRelationshipCollection$1 as b
176
188
  };
177
- //# sourceMappingURL=ProfileRelationshipCollection-C0IM8UQR.js.map
189
+ //# sourceMappingURL=ProfileRelationshipCollection-_TsY7MHL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProfileRelationshipCollection-_TsY7MHL.js","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: true,\n})\nexport class ProfileRelationship extends SmrtObject {\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"],"names":[],"mappings":"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"}
@@ -1,14 +1,14 @@
1
1
  import { ObjectRegistry, foreignKey, smrt, SmrtObject, SmrtCollection, field } from "@happyvertical/smrt-core";
2
- import { P as ProfileType, a as Profile } from "./ProfileCollection-DQD1uJEc.js";
2
+ import { P as ProfileType, a as Profile } from "./ProfileCollection-M2PK8bp-.js";
3
3
  import { createHash, randomBytes } from "node:crypto";
4
4
  import { N as NostrIdentityCollection, g as generateNostrKeypair, e as encryptPrivkey, a as NostrIdentity, v as verifyAuthEvent } from "./NostrIdentityCollection-DadQBHWy.js";
5
5
  import { ApiKey } from "./ApiKey-B2LKEaP8.js";
6
6
  import "./ApiKeyCollection-B6Op817e.js";
7
7
  import "./AuditLogCollection-BYqCj0uE.js";
8
- import "./ProfileAssetCollection-ChX4kLjN.js";
8
+ import "./ProfileAssetCollection-CUM5QfuJ.js";
9
9
  import "./ProfileMetadataCollection-DEhmljMY.js";
10
10
  import "./ProfileMetafieldCollection-DMKhSHXX.js";
11
- import "./ProfileRelationshipCollection-C0IM8UQR.js";
11
+ import "./ProfileRelationshipCollection-_TsY7MHL.js";
12
12
  import "./ProfileRelationshipTermCollection-CXem_qT-.js";
13
13
  import "./ProfileRelationshipTypeCollection-CF8YvLTV.js";
14
14
  import "./ProfileRelationshipType-BXBLldea.js";
@@ -345,7 +345,7 @@ function createMagicLinkService(config) {
345
345
  const typeCollection = await ProfileTypeCollection2.create({ db });
346
346
  let personType = await typeCollection.getBySlug("person");
347
347
  if (!personType) {
348
- const { ProfileType: ProfileType2 } = await import("./ProfileCollection-DQD1uJEc.js").then((n) => n.c);
348
+ const { ProfileType: ProfileType2 } = await import("./ProfileCollection-M2PK8bp-.js").then((n) => n.c);
349
349
  personType = new ProfileType2({
350
350
  db,
351
351
  slug: "person",
@@ -707,7 +707,7 @@ async function findProfileByExternalId(provider, externalId, options) {
707
707
  if (profile) return profile;
708
708
  }
709
709
  }
710
- const { ProfileCollection } = await import("./ProfileCollection-DQD1uJEc.js").then((n) => n.d);
710
+ const { ProfileCollection } = await import("./ProfileCollection-M2PK8bp-.js").then((n) => n.d);
711
711
  const profileCollection = await ProfileCollection.create(options);
712
712
  const profiles = await profileCollection.list({
713
713
  where: {
@@ -740,7 +740,7 @@ async function createProfileFromOidc(claims, provider, options) {
740
740
  }
741
741
  }
742
742
  if (claims.email && claims.email_verified) {
743
- const { ProfileCollection } = await import("./ProfileCollection-DQD1uJEc.js").then((n) => n.d);
743
+ const { ProfileCollection } = await import("./ProfileCollection-M2PK8bp-.js").then((n) => n.d);
744
744
  const profileCollection = await ProfileCollection.create(options);
745
745
  const existingProfile = await profileCollection.findByEmail(claims.email);
746
746
  if (existingProfile) {
@@ -766,7 +766,7 @@ async function createProfileFromOidc(claims, provider, options) {
766
766
  const typeCollection = await ProfileTypeCollection2.create(options);
767
767
  let personType = await typeCollection.getBySlug("person");
768
768
  if (!personType) {
769
- const { ProfileType: ProfileType2 } = await import("./ProfileCollection-DQD1uJEc.js").then((n) => n.c);
769
+ const { ProfileType: ProfileType2 } = await import("./ProfileCollection-M2PK8bp-.js").then((n) => n.c);
770
770
  personType = new ProfileType2({
771
771
  ...options,
772
772
  slug: "person",
@@ -821,7 +821,7 @@ async function createProfileFromNostr(email, nostrData, options) {
821
821
  const typeCollection = await ProfileTypeCollection2.create(options);
822
822
  let personType = await typeCollection.getBySlug("person");
823
823
  if (!personType) {
824
- const { ProfileType: ProfileType2 } = await import("./ProfileCollection-DQD1uJEc.js").then((n) => n.c);
824
+ const { ProfileType: ProfileType2 } = await import("./ProfileCollection-M2PK8bp-.js").then((n) => n.c);
825
825
  personType = new ProfileType2({
826
826
  ...options,
827
827
  slug: "person",
@@ -1026,4 +1026,4 @@ export {
1026
1026
  parseNip05Identifier as p,
1027
1027
  resolveIdentity as r
1028
1028
  };
1029
- //# sourceMappingURL=index-DHLYp075.js.map
1029
+ //# sourceMappingURL=index-B9lXQy7N.js.map