@relyio/sdk 0.2.0 → 0.3.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.
- package/CHANGELOG.md +40 -0
- package/README.md +5 -310
- package/dist/.tsbuildinfo +1 -1
- package/dist/{chunk-7W4MJXQ4.cjs → chunk-54WP2PWG.cjs} +215 -96
- package/dist/chunk-BBUB7C2Z.js +81 -0
- package/dist/{chunk-FJK7ZWKK.cjs → chunk-HMVGXUGR.cjs} +156 -221
- package/dist/chunk-LSRPMNPT.cjs +89 -0
- package/dist/{chunk-2QUK2ZGD.js → chunk-LYRYCIX5.js} +157 -219
- package/dist/{chunk-RJBIJ2ZK.js → chunk-QIZOBT5F.js} +215 -96
- package/dist/client/index.cjs +4 -3
- package/dist/client/index.d.cts +4 -3
- package/dist/client/index.d.ts +4 -3
- package/dist/client/index.js +2 -1
- package/dist/define-content-type-CBfnTWSS.d.cts +716 -0
- package/dist/define-content-type-CBfnTWSS.d.ts +716 -0
- package/dist/{define-schema-DHvUCKwj.d.cts → define-schema-BD6HSPnG.d.ts} +55 -722
- package/dist/{define-schema-DHvUCKwj.d.ts → define-schema-BfXeR6K8.d.cts} +55 -722
- package/dist/dev-handshake/index.cjs +37 -0
- package/dist/dev-handshake/index.d.cts +144 -0
- package/dist/dev-handshake/index.d.ts +144 -0
- package/dist/dev-handshake/index.js +4 -0
- package/dist/{index-DGWaawHt.d.cts → index-BDpar3FO.d.cts} +22 -6
- package/dist/{index-BsUqCAu8.d.cts → index-DuEhsGdE.d.ts} +516 -2155
- package/dist/{index-B-KiFHbx.d.ts → index-Dx01iwaf.d.ts} +22 -6
- package/dist/{index-BsUqCAu8.d.ts → index-ulOrcfPa.d.cts} +516 -2155
- package/dist/index.cjs +67 -70
- package/dist/index.d.cts +28 -13
- package/dist/index.d.ts +28 -13
- package/dist/index.js +3 -2
- package/dist/schema/index.cjs +35 -47
- package/dist/schema/index.d.cts +3 -2
- package/dist/schema/index.d.ts +3 -2
- package/dist/schema/index.js +1 -1
- package/dist/types/index.d.cts +2 -1
- package/dist/types/index.d.ts +2 -1
- package/package.json +15 -17
|
@@ -0,0 +1,716 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Field type definitions matching @relyio/schema package
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* AI configuration. A single prompt — `instructions` — describes what the
|
|
6
|
+
* element is and how AI should produce its value. Attaches to fields, content
|
|
7
|
+
* types, components, fieldsets, and (extended) asset types.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* fields.richText('body', {
|
|
12
|
+
* ai: {
|
|
13
|
+
* instructions: `
|
|
14
|
+
* Write in a conversational tone.
|
|
15
|
+
* Use short paragraphs (2-3 sentences).
|
|
16
|
+
* Target grade 8 reading level.
|
|
17
|
+
* `
|
|
18
|
+
* }
|
|
19
|
+
* })
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
interface AIConfig {
|
|
23
|
+
/**
|
|
24
|
+
* AI brief for this element: what it should contain and how to produce it.
|
|
25
|
+
*
|
|
26
|
+
* Used by the Studio authoring agent and — on asset types with
|
|
27
|
+
* `ai.autoGenerate` — by the automatic post-upload run.
|
|
28
|
+
*
|
|
29
|
+
* The fallback chain for AI guidance is:
|
|
30
|
+
* 1. ai.instructions (most specific)
|
|
31
|
+
* 2. ui.description (general field description)
|
|
32
|
+
* 3. Field displayName + type (inferred from semantics)
|
|
33
|
+
*/
|
|
34
|
+
instructions?: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Field-level AI config. `inputs` names the fields this instruction reads.
|
|
38
|
+
* Unknown ids and cycles are refused when the schema is parsed.
|
|
39
|
+
*/
|
|
40
|
+
interface FieldAIConfig extends AIConfig {
|
|
41
|
+
/** Field ids this instruction reads. Never inferred from instruction text. */
|
|
42
|
+
inputs?: string[];
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Asset-type AI configuration. Extends {@link AIConfig} with `autoGenerate`,
|
|
46
|
+
* the single switch that turns on automatic field generation after upload.
|
|
47
|
+
*/
|
|
48
|
+
interface AssetAIConfig extends AIConfig {
|
|
49
|
+
/**
|
|
50
|
+
* Master switch for automatic, post-upload field generation. When `true`, the
|
|
51
|
+
* derived analysis agent fills every field that declares `ai.instructions`,
|
|
52
|
+
* applied as a review proposal. Only meaningful for image asset types in v1.
|
|
53
|
+
*/
|
|
54
|
+
autoGenerate?: boolean;
|
|
55
|
+
}
|
|
56
|
+
interface BaseFieldConfig {
|
|
57
|
+
/** Whether the field is required */
|
|
58
|
+
required?: boolean;
|
|
59
|
+
/** Whether the field value must be unique */
|
|
60
|
+
unique?: boolean;
|
|
61
|
+
/** Default value for the field */
|
|
62
|
+
defaultValue?: unknown;
|
|
63
|
+
}
|
|
64
|
+
interface FieldUIConfig {
|
|
65
|
+
/** Display name shown in the UI */
|
|
66
|
+
displayName: string;
|
|
67
|
+
/** Field description/help text */
|
|
68
|
+
description?: string;
|
|
69
|
+
/** Widget-specific options */
|
|
70
|
+
options?: Record<string, unknown>;
|
|
71
|
+
}
|
|
72
|
+
interface RuleCondition {
|
|
73
|
+
field: string;
|
|
74
|
+
operator: 'equals' | 'not_equals' | 'contains' | 'not_contains' | 'greater_than' | 'less_than' | 'is_empty' | 'is_not_empty';
|
|
75
|
+
value?: unknown;
|
|
76
|
+
}
|
|
77
|
+
interface RuleConditions {
|
|
78
|
+
mode: 'all' | 'any' | 'none';
|
|
79
|
+
conditions: RuleCondition[];
|
|
80
|
+
}
|
|
81
|
+
interface VisibilityRule {
|
|
82
|
+
type: 'visibility';
|
|
83
|
+
action: 'show' | 'hide';
|
|
84
|
+
conditions: RuleConditions;
|
|
85
|
+
}
|
|
86
|
+
interface RequirementRule {
|
|
87
|
+
type: 'requirement';
|
|
88
|
+
action: 'require' | 'optional';
|
|
89
|
+
conditions: RuleConditions;
|
|
90
|
+
}
|
|
91
|
+
interface ValidationRule {
|
|
92
|
+
type: 'validation';
|
|
93
|
+
action: 'validate' | 'skip';
|
|
94
|
+
message?: string;
|
|
95
|
+
conditions: RuleConditions;
|
|
96
|
+
}
|
|
97
|
+
interface ReadOnlyRule {
|
|
98
|
+
type: 'readOnly';
|
|
99
|
+
action: 'enable' | 'disable';
|
|
100
|
+
conditions: RuleConditions;
|
|
101
|
+
}
|
|
102
|
+
type FieldRule = VisibilityRule | RequirementRule | ValidationRule | ReadOnlyRule;
|
|
103
|
+
type LocalizationConfig = boolean | string[] | {
|
|
104
|
+
enabled: boolean;
|
|
105
|
+
requiredLocales?: string[];
|
|
106
|
+
fallback?: boolean;
|
|
107
|
+
};
|
|
108
|
+
interface FieldDefinition<TId extends string = string, TType extends string = string, TConfig = unknown> {
|
|
109
|
+
/** Unique field identifier - preserves literal type for type inference */
|
|
110
|
+
readonly id: TId;
|
|
111
|
+
/** Field type */
|
|
112
|
+
readonly type: TType;
|
|
113
|
+
/** Type-specific configuration */
|
|
114
|
+
config?: TConfig;
|
|
115
|
+
/** UI display configuration */
|
|
116
|
+
ui?: FieldUIConfig;
|
|
117
|
+
/** AI configuration: generation/review guidance for this field */
|
|
118
|
+
ai?: FieldAIConfig;
|
|
119
|
+
/** Dynamic field rules */
|
|
120
|
+
rules?: FieldRule[];
|
|
121
|
+
/** Localization settings */
|
|
122
|
+
localization?: LocalizationConfig;
|
|
123
|
+
/** Fallback value when field is empty */
|
|
124
|
+
fallback?: unknown;
|
|
125
|
+
/** Whether this field is deprecated */
|
|
126
|
+
deprecated?: boolean;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Any field definition - used in arrays where we need to preserve specific field types
|
|
130
|
+
*/
|
|
131
|
+
type AnyFieldDefinition = FieldDefinition<string, string, unknown>;
|
|
132
|
+
interface ShortTextConfig extends BaseFieldConfig {
|
|
133
|
+
/** Maximum character length */
|
|
134
|
+
maxLength?: number;
|
|
135
|
+
/** Regex pattern for validation */
|
|
136
|
+
pattern?: string;
|
|
137
|
+
}
|
|
138
|
+
interface LongTextConfig extends BaseFieldConfig {
|
|
139
|
+
minLength?: number;
|
|
140
|
+
maxLength?: number;
|
|
141
|
+
}
|
|
142
|
+
interface RichTextConfig extends BaseFieldConfig {
|
|
143
|
+
/** Maximum character length for the rich text content */
|
|
144
|
+
maxLength?: number;
|
|
145
|
+
/** Allowed formatting options (e.g., bold, italic, underline) */
|
|
146
|
+
allowedFormats?: string[];
|
|
147
|
+
/** Allowed embed types (e.g., image, video, code) */
|
|
148
|
+
embedTypes?: string[];
|
|
149
|
+
}
|
|
150
|
+
interface SlugConfig extends BaseFieldConfig {
|
|
151
|
+
/** Source field to generate slug from */
|
|
152
|
+
sourceField?: string;
|
|
153
|
+
/** Maximum character length */
|
|
154
|
+
maxLength?: number;
|
|
155
|
+
}
|
|
156
|
+
interface UrlConfig extends BaseFieldConfig {
|
|
157
|
+
/** Allowed URL protocols */
|
|
158
|
+
allowedProtocols?: ('http' | 'https' | 'ftp' | 'ftps')[];
|
|
159
|
+
/** Maximum character length */
|
|
160
|
+
maxLength?: number;
|
|
161
|
+
}
|
|
162
|
+
interface EmailConfig extends BaseFieldConfig {
|
|
163
|
+
/** Maximum character length */
|
|
164
|
+
maxLength?: number;
|
|
165
|
+
/** Whitelist of allowed email domains */
|
|
166
|
+
domainWhitelist?: string[];
|
|
167
|
+
}
|
|
168
|
+
interface IntegerConfig extends BaseFieldConfig {
|
|
169
|
+
min?: number;
|
|
170
|
+
max?: number;
|
|
171
|
+
}
|
|
172
|
+
interface DecimalConfig extends BaseFieldConfig {
|
|
173
|
+
min?: number;
|
|
174
|
+
max?: number;
|
|
175
|
+
decimalPlaces?: number;
|
|
176
|
+
roundingMode?: 'HALF_UP' | 'FLOOR' | 'CEILING' | 'ROUND' | 'TRUNCATE';
|
|
177
|
+
}
|
|
178
|
+
interface BooleanConfig extends BaseFieldConfig {
|
|
179
|
+
trueLabel?: string;
|
|
180
|
+
falseLabel?: string;
|
|
181
|
+
}
|
|
182
|
+
interface EnumConfig extends BaseFieldConfig {
|
|
183
|
+
options: Array<{
|
|
184
|
+
value: string;
|
|
185
|
+
label?: string;
|
|
186
|
+
}>;
|
|
187
|
+
multi?: boolean;
|
|
188
|
+
}
|
|
189
|
+
interface DateConfig extends BaseFieldConfig {
|
|
190
|
+
minDate?: string;
|
|
191
|
+
maxDate?: string;
|
|
192
|
+
format?: string;
|
|
193
|
+
}
|
|
194
|
+
interface DateTimeConfig extends BaseFieldConfig {
|
|
195
|
+
minDateTime?: string;
|
|
196
|
+
maxDateTime?: string;
|
|
197
|
+
format?: string;
|
|
198
|
+
timezone?: boolean;
|
|
199
|
+
}
|
|
200
|
+
interface ReferenceConfig extends BaseFieldConfig {
|
|
201
|
+
/**
|
|
202
|
+
* Target entry type id(s) — content type or asset type ids. Pass a single id
|
|
203
|
+
* for one target or an array for several. All ids must belong to the same
|
|
204
|
+
* family (all content types or all asset types).
|
|
205
|
+
*/
|
|
206
|
+
to: string | string[];
|
|
207
|
+
/** Allow multiple references (the field value is a list). */
|
|
208
|
+
multi?: boolean;
|
|
209
|
+
/** Reference strength for publish/unpublish behavior. */
|
|
210
|
+
referenceStrength?: 'strong' | 'weak';
|
|
211
|
+
/** Behavior when a referenced entry is deleted. */
|
|
212
|
+
onTargetDelete?: 'block' | 'nullify';
|
|
213
|
+
}
|
|
214
|
+
interface TagsConfig extends BaseFieldConfig {
|
|
215
|
+
allowCustom?: boolean;
|
|
216
|
+
predefinedTags?: string[];
|
|
217
|
+
maxTags?: number;
|
|
218
|
+
}
|
|
219
|
+
interface ListConfig extends BaseFieldConfig {
|
|
220
|
+
dragAndDrop?: boolean;
|
|
221
|
+
minItems?: number;
|
|
222
|
+
maxItems?: number;
|
|
223
|
+
/** Subfields for list items */
|
|
224
|
+
subfields?: FieldDefinition[];
|
|
225
|
+
}
|
|
226
|
+
type FieldType = 'shortText' | 'longText' | 'richText' | 'slug' | 'url' | 'email' | 'integer' | 'decimal' | 'boolean' | 'enum' | 'date' | 'dateTime' | 'reference' | 'tags' | 'list';
|
|
227
|
+
type ComponentFieldType = `component(${string})`;
|
|
228
|
+
type AllFieldTypes = FieldType | ComponentFieldType;
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Workflow definition for content approval pipelines
|
|
232
|
+
*
|
|
233
|
+
* Workflows define approval stages that content must pass through before
|
|
234
|
+
* publication. They can be configured globally and per content type.
|
|
235
|
+
*
|
|
236
|
+
* @example
|
|
237
|
+
* // Simple workflow with one approval stage
|
|
238
|
+
* const workflow = defineWorkflow({
|
|
239
|
+
* enabled: true,
|
|
240
|
+
* stages: [
|
|
241
|
+
* defineWorkflowStage('review', {
|
|
242
|
+
* displayName: 'Editorial Review',
|
|
243
|
+
* allowedRoles: ['editor', 'admin']
|
|
244
|
+
* })
|
|
245
|
+
* ]
|
|
246
|
+
* })
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* // Multi-stage workflow
|
|
250
|
+
* const workflow = defineWorkflow({
|
|
251
|
+
* enabled: true,
|
|
252
|
+
* stages: [
|
|
253
|
+
* defineWorkflowStage('editorial-review', {
|
|
254
|
+
* displayName: 'Editorial Review',
|
|
255
|
+
* allowedRoles: ['editor']
|
|
256
|
+
* }),
|
|
257
|
+
* defineWorkflowStage('legal-approval', {
|
|
258
|
+
* displayName: 'Legal Approval',
|
|
259
|
+
* requiredApprovals: 1,
|
|
260
|
+
* allowedRoles: ['legal-reviewer']
|
|
261
|
+
* }),
|
|
262
|
+
* defineWorkflowStage('final-approval', {
|
|
263
|
+
* displayName: 'Final Approval',
|
|
264
|
+
* requiredApprovals: 2,
|
|
265
|
+
* allowedRoles: ['publisher', 'admin']
|
|
266
|
+
* })
|
|
267
|
+
* ]
|
|
268
|
+
* })
|
|
269
|
+
*/
|
|
270
|
+
/**
|
|
271
|
+
* Escalation configuration when a workflow stage times out
|
|
272
|
+
*/
|
|
273
|
+
interface WorkflowEscalation {
|
|
274
|
+
/** Roles to notify when stage times out */
|
|
275
|
+
notifyRoles?: string[];
|
|
276
|
+
/** Roles to escalate to if still pending after another timeout period */
|
|
277
|
+
escalateToRoles?: string[];
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Auto-assignment configuration for workflow stages
|
|
281
|
+
*/
|
|
282
|
+
interface WorkflowAutoAssign {
|
|
283
|
+
/** Roles whose users should be notified when content enters this stage */
|
|
284
|
+
roles: string[];
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Workflow stage configuration
|
|
288
|
+
*/
|
|
289
|
+
interface WorkflowStageConfig {
|
|
290
|
+
/** Human-readable name shown in Studio */
|
|
291
|
+
displayName: string;
|
|
292
|
+
/** Optional description for reviewers */
|
|
293
|
+
description?: string;
|
|
294
|
+
/** Number of approvals needed to pass this stage (default: 1) */
|
|
295
|
+
requiredApprovals?: number;
|
|
296
|
+
/** Roles that can approve this stage */
|
|
297
|
+
allowedRoles?: string[];
|
|
298
|
+
/** Auto-assignment configuration */
|
|
299
|
+
autoAssign?: WorkflowAutoAssign;
|
|
300
|
+
/** Days before escalation triggers (optional) */
|
|
301
|
+
timeoutDays?: number;
|
|
302
|
+
/** Escalation configuration when stage times out */
|
|
303
|
+
escalation?: WorkflowEscalation;
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Complete workflow stage definition
|
|
307
|
+
*/
|
|
308
|
+
interface WorkflowStageDefinition {
|
|
309
|
+
readonly _tag: 'workflowStage';
|
|
310
|
+
readonly id: string;
|
|
311
|
+
readonly displayName: string;
|
|
312
|
+
readonly description?: string;
|
|
313
|
+
readonly requiredApprovals: number;
|
|
314
|
+
readonly allowedRoles?: string[];
|
|
315
|
+
readonly autoAssign?: WorkflowAutoAssign;
|
|
316
|
+
readonly timeoutDays?: number;
|
|
317
|
+
readonly escalation?: WorkflowEscalation;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Workflow configuration
|
|
321
|
+
*/
|
|
322
|
+
interface WorkflowConfig {
|
|
323
|
+
/** Enable/disable workflow for the branch (default: false) */
|
|
324
|
+
enabled?: boolean;
|
|
325
|
+
/** Array of approval stage definitions */
|
|
326
|
+
stages?: WorkflowStageDefinition[];
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Complete workflow definition
|
|
330
|
+
*/
|
|
331
|
+
interface WorkflowDefinition {
|
|
332
|
+
readonly _tag: 'workflow';
|
|
333
|
+
readonly enabled: boolean;
|
|
334
|
+
readonly stages: WorkflowStageDefinition[];
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Per-content-type workflow configuration
|
|
338
|
+
*/
|
|
339
|
+
interface ContentTypeWorkflowConfig {
|
|
340
|
+
/** Enable workflow for this content type (inherits from global if not set) */
|
|
341
|
+
enabled?: boolean;
|
|
342
|
+
/** Which global stages apply to this content type (subset of global stages) */
|
|
343
|
+
stages?: string[];
|
|
344
|
+
/** Publish automatically after all stages are approved */
|
|
345
|
+
autoPublish?: boolean;
|
|
346
|
+
/** Require all locales to be approved before publishing */
|
|
347
|
+
requireAllLocales?: boolean;
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Define a workflow stage
|
|
351
|
+
*
|
|
352
|
+
* @param id - Unique identifier for the stage (kebab-case or camelCase)
|
|
353
|
+
* @param config - Stage configuration
|
|
354
|
+
*
|
|
355
|
+
* @example
|
|
356
|
+
* const editorialReview = defineWorkflowStage('editorial-review', {
|
|
357
|
+
* displayName: 'Editorial Review',
|
|
358
|
+
* description: 'Content quality and style check',
|
|
359
|
+
* requiredApprovals: 1,
|
|
360
|
+
* allowedRoles: ['editor', 'senior-editor']
|
|
361
|
+
* })
|
|
362
|
+
*
|
|
363
|
+
* @example
|
|
364
|
+
* // Stage with auto-assignment and timeout
|
|
365
|
+
* const legalApproval = defineWorkflowStage('legal-approval', {
|
|
366
|
+
* displayName: 'Legal Approval',
|
|
367
|
+
* allowedRoles: ['legal-reviewer'],
|
|
368
|
+
* autoAssign: { roles: ['legal-reviewer'] },
|
|
369
|
+
* timeoutDays: 3,
|
|
370
|
+
* escalation: {
|
|
371
|
+
* notifyRoles: ['legal-reviewer'],
|
|
372
|
+
* escalateToRoles: ['admin']
|
|
373
|
+
* }
|
|
374
|
+
* })
|
|
375
|
+
*/
|
|
376
|
+
declare function defineWorkflowStage(id: string, config: WorkflowStageConfig): WorkflowStageDefinition;
|
|
377
|
+
/**
|
|
378
|
+
* Define a workflow configuration
|
|
379
|
+
*
|
|
380
|
+
* @param config - Workflow configuration with enabled flag and stages
|
|
381
|
+
*
|
|
382
|
+
* @example
|
|
383
|
+
* // Simple workflow
|
|
384
|
+
* const workflow = defineWorkflow({
|
|
385
|
+
* enabled: true,
|
|
386
|
+
* stages: [
|
|
387
|
+
* defineWorkflowStage('review', {
|
|
388
|
+
* displayName: 'Review',
|
|
389
|
+
* allowedRoles: ['editor']
|
|
390
|
+
* })
|
|
391
|
+
* ]
|
|
392
|
+
* })
|
|
393
|
+
*
|
|
394
|
+
* @example
|
|
395
|
+
* // Disabled workflow (direct publish)
|
|
396
|
+
* const workflow = defineWorkflow({
|
|
397
|
+
* enabled: false
|
|
398
|
+
* })
|
|
399
|
+
*/
|
|
400
|
+
declare function defineWorkflow(config: WorkflowConfig): WorkflowDefinition;
|
|
401
|
+
/**
|
|
402
|
+
* Define content-type specific workflow configuration
|
|
403
|
+
*
|
|
404
|
+
* @param config - Content type workflow configuration
|
|
405
|
+
*
|
|
406
|
+
* @example
|
|
407
|
+
* // Use specific stages from global workflow
|
|
408
|
+
* const blogPostWorkflow = defineContentTypeWorkflow({
|
|
409
|
+
* enabled: true,
|
|
410
|
+
* stages: ['editorial-review', 'final-approval'], // Skip legal
|
|
411
|
+
* autoPublish: false
|
|
412
|
+
* })
|
|
413
|
+
*
|
|
414
|
+
* @example
|
|
415
|
+
* // Disable workflow for this content type
|
|
416
|
+
* const quickUpdateWorkflow = defineContentTypeWorkflow({
|
|
417
|
+
* enabled: false
|
|
418
|
+
* })
|
|
419
|
+
*
|
|
420
|
+
* @example
|
|
421
|
+
* // Require all locales to be approved
|
|
422
|
+
* const marketingPageWorkflow = defineContentTypeWorkflow({
|
|
423
|
+
* enabled: true,
|
|
424
|
+
* stages: ['translation-review', 'regional-approval'],
|
|
425
|
+
* requireAllLocales: true
|
|
426
|
+
* })
|
|
427
|
+
*/
|
|
428
|
+
declare function defineContentTypeWorkflow(config: ContentTypeWorkflowConfig): ContentTypeWorkflowConfig;
|
|
429
|
+
/**
|
|
430
|
+
* Check if a value is a workflow stage definition
|
|
431
|
+
*/
|
|
432
|
+
declare function isWorkflowStageDefinition(value: unknown): value is WorkflowStageDefinition;
|
|
433
|
+
/**
|
|
434
|
+
* Check if a value is a workflow definition
|
|
435
|
+
*/
|
|
436
|
+
declare function isWorkflowDefinition(value: unknown): value is WorkflowDefinition;
|
|
437
|
+
/**
|
|
438
|
+
* Get all stage IDs from a workflow definition
|
|
439
|
+
*/
|
|
440
|
+
declare function getWorkflowStageIds(workflow: WorkflowDefinition): string[];
|
|
441
|
+
/**
|
|
442
|
+
* Find a stage by ID in a workflow definition
|
|
443
|
+
*/
|
|
444
|
+
declare function findWorkflowStage(workflow: WorkflowDefinition, stageId: string): WorkflowStageDefinition | undefined;
|
|
445
|
+
/**
|
|
446
|
+
* Get the next stage after a given stage ID (null if last stage)
|
|
447
|
+
*/
|
|
448
|
+
declare function getNextWorkflowStage(workflow: WorkflowDefinition, currentStageId: string): WorkflowStageDefinition | null;
|
|
449
|
+
/**
|
|
450
|
+
* Get the first stage in the workflow (null if no stages)
|
|
451
|
+
*/
|
|
452
|
+
declare function getFirstWorkflowStage(workflow: WorkflowDefinition): WorkflowStageDefinition | null;
|
|
453
|
+
/**
|
|
454
|
+
* Check if a stage is the final stage in the workflow
|
|
455
|
+
*/
|
|
456
|
+
declare function isFinalWorkflowStage(workflow: WorkflowDefinition, stageId: string): boolean;
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* Content type definition matching @relyio/schema ContentTypeSchema
|
|
460
|
+
*
|
|
461
|
+
* Uses advanced TypeScript generics to preserve literal field IDs through
|
|
462
|
+
* the type system, enabling full autocomplete in SDK methods like where().
|
|
463
|
+
*/
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Fieldset for organizing related fields
|
|
467
|
+
* Generic over fields to preserve literal field IDs
|
|
468
|
+
*/
|
|
469
|
+
interface Fieldset<TFields extends readonly AnyFieldDefinition[] = readonly AnyFieldDefinition[]> {
|
|
470
|
+
/** Unique fieldset identifier */
|
|
471
|
+
readonly id: string;
|
|
472
|
+
/** Display name shown in the UI */
|
|
473
|
+
readonly displayName: string;
|
|
474
|
+
/** Optional description */
|
|
475
|
+
readonly description?: string;
|
|
476
|
+
/** AI configuration for content generation and review */
|
|
477
|
+
readonly ai?: AIConfig;
|
|
478
|
+
/** Fields within this fieldset - preserves literal types */
|
|
479
|
+
readonly fields: TFields;
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Type alias for a fieldset with any fields.
|
|
483
|
+
* Used in generic constraints where we need to accept any fieldset type.
|
|
484
|
+
*/
|
|
485
|
+
type AnyFieldset = Fieldset<any>;
|
|
486
|
+
/**
|
|
487
|
+
* Create a fieldset for organizing fields
|
|
488
|
+
* Generic to preserve the specific field types for type inference
|
|
489
|
+
*
|
|
490
|
+
* @example
|
|
491
|
+
* const seoFieldset = fieldset('seo', {
|
|
492
|
+
* displayName: 'SEO Settings',
|
|
493
|
+
* fields: [
|
|
494
|
+
* fields.shortText('metaTitle', { config: { maxLength: 60 } }),
|
|
495
|
+
* fields.longText('metaDescription', { config: { maxLength: 160 } }),
|
|
496
|
+
* ]
|
|
497
|
+
* })
|
|
498
|
+
*/
|
|
499
|
+
declare function fieldset<TFields extends readonly AnyFieldDefinition[]>(id: string, config: {
|
|
500
|
+
displayName: string;
|
|
501
|
+
description?: string;
|
|
502
|
+
ai?: AIConfig;
|
|
503
|
+
fields: TFields;
|
|
504
|
+
}): Fieldset<TFields>;
|
|
505
|
+
/**
|
|
506
|
+
* Content type configuration using direct fields
|
|
507
|
+
* Generic to preserve literal field IDs for type inference
|
|
508
|
+
*/
|
|
509
|
+
interface ContentTypeConfigWithFields<TFields extends readonly AnyFieldDefinition[] = readonly AnyFieldDefinition[]> {
|
|
510
|
+
/** Display name shown in the UI */
|
|
511
|
+
displayName: string;
|
|
512
|
+
/** Plural display name shown in the UI (e.g., "Products" for "Product") */
|
|
513
|
+
displayNamePlural?: string;
|
|
514
|
+
/** Description of the content type */
|
|
515
|
+
description?: string;
|
|
516
|
+
/** AI configuration: generation/review guidance */
|
|
517
|
+
ai?: AIConfig;
|
|
518
|
+
/**
|
|
519
|
+
* Field ID to use as entry display title in lists, references, and editor header.
|
|
520
|
+
* If not set, falls back to: title → name → slug → first shortText field → entryUid
|
|
521
|
+
*/
|
|
522
|
+
displayField?: string;
|
|
523
|
+
/** Whether this content type supports hierarchical (parent-child) relationships */
|
|
524
|
+
hierarchical?: boolean;
|
|
525
|
+
/** Access tags for role-based access control */
|
|
526
|
+
accessTags?: string[];
|
|
527
|
+
/** Workflow configuration for this content type */
|
|
528
|
+
workflow?: ContentTypeWorkflowConfig;
|
|
529
|
+
/** Direct field definitions - preserves literal types */
|
|
530
|
+
fields: TFields;
|
|
531
|
+
/** Cannot have fieldsets when using fields */
|
|
532
|
+
fieldsets?: never;
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* Content type configuration using fieldsets
|
|
536
|
+
* Generic to preserve fieldset field types
|
|
537
|
+
*/
|
|
538
|
+
interface ContentTypeConfigWithFieldsets<TFieldsets extends readonly AnyFieldset[] = readonly AnyFieldset[]> {
|
|
539
|
+
/** Display name shown in the UI */
|
|
540
|
+
displayName: string;
|
|
541
|
+
/** Plural display name shown in the UI (e.g., "Products" for "Product") */
|
|
542
|
+
displayNamePlural?: string;
|
|
543
|
+
/** Description of the content type */
|
|
544
|
+
description?: string;
|
|
545
|
+
/** AI configuration: generation/review guidance */
|
|
546
|
+
ai?: AIConfig;
|
|
547
|
+
/**
|
|
548
|
+
* Field ID to use as entry display title in lists, references, and editor header.
|
|
549
|
+
* If not set, falls back to: title → name → slug → first shortText field → entryUid
|
|
550
|
+
*/
|
|
551
|
+
displayField?: string;
|
|
552
|
+
/** Access tags for role-based access control */
|
|
553
|
+
accessTags?: string[];
|
|
554
|
+
/** Whether this content type supports hierarchical (parent-child) relationships */
|
|
555
|
+
hierarchical?: boolean;
|
|
556
|
+
/** Workflow configuration for this content type */
|
|
557
|
+
workflow?: ContentTypeWorkflowConfig;
|
|
558
|
+
/** Field organization via fieldsets - preserves literal types */
|
|
559
|
+
fieldsets: TFieldsets;
|
|
560
|
+
/** Cannot have direct fields when using fieldsets */
|
|
561
|
+
fields?: never;
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* Content type configuration (either fields OR fieldsets, not both)
|
|
565
|
+
*/
|
|
566
|
+
type ContentTypeConfig<TFields extends readonly AnyFieldDefinition[] = readonly AnyFieldDefinition[], TFieldsets extends readonly AnyFieldset[] = readonly AnyFieldset[]> = ContentTypeConfigWithFields<TFields> | ContentTypeConfigWithFieldsets<TFieldsets>;
|
|
567
|
+
/**
|
|
568
|
+
* Content type definition - preserves field types for inference
|
|
569
|
+
*/
|
|
570
|
+
interface ContentTypeDefinition<TFields extends readonly AnyFieldDefinition[] = readonly AnyFieldDefinition[], TFieldsets extends readonly AnyFieldset[] = readonly AnyFieldset[]> {
|
|
571
|
+
readonly _tag: 'contentType';
|
|
572
|
+
readonly name: string;
|
|
573
|
+
readonly displayName: string;
|
|
574
|
+
readonly displayNamePlural?: string;
|
|
575
|
+
readonly description?: string;
|
|
576
|
+
/** AI configuration: generation/review guidance */
|
|
577
|
+
readonly ai?: AIConfig;
|
|
578
|
+
/** Field ID to use as entry display title */
|
|
579
|
+
readonly displayField?: string;
|
|
580
|
+
readonly hierarchical: boolean;
|
|
581
|
+
readonly accessTags?: string[];
|
|
582
|
+
readonly workflow?: ContentTypeWorkflowConfig;
|
|
583
|
+
readonly fields?: TFields;
|
|
584
|
+
readonly fieldsets?: TFieldsets;
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* Define a content type with type-safe fields
|
|
588
|
+
*
|
|
589
|
+
* The generic type parameters preserve the literal field IDs through the type
|
|
590
|
+
* system, enabling autocomplete in SDK methods like where(), select(), etc.
|
|
591
|
+
*
|
|
592
|
+
* @example
|
|
593
|
+
* // Using direct fields
|
|
594
|
+
* const product = defineContentType('product', {
|
|
595
|
+
* displayName: 'Product',
|
|
596
|
+
* fields: [
|
|
597
|
+
* fields.shortText('title', { config: { required: true } }),
|
|
598
|
+
* fields.currency('price', { config: { currencyCode: 'USD' } }),
|
|
599
|
+
* ]
|
|
600
|
+
* })
|
|
601
|
+
*
|
|
602
|
+
* @example
|
|
603
|
+
* // Using fieldsets for organization
|
|
604
|
+
* const product = defineContentType('product', {
|
|
605
|
+
* displayName: 'Product',
|
|
606
|
+
* fieldsets: [
|
|
607
|
+
* fieldset('basic', {
|
|
608
|
+
* displayName: 'Basic Info',
|
|
609
|
+
* fields: [
|
|
610
|
+
* fields.shortText('title', { config: { required: true } }),
|
|
611
|
+
* ]
|
|
612
|
+
* }),
|
|
613
|
+
* fieldset('pricing', {
|
|
614
|
+
* displayName: 'Pricing',
|
|
615
|
+
* fields: [
|
|
616
|
+
* fields.currency('price', { config: { currencyCode: 'USD' } }),
|
|
617
|
+
* ]
|
|
618
|
+
* }),
|
|
619
|
+
* ]
|
|
620
|
+
* })
|
|
621
|
+
*/
|
|
622
|
+
declare function defineContentType<TFields extends readonly AnyFieldDefinition[], _TFieldsets extends readonly Fieldset<AnyFieldDefinition[]>[]>(name: string, config: ContentTypeConfigWithFields<TFields>): ContentTypeDefinition<TFields, readonly []>;
|
|
623
|
+
declare function defineContentType<_TFields extends readonly AnyFieldDefinition[], TFieldsets extends readonly Fieldset<AnyFieldDefinition[]>[]>(name: string, config: ContentTypeConfigWithFieldsets<TFieldsets>): ContentTypeDefinition<readonly [], TFieldsets>;
|
|
624
|
+
/**
|
|
625
|
+
* Type alias for any content type definition.
|
|
626
|
+
*/
|
|
627
|
+
type AnyContentTypeDefinition = ContentTypeDefinition<any, any>;
|
|
628
|
+
/**
|
|
629
|
+
* Extract field IDs from a content type definition
|
|
630
|
+
* Works with both direct fields and fieldsets
|
|
631
|
+
*/
|
|
632
|
+
type ExtractFieldIds<T extends AnyContentTypeDefinition> = NonNullable<T['fields']> extends (infer F)[] ? F extends AnyFieldDefinition ? F['id'] : ExtractFromFieldsets<T> : ExtractFromFieldsets<T>;
|
|
633
|
+
type ExtractFromFieldsets<T extends AnyContentTypeDefinition> = NonNullable<T['fieldsets']> extends (infer FS)[] ? FS extends Fieldset<infer Fields> ? Fields extends AnyFieldDefinition[] ? Fields[number]['id'] : never : never : never;
|
|
634
|
+
/**
|
|
635
|
+
* The per-locale publication half of an entry's metadata, declared once for this package.
|
|
636
|
+
*
|
|
637
|
+
* This is a **mirror** of `LocalePublicationFacts` in `@relyio/content-db`, the return type of the
|
|
638
|
+
* one derivation that produces these values server-side
|
|
639
|
+
* (`INV-LM-PUBLICATION-IS-REPORTED-PER-LOCALE`). It is declared again here rather than imported
|
|
640
|
+
* because this package is published to npm with exactly one runtime dependency and is built for
|
|
641
|
+
* browsers; taking a dependency on the content database's document layer to reach three field names
|
|
642
|
+
* is not a trade this SDK can make.
|
|
643
|
+
*
|
|
644
|
+
* Every field is **optional**, and that is deliberate rather than lax: a published client is always
|
|
645
|
+
* older than the service it talks to, so it must read a body that predates a field it knows about.
|
|
646
|
+
* Server-side the same three fields are required — `EntryMetadataResponse` in `apps/services/api`
|
|
647
|
+
* declares them so and `implements LocalePublicationFacts` proves it.
|
|
648
|
+
*/
|
|
649
|
+
interface LocalePublicationFields {
|
|
650
|
+
/** Publication state of `locale`; absent when that locale has no content of its own. */
|
|
651
|
+
localeStatus?: 'draft' | 'published' | 'archived';
|
|
652
|
+
/** Whether `locale` has unpublished changes of its own. */
|
|
653
|
+
localeHasDraft?: boolean;
|
|
654
|
+
/** Every locale with unpublished changes, including shared-field drafts. */
|
|
655
|
+
draftLocales?: string[];
|
|
656
|
+
}
|
|
657
|
+
/**
|
|
658
|
+
* Entry metadata that's present on all content entries.
|
|
659
|
+
*
|
|
660
|
+
* The per-locale publication half is inherited from `LocalePublicationFields` rather than restated,
|
|
661
|
+
* so this package holds one copy of it and not one per file.
|
|
662
|
+
*/
|
|
663
|
+
interface EntryMetadata extends LocalePublicationFields {
|
|
664
|
+
/** Unique entry identifier */
|
|
665
|
+
id: string;
|
|
666
|
+
/** Content type id (API field name is `type`) */
|
|
667
|
+
type: string;
|
|
668
|
+
/** Entry type (content, asset, singleton, settings) */
|
|
669
|
+
entryType: string;
|
|
670
|
+
/**
|
|
671
|
+
* Container lifecycle only (`active` | `archived` | `proposed`).
|
|
672
|
+
* Publication is `localeStatus` (`INV-LM-STATUS-IS-TWO-FIELDS`).
|
|
673
|
+
*/
|
|
674
|
+
status: 'active' | 'archived' | 'proposed';
|
|
675
|
+
/** Per-locale version number */
|
|
676
|
+
version: number;
|
|
677
|
+
/** Parent ID for hierarchical content */
|
|
678
|
+
parentId?: string | null;
|
|
679
|
+
/** Content locale this payload is reported in */
|
|
680
|
+
locale: string;
|
|
681
|
+
/** Whether the shared (non-localized) fields have an unpublished overlay. */
|
|
682
|
+
hasDraft?: boolean;
|
|
683
|
+
/** Creation timestamp */
|
|
684
|
+
createdAt: Date;
|
|
685
|
+
/** Last update timestamp */
|
|
686
|
+
updatedAt: Date;
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* Infer the TypeScript type from a content type definition
|
|
690
|
+
*
|
|
691
|
+
* This extracts all field IDs from the definition and creates a type
|
|
692
|
+
* with those fields as optional properties. Field names will autocomplete
|
|
693
|
+
* in SDK methods like where(), select(), etc.
|
|
694
|
+
*
|
|
695
|
+
* Note: Field values are typed as `unknown`. For full value type inference,
|
|
696
|
+
* use the codegen tool to generate proper types.
|
|
697
|
+
*
|
|
698
|
+
* @example
|
|
699
|
+
* const product = defineContentType('product', {
|
|
700
|
+
* displayName: 'Product',
|
|
701
|
+
* fields: [
|
|
702
|
+
* fields.shortText('title'),
|
|
703
|
+
* fields.currency('price'),
|
|
704
|
+
* ]
|
|
705
|
+
* })
|
|
706
|
+
*
|
|
707
|
+
* type Product = InferContentType<typeof product>
|
|
708
|
+
* // { title?: unknown; price?: unknown; _metadata: EntryMetadata }
|
|
709
|
+
*/
|
|
710
|
+
type InferContentType<T extends AnyContentTypeDefinition> = {
|
|
711
|
+
[K in ExtractFieldIds<T> & string]?: unknown;
|
|
712
|
+
} & {
|
|
713
|
+
_metadata: EntryMetadata;
|
|
714
|
+
};
|
|
715
|
+
|
|
716
|
+
export { type WorkflowEscalation as $, type AIConfig as A, type BooleanConfig as B, type ComponentFieldType as C, type DecimalConfig as D, type EmailConfig as E, type FieldUIConfig as F, type ContentTypeDefinition as G, type EntryMetadata as H, type IntegerConfig as I, type InferContentType as J, type LocalePublicationFields as K, type LocalizationConfig as L, defineWorkflow as M, defineWorkflowStage as N, defineContentTypeWorkflow as O, isWorkflowDefinition as P, isWorkflowStageDefinition as Q, type RichTextConfig as R, type ShortTextConfig as S, type TagsConfig as T, type UrlConfig as U, type ValidationRule as V, getWorkflowStageIds as W, findWorkflowStage as X, getNextWorkflowStage as Y, getFirstWorkflowStage as Z, isFinalWorkflowStage as _, type FieldAIConfig as a, type WorkflowAutoAssign as a0, type WorkflowStageConfig as a1, type WorkflowStageDefinition as a2, type WorkflowConfig as a3, type WorkflowDefinition as a4, type ContentTypeWorkflowConfig as a5, type FieldRule as b, type FieldDefinition as c, type LongTextConfig as d, type SlugConfig as e, type EnumConfig as f, type DateConfig as g, type DateTimeConfig as h, type ReferenceConfig as i, type ListConfig as j, type AllFieldTypes as k, type AnyFieldDefinition as l, type AssetAIConfig as m, type BaseFieldConfig as n, type FieldType as o, type ReadOnlyRule as p, type RequirementRule as q, type RuleCondition as r, type RuleConditions as s, type VisibilityRule as t, defineContentType as u, fieldset as v, type Fieldset as w, type ContentTypeConfig as x, type ContentTypeConfigWithFields as y, type ContentTypeConfigWithFieldsets as z };
|