@relyio/sdk 0.16.0 → 0.18.0

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 (74) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/automations/index.cjs +70 -0
  3. package/dist/automations/index.d.cts +1309 -0
  4. package/dist/automations/index.d.ts +1309 -0
  5. package/dist/automations/index.js +5 -0
  6. package/dist/{chunk-RSHMA4KT.cjs → chunk-2SPPU2WG.cjs} +68 -68
  7. package/dist/chunk-7I3SC7SV.cjs +40 -0
  8. package/dist/chunk-DI6KFDBO.js +43 -0
  9. package/dist/chunk-EDE2H37D.js +686 -0
  10. package/dist/chunk-HDHBYYEY.js +36 -0
  11. package/dist/{chunk-RLLZUFDB.cjs → chunk-IFKF72VJ.cjs} +718 -331
  12. package/dist/chunk-L6DXCKVQ.cjs +50 -0
  13. package/dist/chunk-LSI26ZN2.cjs +535 -0
  14. package/dist/{chunk-TZL374LS.cjs → chunk-M7MWNV3Q.cjs} +21 -21
  15. package/dist/{chunk-H6IBQSMM.js → chunk-NJQK5STK.js} +3 -3
  16. package/dist/chunk-R6E4HE7R.js +520 -0
  17. package/dist/chunk-SHSK7UUY.cjs +706 -0
  18. package/dist/{chunk-BBUB7C2Z.js → chunk-W2A4OTCI.js} +3 -3
  19. package/dist/chunk-W7JFHSFM.js +18718 -0
  20. package/dist/{chunk-5UMY6CS4.js → chunk-ZAKEY6DY.js} +3 -3
  21. package/dist/chunk-ZAMAR3X2.cjs +18759 -0
  22. package/dist/{chunk-NIUOPIIB.js → chunk-ZHTJ7GXH.js} +400 -19
  23. package/dist/{chunk-LSRPMNPT.cjs → chunk-ZO6QDYJG.cjs} +7 -7
  24. package/dist/client/index.cjs +8 -7
  25. package/dist/client/index.d.cts +4 -3
  26. package/dist/client/index.d.ts +4 -3
  27. package/dist/client/index.js +6 -5
  28. package/dist/{define-content-type-LkI0rS2W.d.cts → define-content-type-NEQDrvdq.d.cts} +3420 -749
  29. package/dist/{define-content-type-CAWSlgn0.d.ts → define-content-type-fb-WCD5e.d.ts} +3420 -749
  30. package/dist/{define-schema-Dxu3RoHV.d.ts → define-schema-DZhtvLiK.d.cts} +157 -10
  31. package/dist/{define-schema-wlsJOrnY.d.cts → define-schema-Dlwh6l_J.d.ts} +157 -10
  32. package/dist/dev-handshake/index.cjs +9 -9
  33. package/dist/dev-handshake/index.js +2 -2
  34. package/dist/extensions/index.cjs +80 -0
  35. package/dist/extensions/index.d.cts +792 -0
  36. package/dist/extensions/index.d.ts +792 -0
  37. package/dist/extensions/index.js +76 -0
  38. package/dist/functions/index.cjs +68 -0
  39. package/dist/functions/index.d.cts +6 -0
  40. package/dist/functions/index.d.ts +6 -0
  41. package/dist/functions/index.js +59 -0
  42. package/dist/{index-CGtYxUuh.d.ts → index-C4LqrNd1.d.ts} +1 -1
  43. package/dist/{index-CcHmRALk.d.cts → index-Dnmt_UOo.d.cts} +1 -1
  44. package/dist/{index-D80MXUkf.d.cts → index-DwHcL6x5.d.cts} +103 -442
  45. package/dist/{index-BH8JksfG.d.ts → index-M3luH06A.d.ts} +103 -442
  46. package/dist/index.cjs +204 -185
  47. package/dist/index.d.cts +93 -13
  48. package/dist/index.d.ts +93 -13
  49. package/dist/index.js +11 -16
  50. package/dist/markdown/index.cjs +382 -382
  51. package/dist/markdown/index.js +1 -1
  52. package/dist/preview/index.cjs +11 -10
  53. package/dist/preview/index.js +3 -2
  54. package/dist/register-B53i97A9.d.ts +677 -0
  55. package/dist/register-BYCs0FpF.d.cts +677 -0
  56. package/dist/rich-text/index.cjs +12 -12
  57. package/dist/rich-text/index.d.cts +2 -2
  58. package/dist/rich-text/index.d.ts +2 -2
  59. package/dist/rich-text/index.js +2 -2
  60. package/dist/schema/index.cjs +62 -34
  61. package/dist/schema/index.d.cts +127 -5
  62. package/dist/schema/index.d.ts +127 -5
  63. package/dist/schema/index.js +2 -2
  64. package/dist/types/index.d.cts +1 -1
  65. package/dist/types/index.d.ts +1 -1
  66. package/dist/utils/index.cjs +20 -20
  67. package/dist/utils/index.js +2 -2
  68. package/package.json +21 -3
  69. package/dist/chunk-7BZW6XYJ.cjs +0 -433
  70. package/dist/chunk-CQHEG7QA.js +0 -411
  71. package/dist/chunk-DIZY6CKM.js +0 -950
  72. package/dist/chunk-GHYB6IZK.cjs +0 -983
  73. package/dist/chunk-MWMSFIWN.cjs +0 -17
  74. package/dist/chunk-XQ4QHWZE.js +0 -13
