@crombolo/data 0.0.0-stage → 0.9.1

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 (72) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +69 -0
  3. package/package.json +31 -4
  4. package/src/change-report.ts +166 -0
  5. package/src/cluster.ts +108 -0
  6. package/src/database.ts +121 -0
  7. package/src/dialect.ts +128 -0
  8. package/src/index.ts +60 -0
  9. package/src/locks.ts +103 -0
  10. package/src/maintenance.ts +51 -0
  11. package/src/migrations.ts +431 -0
  12. package/src/node-ref.ts +107 -0
  13. package/src/pending.ts +25 -0
  14. package/src/repositories/bundles.ts +191 -0
  15. package/src/repositories/content-types.ts +831 -0
  16. package/src/repositories/data-types.ts +222 -0
  17. package/src/repositories/dictionary.ts +259 -0
  18. package/src/repositories/documents.ts +2389 -0
  19. package/src/repositories/domains.ts +108 -0
  20. package/src/repositories/folders.ts +120 -0
  21. package/src/repositories/form-entries.ts +314 -0
  22. package/src/repositories/form-workflows.ts +213 -0
  23. package/src/repositories/languages.ts +108 -0
  24. package/src/repositories/log-searches.ts +33 -0
  25. package/src/repositories/members.ts +427 -0
  26. package/src/repositories/nodes.ts +361 -0
  27. package/src/repositories/notifications.ts +54 -0
  28. package/src/repositories/public-access.ts +187 -0
  29. package/src/repositories/redirects.ts +274 -0
  30. package/src/repositories/references.ts +162 -0
  31. package/src/repositories/tags.ts +93 -0
  32. package/src/repositories/templates.ts +114 -0
  33. package/src/repositories/transfer-runs.ts +190 -0
  34. package/src/repositories/user-data.ts +90 -0
  35. package/src/repositories/users.ts +898 -0
  36. package/src/schema/assistant.ts +74 -0
  37. package/src/schema/built-in-content-types.ts +106 -0
  38. package/src/schema/built-in-media-types.ts +335 -0
  39. package/src/schema/built-in-member-types.ts +61 -0
  40. package/src/schema/bundle-components.ts +49 -0
  41. package/src/schema/bundles-rename.ts +32 -0
  42. package/src/schema/change-report.ts +46 -0
  43. package/src/schema/client-id-prefix.ts +43 -0
  44. package/src/schema/content-editing.ts +50 -0
  45. package/src/schema/content-seed.ts +586 -0
  46. package/src/schema/content.ts +263 -0
  47. package/src/schema/created-packages.ts +56 -0
  48. package/src/schema/elements.ts +62 -0
  49. package/src/schema/form-permission-prefix.ts +50 -0
  50. package/src/schema/form-permissions.ts +26 -0
  51. package/src/schema/form-workflows.ts +54 -0
  52. package/src/schema/forms.ts +63 -0
  53. package/src/schema/group-permissions.ts +20 -0
  54. package/src/schema/identity.ts +176 -0
  55. package/src/schema/log-viewer.ts +68 -0
  56. package/src/schema/member-property-type.ts +30 -0
  57. package/src/schema/members.ts +97 -0
  58. package/src/schema/plan.ts +73 -0
  59. package/src/schema/public-access.ts +56 -0
  60. package/src/schema/recycle-bin.ts +21 -0
  61. package/src/schema/redirects.ts +57 -0
  62. package/src/schema/rich-text-ui.ts +34 -0
  63. package/src/schema/seed.ts +298 -0
  64. package/src/schema/server-role.ts +21 -0
  65. package/src/schema/since-version.ts +26 -0
  66. package/src/schema/transfer-runs.ts +71 -0
  67. package/src/schema/upgrade-report.ts +43 -0
  68. package/src/schema/users-localisation.ts +85 -0
  69. package/src/schema/values.ts +108 -0
  70. package/src/schema-ops.ts +35 -0
  71. package/src/schema-state.ts +196 -0
  72. package/README.md +0 -3
