@happyvertical/smrt-profiles 0.37.2 → 0.37.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.
Files changed (61) hide show
  1. package/dist/chunks/ApiKey-3DlNEc91.js +145 -0
  2. package/dist/chunks/ApiKey-3DlNEc91.js.map +1 -0
  3. package/dist/chunks/ApiKeyCollection-PwVs0qDb.js +83 -0
  4. package/dist/chunks/ApiKeyCollection-PwVs0qDb.js.map +1 -0
  5. package/dist/chunks/AuditLogCollection-CnIYU0aK.js +191 -0
  6. package/dist/chunks/AuditLogCollection-CnIYU0aK.js.map +1 -0
  7. package/dist/chunks/NostrIdentityCollection-CG6HGf6c.js +3267 -0
  8. package/dist/chunks/NostrIdentityCollection-CG6HGf6c.js.map +1 -0
  9. package/dist/chunks/OidcIdentityCollection-DiLneB7J.js +158 -0
  10. package/dist/chunks/OidcIdentityCollection-DiLneB7J.js.map +1 -0
  11. package/dist/chunks/ProfileAssetCollection-BY2Wbem3.js +93 -0
  12. package/dist/chunks/ProfileAssetCollection-BY2Wbem3.js.map +1 -0
  13. package/dist/chunks/ProfileCollection-DlhdOnDr.js +641 -0
  14. package/dist/chunks/ProfileCollection-DlhdOnDr.js.map +1 -0
  15. package/dist/chunks/ProfileMetadataCollection-CGcO4Iw_.js +105 -0
  16. package/dist/chunks/ProfileMetadataCollection-CGcO4Iw_.js.map +1 -0
  17. package/dist/chunks/ProfileMetafieldCollection-C8TX9HvN.js +142 -0
  18. package/dist/chunks/ProfileMetafieldCollection-C8TX9HvN.js.map +1 -0
  19. package/dist/chunks/ProfileRelationshipCollection-JnskbZTd.js +159 -0
  20. package/dist/chunks/ProfileRelationshipCollection-JnskbZTd.js.map +1 -0
  21. package/dist/chunks/ProfileRelationshipTermCollection-UopP7sja.js +105 -0
  22. package/dist/chunks/ProfileRelationshipTermCollection-UopP7sja.js.map +1 -0
  23. package/dist/chunks/ProfileRelationshipType-OMBn5cWR.js +98 -0
  24. package/dist/chunks/ProfileRelationshipType-OMBn5cWR.js.map +1 -0
  25. package/dist/chunks/ProfileRelationshipTypeCollection-CQu08kxF.js +54 -0
  26. package/dist/chunks/ProfileRelationshipTypeCollection-CQu08kxF.js.map +1 -0
  27. package/dist/index.js +690 -69
  28. package/dist/index.js.map +1 -1
  29. package/dist/manifest.json +2 -2
  30. package/dist/smrt-knowledge.json +9 -9
  31. package/dist/types.js +0 -2
  32. package/dist/utils.js +18 -36
  33. package/dist/utils.js.map +1 -1
  34. package/package.json +16 -16
  35. package/dist/chunks/ApiKey-B2LKEaP8.js +0 -143
  36. package/dist/chunks/ApiKey-B2LKEaP8.js.map +0 -1
  37. package/dist/chunks/ApiKeyCollection-B6Op817e.js +0 -91
  38. package/dist/chunks/ApiKeyCollection-B6Op817e.js.map +0 -1
  39. package/dist/chunks/AuditLogCollection-BYqCj0uE.js +0 -195
  40. package/dist/chunks/AuditLogCollection-BYqCj0uE.js.map +0 -1
  41. package/dist/chunks/NostrIdentityCollection-DadQBHWy.js +0 -3065
  42. package/dist/chunks/NostrIdentityCollection-DadQBHWy.js.map +0 -1
  43. package/dist/chunks/ProfileAssetCollection-CUM5QfuJ.js +0 -122
  44. package/dist/chunks/ProfileAssetCollection-CUM5QfuJ.js.map +0 -1
  45. package/dist/chunks/ProfileCollection-M2PK8bp-.js +0 -800
  46. package/dist/chunks/ProfileCollection-M2PK8bp-.js.map +0 -1
  47. package/dist/chunks/ProfileMetadataCollection-DEhmljMY.js +0 -120
  48. package/dist/chunks/ProfileMetadataCollection-DEhmljMY.js.map +0 -1
  49. package/dist/chunks/ProfileMetafieldCollection-DMKhSHXX.js +0 -184
  50. package/dist/chunks/ProfileMetafieldCollection-DMKhSHXX.js.map +0 -1
  51. package/dist/chunks/ProfileRelationshipCollection-_TsY7MHL.js +0 -189
  52. package/dist/chunks/ProfileRelationshipCollection-_TsY7MHL.js.map +0 -1
  53. package/dist/chunks/ProfileRelationshipTermCollection-CXem_qT-.js +0 -117
  54. package/dist/chunks/ProfileRelationshipTermCollection-CXem_qT-.js.map +0 -1
  55. package/dist/chunks/ProfileRelationshipType-BXBLldea.js +0 -103
  56. package/dist/chunks/ProfileRelationshipType-BXBLldea.js.map +0 -1
  57. package/dist/chunks/ProfileRelationshipTypeCollection-CF8YvLTV.js +0 -48
  58. package/dist/chunks/ProfileRelationshipTypeCollection-CF8YvLTV.js.map +0 -1
  59. package/dist/chunks/index-B9lXQy7N.js +0 -1029
  60. package/dist/chunks/index-B9lXQy7N.js.map +0 -1
  61. package/dist/types.js.map +0 -1