@@ -1,950 +0,0 @@
1
- import { __name, __export } from './chunk-XQ4QHWZE.js';
2
-
3
- /* RelyIO SDK - Built with ❤️ by the RelyIO Team */
4
-
5
- // src/schema/fields/keyed.ts
6
- var KEYED_FIELD_OPTIONS = [
7
- "displayName",
8
- "description",
9
- "ui",
10
- "ai",
11
- "rules",
12
- "localized",
13
- "fallback",
14
- "deprecated"
15
- ];
16
- function keyedField(type, options) {
17
- if (typeof options !== "object" || options === null || Array.isArray(options)) {
18
- throw new Error(
19
- `fields.${type} takes one options object: the id-first form, fields.${type}('id', { config }), was removed in 0.14. Write the Field under its key, as id: fields.${type}({ \u2026 })`
20
- );
21
- }
22
- return { _tag: "keyedField", type, options: { ...options } };
23
- }
24
- __name(keyedField, "keyedField");
25
- function labelFromKey(key) {
26
- const words = key.replace(/[_\-\s]+/g, " ").replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").trim().split(/\s+/).filter((word) => word.length > 0);
27
- return words.map((word, index) => {
28
- const acronym = word.length > 1 && word === word.toUpperCase() && /[A-Z]/.test(word);
29
- const cased = acronym ? word : word.toLowerCase();
30
- return index === 0 ? cased.charAt(0).toUpperCase() + cased.slice(1) : cased;
31
- }).join(" ");
32
- }
33
- __name(labelFromKey, "labelFromKey");
34
- function isKeyedField(value) {
35
- return typeof value === "object" && value !== null && value._tag === "keyedField";
36
- }
37
- __name(isKeyedField, "isKeyedField");
38
- function localizationOf(localized, id) {
39
- if (localized === true) return true;
40
- if (typeof localized === "object" && localized !== null && !Array.isArray(localized)) {
41
- const { requiredLocales, fallback } = localized;
42
- return {
43
- enabled: true,
44
- ...requiredLocales !== void 0 && { requiredLocales },
45
- ...fallback !== void 0 && { fallback }
46
- };
47
- }
48
- throw new Error(
49
- `Field '${id}' has localized: ${JSON.stringify(localized)}. It takes true, or { requiredLocales, fallback } \u2014 leave it out for a Field every locale shares`
50
- );
51
- }
52
- __name(localizationOf, "localizationOf");
53
- function compileKeyedField(id, field) {
54
- const config = {};
55
- const shared = {};
56
- const sharedNames = new Set(KEYED_FIELD_OPTIONS);
57
- for (const [key, value] of Object.entries(field.options)) {
58
- if (value === void 0) continue;
59
- if (sharedNames.has(key)) shared[key] = value;
60
- else config[key] = value;
61
- }
62
- return {
63
- id,
64
- type: field.type,
65
- ...Object.keys(config).length > 0 && { config },
66
- ui: {
67
- displayName: typeof shared.displayName === "string" ? shared.displayName : labelFromKey(id),
68
- ...shared.description !== void 0 && { description: shared.description },
69
- ...shared.ui !== void 0 && { options: shared.ui }
70
- },
71
- ...shared.ai !== void 0 && { ai: shared.ai },
72
- ...shared.rules !== void 0 && { rules: shared.rules },
73
- ...shared.localized !== void 0 && { localization: localizationOf(shared.localized, id) },
74
- ...shared.fallback !== void 0 && { fallback: shared.fallback },
75
- ...shared.deprecated !== void 0 && { deprecated: shared.deprecated }
76
- };
77
- }
78
- __name(compileKeyedField, "compileKeyedField");
79
- function isSection(value) {
80
- return typeof value === "object" && value !== null && !("type" in value) && "fields" in value && Array.isArray(value.fields);
81
- }
82
- __name(isSection, "isSection");
83
- function notKeyed(id) {
84
- return new Error(
85
- `Field '${id}' is not written in the keyed form: under a key, write it without an id, as fields.shortText({ \u2026 })`
86
- );
87
- }
88
- __name(notKeyed, "notKeyed");
89
- function compileKeyedFields(fields2) {
90
- return Object.entries(fields2).map(([id, field]) => {
91
- if (isSection(field)) {
92
- throw new Error(
93
- `'${id}' is a fieldset, and a settings group holds no Sections: write its Fields beside the others`
94
- );
95
- }
96
- if (!isKeyedField(field)) throw notKeyed(id);
97
- return compileKeyedField(id, field);
98
- });
99
- }
100
- __name(compileKeyedFields, "compileKeyedFields");
101
- function compileKeyedMembers(members) {
102
- const compiled = Object.entries(members).map(([id, member]) => {
103
- if (isKeyedField(member)) return compileKeyedField(id, member);
104
- if (!isSection(member)) throw notKeyed(id);
105
- if (member.id !== id) {
106
- throw new Error(
107
- `Section '${id}' holds fieldset '${member.id}': a Section's key is its fieldset's id, so write it as ${member.id}: \u2026`
108
- );
109
- }
110
- return member;
111
- });
112
- refuseAFieldIdTwice(compiled);
113
- return compiled;
114
- }
115
- __name(compileKeyedMembers, "compileKeyedMembers");
116
- function fieldPaths(members, prefix) {
117
- return members.flatMap((member) => {
118
- if (isSection(member)) return fieldPaths(member.fields, `${prefix}${member.id}.`);
119
- const { id } = member;
120
- return [[id, `${prefix}${id}`]];
121
- });
122
- }
123
- __name(fieldPaths, "fieldPaths");
124
- function refuseAFieldIdTwice(members) {
125
- const firstPath = /* @__PURE__ */ new Map();
126
- for (const [id, path] of fieldPaths(members, "")) {
127
- const first = firstPath.get(id);
128
- if (first !== void 0) {
129
- throw new Error(
130
- `Field '${id}' is declared twice, at '${first}' and at '${path}': a Section's Fields join the record it sits in, so a Field id is used once across its Sections`
131
- );
132
- }
133
- firstPath.set(id, path);
134
- }
135
- }
136
- __name(refuseAFieldIdTwice, "refuseAFieldIdTwice");
137
-
138
- // src/schema/define-content-type.ts
139
- function fieldset(id, config) {
140
- if (Array.isArray(config.fields)) {
141
- throw new Error(
142
- `fieldset('${id}') takes its fields as a record, each Field under its id: the list form was removed in 0.14`
143
- );
144
- }
145
- return {
146
- id,
147
- displayName: config.displayName ?? labelFromKey(id),
148
- ...config.description !== void 0 && { description: config.description },
149
- ...config.collapsed !== void 0 && { collapsedByDefault: config.collapsed },
150
- ...config.ai !== void 0 && { ai: config.ai },
151
- fields: compileKeyedMembers(config.fields)
152
- };
153
- }
154
- __name(fieldset, "fieldset");
155
- function keyedSettings(config) {
156
- return {
157
- ...config.displayName !== void 0 && { displayName: config.displayName },
158
- ...config.displayNamePlural !== void 0 && { displayNamePlural: config.displayNamePlural },
159
- ...config.description !== void 0 && { description: config.description },
160
- ...config.ai !== void 0 && { ai: config.ai },
161
- ...config.displayField !== void 0 && { displayField: config.displayField },
162
- ...config.accessTags !== void 0 && { accessTags: config.accessTags },
163
- ...config.workflow !== void 0 && { workflow: config.workflow }
164
- };
165
- }
166
- __name(keyedSettings, "keyedSettings");
167
- function idFormRemoved(builder, name) {
168
- return new Error(
169
- `${builder}('${name}', \u2026) is the id-first form, removed in 0.14: write ${builder}({ \u2026 }) under its key in defineSchema`
170
- );
171
- }
172
- __name(idFormRemoved, "idFormRemoved");
173
- function defineContentType(config) {
174
- if (typeof config === "string") throw idFormRemoved("defineContentType", config);
175
- return {
176
- _tag: "contentType",
177
- ...keyedSettings(config),
178
- // Written only when given, so a TypeScript type and its YAML twin hash alike (REL-1458)
179
- ...config.hierarchical !== void 0 && { hierarchical: config.hierarchical },
180
- fields: compileKeyedMembers(config.fields)
181
- };
182
- }
183
- __name(defineContentType, "defineContentType");
184
-
185
- // src/schema/keyed-declarations.ts
186
- function isList(value) {
187
- return Array.isArray(value);
188
- }
189
- __name(isList, "isList");
190
- function isKeyed(value, tag) {
191
- return typeof value === "object" && value !== null && value._tag === tag;
192
- }
193
- __name(isKeyed, "isKeyed");
194
-
195
- // src/schema/define-role.ts
196
- var BUILT_IN_ROLES = ["admin", "editor", "viewer"];
197
- var ROLE_ACTIONS = [
198
- "create",
199
- "read",
200
- "update",
201
- "delete",
202
- "publish",
203
- "unpublish",
204
- "duplicate",
205
- "comment",
206
- "approveElevated"
207
- ];
208
- var BUILT_IN_ROLE_ACTIONS = {
209
- admin: ["create", "read", "update", "delete", "publish", "unpublish", "duplicate", "comment"],
210
- editor: ["create", "read", "update", "delete", "publish", "unpublish", "duplicate", "comment"],
211
- viewer: ["read", "comment"]
212
- };
213
- function defineRole(config) {
214
- if (typeof config === "string") throw idFormRemoved("defineRole", config);
215
- return { ...config, _tag: "keyedRole" };
216
- }
217
- __name(defineRole, "defineRole");
218
- function compileKeyedRoles(roles) {
219
- return Object.entries(roles).map(([id, role]) => {
220
- if (!isKeyed(role, "keyedRole")) {
221
- throw new Error(
222
- `Role '${id}' is not written in the keyed form: under a key, write it without an id, as defineRole({ \u2026 })`
223
- );
224
- }
225
- const { _tag: _keyed, displayName, ...config } = role;
226
- return roleDefinition(id, { ...config, displayName: displayName ?? labelFromKey(id) });
227
- });
228
- }
229
- __name(compileKeyedRoles, "compileKeyedRoles");
230
- function roleDefinition(id, config) {
231
- if (!id || id.length === 0) {
232
- throw new Error("Role ID is required");
233
- }
234
- const roleIdPattern = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$|^[a-z][a-zA-Z0-9]*$/;
235
- if (!roleIdPattern.test(id)) {
236
- throw new Error(
237
- `Role ID '${id}' must be kebab-case (e.g., blog-editor) or camelCase (e.g., blogEditor)`
238
- );
239
- }
240
- if (BUILT_IN_ROLES.includes(id)) {
241
- throw new Error(`Role ID '${id}' cannot use a built-in role name (admin, editor, viewer)`);
242
- }
243
- if (!config.displayName || config.displayName.length === 0) {
244
- throw new Error("Role displayName is required");
245
- }
246
- const hasBaseRole = config.baseRole !== void 0;
247
- const hasIncludes = Array.isArray(config.includes) && config.includes.length > 0;
248
- const hasPermissions = Array.isArray(config.permissions) && config.permissions.length > 0;
249
- const hasHiddenFields = config.fields !== void 0 && Array.isArray(config.fields.hidden) && config.fields.hidden.length > 0;
250
- const hasReadonlyFields = config.fields !== void 0 && Array.isArray(config.fields.readonly) && config.fields.readonly.length > 0;
251
- const hasFields = hasHiddenFields || hasReadonlyFields;
252
- if (!hasBaseRole && !hasIncludes && !hasPermissions && !hasFields) {
253
- throw new Error(
254
- `Role '${id}' must have at least one of: 'baseRole', 'includes', or permissions (with tags/actions or fields)`
255
- );
256
- }
257
- if (Array.isArray(config.permissions) && config.permissions.length > 0) {
258
- for (const perm of config.permissions) {
259
- if (perm.tags.length === 0) {
260
- throw new Error(`Permission in role '${id}' must have at least one tag`);
261
- }
262
- if (perm.actions.length === 0) {
263
- throw new Error(`Permission in role '${id}' must have at least one action`);
264
- }
265
- for (const action of perm.actions) {
266
- if (!ROLE_ACTIONS.includes(action)) {
267
- throw new Error(
268
- `Invalid action '${action}' in role '${id}'. Valid actions: ${ROLE_ACTIONS.join(", ")}`
269
- );
270
- }
271
- }
272
- }
273
- }
274
- return {
275
- _tag: "role",
276
- id,
277
- displayName: config.displayName,
278
- ...config.description !== void 0 && { description: config.description },
279
- ...config.baseRole !== void 0 && { baseRole: config.baseRole },
280
- ...config.includes !== void 0 && { includes: config.includes },
281
- ...config.permissions !== void 0 && { permissions: config.permissions },
282
- ...config.fields !== void 0 && { fields: config.fields }
283
- };
284
- }
285
- __name(roleDefinition, "roleDefinition");
286
- function isRoleDefinition(value) {
287
- return typeof value === "object" && value !== null && "_tag" in value && value._tag === "role";
288
- }
289
- __name(isRoleDefinition, "isRoleDefinition");
290
- function isBuiltInRole(roleId) {
291
- return BUILT_IN_ROLES.includes(roleId);
292
- }
293
- __name(isBuiltInRole, "isBuiltInRole");
294
- function getBuiltInRoleActions(roleId) {
295
- return BUILT_IN_ROLE_ACTIONS[roleId];
296
- }
297
- __name(getBuiltInRoleActions, "getBuiltInRoleActions");
298
-
299
- // src/schema/define-view.ts
300
- function defineView(config) {
301
- if (typeof config === "string") throw idFormRemoved("defineView", config);
302
- return { ...config, _tag: "keyedView" };
303
- }
304
- __name(defineView, "defineView");
305
- function compileKeyedViews(views) {
306
- return Object.entries(views).map(([id, view]) => {
307
- if (!isKeyed(view, "keyedView")) {
308
- throw new Error(
309
- `View '${id}' is not written in the keyed form: under a key, write it without an id, as defineView({ \u2026 })`
310
- );
311
- }
312
- const { _tag: _keyed, name, ...config } = view;
313
- return viewDefinition(id, { ...config, name: name ?? labelFromKey(id) });
314
- });
315
- }
316
- __name(compileKeyedViews, "compileKeyedViews");
317
- function viewDefinition(id, config) {
318
- if (!id.match(/^[a-zA-Z][a-zA-Z0-9_-]*$/)) {
319
- throw new Error(
320
- `View ID '${id}' must start with a letter and contain only letters, numbers, underscores, and hyphens`
321
- );
322
- }
323
- if (!config.name || config.name.length === 0) {
324
- throw new Error(`View '${id}' must have a name`);
325
- }
326
- if (config.metadataFields && config.metadataFields.length > 3) {
327
- throw new Error(`View '${id}' can have at most 3 metadata fields`);
328
- }
329
- if (!config.scope?.type) {
330
- throw new Error(`View '${id}' must have a valid scope`);
331
- }
332
- const grouped = (config.filters ?? []).findIndex(
333
- (filter) => typeof filter === "object" && filter !== null && "conditions" in filter
334
- );
335
- if (grouped !== -1) {
336
- throw new Error(
337
- `View '${id}' filter ${grouped} is a filter group: a view's filters are a flat list, joined by AND. List each of its conditions as a filter of its own, or use 'isAnyOf' for an OR within one field.`
338
- );
339
- }
340
- if (config.slug !== void 0 && !/^[a-z][a-z0-9-]*$/.test(config.slug)) {
341
- throw new Error(
342
- `View '${id}' slug '${config.slug}' must be lowercase, start with a letter, and contain only letters, numbers, and hyphens`
343
- );
344
- }
345
- return {
346
- _tag: "view",
347
- id,
348
- ...config
349
- };
350
- }
351
- __name(viewDefinition, "viewDefinition");
352
-
353
- // src/schema/define-schema.ts
354
- function defineSchema(config) {
355
- if (config.contentTypes == null) {
356
- throw new Error("Schema must declare contentTypes (an empty object declares none)");
357
- }
358
- refuseOneDefinitionUnderTwoKeys(config);
359
- const roles = config.roles === void 0 ? void 0 : listed("roles", config.roles, compileKeyedRoles);
360
- const views = config.views === void 0 ? void 0 : listed("views", config.views, compileKeyedViews);
361
- if (config.locales && config.locales.length > 0) {
362
- const defaultLocales = config.locales.filter((l) => l.default === true);
363
- if (defaultLocales.length === 0) {
364
- throw new Error("Schema with locales must have exactly one default locale");
365
- }
366
- if (defaultLocales.length > 1) {
367
- throw new Error(
368
- `Schema has ${defaultLocales.length} default locales. Only one locale can be the default.`
369
- );
370
- }
371
- const codes = config.locales.map((l) => l.code);
372
- const uniqueCodes = new Set(codes);
373
- if (codes.length !== uniqueCodes.size) {
374
- throw new Error("Schema has duplicate locale codes");
375
- }
376
- for (const locale of config.locales) {
377
- if (locale.fallback) {
378
- for (const fallbackCode of locale.fallback) {
379
- if (!uniqueCodes.has(fallbackCode)) {
380
- throw new Error(
381
- `Locale '${locale.code}' has fallback to non-existent locale '${fallbackCode}'`
382
- );
383
- }
384
- }
385
- }
386
- }
387
- }
388
- if (roles && roles.length > 0) {
389
- const roleIds = /* @__PURE__ */ new Set();
390
- for (const role of roles) {
391
- if (roleIds.has(role.id)) {
392
- throw new Error(`Duplicate role ID '${role.id}'`);
393
- }
394
- roleIds.add(role.id);
395
- }
396
- }
397
- if (config.workflow) {
398
- const builtInRoles = /* @__PURE__ */ new Set(["admin", "editor", "viewer"]);
399
- const customRoleIds = new Set(roles?.map((r) => r.id) ?? []);
400
- const allRoleIds = /* @__PURE__ */ new Set([...builtInRoles, ...customRoleIds]);
401
- for (const stage of config.workflow.stages ?? []) {
402
- if (stage.allowedRoles) {
403
- for (const roleId of stage.allowedRoles) {
404
- if (!allRoleIds.has(roleId)) {
405
- throw new Error(`Workflow stage '${stage.id}' references non-existent role '${roleId}'`);
406
- }
407
- }
408
- }
409
- if (stage.autoAssign?.roles) {
410
- for (const roleId of stage.autoAssign.roles) {
411
- if (!allRoleIds.has(roleId)) {
412
- throw new Error(
413
- `Workflow stage '${stage.id}' autoAssign references non-existent role '${roleId}'`
414
- );
415
- }
416
- }
417
- }
418
- if (stage.escalation) {
419
- for (const roleId of stage.escalation.notifyRoles ?? []) {
420
- if (!allRoleIds.has(roleId)) {
421
- throw new Error(
422
- `Workflow stage '${stage.id}' escalation.notifyRoles references non-existent role '${roleId}'`
423
- );
424
- }
425
- }
426
- for (const roleId of stage.escalation.escalateToRoles ?? []) {
427
- if (!allRoleIds.has(roleId)) {
428
- throw new Error(
429
- `Workflow stage '${stage.id}' escalation.escalateToRoles references non-existent role '${roleId}'`
430
- );
431
- }
432
- }
433
- }
434
- }
435
- }
436
- if (views && views.length > 0) {
437
- const viewIds = /* @__PURE__ */ new Set();
438
- for (const view of views) {
439
- if (viewIds.has(view.id)) {
440
- throw new Error(`Duplicate view ID '${view.id}'`);
441
- }
442
- viewIds.add(view.id);
443
- }
444
- }
445
- return {
446
- _tag: "schema",
447
- ...config.locales !== void 0 && { locales: config.locales },
448
- contentTypes: withKeys(config.contentTypes, "labelled"),
449
- singletonContentTypes: withKeys(
450
- config.singletonContentTypes ?? {},
451
- "labelled"
452
- ),
453
- queries: withKeys(config.queries ?? {}, "unlabelled"),
454
- settingsGroups: config.settingsGroups && withKeys(config.settingsGroups, "labelled"),
455
- ...config.assetTypes && { assetTypes: withKeys(config.assetTypes, "labelled") },
456
- // A keyed record's list is the one it compiled to, each item under its key as its id — what
457
- // `RolesAsList` and `ViewsAsList` say, which is all the casts say
458
- ...roles !== void 0 && { roles },
459
- ...config.workflow && { workflow: config.workflow },
460
- ...views !== void 0 && { views }
461
- };
462
- }
463
- __name(defineSchema, "defineSchema");
464
- function listed(section, keyed, compile) {
465
- if (Array.isArray(keyed)) {
466
- throw new Error(
467
- `defineSchema takes ${section} as a record, each under its id: the list form was removed in 0.14`
468
- );
469
- }
470
- return compile(keyed);
471
- }
472
- __name(listed, "listed");
473
- function withKeys(items, labels) {
474
- return Object.fromEntries(
475
- Object.entries(items).map(([key, definition]) => {
476
- const written = definition;
477
- if (written.name !== void 0) return [key, definition];
478
- return [
479
- key,
480
- {
481
- ...definition,
482
- name: key,
483
- ...labels === "labelled" && written.displayName === void 0 && { displayName: labelFromKey(key) }
484
- }
485
- ];
486
- })
487
- );
488
- }
489
- __name(withKeys, "withKeys");
490
- var KEYED_SECTIONS = [
491
- "contentTypes",
492
- "singletonContentTypes",
493
- "assetTypes",
494
- "queries",
495
- "settingsGroups",
496
- "roles",
497
- "views"
498
- ];
499
- function refuseOneDefinitionUnderTwoKeys(config) {
500
- const seen = /* @__PURE__ */ new Map();
501
- for (const section of KEYED_SECTIONS) {
502
- const items = config[section];
503
- if (items === null || typeof items !== "object" || Array.isArray(items)) continue;
504
- for (const [key, definition] of Object.entries(items)) {
505
- if (definition === null || typeof definition !== "object") continue;
506
- const path = `${section}.${key}`;
507
- const first = seen.get(definition);
508
- if (first !== void 0) {
509
- throw new Error(
510
- `One definition is registered under two keys, '${first}' and '${path}': each key deploys a declaration of its own, so give each key its own definition`
511
- );
512
- }
513
- seen.set(definition, path);
514
- }
515
- }
516
- }
517
- __name(refuseOneDefinitionUnderTwoKeys, "refuseOneDefinitionUnderTwoKeys");
518
-
519
- // src/schema/define-locale.ts
520
- var BCP47_PATTERN = /^[a-z]{2}(-[A-Z]{2})?$/;
521
- function defineLocale(code2, options) {
522
- if (!BCP47_PATTERN.test(code2)) {
523
- throw new Error(
524
- `Invalid locale code '${code2}'. Expected BCP 47 format: 'xx' or 'xx-XX' (e.g., 'en', 'en-US', 'fr-FR')`
525
- );
526
- }
527
- if (!options.displayName || options.displayName.trim().length === 0) {
528
- throw new Error(`Locale '${code2}' requires a displayName`);
529
- }
530
- if (options.fallback) {
531
- for (const fallbackCode of options.fallback) {
532
- if (typeof fallbackCode !== "string" || !BCP47_PATTERN.test(fallbackCode)) {
533
- throw new Error(
534
- `Invalid fallback locale code '${fallbackCode}' in locale '${code2}'. Expected BCP 47 format.`
535
- );
536
- }
537
- if (fallbackCode === code2) {
538
- throw new Error(`Locale '${code2}' cannot reference itself in fallback chain`);
539
- }
540
- }
541
- }
542
- return {
543
- _tag: "locale",
544
- code: code2,
545
- displayName: options.displayName,
546
- ...options.default !== void 0 && { default: options.default },
547
- ...options.fallback !== void 0 && { fallback: options.fallback },
548
- ...options.direction !== void 0 && { direction: options.direction },
549
- ...options.active !== void 0 && { active: options.active }
550
- };
551
- }
552
- __name(defineLocale, "defineLocale");
553
- function isLocaleDefinition(value) {
554
- return typeof value === "object" && value !== null && "_tag" in value && value._tag === "locale";
555
- }
556
- __name(isLocaleDefinition, "isLocaleDefinition");
557
- function getLocaleCodes(locales) {
558
- return locales.map((l) => l.code);
559
- }
560
- __name(getLocaleCodes, "getLocaleCodes");
561
- function findDefaultLocale(locales) {
562
- return locales.find((l) => l.default === true);
563
- }
564
- __name(findDefaultLocale, "findDefaultLocale");
565
- function getActiveLocales(locales) {
566
- return locales.filter((l) => l.active !== false);
567
- }
568
- __name(getActiveLocales, "getActiveLocales");
569
- function buildFallbackChain(localeCode, locales, maxDepth = 10) {
570
- const localeMap = new Map(locales.map((l) => [l.code, l]));
571
- const chain = [];
572
- const visited = /* @__PURE__ */ new Set();
573
- function addFallbacks(code2, depth) {
574
- if (depth > maxDepth || visited.has(code2)) return;
575
- const locale = localeMap.get(code2);
576
- if (!locale?.fallback) return;
577
- visited.add(code2);
578
- for (const fallbackCode of locale.fallback) {
579
- if (!chain.includes(fallbackCode) && fallbackCode !== localeCode) {
580
- chain.push(fallbackCode);
581
- addFallbacks(fallbackCode, depth + 1);
582
- }
583
- }
584
- }
585
- __name(addFallbacks, "addFallbacks");
586
- addFallbacks(localeCode, 0);
587
- return chain;
588
- }
589
- __name(buildFallbackChain, "buildFallbackChain");
590
-
591
- // src/schema/define-singleton.ts
592
- function defineSingleton(config) {
593
- if (typeof config === "string") throw idFormRemoved("defineSingleton", config);
594
- return {
595
- _tag: "singletonContentType",
596
- ...keyedSettings(config),
597
- // Written only when given, as a content type's is (REL-1458)
598
- ...config.hierarchical !== void 0 && { hierarchical: config.hierarchical },
599
- fields: compileKeyedMembers(config.fields)
600
- };
601
- }
602
- __name(defineSingleton, "defineSingleton");
603
-
604
- // src/schema/define-settings-group.ts
605
- function defineSettingsGroup(config) {
606
- if (typeof config === "string") throw idFormRemoved("defineSettingsGroup", config);
607
- return {
608
- _tag: "settingsGroup",
609
- ...config.displayName !== void 0 && { displayName: config.displayName },
610
- ...config.description !== void 0 && { description: config.description },
611
- ...config.ai !== void 0 && { ai: config.ai },
612
- ...config.accessTags !== void 0 && { accessTags: config.accessTags },
613
- fields: compileKeyedFields(config.fields)
614
- };
615
- }
616
- __name(defineSettingsGroup, "defineSettingsGroup");
617
-
618
- // src/schema/define-asset-type.ts
619
- function refuseKindKeys(config, what) {
620
- const kindKeys = ["image", "video", "file"].filter((k) => config[k] !== void 0);
621
- if (kindKeys.length === 0) {
622
- throw new Error(`${what} must declare exactly one kind key: image, video, or file`);
623
- }
624
- if (kindKeys.length > 1) {
625
- throw new Error(
626
- `${what} declares multiple kind keys (${kindKeys.join(", ")}); exactly one is allowed`
627
- );
628
- }
629
- }
630
- __name(refuseKindKeys, "refuseKindKeys");
631
- function defineAssetType(config) {
632
- if (typeof config === "string") throw idFormRemoved("defineAssetType", config);
633
- refuseKindKeys(config, "An asset type");
634
- return {
635
- _tag: "assetType",
636
- ...keyedSettings(config),
637
- ...config.image !== void 0 && { image: config.image },
638
- ...config.video !== void 0 && { video: config.video },
639
- ...config.file !== void 0 && { file: config.file },
640
- ...config.fields !== void 0 && { fields: compileKeyedMembers(config.fields) }
641
- };
642
- }
643
- __name(defineAssetType, "defineAssetType");
644
-
645
- // src/schema/define-workflow.ts
646
- function defineWorkflowStage(config) {
647
- if (typeof config === "string") throw idFormRemoved("defineWorkflowStage", config);
648
- return { ...config, _tag: "keyedWorkflowStage" };
649
- }
650
- __name(defineWorkflowStage, "defineWorkflowStage");
651
- function compileKeyedStages(stages) {
652
- const seen = /* @__PURE__ */ new Map();
653
- return Object.entries(stages).map(([id, stage]) => {
654
- if (!isKeyed(stage, "keyedWorkflowStage")) {
655
- throw new Error(
656
- `Workflow stage '${id}' is not written in the keyed form: under a key, write it without an id, as defineWorkflowStage({ \u2026 })`
657
- );
658
- }
659
- const first = seen.get(stage);
660
- if (first !== void 0) {
661
- throw new Error(
662
- `One stage is registered under two keys, '${first}' and '${id}': each key is a stage of its own, so give each key its own defineWorkflowStage({ \u2026 })`
663
- );
664
- }
665
- seen.set(stage, id);
666
- const { _tag: _keyed, displayName, ...config } = stage;
667
- return stageDefinition(id, { ...config, displayName: displayName ?? labelFromKey(id) });
668
- });
669
- }
670
- __name(compileKeyedStages, "compileKeyedStages");
671
- function stageDefinition(id, config) {
672
- if (!id || id.length === 0) {
673
- throw new Error("Workflow stage ID is required");
674
- }
675
- const stageIdPattern = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$|^[a-z][a-zA-Z0-9]*$/;
676
- if (!stageIdPattern.test(id)) {
677
- throw new Error(
678
- `Workflow stage ID '${id}' must be kebab-case (e.g., editorial-review) or camelCase (e.g., editorialReview)`
679
- );
680
- }
681
- if (id.length > 64) {
682
- throw new Error(`Workflow stage ID '${id}' must be 64 characters or less`);
683
- }
684
- if (!config.displayName || config.displayName.length === 0) {
685
- throw new Error("Workflow stage displayName is required");
686
- }
687
- if (config.displayName.length > 128) {
688
- throw new Error(`Workflow stage displayName must be 128 characters or less`);
689
- }
690
- if (config.description != null && config.description.length > 512) {
691
- throw new Error(`Workflow stage description must be 512 characters or less`);
692
- }
693
- if (config.requiredApprovals !== void 0 && (config.requiredApprovals < 1 || config.requiredApprovals > 10)) {
694
- throw new Error(`requiredApprovals must be between 1 and 10`);
695
- }
696
- if (config.timeoutDays !== void 0) {
697
- if (config.timeoutDays < 1 || config.timeoutDays > 365) {
698
- throw new Error(`timeoutDays must be between 1 and 365`);
699
- }
700
- }
701
- if (config.autoAssign) {
702
- if (!Array.isArray(config.autoAssign.roles) || config.autoAssign.roles.length === 0) {
703
- throw new Error(`autoAssign.roles must be a non-empty array`);
704
- }
705
- }
706
- return {
707
- _tag: "workflowStage",
708
- id,
709
- displayName: config.displayName,
710
- ...config.description !== void 0 && { description: config.description },
711
- ...config.requiredApprovals !== void 0 && { requiredApprovals: config.requiredApprovals },
712
- ...config.allowedRoles !== void 0 && { allowedRoles: config.allowedRoles },
713
- ...config.autoAssign !== void 0 && { autoAssign: config.autoAssign },
714
- ...config.timeoutDays !== void 0 && { timeoutDays: config.timeoutDays },
715
- ...config.escalation !== void 0 && { escalation: config.escalation }
716
- };
717
- }
718
- __name(stageDefinition, "stageDefinition");
719
- function defineWorkflow(config) {
720
- if (config.stages !== void 0 && isList(config.stages)) {
721
- throw new Error(
722
- "defineWorkflow takes its stages as a record keyed by stage id, in the order content moves through them: the list form was removed in 0.14 \u2014 write stages: { review: defineWorkflowStage({ \u2026 }) }"
723
- );
724
- }
725
- const stages = config.stages === void 0 ? void 0 : compileKeyedStages(config.stages);
726
- const stageIds = /* @__PURE__ */ new Set();
727
- for (const stage of stages ?? []) {
728
- if (stageIds.has(stage.id)) {
729
- throw new Error(`Duplicate workflow stage ID '${stage.id}'`);
730
- }
731
- stageIds.add(stage.id);
732
- }
733
- return {
734
- _tag: "workflow",
735
- ...config.enabled !== void 0 && { enabled: config.enabled },
736
- ...stages !== void 0 && { stages }
737
- };
738
- }
739
- __name(defineWorkflow, "defineWorkflow");
740
- function defineContentTypeWorkflow(config) {
741
- return {
742
- ...config.enabled !== void 0 && { enabled: config.enabled },
743
- // An empty list too, as YAML keeps it (REL-1458)
744
- ...config.stages !== void 0 && { stages: config.stages },
745
- ...config.autoPublish !== void 0 && { autoPublish: config.autoPublish },
746
- ...config.requireAllLocales !== void 0 && { requireAllLocales: config.requireAllLocales }
747
- };
748
- }
749
- __name(defineContentTypeWorkflow, "defineContentTypeWorkflow");
750
- function isWorkflowStageDefinition(value) {
751
- return typeof value === "object" && value !== null && "_tag" in value && value._tag === "workflowStage";
752
- }
753
- __name(isWorkflowStageDefinition, "isWorkflowStageDefinition");
754
- function isWorkflowDefinition(value) {
755
- return typeof value === "object" && value !== null && "_tag" in value && value._tag === "workflow";
756
- }
757
- __name(isWorkflowDefinition, "isWorkflowDefinition");
758
- function stagesOf(workflow) {
759
- return workflow.stages ?? [];
760
- }
761
- __name(stagesOf, "stagesOf");
762
- function getWorkflowStageIds(workflow) {
763
- return stagesOf(workflow).map((s) => s.id);
764
- }
765
- __name(getWorkflowStageIds, "getWorkflowStageIds");
766
- function findWorkflowStage(workflow, stageId) {
767
- return stagesOf(workflow).find((s) => s.id === stageId);
768
- }
769
- __name(findWorkflowStage, "findWorkflowStage");
770
- function getNextWorkflowStage(workflow, currentStageId) {
771
- const stages = stagesOf(workflow);
772
- const currentIndex = stages.findIndex((s) => s.id === currentStageId);
773
- if (currentIndex === -1 || currentIndex === stages.length - 1) {
774
- return null;
775
- }
776
- const nextStage = stages[currentIndex + 1];
777
- return nextStage ?? null;
778
- }
779
- __name(getNextWorkflowStage, "getNextWorkflowStage");
780
- function getFirstWorkflowStage(workflow) {
781
- const stages = stagesOf(workflow);
782
- if (stages.length === 0) return null;
783
- const firstStage = stages[0];
784
- return firstStage ?? null;
785
- }
786
- __name(getFirstWorkflowStage, "getFirstWorkflowStage");
787
- function isFinalWorkflowStage(workflow, stageId) {
788
- const stages = stagesOf(workflow);
789
- if (stages.length === 0) return false;
790
- const lastStage = stages[stages.length - 1];
791
- return lastStage?.id === stageId;
792
- }
793
- __name(isFinalWorkflowStage, "isFinalWorkflowStage");
794
-
795
- // src/schema/define-query.ts
796
- function defineQuery(config) {
797
- if (typeof config === "string") throw idFormRemoved("defineQuery", config);
798
- if (!config.fetch && !config.aggregate && !config.search) {
799
- throw new Error("Query must have at least one of: fetch, aggregate or search");
800
- }
801
- if (!config.endpoint.startsWith("/api/")) {
802
- throw new Error("Query endpoint must start with /api/");
803
- }
804
- return {
805
- _tag: "query",
806
- type: config.type,
807
- endpoint: config.endpoint,
808
- description: config.description,
809
- fetch: config.fetch,
810
- aggregate: config.aggregate,
811
- search: config.search,
812
- include: config.include,
813
- filters: config.filters,
814
- fullText: config.fullText,
815
- select: config.select,
816
- cache: config.cache,
817
- parameters: config.parameters,
818
- cardinality: config.cardinality
819
- };
820
- }
821
- __name(defineQuery, "defineQuery");
822
-
823
- // src/schema/fields/index.ts
824
- var fields_exports = {};
825
- __export(fields_exports, {
826
- boolean: () => boolean,
827
- code: () => code,
828
- date: () => date,
829
- dateTime: () => dateTime,
830
- decimal: () => decimal,
831
- email: () => email,
832
- enum: () => enumField,
833
- integer: () => integer,
834
- json: () => json,
835
- list: () => list,
836
- longText: () => longText,
837
- object: () => object,
838
- reference: () => reference,
839
- richText: () => richText,
840
- shortText: () => shortText,
841
- slug: () => slug,
842
- table: () => table,
843
- tags: () => tags,
844
- url: () => url
845
- });
846
-
847
- // src/schema/fields/builders.ts
848
- function shortText(options = {}) {
849
- return keyedField("shortText", options);
850
- }
851
- __name(shortText, "shortText");
852
- function longText(options = {}) {
853
- return keyedField("longText", options);
854
- }
855
- __name(longText, "longText");
856
- function richText(options = {}) {
857
- return keyedField("richText", options);
858
- }
859
- __name(richText, "richText");
860
- function table(options = {}) {
861
- return keyedField("table", options);
862
- }
863
- __name(table, "table");
864
- function code(options = {}) {
865
- return keyedField("code", options);
866
- }
867
- __name(code, "code");
868
- function slug(options = {}) {
869
- return keyedField("slug", options);
870
- }
871
- __name(slug, "slug");
872
- function url(options = {}) {
873
- return keyedField("url", options);
874
- }
875
- __name(url, "url");
876
- function email(options = {}) {
877
- return keyedField("email", options);
878
- }
879
- __name(email, "email");
880
- function integer(options = {}) {
881
- return keyedField("integer", options);
882
- }
883
- __name(integer, "integer");
884
- function decimal(options = {}) {
885
- return keyedField("decimal", options);
886
- }
887
- __name(decimal, "decimal");
888
- function boolean(options = {}) {
889
- return keyedField("boolean", options);
890
- }
891
- __name(boolean, "boolean");
892
- function enumOptionsList(options) {
893
- if (typeof options !== "object" || options === null || Array.isArray(options)) {
894
- throw new Error(
895
- "An enum's options in the keyed form are a value-to-label map, { draft: 'Draft', live: 'Live' }, in the order the editor shows them"
896
- );
897
- }
898
- return Object.entries(options).map(([value, label]) => {
899
- if (/^(0|[1-9]\d*)$/.test(value)) {
900
- throw new Error(
901
- `An enum option's value '${value}' is a whole number, which a value-to-label map cannot keep in the order it was written: JavaScript orders such keys first`
902
- );
903
- }
904
- if (typeof label !== "string") {
905
- throw new Error(`An enum option's label must be a string: '${value}' has ${String(label)}`);
906
- }
907
- return { value, label };
908
- });
909
- }
910
- __name(enumOptionsList, "enumOptionsList");
911
- function enumField(options) {
912
- const written = options;
913
- return keyedField("enum", { ...written, options: enumOptionsList(written.options) });
914
- }
915
- __name(enumField, "enumField");
916
- function date(options = {}) {
917
- return keyedField("date", options);
918
- }
919
- __name(date, "date");
920
- function dateTime(options = {}) {
921
- return keyedField("dateTime", options);
922
- }
923
- __name(dateTime, "dateTime");
924
- function reference(options) {
925
- return keyedField("reference", options);
926
- }
927
- __name(reference, "reference");
928
- function tags(options = {}) {
929
- return keyedField("tags", options);
930
- }
931
- __name(tags, "tags");
932
- function list(options = {}) {
933
- return keyedField("list", options);
934
- }
935
- __name(list, "list");
936
- function object(options) {
937
- return keyedField("object", options);
938
- }
939
- __name(object, "object");
940
- function json(options = {}) {
941
- return keyedField("json", options);
942
- }
943
- __name(json, "json");
944
-
945
- // src/schema/index.ts
946
- var fields = fields_exports;
947
-
948
- export { BUILT_IN_ROLES, BUILT_IN_ROLE_ACTIONS, ROLE_ACTIONS, buildFallbackChain, defineAssetType, defineContentType, defineContentTypeWorkflow, defineLocale, defineQuery, defineRole, defineSchema, defineSettingsGroup, defineSingleton, defineView, defineWorkflow, defineWorkflowStage, fields, fieldset, findDefaultLocale, findWorkflowStage, getActiveLocales, getBuiltInRoleActions, getFirstWorkflowStage, getLocaleCodes, getNextWorkflowStage, getWorkflowStageIds, isBuiltInRole, isFinalWorkflowStage, isLocaleDefinition, isRoleDefinition, isWorkflowDefinition, isWorkflowStageDefinition };
949
- //# sourceMappingURL=chunk-DIZY6CKM.js.map
950
- //# sourceMappingURL=chunk-DIZY6CKM.js.map