@happyvertical/smrt-cli 0.53.3 → 0.53.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +3 -0
- package/README.md +64 -0
- package/agents/app-commands.md +118 -0
- package/bin/smrt-web.mjs +19 -0
- package/bin/smrt.js +18 -12
- package/dist/{ApiKey-BZmbOTnL-DchyhIPA.js → ApiKey-BZmbOTnL-BbZupUZ3.js} +2 -2
- package/dist/ApiKeyCollection-Bfb_nw81-DYAZwx0O.js +87 -0
- package/dist/AuditLogCollection-B1YonCAP-Bkj2Ezon.js +193 -0
- package/dist/{NostrIdentity-n70E0vck-CLGPdJ1W.js → NostrIdentity-n70E0vck-Di3_eNCq.js} +4 -4
- package/dist/NostrIdentityCollection-Ca74dkaL-DvjOg9Xy.js +127 -0
- package/dist/{OidcIdentity-Cb1bxreM-DPBTZddF.js → OidcIdentity-Cb1bxreM-LXmC7uAf.js} +2 -2
- package/dist/OidcIdentityCollection-TV8VdK69-Cv1ZTeuk.js +86 -0
- package/dist/ProfileAssetCollection-B9hacUJa-CPuaWLk4.js +101 -0
- package/dist/{ProfileCollection-DuJT7Mum-BUYQQ9xZ.js → ProfileCollection-DuJT7Mum-nXbHrPpX.js} +31 -31
- package/dist/ProfileLinkCollection-4uNURz32-CbKZYmYm.js +233 -0
- package/dist/ProfileMetadataCollection-DQhbfEfa-_1rQCLTR.js +108 -0
- package/dist/ProfileMetafieldCollection-CoBuM_5G-CPjW3l5r.js +145 -0
- package/dist/ProfileRelationshipCollection-DUVgaIqf-RCDqYz6O.js +161 -0
- package/dist/ProfileRelationshipTermCollection-DtA9OM23-BoGhQBSQ.js +107 -0
- package/dist/{ProfileRelationshipType-BRiRka6t-xzRfZRFG.js → ProfileRelationshipType-BRiRka6t-Dezjv5jP.js} +1 -1
- package/dist/ProfileRelationshipTypeCollection-BdXwd7Kf-HoTmV1q-.js +57 -0
- package/dist/app/cli.d.ts +51 -0
- package/dist/app/cli.d.ts.map +1 -0
- package/dist/app/errors.d.ts +55 -0
- package/dist/app/errors.d.ts.map +1 -0
- package/dist/app/identity.d.ts +24 -0
- package/dist/app/identity.d.ts.map +1 -0
- package/dist/app/index.d.ts +20 -0
- package/dist/app/index.d.ts.map +1 -0
- package/dist/app/launchers.d.ts +51 -0
- package/dist/app/launchers.d.ts.map +1 -0
- package/dist/app/operations.d.ts +30 -0
- package/dist/app/operations.d.ts.map +1 -0
- package/dist/app/portability-assets.d.ts +151 -0
- package/dist/app/portability-assets.d.ts.map +1 -0
- package/dist/app/portability.d.ts +117 -0
- package/dist/app/portability.d.ts.map +1 -0
- package/dist/app/process-record.d.ts +54 -0
- package/dist/app/process-record.d.ts.map +1 -0
- package/dist/app/runtime.d.ts +98 -0
- package/dist/app/runtime.d.ts.map +1 -0
- package/dist/app/tokens.d.ts +21 -0
- package/dist/app/tokens.d.ts.map +1 -0
- package/dist/app.d.ts +1 -0
- package/dist/app.js +4 -0
- package/dist/cli-OZsH5cdL.js +1602 -0
- package/dist/cli-generator.d.ts.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/utilities.d.ts.map +1 -1
- package/dist/{commands-B8N38deG.js → commands-UXK2F_0j.js} +49 -336
- package/dist/database-environment-D_Gk1Brf.js +20 -0
- package/dist/database-environment.d.ts +43 -0
- package/dist/database-environment.d.ts.map +1 -0
- package/dist/dist-BVjJWjT-.js +20 -0
- package/dist/{dist-B62O-xH6.js → dist-C87Ib9Vx.js} +2 -2
- package/dist/{dist-CL9KGm1j.js → dist-DLw_E34G.js} +1654 -1748
- package/dist/{dist-BBQyIRsO.js → dist-GIaWaUho.js} +4 -4
- package/dist/{dist-C8BOgli4.js → dist-RSE5hCY4.js} +3 -3
- package/dist/index.js +19 -9
- package/dist/mcp-apps-packaging-CixRnxz_.js +286 -0
- package/dist/{oidcProvisioningPrimitives-D9OYu5-F-l8afZs4F.js → oidcProvisioningPrimitives-D9OYu5-F-T9KkkDCd.js} +5 -5
- package/dist/portability-CES1YC2m.js +859 -0
- package/dist/resolveIdentity-B-PK6RwU-C9ogf8YG.js +269 -0
- package/package.json +19 -14
- package/dist/ApiKeyCollection-Bfb_nw81-DR5XF_SZ.js +0 -2
- package/dist/AuditLogCollection-B1YonCAP-PbzALncL.js +0 -2
- package/dist/NostrIdentityCollection-Ca74dkaL-C2r-uDlC.js +0 -2
- package/dist/OidcIdentityCollection-TV8VdK69-2fZROnih.js +0 -2
- package/dist/ProfileAssetCollection-B9hacUJa-D33sifgF.js +0 -2
- package/dist/ProfileLinkCollection-4uNURz32-CHDTinax.js +0 -2
- package/dist/ProfileMetadataCollection-DQhbfEfa-BQTogfVX.js +0 -2
- package/dist/ProfileMetafieldCollection-CoBuM_5G-BXtoIP02.js +0 -2
- package/dist/ProfileRelationshipCollection-DUVgaIqf-CNMliUF3.js +0 -2
- package/dist/ProfileRelationshipTermCollection-DtA9OM23-DPOMtMr7.js +0 -2
- package/dist/ProfileRelationshipTypeCollection-BdXwd7Kf-Co3PdH01.js +0 -2
- package/dist/resolveIdentity-B-PK6RwU-B306Ch1I.js +0 -2
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
|
|
2
|
+
import { i as tenantId, r as TenantScoped } from "./dist-C87Ib9Vx.js";
|
|
3
|
+
import { n as __exportAll$1 } from "./NostrIdentity-n70E0vck-Di3_eNCq.js";
|
|
4
|
+
import { SmrtCollection, SmrtObject, field, foreignKey, isEmbeddedDatabase, smrt, withEmbeddedWriteTransaction } from "@happyvertical/smrt-core";
|
|
5
|
+
//#region ../profiles/dist/chunks/ProfileLinkCollection-4uNURz32.js
|
|
6
|
+
var ProfileLinkCollection_4uNURz32_exports = /* @__PURE__ */ __exportAll({
|
|
7
|
+
a: () => PROFILE_LINK_MAX_URL_LENGTH,
|
|
8
|
+
c: () => isProfileLinkPlatform,
|
|
9
|
+
i: () => 200,
|
|
10
|
+
l: () => normalizeProfileLinkUrl,
|
|
11
|
+
n: () => ProfileLinkCollection,
|
|
12
|
+
o: () => PROFILE_LINK_PLATFORMS,
|
|
13
|
+
r: () => ProfileLinkCollection_exports,
|
|
14
|
+
s: () => ProfileLink,
|
|
15
|
+
t: () => 50
|
|
16
|
+
});
|
|
17
|
+
var __defProp = Object.defineProperty;
|
|
18
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
19
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
20
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
21
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
22
|
+
if (kind && result) __defProp(target, key, result);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var PROFILE_LINK_PLATFORMS = [
|
|
26
|
+
"facebook",
|
|
27
|
+
"instagram",
|
|
28
|
+
"x",
|
|
29
|
+
"linkedin",
|
|
30
|
+
"youtube",
|
|
31
|
+
"tiktok",
|
|
32
|
+
"website",
|
|
33
|
+
"other"
|
|
34
|
+
];
|
|
35
|
+
function isProfileLinkPlatform(value) {
|
|
36
|
+
return typeof value === "string" && PROFILE_LINK_PLATFORMS.includes(value);
|
|
37
|
+
}
|
|
38
|
+
function normalizeProfileLinkUrl(raw) {
|
|
39
|
+
const text = String(raw ?? "").trim();
|
|
40
|
+
if (!text) throw new Error("A profile link needs a web address");
|
|
41
|
+
if (text.length > 2048 || /\s/.test(text)) throw new Error("A profile link must be a single web address");
|
|
42
|
+
let url;
|
|
43
|
+
try {
|
|
44
|
+
url = new URL(text);
|
|
45
|
+
} catch {
|
|
46
|
+
throw new Error(`Not a web address: ${text}`);
|
|
47
|
+
}
|
|
48
|
+
if (url.protocol !== "https:" && url.protocol !== "http:") throw new Error("A profile link must start with http:// or https://");
|
|
49
|
+
if (url.username || url.password) throw new Error("A profile link cannot carry a user name or password");
|
|
50
|
+
if (!url.hostname) throw new Error(`Not a web address: ${text}`);
|
|
51
|
+
return url.toString();
|
|
52
|
+
}
|
|
53
|
+
var ProfileLink = class extends SmrtObject {
|
|
54
|
+
tenantId = null;
|
|
55
|
+
profileId = "";
|
|
56
|
+
platform = "website";
|
|
57
|
+
url = "";
|
|
58
|
+
label = null;
|
|
59
|
+
sortOrder = 0;
|
|
60
|
+
constructor(options = {}) {
|
|
61
|
+
super(options);
|
|
62
|
+
if (options.profileId) this.profileId = options.profileId;
|
|
63
|
+
if (options.platform) this.platform = options.platform;
|
|
64
|
+
if (options.url) this.url = options.url;
|
|
65
|
+
if (options.label !== void 0) this.label = options.label;
|
|
66
|
+
if (options.sortOrder !== void 0) this.sortOrder = options.sortOrder;
|
|
67
|
+
if (options.tenantId !== void 0) this.tenantId = options.tenantId;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* A link's address and label are not its identity: two people can link the
|
|
71
|
+
* same page, and one person can relabel a link. Without an explicit slug
|
|
72
|
+
* the default (label-derived) slug would make a new link adopt another row
|
|
73
|
+
* through the (tenant, slug, context) natural key, so a link's default slug
|
|
74
|
+
* is its id.
|
|
75
|
+
*/
|
|
76
|
+
async getSlug() {
|
|
77
|
+
if (!this.slug && this.id) this.slug = String(this.id);
|
|
78
|
+
return super.getSlug();
|
|
79
|
+
}
|
|
80
|
+
/** Validates and normalizes the link before it is written. */
|
|
81
|
+
async save(...args) {
|
|
82
|
+
if (!this.profileId) throw new Error("A profile link needs a profile");
|
|
83
|
+
if (!isProfileLinkPlatform(this.platform)) throw new Error(`Unknown profile link platform: ${this.platform}`);
|
|
84
|
+
this.url = normalizeProfileLinkUrl(this.url);
|
|
85
|
+
const label = this.label?.trim() ?? "";
|
|
86
|
+
if (label.length > 200) throw new Error("A profile link label is too long");
|
|
87
|
+
this.label = label || null;
|
|
88
|
+
if (!Number.isInteger(this.sortOrder) || this.sortOrder < 0) throw new Error("A profile link sortOrder must be a whole number ≥ 0");
|
|
89
|
+
return super.save(...args);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
__decorateClass([tenantId({ nullable: true })], ProfileLink.prototype, "tenantId", 2);
|
|
93
|
+
__decorateClass([foreignKey("Profile", {
|
|
94
|
+
required: true,
|
|
95
|
+
onDelete: "CASCADE"
|
|
96
|
+
})], ProfileLink.prototype, "profileId", 2);
|
|
97
|
+
__decorateClass([field({
|
|
98
|
+
required: true,
|
|
99
|
+
maxLength: 32
|
|
100
|
+
})], ProfileLink.prototype, "platform", 2);
|
|
101
|
+
__decorateClass([field({
|
|
102
|
+
required: true,
|
|
103
|
+
maxLength: 2048
|
|
104
|
+
})], ProfileLink.prototype, "url", 2);
|
|
105
|
+
__decorateClass([field({
|
|
106
|
+
nullable: true,
|
|
107
|
+
maxLength: 200
|
|
108
|
+
})], ProfileLink.prototype, "label", 2);
|
|
109
|
+
__decorateClass([field()], ProfileLink.prototype, "sortOrder", 2);
|
|
110
|
+
ProfileLink = __decorateClass([TenantScoped({ mode: "optional" }), smrt({
|
|
111
|
+
tableName: "profile_links",
|
|
112
|
+
api: false,
|
|
113
|
+
mcp: false,
|
|
114
|
+
cli: false
|
|
115
|
+
})], ProfileLink);
|
|
116
|
+
var ProfileLinkCollection_exports = /* @__PURE__ */ __exportAll$1({
|
|
117
|
+
PROFILE_LINK_LIMIT: () => 50,
|
|
118
|
+
ProfileLinkCollection: () => ProfileLinkCollection
|
|
119
|
+
});
|
|
120
|
+
var ProfileLinkCollection = class ProfileLinkCollection extends SmrtCollection {
|
|
121
|
+
static _itemClass = ProfileLink;
|
|
122
|
+
/** The profile's links in display order (sortOrder, then age). */
|
|
123
|
+
async listForProfile(profileId) {
|
|
124
|
+
if (!profileId) return [];
|
|
125
|
+
return (await this.list({ where: { profileId } })).sort(compareLinks);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Makes the profile's links exactly `links`, in that order, in one
|
|
129
|
+
* transaction: a link whose address is already on the profile keeps its row
|
|
130
|
+
* (and id), new addresses are added, and links left out are removed. The
|
|
131
|
+
* same address given twice is kept once, at its first position. New links
|
|
132
|
+
* take the profile's tenant. Throws, changing nothing, when the profile is
|
|
133
|
+
* not visible in the current tenant context or a link is invalid.
|
|
134
|
+
*/
|
|
135
|
+
async replaceForProfile(profileId, links) {
|
|
136
|
+
const wanted = normalizeInputs(links);
|
|
137
|
+
return this.inTransaction(async (bound) => {
|
|
138
|
+
const tenantId = await bound.requireProfileTenant(profileId);
|
|
139
|
+
const existing = await bound.listForProfile(profileId);
|
|
140
|
+
const byUrl = /* @__PURE__ */ new Map();
|
|
141
|
+
for (const link of existing) if (!byUrl.has(link.url)) byUrl.set(link.url, link);
|
|
142
|
+
const kept = /* @__PURE__ */ new Set();
|
|
143
|
+
const result = [];
|
|
144
|
+
for (const [index, input] of wanted.entries()) {
|
|
145
|
+
const current = byUrl.get(input.url);
|
|
146
|
+
if (current) {
|
|
147
|
+
kept.add(current);
|
|
148
|
+
const changed = current.platform !== input.platform || (current.label ?? null) !== input.label || current.sortOrder !== index || !current.tenantId && tenantId !== null;
|
|
149
|
+
current.platform = input.platform;
|
|
150
|
+
current.label = input.label;
|
|
151
|
+
current.sortOrder = index;
|
|
152
|
+
if (!current.tenantId && tenantId) current.tenantId = tenantId;
|
|
153
|
+
if (changed) await current.save();
|
|
154
|
+
result.push(current);
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
const created = await bound.create({
|
|
158
|
+
profileId,
|
|
159
|
+
platform: input.platform,
|
|
160
|
+
url: input.url,
|
|
161
|
+
label: input.label,
|
|
162
|
+
sortOrder: index,
|
|
163
|
+
...tenantId ? { tenantId } : {}
|
|
164
|
+
});
|
|
165
|
+
result.push(created);
|
|
166
|
+
}
|
|
167
|
+
for (const link of existing) if (!kept.has(link)) await link.delete();
|
|
168
|
+
return result;
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Puts the profile's links in the order of `linkIds`, which must name every
|
|
173
|
+
* link on the profile exactly once. One transaction; throws, changing
|
|
174
|
+
* nothing, on a missing, extra or repeated id.
|
|
175
|
+
*/
|
|
176
|
+
async reorder(profileId, linkIds) {
|
|
177
|
+
return this.inTransaction(async (bound) => {
|
|
178
|
+
await bound.requireProfileTenant(profileId);
|
|
179
|
+
const existing = await bound.listForProfile(profileId);
|
|
180
|
+
const byId = new Map(existing.map((link) => [String(link.id), link]));
|
|
181
|
+
const ids = linkIds.map(String);
|
|
182
|
+
if (ids.length !== existing.length || new Set(ids).size !== ids.length || ids.some((id) => !byId.has(id))) throw new Error("Reorder must list every link on the profile exactly once");
|
|
183
|
+
const ordered = [];
|
|
184
|
+
for (const [index, id] of ids.entries()) {
|
|
185
|
+
const link = byId.get(id);
|
|
186
|
+
if (link.sortOrder !== index) {
|
|
187
|
+
link.sortOrder = index;
|
|
188
|
+
await link.save();
|
|
189
|
+
}
|
|
190
|
+
ordered.push(link);
|
|
191
|
+
}
|
|
192
|
+
return ordered;
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
/** The profile's tenant; throws when the profile is not visible here. */
|
|
196
|
+
async requireProfileTenant(profileId) {
|
|
197
|
+
if (!profileId) throw new Error("A profile link needs a profile");
|
|
198
|
+
const { ProfileCollection } = await import("./ProfileCollection-DuJT7Mum-nXbHrPpX.js").then((n) => n.o).then((n) => n.r);
|
|
199
|
+
const profile = await (await ProfileCollection.create({ db: this.db })).get({ id: profileId });
|
|
200
|
+
if (!profile) throw new Error(`Profile '${profileId}' not found`);
|
|
201
|
+
return profile.tenantId ?? null;
|
|
202
|
+
}
|
|
203
|
+
async inTransaction(work) {
|
|
204
|
+
const db = this.db;
|
|
205
|
+
return withEmbeddedWriteTransaction(db, isEmbeddedDatabase(db), async (transaction) => work(await ProfileLinkCollection.create({ db: transaction })));
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
function compareLinks(a, b) {
|
|
209
|
+
if (a.sortOrder !== b.sortOrder) return a.sortOrder - b.sortOrder;
|
|
210
|
+
const aTime = new Date(a.created_at ?? 0).getTime();
|
|
211
|
+
const bTime = new Date(b.created_at ?? 0).getTime();
|
|
212
|
+
if (aTime !== bTime) return aTime - bTime;
|
|
213
|
+
return String(a.id).localeCompare(String(b.id));
|
|
214
|
+
}
|
|
215
|
+
function normalizeInputs(links) {
|
|
216
|
+
if (links.length > 50) throw new Error(`A profile can hold at most 50 links (got ${links.length})`);
|
|
217
|
+
const seen = /* @__PURE__ */ new Set();
|
|
218
|
+
const out = [];
|
|
219
|
+
for (const link of links) {
|
|
220
|
+
if (!isProfileLinkPlatform(link.platform)) throw new Error(`Unknown profile link platform: ${link.platform}`);
|
|
221
|
+
const url = normalizeProfileLinkUrl(link.url);
|
|
222
|
+
if (seen.has(url)) continue;
|
|
223
|
+
seen.add(url);
|
|
224
|
+
out.push({
|
|
225
|
+
platform: link.platform,
|
|
226
|
+
url,
|
|
227
|
+
label: link.label?.trim() ? link.label.trim() : null
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
return out;
|
|
231
|
+
}
|
|
232
|
+
//#endregion
|
|
233
|
+
export { isProfileLinkPlatform as a, ProfileLinkCollection_4uNURz32_exports as i, ProfileLink as n, normalizeProfileLinkUrl as o, ProfileLinkCollection as r, PROFILE_LINK_PLATFORMS as t };
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
|
|
2
|
+
import { i as tenantId, r as TenantScoped } from "./dist-C87Ib9Vx.js";
|
|
3
|
+
import { n as __exportAll$1 } from "./NostrIdentity-n70E0vck-Di3_eNCq.js";
|
|
4
|
+
import { SmrtCollection, SmrtObject, field, foreignKey, smrt } from "@happyvertical/smrt-core";
|
|
5
|
+
//#region ../profiles/dist/chunks/ProfileMetadataCollection-DQhbfEfa.js
|
|
6
|
+
var ProfileMetadataCollection_DQhbfEfa_exports = /* @__PURE__ */ __exportAll({
|
|
7
|
+
n: () => ProfileMetadataCollection_exports,
|
|
8
|
+
r: () => ProfileMetadata,
|
|
9
|
+
t: () => ProfileMetadataCollection
|
|
10
|
+
});
|
|
11
|
+
var __defProp = Object.defineProperty;
|
|
12
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
13
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
14
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
15
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
16
|
+
if (kind && result) __defProp(target, key, result);
|
|
17
|
+
return result;
|
|
18
|
+
};
|
|
19
|
+
var ProfileMetadata = class extends SmrtObject {
|
|
20
|
+
tenantId = null;
|
|
21
|
+
profileId;
|
|
22
|
+
metafieldId;
|
|
23
|
+
value = "";
|
|
24
|
+
constructor(options = {}) {
|
|
25
|
+
super(options);
|
|
26
|
+
if (options.profileId !== void 0) this.profileId = options.profileId;
|
|
27
|
+
if (options.metafieldId !== void 0) this.metafieldId = options.metafieldId;
|
|
28
|
+
if (options.value) this.value = options.value;
|
|
29
|
+
if (options.tenantId !== void 0) this.tenantId = options.tenantId;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Validate this metadata value against the metafield's validation schema
|
|
33
|
+
*
|
|
34
|
+
* @returns True if valid, throws error if invalid
|
|
35
|
+
*/
|
|
36
|
+
async validate() {
|
|
37
|
+
const metafield = await this.loadRelated("metafieldId");
|
|
38
|
+
if (!metafield) throw new Error("Metafield not found");
|
|
39
|
+
return await metafield.validateValue(this.value);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Get the metafield slug for this metadata
|
|
43
|
+
*
|
|
44
|
+
* @returns The slug of the metafield
|
|
45
|
+
*/
|
|
46
|
+
async getMetafieldSlug() {
|
|
47
|
+
return (await this.loadRelated("metafieldId"))?.slug || "";
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
__decorateClass([tenantId({ nullable: true })], ProfileMetadata.prototype, "tenantId", 2);
|
|
51
|
+
__decorateClass([foreignKey("Profile", { required: true })], ProfileMetadata.prototype, "profileId", 2);
|
|
52
|
+
__decorateClass([foreignKey("ProfileMetafield", { required: true })], ProfileMetadata.prototype, "metafieldId", 2);
|
|
53
|
+
__decorateClass([field({ required: true })], ProfileMetadata.prototype, "value", 2);
|
|
54
|
+
ProfileMetadata = __decorateClass([TenantScoped({ mode: "optional" }), smrt({
|
|
55
|
+
tableStrategy: "sti",
|
|
56
|
+
api: { include: [
|
|
57
|
+
"list",
|
|
58
|
+
"get",
|
|
59
|
+
"create",
|
|
60
|
+
"update",
|
|
61
|
+
"delete"
|
|
62
|
+
] },
|
|
63
|
+
mcp: { include: ["list", "get"] },
|
|
64
|
+
cli: { skipApiCheck: true }
|
|
65
|
+
})], ProfileMetadata);
|
|
66
|
+
var ProfileMetadataCollection_exports = /* @__PURE__ */ __exportAll$1({ ProfileMetadataCollection: () => ProfileMetadataCollection });
|
|
67
|
+
var ProfileMetadataCollection = class extends SmrtCollection {
|
|
68
|
+
static _itemClass = ProfileMetadata;
|
|
69
|
+
/**
|
|
70
|
+
* Get all metadata for a profile
|
|
71
|
+
*
|
|
72
|
+
* @param profileId - The profile UUID
|
|
73
|
+
* @returns Array of ProfileMetadata instances
|
|
74
|
+
*/
|
|
75
|
+
async getByProfile(profileId) {
|
|
76
|
+
return await this.list({ where: { profileId } });
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Get metadata as key-value object for a profile
|
|
80
|
+
*
|
|
81
|
+
* @param profileId - The profile UUID
|
|
82
|
+
* @returns Object with metafield slugs as keys
|
|
83
|
+
*/
|
|
84
|
+
async getMetadataObject(profileId) {
|
|
85
|
+
const metadata = await this.getByProfile(profileId);
|
|
86
|
+
const result = {};
|
|
87
|
+
for (const item of metadata) {
|
|
88
|
+
const slug = await item.getMetafieldSlug();
|
|
89
|
+
if (slug) result[slug] = item.value;
|
|
90
|
+
}
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Find all profiles with a specific metadata key-value pair
|
|
95
|
+
*
|
|
96
|
+
* @param metafieldId - The metafield UUID
|
|
97
|
+
* @param value - The value to match
|
|
98
|
+
* @returns Array of profile UUIDs
|
|
99
|
+
*/
|
|
100
|
+
async findProfilesByMetadata(metafieldId, value) {
|
|
101
|
+
return (await this.list({ where: {
|
|
102
|
+
metafieldId,
|
|
103
|
+
value: String(value)
|
|
104
|
+
} })).map((m) => m.profileId).filter((id) => typeof id === "string");
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
//#endregion
|
|
108
|
+
export { ProfileMetadataCollection as n, ProfileMetadataCollection_DQhbfEfa_exports as r, ProfileMetadata as t };
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
|
|
2
|
+
import { i as tenantId, r as TenantScoped } from "./dist-C87Ib9Vx.js";
|
|
3
|
+
import { n as __exportAll$1 } from "./NostrIdentity-n70E0vck-Di3_eNCq.js";
|
|
4
|
+
import { SmrtCollection, SmrtObject, field, smrt } from "@happyvertical/smrt-core";
|
|
5
|
+
//#region ../profiles/dist/chunks/ProfileMetafieldCollection-CoBuM_5G.js
|
|
6
|
+
var ProfileMetafieldCollection_CoBuM_5G_exports = /* @__PURE__ */ __exportAll({
|
|
7
|
+
n: () => ProfileMetafieldCollection_exports,
|
|
8
|
+
r: () => ProfileMetafield,
|
|
9
|
+
t: () => ProfileMetafieldCollection
|
|
10
|
+
});
|
|
11
|
+
var __defProp = Object.defineProperty;
|
|
12
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
13
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
14
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
15
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
16
|
+
if (kind && result) __defProp(target, key, result);
|
|
17
|
+
return result;
|
|
18
|
+
};
|
|
19
|
+
function getCustomValidators() {
|
|
20
|
+
if (!globalThis.__smrtProfileMetafieldValidators) globalThis.__smrtProfileMetafieldValidators = /* @__PURE__ */ new Map();
|
|
21
|
+
return globalThis.__smrtProfileMetafieldValidators;
|
|
22
|
+
}
|
|
23
|
+
var ProfileMetafield = class extends SmrtObject {
|
|
24
|
+
tenantId = null;
|
|
25
|
+
name = "";
|
|
26
|
+
description;
|
|
27
|
+
validation;
|
|
28
|
+
constructor(options = {}) {
|
|
29
|
+
super(options);
|
|
30
|
+
if (options.name) this.name = options.name;
|
|
31
|
+
if (options.description !== void 0) this.description = options.description;
|
|
32
|
+
if (options.validation !== void 0) this.validation = options.validation;
|
|
33
|
+
if (options.tenantId !== void 0) this.tenantId = options.tenantId;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Convenience method for slug-based lookup
|
|
37
|
+
*
|
|
38
|
+
* @param slug - The slug to search for
|
|
39
|
+
* @returns ProfileMetafield instance or null if not found
|
|
40
|
+
*/
|
|
41
|
+
static async getBySlug(_slug) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Register a custom validator function
|
|
46
|
+
*
|
|
47
|
+
* @param name - Name of the validator (used in validation.custom field)
|
|
48
|
+
* @param validator - The validator function
|
|
49
|
+
*/
|
|
50
|
+
static registerValidator(name, validator) {
|
|
51
|
+
getCustomValidators().set(name, validator);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Get a registered custom validator
|
|
55
|
+
*
|
|
56
|
+
* @param name - Name of the validator
|
|
57
|
+
* @returns The validator function or undefined
|
|
58
|
+
*/
|
|
59
|
+
static getValidator(name) {
|
|
60
|
+
return getCustomValidators().get(name);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Validate a value against this metafield's validation schema
|
|
64
|
+
*
|
|
65
|
+
* @param value - The value to validate
|
|
66
|
+
* @returns True if valid, throws ValidationError if invalid
|
|
67
|
+
*/
|
|
68
|
+
async validateValue(value) {
|
|
69
|
+
if (!this.validation) return true;
|
|
70
|
+
const schema = this.validation;
|
|
71
|
+
if (schema.type) {
|
|
72
|
+
const actualType = typeof value;
|
|
73
|
+
const expectedType = schema.type;
|
|
74
|
+
if (expectedType === "number" && actualType !== "number") throw new Error(schema.message || `Expected ${expectedType}, got ${actualType}`);
|
|
75
|
+
if (expectedType === "string" && actualType !== "string") throw new Error(schema.message || `Expected ${expectedType}, got ${actualType}`);
|
|
76
|
+
if (expectedType === "boolean" && actualType !== "boolean") throw new Error(schema.message || `Expected ${expectedType}, got ${actualType}`);
|
|
77
|
+
}
|
|
78
|
+
if (schema.pattern && typeof value === "string") {
|
|
79
|
+
if (!new RegExp(schema.pattern).test(value)) throw new Error(schema.message || "Pattern validation failed");
|
|
80
|
+
}
|
|
81
|
+
if (schema.minLength && typeof value === "string") {
|
|
82
|
+
if (value.length < schema.minLength) throw new Error(schema.message || `Minimum length is ${schema.minLength}, got ${value.length}`);
|
|
83
|
+
}
|
|
84
|
+
if (schema.maxLength && typeof value === "string") {
|
|
85
|
+
if (value.length > schema.maxLength) throw new Error(schema.message || `Maximum length is ${schema.maxLength}, got ${value.length}`);
|
|
86
|
+
}
|
|
87
|
+
if (schema.min !== void 0 && typeof value === "number") {
|
|
88
|
+
if (value < schema.min) throw new Error(schema.message || `Value must be at least ${schema.min}`);
|
|
89
|
+
}
|
|
90
|
+
if (schema.max !== void 0 && typeof value === "number") {
|
|
91
|
+
if (value > schema.max) throw new Error(schema.message || `Value must be at most ${schema.max}`);
|
|
92
|
+
}
|
|
93
|
+
if (schema.custom) {
|
|
94
|
+
const validator = ProfileMetafield.getValidator(schema.custom);
|
|
95
|
+
if (!validator) throw new Error(`Custom validator '${schema.custom}' not registered`);
|
|
96
|
+
if (!await validator(value)) throw new Error(schema.message || "Custom validation failed");
|
|
97
|
+
}
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
__decorateClass([tenantId({ nullable: true })], ProfileMetafield.prototype, "tenantId", 2);
|
|
102
|
+
__decorateClass([field({ required: true })], ProfileMetafield.prototype, "name", 2);
|
|
103
|
+
ProfileMetafield = __decorateClass([TenantScoped({ mode: "optional" }), smrt({
|
|
104
|
+
tableStrategy: "sti",
|
|
105
|
+
api: { include: [
|
|
106
|
+
"list",
|
|
107
|
+
"get",
|
|
108
|
+
"create",
|
|
109
|
+
"update"
|
|
110
|
+
] },
|
|
111
|
+
mcp: { include: ["list", "get"] },
|
|
112
|
+
cli: { skipApiCheck: true }
|
|
113
|
+
})], ProfileMetafield);
|
|
114
|
+
var ProfileMetafieldCollection_exports = /* @__PURE__ */ __exportAll$1({ ProfileMetafieldCollection: () => ProfileMetafieldCollection });
|
|
115
|
+
var ProfileMetafieldCollection = class extends SmrtCollection {
|
|
116
|
+
static _itemClass = ProfileMetafield;
|
|
117
|
+
/**
|
|
118
|
+
* Get metafield by slug
|
|
119
|
+
*
|
|
120
|
+
* @param slug - The slug to search for
|
|
121
|
+
* @returns ProfileMetafield instance or null
|
|
122
|
+
*/
|
|
123
|
+
async getBySlug(slug) {
|
|
124
|
+
return await this.get({ slug });
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Get or create a metafield by slug
|
|
128
|
+
*
|
|
129
|
+
* @param slug - The slug to search for
|
|
130
|
+
* @param defaults - Default values if creating
|
|
131
|
+
* @returns ProfileMetafield instance
|
|
132
|
+
*/
|
|
133
|
+
async getOrCreateBySlug(slug, defaults) {
|
|
134
|
+
const existing = await this.getBySlug(slug);
|
|
135
|
+
if (existing) return existing;
|
|
136
|
+
const metafield = await this.create({
|
|
137
|
+
slug,
|
|
138
|
+
...defaults
|
|
139
|
+
});
|
|
140
|
+
await metafield.save();
|
|
141
|
+
return metafield;
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
//#endregion
|
|
145
|
+
export { ProfileMetafieldCollection as n, ProfileMetafieldCollection_CoBuM_5G_exports as r, ProfileMetafield as t };
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
|
|
2
|
+
import { i as tenantId, r as TenantScoped } from "./dist-C87Ib9Vx.js";
|
|
3
|
+
import { n as __exportAll$1 } from "./NostrIdentity-n70E0vck-Di3_eNCq.js";
|
|
4
|
+
import { SmrtCollection, SmrtObject, foreignKey, oneToMany, smrt } from "@happyvertical/smrt-core";
|
|
5
|
+
//#region ../profiles/dist/chunks/ProfileRelationshipCollection-DUVgaIqf.js
|
|
6
|
+
var ProfileRelationshipCollection_DUVgaIqf_exports = /* @__PURE__ */ __exportAll({
|
|
7
|
+
n: () => ProfileRelationshipCollection_exports,
|
|
8
|
+
r: () => ProfileRelationship,
|
|
9
|
+
t: () => ProfileRelationshipCollection
|
|
10
|
+
});
|
|
11
|
+
var __defProp = Object.defineProperty;
|
|
12
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
13
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
14
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
15
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
16
|
+
if (kind && result) __defProp(target, key, result);
|
|
17
|
+
return result;
|
|
18
|
+
};
|
|
19
|
+
var ProfileRelationship = class extends SmrtObject {
|
|
20
|
+
tenantId = null;
|
|
21
|
+
fromProfileId;
|
|
22
|
+
toProfileId;
|
|
23
|
+
typeId;
|
|
24
|
+
contextProfileId;
|
|
25
|
+
terms = [];
|
|
26
|
+
constructor(options = {}) {
|
|
27
|
+
super(options);
|
|
28
|
+
if (options.fromProfileId !== void 0) this.fromProfileId = options.fromProfileId;
|
|
29
|
+
if (options.toProfileId !== void 0) this.toProfileId = options.toProfileId;
|
|
30
|
+
if (options.typeId !== void 0) this.typeId = options.typeId;
|
|
31
|
+
if (options.contextProfileId !== void 0) this.contextProfileId = options.contextProfileId;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Get the relationship type slug
|
|
35
|
+
*
|
|
36
|
+
* @returns The slug of the relationship type
|
|
37
|
+
*/
|
|
38
|
+
async getTypeSlug() {
|
|
39
|
+
return (await this.loadRelated("typeId"))?.slug || "";
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Add a term (time period) to this relationship
|
|
43
|
+
*
|
|
44
|
+
* @param startedAt - Start date of the term
|
|
45
|
+
* @param endedAt - Optional end date of the term
|
|
46
|
+
*/
|
|
47
|
+
async addTerm(startedAt, endedAt) {
|
|
48
|
+
if (!this.id) throw new Error("ProfileRelationship.addTerm requires a persisted relationship (missing id)");
|
|
49
|
+
const relationshipId = this.id;
|
|
50
|
+
const { ProfileRelationshipTermCollection } = await import("./ProfileRelationshipTermCollection-DtA9OM23-BoGhQBSQ.js").then((n) => n.r).then((n) => n.n);
|
|
51
|
+
await (await (await ProfileRelationshipTermCollection.create(this.options)).create({
|
|
52
|
+
relationshipId,
|
|
53
|
+
startedAt,
|
|
54
|
+
endedAt
|
|
55
|
+
})).save();
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* End the current active term
|
|
59
|
+
*
|
|
60
|
+
* @param endedAt - End date for the term
|
|
61
|
+
*/
|
|
62
|
+
async endCurrentTerm(endedAt) {
|
|
63
|
+
const activeTerm = await this.getActiveTerm();
|
|
64
|
+
if (activeTerm) await activeTerm.end(endedAt);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Get all terms for this relationship
|
|
68
|
+
*
|
|
69
|
+
* @returns Array of ProfileRelationshipTerm instances
|
|
70
|
+
*/
|
|
71
|
+
async getTerms() {
|
|
72
|
+
const { ProfileRelationshipTermCollection } = await import("./ProfileRelationshipTermCollection-DtA9OM23-BoGhQBSQ.js").then((n) => n.r).then((n) => n.n);
|
|
73
|
+
return await (await ProfileRelationshipTermCollection.create(this.options)).getByRelationship(this.id);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Get the active term (no end date)
|
|
77
|
+
*
|
|
78
|
+
* @returns Current term or null if none active
|
|
79
|
+
*/
|
|
80
|
+
async getActiveTerm() {
|
|
81
|
+
const { ProfileRelationshipTermCollection } = await import("./ProfileRelationshipTermCollection-DtA9OM23-BoGhQBSQ.js").then((n) => n.r).then((n) => n.n);
|
|
82
|
+
return await (await ProfileRelationshipTermCollection.create(this.options)).getActiveTerm(this.id);
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
__decorateClass([tenantId({ nullable: true })], ProfileRelationship.prototype, "tenantId", 2);
|
|
86
|
+
__decorateClass([foreignKey("Profile", { required: true })], ProfileRelationship.prototype, "fromProfileId", 2);
|
|
87
|
+
__decorateClass([foreignKey("Profile", { required: true })], ProfileRelationship.prototype, "toProfileId", 2);
|
|
88
|
+
__decorateClass([foreignKey("ProfileRelationshipType", { required: true })], ProfileRelationship.prototype, "typeId", 2);
|
|
89
|
+
__decorateClass([foreignKey("Profile")], ProfileRelationship.prototype, "contextProfileId", 2);
|
|
90
|
+
__decorateClass([oneToMany("ProfileRelationshipTerm")], ProfileRelationship.prototype, "terms", 2);
|
|
91
|
+
ProfileRelationship = __decorateClass([TenantScoped({ mode: "optional" }), smrt({
|
|
92
|
+
tableStrategy: "sti",
|
|
93
|
+
api: { include: [
|
|
94
|
+
"list",
|
|
95
|
+
"get",
|
|
96
|
+
"create",
|
|
97
|
+
"delete"
|
|
98
|
+
] },
|
|
99
|
+
mcp: { include: ["list", "get"] },
|
|
100
|
+
cli: { skipApiCheck: true }
|
|
101
|
+
})], ProfileRelationship);
|
|
102
|
+
var ProfileRelationshipCollection_exports = /* @__PURE__ */ __exportAll$1({ ProfileRelationshipCollection: () => ProfileRelationshipCollection });
|
|
103
|
+
var ProfileRelationshipCollection = class extends SmrtCollection {
|
|
104
|
+
static _itemClass = ProfileRelationship;
|
|
105
|
+
/**
|
|
106
|
+
* Get all relationships from a profile
|
|
107
|
+
*
|
|
108
|
+
* @param fromProfileId - The origin profile UUID
|
|
109
|
+
* @param typeId - Optional filter by relationship type UUID
|
|
110
|
+
* @returns Array of ProfileRelationship instances
|
|
111
|
+
*/
|
|
112
|
+
async getFromProfile(fromProfileId, typeId) {
|
|
113
|
+
const where = { fromProfileId };
|
|
114
|
+
if (typeId) where.typeId = typeId;
|
|
115
|
+
return await this.list({ where });
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Get all relationships to a profile
|
|
119
|
+
*
|
|
120
|
+
* @param toProfileId - The target profile UUID
|
|
121
|
+
* @param typeId - Optional filter by relationship type UUID
|
|
122
|
+
* @returns Array of ProfileRelationship instances
|
|
123
|
+
*/
|
|
124
|
+
async getToProfile(toProfileId, typeId) {
|
|
125
|
+
const where = { toProfileId };
|
|
126
|
+
if (typeId) where.typeId = typeId;
|
|
127
|
+
return await this.list({ where });
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Get all relationships for a profile (both directions)
|
|
131
|
+
*
|
|
132
|
+
* @param profileId - The profile UUID
|
|
133
|
+
* @param typeId - Optional filter by relationship type UUID
|
|
134
|
+
* @returns Array of ProfileRelationship instances
|
|
135
|
+
*/
|
|
136
|
+
async getForProfile(profileId, typeId) {
|
|
137
|
+
const fromRelationships = await this.getFromProfile(profileId, typeId);
|
|
138
|
+
const toRelationships = await this.getToProfile(profileId, typeId);
|
|
139
|
+
return [...fromRelationships, ...toRelationships];
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Check if a relationship exists between two profiles
|
|
143
|
+
*
|
|
144
|
+
* @param fromProfileId - The origin profile UUID
|
|
145
|
+
* @param toProfileId - The target profile UUID
|
|
146
|
+
* @param typeId - The relationship type UUID
|
|
147
|
+
* @returns True if relationship exists
|
|
148
|
+
*/
|
|
149
|
+
async exists(fromProfileId, toProfileId, typeId) {
|
|
150
|
+
return (await this.list({
|
|
151
|
+
where: {
|
|
152
|
+
fromProfileId,
|
|
153
|
+
toProfileId,
|
|
154
|
+
typeId
|
|
155
|
+
},
|
|
156
|
+
limit: 1
|
|
157
|
+
})).length > 0;
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
//#endregion
|
|
161
|
+
export { ProfileRelationshipCollection as n, ProfileRelationshipCollection_DUVgaIqf_exports as r, ProfileRelationship as t };
|