@@ -1,800 +0,0 @@
1
- import { resolveOwnedAssetsById, assertValidOwnedAssetRelationship, assertValidOwnedAssetSortOrder, getOwnedAssetsFromCollection, addOwnedAssetFromCollection, removeOwnedAssetFromCollection } from "@happyvertical/smrt-assets";
2
- import { field, smrt, SmrtObject, foreignKey, oneToMany, SmrtCollection } from "@happyvertical/smrt-core";
3
- import { tenantId, TenantScoped, queryGlobal, queryWithGlobals } from "@happyvertical/smrt-tenancy";
4
- import { definePrompt, resolvePrompt } from "@happyvertical/smrt-prompts";
5
- const smrtProfilesGenerateBioPrompt = definePrompt({
6
- key: "smrtProfiles.profile.generateBio",
7
- template: `Write a short, professional bio for this person.
8
-
9
- Profile name: {profileName}
10
- Profile description: {profileDescription}
11
-
12
- Return only the bio text, with no commentary or surrounding quotation marks.`,
13
- editable: {
14
- template: true,
15
- profile: true,
16
- model: true,
17
- params: true
18
- }
19
- });
20
- function promptMessageOptions(ai) {
21
- return {
22
- ...ai.params || {},
23
- ...ai.model ? { model: ai.model } : {},
24
- ...typeof ai.temperature === "number" ? { temperature: ai.temperature } : {},
25
- ...typeof ai.maxTokens === "number" ? { maxTokens: ai.maxTokens } : {}
26
- };
27
- }
28
- var __defProp$1 = Object.defineProperty;
29
- var __getOwnPropDesc$1 = Object.getOwnPropertyDescriptor;
30
- var __decorateClass$1 = (decorators, target, key, kind) => {
31
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$1(target, key) : target;
32
- for (var i = decorators.length - 1, decorator; i >= 0; i--)
33
- if (decorator = decorators[i])
34
- result = (kind ? decorator(target, key, result) : decorator(result)) || result;
35
- if (kind && result) __defProp$1(target, key, result);
36
- return result;
37
- };
38
- let ProfileType = class extends SmrtObject {
39
- tenantId = null;
40
- name = "";
41
- description;
42
- constructor(options = {}) {
43
- super(options);
44
- if (options.name) this.name = options.name;
45
- if (options.description !== void 0)
46
- this.description = options.description;
47
- }
48
- /**
49
- * Convenience method for slug-based lookup
50
- *
51
- * @param slug - The slug to search for
52
- * @returns ProfileType instance or null if not found
53
- */
54
- static async getBySlug(_slug) {
55
- return null;
56
- }
57
- };
58
- __decorateClass$1([
59
- tenantId({ nullable: true })
60
- ], ProfileType.prototype, "tenantId", 2);
61
- __decorateClass$1([
62
- field({ required: true })
63
- ], ProfileType.prototype, "name", 2);
64
- ProfileType = __decorateClass$1([
65
- TenantScoped({ mode: "optional" }),
66
- smrt({
67
- tableStrategy: "sti",
68
- api: { include: ["list", "get", "create", "update"] },
69
- mcp: { include: ["list", "get"] },
70
- cli: true
71
- })
72
- ], ProfileType);
73
- const ProfileType$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
74
- __proto__: null,
75
- get ProfileType() {
76
- return ProfileType;
77
- }
78
- }, Symbol.toStringTag, { value: "Module" }));
79
- var __defProp = Object.defineProperty;
80
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
81
- var __decorateClass = (decorators, target, key, kind) => {
82
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
83
- for (var i = decorators.length - 1, decorator; i >= 0; i--)
84
- if (decorator = decorators[i])
85
- result = (kind ? decorator(target, key, result) : decorator(result)) || result;
86
- if (kind && result) __defProp(target, key, result);
87
- return result;
88
- };
89
- let Profile = class extends SmrtObject {
90
- tenantId = null;
91
- typeId;
92
- email;
93
- name = "";
94
- // Display name
95
- description;
96
- metadata = [];
97
- relationshipsFrom = [];
98
- relationshipsTo = [];
99
- constructor(options = {}) {
100
- super(options);
101
- if (options.typeId !== void 0) this.typeId = options.typeId;
102
- if (options.email !== void 0) this.email = options.email;
103
- if (options.name) this.name = options.name;
104
- if (options.description !== void 0)
105
- this.description = options.description;
106
- }
107
- /**
108
- * Get the profile type slug for this profile
109
- *
110
- * @returns The slug of the profile type
111
- */
112
- async getTypeSlug() {
113
- const type = await this.loadRelated("typeId");
114
- return type?.slug || "";
115
- }
116
- /**
117
- * Set the profile type by slug
118
- *
119
- * @param slug - The slug of the profile type
120
- * @throws Error if profile type not found
121
- */
122
- async setTypeBySlug(slug) {
123
- const type = await ProfileType.getBySlug(slug);
124
- if (!type) throw new Error(`Profile type '${slug}' not found`);
125
- this.typeId = type.id;
126
- }
127
- /**
128
- * Add metadata to this profile
129
- *
130
- * @param metafieldSlug - The slug of the metafield
131
- * @param value - The value to set
132
- */
133
- async addMetadata(metafieldSlug, value) {
134
- const { ProfileMetafieldCollection } = await import("./ProfileMetafieldCollection-DMKhSHXX.js").then((n) => n.b);
135
- const { ProfileMetadataCollection } = await import("./ProfileMetadataCollection-DEhmljMY.js").then((n) => n.b);
136
- const metafieldCollection = await ProfileMetafieldCollection.create(
137
- this.options
138
- );
139
- const metafield = await metafieldCollection.getBySlug(metafieldSlug);
140
- if (!metafield) {
141
- throw new Error(`Metafield '${metafieldSlug}' not found`);
142
- }
143
- await metafield.validateValue(value);
144
- const metadataCollection = await ProfileMetadataCollection.create(
145
- this.options
146
- );
147
- const existing = await metadataCollection.list({
148
- where: { profileId: this.id, metafieldId: metafield.id },
149
- limit: 1
150
- });
151
- if (existing.length > 0) {
152
- const metadata = existing[0];
153
- metadata.value = String(value);
154
- await metadata.save();
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
- }
161
- const metadata = await metadataCollection.create({
162
- profileId: this.id,
163
- metafieldId: metafield.id,
164
- value: String(value)
165
- });
166
- await metadata.save();
167
- }
168
- }
169
- /**
170
- * Get all metadata for this profile as key-value object
171
- *
172
- * @returns Object with metafield slugs as keys
173
- */
174
- async getMetadata() {
175
- const { ProfileMetadataCollection } = await import("./ProfileMetadataCollection-DEhmljMY.js").then((n) => n.b);
176
- const metadataCollection = await ProfileMetadataCollection.create(
177
- this.options
178
- );
179
- return await metadataCollection.getMetadataObject(this.id);
180
- }
181
- /**
182
- * Update multiple metadata values
183
- *
184
- * @param metadata - Object with metafield slugs as keys and values
185
- */
186
- async updateMetadata(metadata) {
187
- for (const [metafieldSlug, value] of Object.entries(metadata)) {
188
- await this.addMetadata(metafieldSlug, value);
189
- }
190
- }
191
- /**
192
- * Remove metadata by metafield slug
193
- *
194
- * @param metafieldSlug - The slug of the metafield to remove
195
- */
196
- async removeMetadata(metafieldSlug) {
197
- const { ProfileMetafieldCollection } = await import("./ProfileMetafieldCollection-DMKhSHXX.js").then((n) => n.b);
198
- const { ProfileMetadataCollection } = await import("./ProfileMetadataCollection-DEhmljMY.js").then((n) => n.b);
199
- const metafieldCollection = await ProfileMetafieldCollection.create(
200
- this.options
201
- );
202
- const metafield = await metafieldCollection.getBySlug(metafieldSlug);
203
- if (!metafield) {
204
- throw new Error(`Metafield '${metafieldSlug}' not found`);
205
- }
206
- const metadataCollection = await ProfileMetadataCollection.create(
207
- this.options
208
- );
209
- const existing = await metadataCollection.list({
210
- where: { profileId: this.id, metafieldId: metafield.id },
211
- limit: 1
212
- });
213
- if (existing.length > 0) {
214
- await existing[0].delete();
215
- }
216
- }
217
- async getProfileAssetCollection() {
218
- const { ProfileAssetCollection } = await import("./ProfileAssetCollection-CUM5QfuJ.js").then((n) => n.b);
219
- return ProfileAssetCollection.create({ db: this.db });
220
- }
221
- async getAssets(relationship) {
222
- if (!this.id) {
223
- return [];
224
- }
225
- const profileAssets = await this.getProfileAssetCollection();
226
- const linkedAssets = await profileAssets.byLeft(
227
- this.id,
228
- relationship ? { relationship } : {}
229
- );
230
- return resolveOwnedAssetsById(
231
- this.db,
232
- linkedAssets.map((link) => link.assetId),
233
- this.tenantId
234
- );
235
- }
236
- async addAsset(asset, relationship = "attachment", sortOrder = 0) {
237
- if (!this.id || !asset.id) {
238
- throw new Error("Cannot associate unsaved profile or asset");
239
- }
240
- assertValidOwnedAssetRelationship(relationship);
241
- assertValidOwnedAssetSortOrder(sortOrder);
242
- const profileAssets = await this.getProfileAssetCollection();
243
- await profileAssets.attach(this.id, asset.id, {
244
- relationship,
245
- sortOrder,
246
- tenantId: this.tenantId
247
- });
248
- }
249
- async removeAsset(assetId, relationship) {
250
- if (!this.id) {
251
- return;
252
- }
253
- const profileAssets = await this.getProfileAssetCollection();
254
- await profileAssets.detach(
255
- this.id,
256
- assetId,
257
- relationship ? { relationship } : {}
258
- );
259
- }
260
- /**
261
- * Add a relationship to another profile
262
- *
263
- * @param toProfile - The target profile
264
- * @param relationshipSlug - The type of relationship
265
- * @param contextProfile - Optional context profile for tertiary relationships
266
- */
267
- async addRelationship(toProfile, relationshipSlug, contextProfile) {
268
- const { ProfileRelationshipTypeCollection } = await import("./ProfileRelationshipTypeCollection-CF8YvLTV.js");
269
- const { ProfileRelationshipCollection } = await import("./ProfileRelationshipCollection-_TsY7MHL.js").then((n) => n.b);
270
- const { ProfileRelationshipType } = await import("./ProfileRelationshipType-BXBLldea.js");
271
- const relationshipTypeCollection = await ProfileRelationshipTypeCollection.create(this.options);
272
- const relationshipType = await relationshipTypeCollection.getBySlug(relationshipSlug);
273
- if (!relationshipType) {
274
- throw new Error(`Relationship type '${relationshipSlug}' not found`);
275
- }
276
- const relationshipCollection = await ProfileRelationshipCollection.create(
277
- this.options
278
- );
279
- const exists = await relationshipCollection.exists(
280
- this.id,
281
- toProfile.id,
282
- relationshipType.id
283
- );
284
- if (!exists) {
285
- const relationship = await relationshipCollection.create({
286
- fromProfileId: this.id ?? void 0,
287
- toProfileId: toProfile.id ?? void 0,
288
- typeId: relationshipType.id ?? void 0,
289
- contextProfileId: contextProfile?.id ?? void 0
290
- });
291
- await relationship.save();
292
- if (relationshipType.reciprocal) {
293
- const handler = ProfileRelationshipType.getReciprocalHandler(relationshipSlug);
294
- if (handler) {
295
- await handler(this, toProfile, contextProfile);
296
- }
297
- }
298
- }
299
- }
300
- /**
301
- * Get all relationships for this profile
302
- *
303
- * @param options - Filter options (typeSlug, direction)
304
- * @returns Array of ProfileRelationship instances
305
- */
306
- async getRelationships(options) {
307
- const { ProfileRelationshipCollection } = await import("./ProfileRelationshipCollection-_TsY7MHL.js").then((n) => n.b);
308
- const { ProfileRelationshipTypeCollection } = await import("./ProfileRelationshipTypeCollection-CF8YvLTV.js");
309
- const relationshipCollection = await ProfileRelationshipCollection.create(
310
- this.options
311
- );
312
- const direction = options?.direction || "all";
313
- let typeId;
314
- if (options?.typeSlug) {
315
- const relationshipTypeCollection = await ProfileRelationshipTypeCollection.create(this.options);
316
- const relationshipType = await relationshipTypeCollection.getBySlug(
317
- options.typeSlug
318
- );
319
- typeId = relationshipType?.id ?? void 0;
320
- }
321
- if (direction === "from") {
322
- return await relationshipCollection.getFromProfile(
323
- this.id,
324
- typeId
325
- );
326
- } else if (direction === "to") {
327
- return await relationshipCollection.getToProfile(
328
- this.id,
329
- typeId
330
- );
331
- } else {
332
- return await relationshipCollection.getForProfile(
333
- this.id,
334
- typeId
335
- );
336
- }
337
- }
338
- /**
339
- * Get related profiles
340
- *
341
- * @param relationshipSlug - Optional filter by relationship type slug
342
- * @returns Array of related Profile instances
343
- */
344
- async getRelatedProfiles(relationshipSlug) {
345
- const { ProfileCollection: ProfileCollection2 } = await Promise.resolve().then(() => ProfileCollection$1);
346
- const relationships = await this.getRelationships({
347
- typeSlug: relationshipSlug,
348
- direction: "all"
349
- });
350
- const profileCollection = await ProfileCollection2.create(this.options);
351
- const relatedProfiles = [];
352
- const seenIds = /* @__PURE__ */ new Set();
353
- for (const relationship of relationships) {
354
- const fromId = String(relationship.fromProfileId);
355
- const toId = String(relationship.toProfileId);
356
- const thisId = String(this.id);
357
- const otherId = fromId === thisId ? toId : fromId;
358
- if (!seenIds.has(otherId)) {
359
- seenIds.add(otherId);
360
- const profile = await profileCollection.get({ id: otherId });
361
- if (profile) {
362
- relatedProfiles.push(profile);
363
- }
364
- }
365
- }
366
- return relatedProfiles;
367
- }
368
- /**
369
- * Remove a relationship to another profile
370
- *
371
- * @param toProfile - The target profile
372
- * @param relationshipSlug - The type of relationship to remove
373
- */
374
- async removeRelationship(toProfile, relationshipSlug) {
375
- const { ProfileRelationshipTypeCollection } = await import("./ProfileRelationshipTypeCollection-CF8YvLTV.js");
376
- const { ProfileRelationshipCollection } = await import("./ProfileRelationshipCollection-_TsY7MHL.js").then((n) => n.b);
377
- const relationshipTypeCollection = await ProfileRelationshipTypeCollection.create(this.options);
378
- const relationshipType = await relationshipTypeCollection.getBySlug(relationshipSlug);
379
- if (!relationshipType) {
380
- throw new Error(`Relationship type '${relationshipSlug}' not found`);
381
- }
382
- const relationshipCollection = await ProfileRelationshipCollection.create(
383
- this.options
384
- );
385
- const relationships = await relationshipCollection.list({
386
- where: {
387
- fromProfileId: this.id,
388
- toProfileId: toProfile.id,
389
- typeId: relationshipType.id
390
- }
391
- });
392
- for (const relationship of relationships) {
393
- await relationship.delete();
394
- }
395
- if (relationshipType.reciprocal) {
396
- const inverseRelationships = await relationshipCollection.list({
397
- where: {
398
- fromProfileId: toProfile.id,
399
- toProfileId: this.id,
400
- typeId: relationshipType.id
401
- }
402
- });
403
- for (const relationship of inverseRelationships) {
404
- await relationship.delete();
405
- }
406
- }
407
- }
408
- /**
409
- * AI-powered: Generate a professional bio for this profile
410
- *
411
- * Uses the `smrtProfiles.profile.generateBio` prompt registered via
412
- * `@happyvertical/smrt-prompts`, allowing tenant- or instance-level
413
- * overrides of the template, model, and parameters at runtime.
414
- *
415
- * @returns Generated bio text
416
- */
417
- async generateBio() {
418
- const db = this.options.db ?? this.options.persistence;
419
- const resolvedPrompt = await resolvePrompt(
420
- smrtProfilesGenerateBioPrompt.key,
421
- {
422
- db,
423
- tenantId: this.tenantId,
424
- variables: {
425
- profileName: this.name || "",
426
- profileDescription: this.description || ""
427
- }
428
- }
429
- );
430
- const ai = await this.getAiClient();
431
- const response = await ai.message(
432
- resolvedPrompt.text,
433
- promptMessageOptions(resolvedPrompt.ai)
434
- );
435
- return response.trim();
436
- }
437
- /**
438
- * AI-powered: Check if profile matches criteria
439
- *
440
- * @param criteria - Criteria to match against
441
- * @returns True if matches criteria
442
- */
443
- async matches(criteria) {
444
- return await this.is(criteria);
445
- }
446
- /**
447
- * Find profiles by metadata key-value pair
448
- *
449
- * @param metafieldSlug - The metafield slug to search
450
- * @param value - The value to match
451
- * @returns Array of matching profiles
452
- */
453
- static async findByMetadata(_metafieldSlug, _value) {
454
- return [];
455
- }
456
- /**
457
- * Find profiles by type slug
458
- *
459
- * @param typeSlug - The profile type slug
460
- * @returns Array of matching profiles
461
- */
462
- static async findByType(_typeSlug) {
463
- return [];
464
- }
465
- /**
466
- * Find related profiles for a given profile
467
- *
468
- * @param profileId - The profile UUID
469
- * @param relationshipSlug - Optional filter by relationship type
470
- * @returns Array of related profiles
471
- */
472
- static async findRelated(_profileId, _relationshipSlug) {
473
- return [];
474
- }
475
- /**
476
- * Search profiles by email
477
- *
478
- * @param email - The email to search for
479
- * @returns Profile or null if not found
480
- */
481
- static async searchByEmail(_email) {
482
- return null;
483
- }
484
- // ========================
485
- // Auth-related methods
486
- // ========================
487
- /**
488
- * Get all API keys for this profile
489
- *
490
- * @returns Array of API keys
491
- */
492
- async getApiKeys() {
493
- const { ApiKeyCollection } = await import("./ApiKeyCollection-B6Op817e.js");
494
- const collection = await ApiKeyCollection.create(this.options);
495
- return await collection.findByProfile(this.id);
496
- }
497
- /**
498
- * Get active (non-revoked, non-expired) API keys for this profile
499
- *
500
- * @returns Array of active API keys
501
- */
502
- async getActiveApiKeys() {
503
- const { ApiKeyCollection } = await import("./ApiKeyCollection-B6Op817e.js");
504
- const collection = await ApiKeyCollection.create(this.options);
505
- return await collection.findActiveByProfile(this.id);
506
- }
507
- /**
508
- * Generate a new API key for this profile
509
- *
510
- * @param options - Key options (name, scopes, expiration)
511
- * @returns The generated key (plaintext) and ApiKey record
512
- */
513
- async generateApiKey(options) {
514
- const { ApiKey } = await import("./ApiKey-B2LKEaP8.js");
515
- return await ApiKey.generate(this, {
516
- ...options,
517
- db: this.options?.db
518
- });
519
- }
520
- /**
521
- * Get all OIDC identities linked to this profile
522
- *
523
- * @returns Array of OIDC identity records
524
- */
525
- async getOidcIdentities() {
526
- const { OidcIdentityCollection } = await import("./index-B9lXQy7N.js").then((n) => n.j);
527
- const collection = await OidcIdentityCollection.create(this.options);
528
- return await collection.findByProfile(this.id);
529
- }
530
- /**
531
- * Link a new OIDC identity to this profile
532
- *
533
- * @param oidcData - OIDC provider data
534
- * @returns The linked OIDC identity record
535
- */
536
- async linkOidcIdentity(oidcData) {
537
- const { OidcIdentityCollection } = await import("./index-B9lXQy7N.js").then((n) => n.j);
538
- const collection = await OidcIdentityCollection.create(this.options);
539
- return await collection.linkToProfile(this, oidcData);
540
- }
541
- /**
542
- * Get all Nostr identities linked to this profile
543
- *
544
- * @returns Array of Nostr identity records
545
- */
546
- async getNostrIdentities() {
547
- const { NostrIdentityCollection } = await import("./NostrIdentityCollection-DadQBHWy.js").then((n) => n.q);
548
- const collection = await NostrIdentityCollection.create(this.options);
549
- return await collection.findByProfile(this.id);
550
- }
551
- /**
552
- * Link a new Nostr identity to this profile
553
- *
554
- * @param nostrData - Nostr identity data (encrypted keypair)
555
- * @returns The linked Nostr identity record
556
- */
557
- async linkNostrIdentity(nostrData) {
558
- const { NostrIdentityCollection } = await import("./NostrIdentityCollection-DadQBHWy.js").then((n) => n.q);
559
- const collection = await NostrIdentityCollection.create(this.options);
560
- return await collection.linkToProfile(this, nostrData);
561
- }
562
- /**
563
- * Get audit logs for actions performed by this profile
564
- *
565
- * @param limit - Maximum number of logs to return
566
- * @returns Array of audit log entries
567
- */
568
- async getAuditLogs(limit = 50) {
569
- const { AuditLogCollection } = await import("./AuditLogCollection-BYqCj0uE.js").then((n) => n.b);
570
- const collection = await AuditLogCollection.create(this.options);
571
- return await collection.getRecentActivity(this.id, limit);
572
- }
573
- /**
574
- * Record an audit log entry for an action by this profile
575
- *
576
- * @param options - Audit log options
577
- * @returns The created audit log entry
578
- */
579
- async recordAction(options) {
580
- const { AuditLogCollection } = await import("./AuditLogCollection-BYqCj0uE.js").then((n) => n.b);
581
- const collection = await AuditLogCollection.create(this.options);
582
- return await collection.record({
583
- profile: this,
584
- ...options
585
- });
586
- }
587
- };
588
- __decorateClass([
589
- tenantId({ nullable: true })
590
- ], Profile.prototype, "tenantId", 2);
591
- __decorateClass([
592
- foreignKey("ProfileType", { required: true })
593
- ], Profile.prototype, "typeId", 2);
594
- __decorateClass([
595
- field({ unique: true })
596
- ], Profile.prototype, "email", 2);
597
- __decorateClass([
598
- field({ required: true })
599
- ], Profile.prototype, "name", 2);
600
- __decorateClass([
601
- oneToMany("ProfileMetadata")
602
- ], Profile.prototype, "metadata", 2);
603
- __decorateClass([
604
- oneToMany("ProfileRelationship", { foreignKey: "fromProfileId" })
605
- ], Profile.prototype, "relationshipsFrom", 2);
606
- __decorateClass([
607
- oneToMany("ProfileRelationship", { foreignKey: "toProfileId" })
608
- ], Profile.prototype, "relationshipsTo", 2);
609
- Profile = __decorateClass([
610
- TenantScoped({ mode: "optional" }),
611
- smrt({
612
- tableStrategy: "sti",
613
- api: { include: ["list", "get", "create", "update", "delete"] },
614
- mcp: { include: ["list", "get", "create", "update"] },
615
- cli: true
616
- })
617
- ], Profile);
618
- class ProfileCollection extends SmrtCollection {
619
- static _itemClass = Profile;
620
- /**
621
- * Find a profile by email address
622
- *
623
- * @param email - The email address to search for
624
- * @returns The matching profile or null
625
- */
626
- async findByEmail(email) {
627
- const normalizedEmail = email.toLowerCase();
628
- const profiles = await this.list({
629
- where: { email: normalizedEmail },
630
- limit: 1
631
- });
632
- return profiles.length > 0 ? profiles[0] : null;
633
- }
634
- /**
635
- * Find profiles by type slug
636
- *
637
- * @param typeSlug - The profile type slug to filter by
638
- * @returns Array of matching profiles
639
- */
640
- async findByType(typeSlug) {
641
- const allProfiles = await this.list({});
642
- const filtered = [];
643
- for (const profile of allProfiles) {
644
- const slug = await profile.getTypeSlug();
645
- if (slug === typeSlug) {
646
- filtered.push(profile);
647
- }
648
- }
649
- return filtered;
650
- }
651
- /**
652
- * Batch get metadata for multiple profiles
653
- *
654
- * @param profileIds - Array of profile UUIDs
655
- * @returns Map of profile ID to metadata object
656
- */
657
- async batchGetMetadata(profileIds) {
658
- const result = /* @__PURE__ */ new Map();
659
- for (const profileId of profileIds) {
660
- const profile = await this.get({ id: profileId });
661
- if (profile) {
662
- const metadata = await profile.getMetadata();
663
- result.set(profileId, metadata);
664
- }
665
- }
666
- return result;
667
- }
668
- /**
669
- * Batch update metadata for multiple profiles
670
- *
671
- * @param updates - Array of { profileId, data } objects
672
- */
673
- async batchUpdateMetadata(updates) {
674
- for (const update of updates) {
675
- const profile = await this.get({ id: update.profileId });
676
- if (profile) {
677
- await profile.updateMetadata(update.data);
678
- }
679
- }
680
- }
681
- /**
682
- * Find related profiles for a given profile
683
- *
684
- * @param profileId - The profile UUID
685
- * @param relationshipSlug - Optional filter by relationship type
686
- * @returns Array of related profiles
687
- */
688
- async findRelated(profileId, relationshipSlug) {
689
- const profile = await this.get({ id: profileId });
690
- if (!profile) return [];
691
- return await profile.getRelatedProfiles(relationshipSlug);
692
- }
693
- async getAssets(profileId, relationship) {
694
- return getOwnedAssetsFromCollection(this, profileId, relationship);
695
- }
696
- async addAsset(profileId, asset, relationship = "attachment", sortOrder = 0) {
697
- await addOwnedAssetFromCollection(
698
- this,
699
- "Profile",
700
- profileId,
701
- asset,
702
- relationship,
703
- sortOrder
704
- );
705
- }
706
- async removeAsset(profileId, assetId, relationship) {
707
- await removeOwnedAssetFromCollection(
708
- this,
709
- "Profile",
710
- profileId,
711
- assetId,
712
- relationship
713
- );
714
- }
715
- /**
716
- * Get the relationship network for a profile up to a maximum depth
717
- *
718
- * @param profileId - The starting profile UUID
719
- * @param options - Configuration options
720
- * @returns Map of profile ID to depth level
721
- */
722
- async getRelationshipNetwork(profileId, options = {}) {
723
- const maxDepth = options.maxDepth || 2;
724
- const network = /* @__PURE__ */ new Map();
725
- const visited = /* @__PURE__ */ new Set();
726
- const queue = [
727
- { id: profileId, depth: 0 }
728
- ];
729
- while (queue.length > 0) {
730
- const current = queue.shift();
731
- if (!current) {
732
- break;
733
- }
734
- if (visited.has(current.id) || current.depth > maxDepth) {
735
- continue;
736
- }
737
- visited.add(current.id);
738
- network.set(current.id, current.depth);
739
- if (current.depth < maxDepth) {
740
- const related = await this.findRelated(current.id);
741
- for (const profile of related) {
742
- if (profile.id && !visited.has(profile.id)) {
743
- queue.push({ id: profile.id, depth: current.depth + 1 });
744
- }
745
- }
746
- }
747
- }
748
- return network;
749
- }
750
- // ─────────────────────────────────────────────────────────────────────────────
751
- // Tenant-scoped helper methods
752
- // ─────────────────────────────────────────────────────────────────────────────
753
- /**
754
- * Find all profiles belonging to a specific tenant
755
- *
756
- * @param tenantId - The tenant UUID to filter by
757
- * @returns Array of profiles for this tenant
758
- */
759
- async findByTenant(tenantId2) {
760
- return this.list({ where: { tenantId: tenantId2 } });
761
- }
762
- /**
763
- * Find all global profiles (no tenant association).
764
- *
765
- * Routes through the shared tenant-global helper so it does not throw under
766
- * an active tenant context (an explicit `tenant_id IS NULL` filter would be
767
- * flagged as an isolation violation). (#1600)
768
- *
769
- * @returns Array of profiles with null tenantId
770
- */
771
- async findGlobal() {
772
- return queryGlobal(this);
773
- }
774
- /**
775
- * Find profiles belonging to a tenant plus all global profiles.
776
- *
777
- * Fails closed if an active tenant context requests a different tenant's
778
- * rows; the admin/system path keeps the cross-tenant capability. (#1600)
779
- *
780
- * @param tenantId - The tenant UUID to include
781
- * @returns Array of tenant-specific and global profiles
782
- */
783
- async findWithGlobals(tenantId2) {
784
- return queryWithGlobals(this, tenantId2, "Profile.findWithGlobals");
785
- }
786
- }
787
- const ProfileCollection$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
788
- __proto__: null,
789
- ProfileCollection
790
- }, Symbol.toStringTag, { value: "Module" }));
791
- export {
792
- ProfileType as P,
793
- Profile as a,
794
- ProfileCollection as b,
795
- ProfileType$1 as c,
796
- ProfileCollection$1 as d,
797
- promptMessageOptions as p,
798
- smrtProfilesGenerateBioPrompt as s
799
- };
800
- //# sourceMappingURL=ProfileCollection-M2PK8bp-.js.map