@@ -0,0 +1,586 @@
1
+ /**
2
+ * Install seed for the content schema: the system nodes, the default language and
3
+ * the core data types.
4
+ *
5
+ * Data type keys are Umbraco's own, so any documentation or example that
6
+ * references a well-known data type still applies.
7
+ */
8
+ import { ObjectTypes, SystemNodes, ValueStorageType } from '@crombolo/core'
9
+ import type { Db } from '../database.ts'
10
+ import { DbDate } from '../dialect.ts'
11
+
12
+ export interface SeedDataType {
13
+ key: string
14
+ alias: string
15
+ name: string
16
+ editorAlias: string
17
+ editorUiAlias: string
18
+ dbType: string
19
+ config?: Record<string, unknown>
20
+ }
21
+
22
+ /** Umbraco's installer configuration for its rich text data type (Tiptap), verbatim. */
23
+ export const RICH_TEXT_CONFIG: Record<string, unknown> = {
24
+ extensions: [
25
+ 'Umb.Tiptap.RichTextEssentials',
26
+ 'Umb.Tiptap.Anchor',
27
+ 'Umb.Tiptap.Block',
28
+ 'Umb.Tiptap.Blockquote',
29
+ 'Umb.Tiptap.Bold',
30
+ 'Umb.Tiptap.BulletList',
31
+ 'Umb.Tiptap.CodeBlock',
32
+ 'Umb.Tiptap.Embed',
33
+ 'Umb.Tiptap.Figure',
34
+ 'Umb.Tiptap.Heading',
35
+ 'Umb.Tiptap.HorizontalRule',
36
+ 'Umb.Tiptap.HtmlAttributeClass',
37
+ 'Umb.Tiptap.HtmlAttributeDataset',
38
+ 'Umb.Tiptap.HtmlAttributeId',
39
+ 'Umb.Tiptap.HtmlAttributeStyle',
40
+ 'Umb.Tiptap.HtmlTagDiv',
41
+ 'Umb.Tiptap.HtmlTagSpan',
42
+ 'Umb.Tiptap.Image',
43
+ 'Umb.Tiptap.Italic',
44
+ 'Umb.Tiptap.Link',
45
+ 'Umb.Tiptap.MediaUpload',
46
+ 'Umb.Tiptap.OrderedList',
47
+ 'Umb.Tiptap.Strike',
48
+ 'Umb.Tiptap.Subscript',
49
+ 'Umb.Tiptap.Superscript',
50
+ 'Umb.Tiptap.Table',
51
+ 'Umb.Tiptap.TextAlign',
52
+ 'Umb.Tiptap.TextDirection',
53
+ 'Umb.Tiptap.TextIndent',
54
+ 'Umb.Tiptap.TrailingNode',
55
+ 'Umb.Tiptap.Underline',
56
+ ],
57
+ maxImageSize: 500,
58
+ overlaySize: 'medium',
59
+ toolbar: [
60
+ [
61
+ ['Umb.Tiptap.Toolbar.SourceEditor'],
62
+ ['Umb.Tiptap.Toolbar.Bold', 'Umb.Tiptap.Toolbar.Italic', 'Umb.Tiptap.Toolbar.Underline'],
63
+ [
64
+ 'Umb.Tiptap.Toolbar.TextAlignLeft',
65
+ 'Umb.Tiptap.Toolbar.TextAlignCenter',
66
+ 'Umb.Tiptap.Toolbar.TextAlignRight',
67
+ ],
68
+ ['Umb.Tiptap.Toolbar.BulletList', 'Umb.Tiptap.Toolbar.OrderedList'],
69
+ ['Umb.Tiptap.Toolbar.Blockquote', 'Umb.Tiptap.Toolbar.HorizontalRule'],
70
+ ['Umb.Tiptap.Toolbar.Link', 'Umb.Tiptap.Toolbar.Unlink'],
71
+ ['Umb.Tiptap.Toolbar.MediaPicker', 'Umb.Tiptap.Toolbar.EmbeddedMedia'],
72
+ ],
73
+ ],
74
+ // Image and Vector Graphics (SVG)
75
+ allowedMediaTypes: 'cc07b313-0843-4aa8-bbda-871c8da728c8,c4b1efcf-a9d5-41c4-9621-e9d273b52a9c',
76
+ }
77
+
78
+ /** Umbraco's installer configuration for its content and media list views. */
79
+ function listViewConfig(collectionViewType: 'Document' | 'Media'): Record<string, unknown> {
80
+ return {
81
+ pageSize: 100,
82
+ orderBy: 'updateDate',
83
+ orderDirection: 'desc',
84
+ layouts: [
85
+ {
86
+ name: 'Grid',
87
+ collectionView: `Umb.CollectionView.${collectionViewType}.Grid`,
88
+ icon: 'icon-thumbnails-small',
89
+ isSystem: true,
90
+ selected: true,
91
+ },
92
+ {
93
+ name: 'List',
94
+ collectionView: `Umb.CollectionView.${collectionViewType}.Table`,
95
+ icon: 'icon-list',
96
+ isSystem: true,
97
+ selected: true,
98
+ },
99
+ ],
100
+ includeProperties: [
101
+ { alias: 'updateDate', header: 'Last edited', isSystem: true },
102
+ { alias: 'creator', header: 'Updated by', isSystem: true },
103
+ ],
104
+ }
105
+ }
106
+
107
+ /**
108
+ * Every data type Umbraco's installer creates, with its keys, names and
109
+ * configuration. Their editor UIs all come from the vendored client, which
110
+ * `tests/vendor.test.ts` holds this list to; ours live in `CROMBOLO_DATA_TYPES`.
111
+ */
112
+ export const DEFAULT_DATA_TYPES: readonly SeedDataType[] = [
113
+ {
114
+ key: 'f0bc4bfb-b499-40d6-ba86-058885a5178c',
115
+ alias: 'label',
116
+ name: 'Label (string)',
117
+ editorAlias: 'Umbraco.Label',
118
+ editorUiAlias: 'Umb.PropertyEditorUi.Label',
119
+ dbType: ValueStorageType.Nvarchar,
120
+ config: { umbracoDataValueType: 'STRING' },
121
+ },
122
+ {
123
+ key: '8e7f995c-bd81-4627-9932-c40e568ec788',
124
+ alias: 'labelInt',
125
+ name: 'Label (integer)',
126
+ editorAlias: 'Umbraco.Label',
127
+ editorUiAlias: 'Umb.PropertyEditorUi.Label',
128
+ dbType: ValueStorageType.Integer,
129
+ config: { umbracoDataValueType: 'INT' },
130
+ },
131
+ {
132
+ key: '930861bf-e262-4ead-a704-f99453565708',
133
+ alias: 'labelBigInt',
134
+ name: 'Label (bigint)',
135
+ editorAlias: 'Umbraco.Label',
136
+ editorUiAlias: 'Umb.PropertyEditorUi.Label',
137
+ dbType: ValueStorageType.Nvarchar,
138
+ config: { umbracoDataValueType: 'BIGINT' },
139
+ },
140
+ {
141
+ key: '0e9794eb-f9b5-4f20-a788-93acd233a7e4',
142
+ alias: 'labelDateTime',
143
+ name: 'Label (datetime)',
144
+ editorAlias: 'Umbraco.Label',
145
+ editorUiAlias: 'Umb.PropertyEditorUi.Label',
146
+ dbType: ValueStorageType.Date,
147
+ config: { umbracoDataValueType: 'DATETIME' },
148
+ },
149
+ {
150
+ key: 'a97cec69-9b71-4c30-8b12-ec398860d7e8',
151
+ alias: 'labelTime',
152
+ name: 'Label (time)',
153
+ editorAlias: 'Umbraco.Label',
154
+ editorUiAlias: 'Umb.PropertyEditorUi.Label',
155
+ dbType: ValueStorageType.Date,
156
+ config: { umbracoDataValueType: 'TIME' },
157
+ },
158
+ {
159
+ key: '8f1ef1e1-9de4-40d3-a072-6673f631ca64',
160
+ alias: 'labelDecimal',
161
+ name: 'Label (decimal)',
162
+ editorAlias: 'Umbraco.Label',
163
+ editorUiAlias: 'Umb.PropertyEditorUi.Label',
164
+ dbType: ValueStorageType.Decimal,
165
+ config: { umbracoDataValueType: 'DECIMAL' },
166
+ },
167
+ {
168
+ key: 'ba5bdbe6-ab3e-46a8-82b3-2c45f10bc47f',
169
+ alias: 'labelBytes',
170
+ name: 'Label (bytes)',
171
+ editorAlias: 'Umbraco.Label',
172
+ editorUiAlias: 'Umb.PropertyEditorUi.Label',
173
+ dbType: ValueStorageType.Nvarchar,
174
+ config: { umbracoDataValueType: 'BIGINT', labelTemplate: '{=value | bytes}' },
175
+ },
176
+ {
177
+ key: '5eb57825-e15e-4fc7-8e37-fca65cdafbde',
178
+ alias: 'labelPixels',
179
+ name: 'Label (pixels)',
180
+ editorAlias: 'Umbraco.Label',
181
+ editorUiAlias: 'Umb.PropertyEditorUi.Label',
182
+ dbType: ValueStorageType.Integer,
183
+ config: { umbracoDataValueType: 'INT', labelTemplate: '{=value}px' },
184
+ },
185
+ {
186
+ key: '84c6b441-31df-4ffe-b67e-67d5bc3ae65a',
187
+ alias: 'upload',
188
+ name: 'Upload File',
189
+ editorAlias: 'Umbraco.UploadField',
190
+ editorUiAlias: 'Umb.PropertyEditorUi.UploadField',
191
+ dbType: ValueStorageType.Nvarchar,
192
+ },
193
+ {
194
+ key: '70575fe7-9812-4396-bbe1-c81a76db71b5',
195
+ alias: 'uploadVideo',
196
+ name: 'Upload Video',
197
+ editorAlias: 'Umbraco.UploadField',
198
+ editorUiAlias: 'Umb.PropertyEditorUi.UploadField',
199
+ dbType: ValueStorageType.Nvarchar,
200
+ config: { fileExtensions: ['mp4', 'webm', 'ogv'] },
201
+ },
202
+ {
203
+ key: '8f430dd6-4e96-447e-9dc0-cb552c8cd1f3',
204
+ alias: 'uploadAudio',
205
+ name: 'Upload Audio',
206
+ editorAlias: 'Umbraco.UploadField',
207
+ editorUiAlias: 'Umb.PropertyEditorUi.UploadField',
208
+ dbType: ValueStorageType.Nvarchar,
209
+ config: { fileExtensions: ['mp3', 'weba', 'oga', 'opus'] },
210
+ },
211
+ {
212
+ key: 'bc1e266c-dac4-4164-bf08-8a1ec6a7143d',
213
+ alias: 'uploadArticle',
214
+ name: 'Upload Article',
215
+ editorAlias: 'Umbraco.UploadField',
216
+ editorUiAlias: 'Umb.PropertyEditorUi.UploadField',
217
+ dbType: ValueStorageType.Nvarchar,
218
+ config: { fileExtensions: ['pdf', 'docx', 'doc'] },
219
+ },
220
+ {
221
+ key: '215cb418-2153-4429-9aef-8c0f0041191b',
222
+ alias: 'uploadVectorGraphics',
223
+ name: 'Upload Vector Graphics',
224
+ editorAlias: 'Umbraco.UploadField',
225
+ editorUiAlias: 'Umb.PropertyEditorUi.UploadField',
226
+ dbType: ValueStorageType.Nvarchar,
227
+ config: { fileExtensions: ['svg'] },
228
+ },
229
+ {
230
+ key: 'c6bac0dd-4ab9-45b1-8e30-e4b619ee5da3',
231
+ alias: 'textarea',
232
+ name: 'Textarea',
233
+ editorAlias: 'Umbraco.TextArea',
234
+ editorUiAlias: 'Umb.PropertyEditorUi.TextArea',
235
+ dbType: ValueStorageType.Ntext,
236
+ },
237
+ {
238
+ key: '0cc0eba1-9960-42c9-bf9b-60e150b429ae',
239
+ alias: 'textstring',
240
+ name: 'Textstring',
241
+ editorAlias: 'Umbraco.TextBox',
242
+ editorUiAlias: 'Umb.PropertyEditorUi.TextBox',
243
+ dbType: ValueStorageType.Nvarchar,
244
+ },
245
+ {
246
+ key: 'ca90c950-0aff-4e72-b976-a30b1ac57dad',
247
+ alias: 'richtext',
248
+ name: 'Richtext editor',
249
+ editorAlias: 'Umbraco.RichText',
250
+ editorUiAlias: 'Umb.PropertyEditorUi.Tiptap',
251
+ dbType: ValueStorageType.Ntext,
252
+ config: RICH_TEXT_CONFIG,
253
+ },
254
+ {
255
+ key: '2e6d3631-066e-44b8-aec4-96f09099b2b5',
256
+ alias: 'numeric',
257
+ name: 'Numeric',
258
+ editorAlias: 'Umbraco.Integer',
259
+ editorUiAlias: 'Umb.PropertyEditorUi.Integer',
260
+ dbType: ValueStorageType.Integer,
261
+ },
262
+ {
263
+ key: '92897bc6-a5f3-4ffe-ae27-f2e7e33dda49',
264
+ alias: 'trueFalse',
265
+ name: 'True/false',
266
+ editorAlias: 'Umbraco.TrueFalse',
267
+ editorUiAlias: 'Umb.PropertyEditorUi.Toggle',
268
+ dbType: ValueStorageType.Integer,
269
+ },
270
+ {
271
+ key: 'fbaf13a8-4036-41f2-93a3-974f678c312a',
272
+ alias: 'checkboxList',
273
+ name: 'Checkbox list',
274
+ editorAlias: 'Umbraco.CheckBoxList',
275
+ editorUiAlias: 'Umb.PropertyEditorUi.CheckBoxList',
276
+ dbType: ValueStorageType.Ntext,
277
+ },
278
+ {
279
+ key: '0b6a45e7-44ba-430d-9da5-4e46060b9e03',
280
+ alias: 'dropdown',
281
+ name: 'Dropdown',
282
+ editorAlias: 'Umbraco.DropDown.Flexible',
283
+ editorUiAlias: 'Umb.PropertyEditorUi.Dropdown',
284
+ dbType: ValueStorageType.Nvarchar,
285
+ config: { multiple: false },
286
+ },
287
+ {
288
+ key: '5046194e-4237-453c-a547-15db3a07c4e1',
289
+ alias: 'datePicker',
290
+ name: 'Date Picker',
291
+ editorAlias: 'Umbraco.DateTime',
292
+ editorUiAlias: 'Umb.PropertyEditorUi.DatePicker',
293
+ dbType: ValueStorageType.Date,
294
+ config: { format: 'YYYY-MM-DD' },
295
+ },
296
+ {
297
+ key: 'bb5f57c9-ce2b-4bb9-b697-4caca783a805',
298
+ alias: 'radiobox',
299
+ name: 'Radiobox',
300
+ editorAlias: 'Umbraco.RadioButtonList',
301
+ editorUiAlias: 'Umb.PropertyEditorUi.RadioButtonList',
302
+ dbType: ValueStorageType.Nvarchar,
303
+ },
304
+ {
305
+ key: 'f38f0ac7-1d27-439c-9f3f-089cd8825a53',
306
+ alias: 'dropdownMultiple',
307
+ name: 'Dropdown multiple',
308
+ editorAlias: 'Umbraco.DropDown.Flexible',
309
+ editorUiAlias: 'Umb.PropertyEditorUi.Dropdown',
310
+ dbType: ValueStorageType.Nvarchar,
311
+ config: { multiple: true },
312
+ },
313
+ {
314
+ key: '0225af17-b302-49cb-9176-b9f35cab9c17',
315
+ alias: 'approvedColor',
316
+ name: 'Approved Color',
317
+ editorAlias: 'Umbraco.ColorPicker',
318
+ editorUiAlias: 'Umb.PropertyEditorUi.ColorPicker',
319
+ dbType: ValueStorageType.Nvarchar,
320
+ },
321
+ {
322
+ key: 'e4d66c0f-b935-4200-81f0-025f7256b89a',
323
+ alias: 'datePickerWithTime',
324
+ name: 'Date Picker with time',
325
+ editorAlias: 'Umbraco.DateTime',
326
+ editorUiAlias: 'Umb.PropertyEditorUi.DatePicker',
327
+ dbType: ValueStorageType.Date,
328
+ config: { format: 'YYYY-MM-DD HH:mm:ss' },
329
+ },
330
+ {
331
+ key: 'c0808dd3-8133-4e4b-8ce8-e2bea84a96a4',
332
+ alias: 'listViewContent',
333
+ name: 'List View - Content',
334
+ editorAlias: 'Umbraco.ListView',
335
+ editorUiAlias: 'Umb.PropertyEditorUi.Collection',
336
+ dbType: ValueStorageType.Nvarchar,
337
+ config: listViewConfig('Document'),
338
+ },
339
+ {
340
+ key: '3a0156c4-3b8c-4803-bdc1-6871faa83fff',
341
+ alias: 'listViewMedia',
342
+ name: 'List View - Media',
343
+ editorAlias: 'Umbraco.ListView',
344
+ editorUiAlias: 'Umb.PropertyEditorUi.Collection',
345
+ dbType: ValueStorageType.Nvarchar,
346
+ config: listViewConfig('Media'),
347
+ },
348
+ {
349
+ key: 'b6b73142-b9c1-4bf8-a16d-e1c23320b549',
350
+ alias: 'tags',
351
+ name: 'Tags',
352
+ editorAlias: 'Umbraco.Tags',
353
+ editorUiAlias: 'Umb.PropertyEditorUi.Tags',
354
+ dbType: ValueStorageType.Ntext,
355
+ config: { group: 'default', storageType: 'Json' },
356
+ },
357
+ {
358
+ key: '1df9f033-e6d4-451f-b8d2-e0cbc50a836f',
359
+ alias: 'imageCropper',
360
+ name: 'Image Cropper',
361
+ editorAlias: 'Umbraco.ImageCropper',
362
+ editorUiAlias: 'Umb.PropertyEditorUi.ImageCropper',
363
+ dbType: ValueStorageType.Ntext,
364
+ },
365
+ {
366
+ key: 'fd1e0da5-5606-4862-b679-5d0cf3a52a59',
367
+ alias: 'contentPicker',
368
+ name: 'Content Picker',
369
+ editorAlias: 'Umbraco.ContentPicker',
370
+ editorUiAlias: 'Umb.PropertyEditorUi.DocumentPicker',
371
+ dbType: ValueStorageType.Nvarchar,
372
+ },
373
+ {
374
+ key: '1ea2e01f-ebd8-4ce1-8d71-6b1149e63548',
375
+ alias: 'memberPicker',
376
+ name: 'Member Picker',
377
+ editorAlias: 'Umbraco.MemberPicker',
378
+ editorUiAlias: 'Umb.PropertyEditorUi.MemberPicker',
379
+ dbType: ValueStorageType.Nvarchar,
380
+ },
381
+ {
382
+ key: 'b4e3535a-1753-47e2-8568-602cf8cfee6f',
383
+ alias: 'multiUrlPicker',
384
+ name: 'Multi URL Picker',
385
+ editorAlias: 'Umbraco.MultiUrlPicker',
386
+ editorUiAlias: 'Umb.PropertyEditorUi.MultiUrlPicker',
387
+ dbType: ValueStorageType.Ntext,
388
+ },
389
+ {
390
+ key: '4309a3ea-0d78-4329-a06c-c80b036af19a',
391
+ alias: 'mediaPicker',
392
+ name: 'Media Picker',
393
+ editorAlias: 'Umbraco.MediaPicker3',
394
+ editorUiAlias: 'Umb.PropertyEditorUi.MediaPicker',
395
+ dbType: ValueStorageType.Ntext,
396
+ config: { multiple: false, validationLimit: { min: 0, max: 1 } },
397
+ },
398
+ {
399
+ key: '1b661f40-2242-4b44-b9cb-3990ee2b13c0',
400
+ alias: 'multipleMediaPicker',
401
+ name: 'Multiple Media Picker',
402
+ editorAlias: 'Umbraco.MediaPicker3',
403
+ editorUiAlias: 'Umb.PropertyEditorUi.MediaPicker',
404
+ dbType: ValueStorageType.Ntext,
405
+ config: { multiple: true },
406
+ },
407
+ {
408
+ key: 'ad9f0cf2-bda2-45d5-9ea1-a63cfc873fd3',
409
+ alias: 'imageMediaPicker',
410
+ name: 'Image Media Picker',
411
+ editorAlias: 'Umbraco.MediaPicker3',
412
+ editorUiAlias: 'Umb.PropertyEditorUi.MediaPicker',
413
+ dbType: ValueStorageType.Ntext,
414
+ config: {
415
+ filter: 'cc07b313-0843-4aa8-bbda-871c8da728c8',
416
+ multiple: false,
417
+ validationLimit: { min: 0, max: 1 },
418
+ },
419
+ },
420
+ {
421
+ key: '0e63d883-b62b-4799-88c3-157f82e83ecc',
422
+ alias: 'multipleImageMediaPicker',
423
+ name: 'Multiple Image Media Picker',
424
+ editorAlias: 'Umbraco.MediaPicker3',
425
+ editorUiAlias: 'Umb.PropertyEditorUi.MediaPicker',
426
+ dbType: ValueStorageType.Ntext,
427
+ config: { filter: 'cc07b313-0843-4aa8-bbda-871c8da728c8', multiple: true },
428
+ },
429
+ {
430
+ key: '88e8a052-30ee-4d44-a507-59f2cdfc769c',
431
+ alias: 'dateTimeWithTimeZone',
432
+ name: 'Date Time Picker (with time zone)',
433
+ editorAlias: 'Umbraco.DateTimeWithTimeZone',
434
+ editorUiAlias: 'Umb.PropertyEditorUi.DateTimeWithTimeZonePicker',
435
+ dbType: ValueStorageType.Ntext,
436
+ config: { timeFormat: 'HH:mm', timeZones: { mode: 'all' } },
437
+ },
438
+ ] as const
439
+
440
+ export const DEFAULT_LANGUAGE = { isoCode: 'en-US', cultureName: 'English (United States)' }
441
+
442
+ async function tableIsEmpty(db: Db, table: string): Promise<boolean> {
443
+ const rows = await db.query<{ n: number }>(`SELECT COUNT(*) AS n FROM ${table}`)
444
+ return Number(rows[0]?.n ?? 0) === 0
445
+ }
446
+
447
+ /** Idempotent. */
448
+ export async function seedContent(db: Db): Promise<boolean> {
449
+ if (!(await tableIsEmpty(db, 'node'))) return false
450
+ const now = DbDate.toDb(new Date())
451
+ const bool = (value: boolean) => db.dialect.boolValue(value)
452
+
453
+ const systemNodes = [
454
+ { id: SystemNodes.Root, text: 'SystemRoot', objectType: ObjectTypes.SystemRoot, path: '-1' },
455
+ {
456
+ id: SystemNodes.ContentRecycleBin,
457
+ text: 'Recycle Bin',
458
+ objectType: ObjectTypes.ContentRecycleBin,
459
+ path: '-1,-20',
460
+ },
461
+ {
462
+ id: SystemNodes.MediaRecycleBin,
463
+ text: 'Recycle Bin',
464
+ objectType: ObjectTypes.MediaRecycleBin,
465
+ path: '-1,-21',
466
+ },
467
+ {
468
+ id: SystemNodes.ElementRecycleBin,
469
+ text: 'Recycle Bin',
470
+ objectType: ObjectTypes.ElementRecycleBin,
471
+ path: '-1,-22',
472
+ },
473
+ ]
474
+ for (const node of systemNodes) {
475
+ await db.exec(
476
+ `INSERT INTO node
477
+ (id, unique_id, parent_id, level, path, sort_order, trashed, text, node_object_type, create_date)
478
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
479
+ [
480
+ node.id,
481
+ crypto.randomUUID(),
482
+ node.id === SystemNodes.Root ? -1 : SystemNodes.Root,
483
+ 0,
484
+ node.path,
485
+ 0,
486
+ bool(false),
487
+ node.text,
488
+ node.objectType,
489
+ now,
490
+ ],
491
+ )
492
+ }
493
+
494
+ await db.exec(
495
+ `INSERT INTO language (iso_code, culture_name, is_default, is_mandatory)
496
+ VALUES (?, ?, ?, ?)`,
497
+ [DEFAULT_LANGUAGE.isoCode, DEFAULT_LANGUAGE.cultureName, bool(true), bool(true)],
498
+ )
499
+
500
+ let sortOrder = 0
501
+ for (const dataType of ALL_SEEDED_DATA_TYPES) await insertDataType(db, dataType, sortOrder++)
502
+ return true
503
+ }
504
+
505
+ /**
506
+ * Data types this CMS adds, whose editor UIs come from our own plugin rather
507
+ * than from the vendored client. Seeded and ensured exactly as Umbraco's are.
508
+ */
509
+ export const CROMBOLO_DATA_TYPES: readonly SeedDataType[] = [
510
+ {
511
+ key: '9c4a7d1e-0100-4b2a-9f31-6d8e2c5a7b40',
512
+ alias: 'formPicker',
513
+ name: 'Form Picker',
514
+ editorAlias: 'Crombolo.FormPicker',
515
+ editorUiAlias: 'Crombolo.PropertyEditorUi.FormPicker',
516
+ // The form's UUID, from `schema/forms/*.toml`. A string rather than a
517
+ // reference: the definition is a file, so there is no row to point at.
518
+ dbType: ValueStorageType.Nvarchar,
519
+ config: {},
520
+ },
521
+ ]
522
+
523
+ /** Every data type that needs no file, Umbraco's and ours. */
524
+ export const ALL_SEEDED_DATA_TYPES: readonly SeedDataType[] = [
525
+ ...DEFAULT_DATA_TYPES,
526
+ ...CROMBOLO_DATA_TYPES,
527
+ ]
528
+
529
+ /** One built-in data type, as the seed and the boot-time ensure both write it. */
530
+ async function insertDataType(db: Db, dataType: SeedDataType, sortOrder: number): Promise<void> {
531
+ const now = DbDate.toDb(new Date())
532
+ const bool = (value: boolean) => db.dialect.boolValue(value)
533
+ await db.exec(
534
+ `INSERT INTO node
535
+ (unique_id, parent_id, level, path, sort_order, trashed, text, node_object_type, create_date)
536
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
537
+ [
538
+ dataType.key,
539
+ SystemNodes.Root,
540
+ 1,
541
+ `-1`,
542
+ sortOrder,
543
+ bool(false),
544
+ dataType.name,
545
+ ObjectTypes.DataType,
546
+ now,
547
+ ],
548
+ )
549
+ const created = await db.query<{ id: number }>('SELECT id FROM node WHERE unique_id = ?', [
550
+ dataType.key,
551
+ ])
552
+ const nodeId = Number(created[0]?.id)
553
+ await db.exec(`UPDATE node SET path = ? WHERE id = ?`, [`-1,${nodeId}`, nodeId])
554
+ await db.exec(
555
+ `INSERT INTO data_type (node_id, alias, editor_alias, editor_ui_alias, db_type, config)
556
+ VALUES (?, ?, ?, ?, ?, ?)`,
557
+ [
558
+ nodeId,
559
+ dataType.alias,
560
+ dataType.editorAlias,
561
+ dataType.editorUiAlias,
562
+ dataType.dbType,
563
+ JSON.stringify(dataType.config ?? {}),
564
+ ],
565
+ )
566
+ }
567
+
568
+ /**
569
+ * Inserts any built-in data type a database seeded by an older version lacks,
570
+ * by its fixed key. Never changes one that exists. Idempotent; runs at boot.
571
+ */
572
+ export async function ensureBuiltInDataTypes(db: Db): Promise<string[]> {
573
+ const added: string[] = []
574
+ const count = await db.query<{ n: number }>(
575
+ 'SELECT COUNT(*) AS n FROM node WHERE node_object_type = ?',
576
+ [ObjectTypes.DataType],
577
+ )
578
+ let sortOrder = Number(count[0]?.n ?? 0)
579
+ for (const dataType of ALL_SEEDED_DATA_TYPES) {
580
+ const found = await db.query('SELECT id FROM node WHERE unique_id = ?', [dataType.key])
581
+ if (found.length > 0) continue
582
+ await insertDataType(db, dataType, sortOrder++)
583
+ added.push(dataType.alias)
584
+ }
585
+ return added
586
+ }