rimecms 0.29.0 → 0.30.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 (215) hide show
  1. package/dist/adapter-sqlite/area.server.js +8 -8
  2. package/dist/adapter-sqlite/generate-schema/column.server.d.ts +13 -0
  3. package/dist/adapter-sqlite/generate-schema/column.server.js +77 -0
  4. package/dist/adapter-sqlite/generate-schema/index.server.js +7 -12
  5. package/dist/adapter-sqlite/generate-schema/root.server.js +35 -39
  6. package/dist/adapter-sqlite/generate-schema/templates.server.d.ts +12 -0
  7. package/dist/adapter-sqlite/generate-schema/templates.server.js +19 -0
  8. package/dist/adapter-sqlite/index.server.d.ts +1 -2
  9. package/dist/adapter-sqlite/index.server.js +0 -2
  10. package/dist/adapter-sqlite/relations.server.js +6 -1
  11. package/dist/adapter-sqlite/util.server.d.ts +1 -6
  12. package/dist/adapter-sqlite/util.server.js +6 -0
  13. package/dist/adapter-sqlite/where.server.js +17 -16
  14. package/dist/adapter-sqlite/with.server.js +9 -9
  15. package/dist/core/collections/auth/fields.d.ts +2 -182
  16. package/dist/core/collections/config/augment-auth.server.js +1 -1
  17. package/dist/core/collections/config/augment-nested.server.js +1 -1
  18. package/dist/core/collections/config/augment-upload.js +2 -2
  19. package/dist/core/collections/config/augment-upload.server.js +4 -1
  20. package/dist/core/collections/operations/duplicate.js +30 -11
  21. package/dist/core/collections/operations/updateById.js +6 -5
  22. package/dist/core/collections/rest/duplicate.server.js +7 -3
  23. package/dist/core/collections/upload/disk/delete.server.d.ts +1 -1
  24. package/dist/core/collections/upload/disk/delete.server.js +48 -1
  25. package/dist/core/collections/upload/hooks/clean-up-files.server.js +2 -2
  26. package/dist/core/collections/upload/hooks/extract-path.server.d.ts +1 -1
  27. package/dist/core/collections/upload/hooks/extract-path.server.js +1 -1
  28. package/dist/core/collections/upload/hooks/process-file-upload.server.js +3 -3
  29. package/dist/core/config/server/validate.server.js +50 -30
  30. package/dist/core/config/shared/find-thumbnail.js +12 -12
  31. package/dist/core/config/shared/find-title.js +13 -13
  32. package/dist/core/config/shared/upload-directories.js +1 -1
  33. package/dist/core/constant.server.d.ts +1 -0
  34. package/dist/core/constant.server.js +2 -0
  35. package/dist/core/dev/cache/index.server.js +9 -9
  36. package/dist/core/dev/cli/build/index.js +2 -2
  37. package/dist/core/dev/cli/clear/index.server.js +2 -1
  38. package/dist/core/dev/cli/generate/index.server.js +3 -2
  39. package/dist/core/dev/cli/init/index.server.js +1 -1
  40. package/dist/core/dev/generate/routes/index.server.js +2 -2
  41. package/dist/core/dev/generate/types/index.server.js +17 -17
  42. package/dist/core/dev/vite/index.server.js +21 -5
  43. package/dist/core/fields/builders/boolean-builder.d.ts +3 -1
  44. package/dist/core/fields/builders/boolean-builder.js +3 -0
  45. package/dist/core/fields/builders/field-builder.d.ts +35 -2
  46. package/dist/core/fields/builders/field-builder.js +33 -2
  47. package/dist/core/fields/builders/form-field-builder.d.ts +71 -12
  48. package/dist/core/fields/builders/form-field-builder.js +96 -6
  49. package/dist/core/fields/builders/select-builder.d.ts +4 -1
  50. package/dist/core/fields/builders/select-builder.js +3 -0
  51. package/dist/core/fields/util.d.ts +8 -16
  52. package/dist/core/fields/util.js +49 -83
  53. package/dist/core/handlers/routes.server.js +16 -3
  54. package/dist/core/naming.d.ts +34 -0
  55. package/dist/core/naming.js +39 -0
  56. package/dist/core/operations/blocks/diff.server.js +1 -1
  57. package/dist/core/operations/blocks/extract.server.js +1 -1
  58. package/dist/core/operations/configMap/buildTreeMap.d.ts +3 -2
  59. package/dist/core/operations/configMap/buildTreeMap.js +1 -1
  60. package/dist/core/operations/configMap/index.d.ts +2 -1
  61. package/dist/core/operations/configMap/index.js +13 -13
  62. package/dist/core/operations/configMap/types.d.ts +2 -2
  63. package/dist/core/operations/hooks/before-read/process-document-fields.server.js +14 -17
  64. package/dist/core/operations/hooks/before-upsert/data-config-map.server.js +1 -1
  65. package/dist/core/operations/hooks/before-upsert/original-config-map.server.js +1 -1
  66. package/dist/core/operations/hooks/before-upsert/set-default-values.server.d.ts +2 -4
  67. package/dist/core/operations/hooks/before-upsert/set-default-values.server.js +10 -15
  68. package/dist/core/operations/hooks/before-upsert/validate-fields.server.js +49 -31
  69. package/dist/core/operations/relations/extract.server.js +5 -5
  70. package/dist/core/operations/shared/fallback-data-from-original.js +2 -2
  71. package/dist/core/operations/tree/diff.server.js +1 -1
  72. package/dist/core/operations/tree/extract.server.js +1 -1
  73. package/dist/core/plugins/cache/cache.server.js +3 -3
  74. package/dist/fields/blocks/component/AddBlockButton.svelte +7 -7
  75. package/dist/fields/blocks/component/AddBlockButton.svelte.d.ts +2 -2
  76. package/dist/fields/blocks/component/Blocks.svelte +6 -7
  77. package/dist/fields/blocks/component/props.d.ts +2 -2
  78. package/dist/fields/blocks/index.d.ts +1 -1
  79. package/dist/fields/blocks/index.js +3 -3
  80. package/dist/fields/blocks/index.server.js +1 -1
  81. package/dist/fields/checkbox/component/Checkbox.svelte +2 -2
  82. package/dist/fields/checkbox/component/props.d.ts +2 -2
  83. package/dist/fields/checkbox/index.server.d.ts +1 -2
  84. package/dist/fields/checkbox/index.server.js +1 -10
  85. package/dist/fields/combobox/component/ComboBox.svelte +3 -3
  86. package/dist/fields/combobox/component/props.d.ts +2 -2
  87. package/dist/fields/combobox/index.server.d.ts +1 -2
  88. package/dist/fields/combobox/index.server.js +2 -11
  89. package/dist/fields/component/index.d.ts +1 -1
  90. package/dist/fields/date/component/Date.svelte +4 -4
  91. package/dist/fields/date/component/Date.svelte.d.ts +2 -2
  92. package/dist/fields/date/index.d.ts +3 -1
  93. package/dist/fields/date/index.js +3 -0
  94. package/dist/fields/date/index.server.d.ts +1 -2
  95. package/dist/fields/date/index.server.js +1 -10
  96. package/dist/fields/email/component/Email.svelte +5 -6
  97. package/dist/fields/email/component/props.d.ts +2 -3
  98. package/dist/fields/email/index.d.ts +3 -2
  99. package/dist/fields/email/index.js +4 -1
  100. package/dist/fields/email/index.server.d.ts +0 -3
  101. package/dist/fields/email/index.server.js +0 -9
  102. package/dist/fields/group/component/Group.svelte +9 -15
  103. package/dist/fields/group/component/Group.svelte.d.ts +2 -2
  104. package/dist/fields/group/index.d.ts +4 -2
  105. package/dist/fields/group/index.server.js +2 -2
  106. package/dist/fields/index.server.d.ts +1 -4
  107. package/dist/fields/index.server.js +17 -13
  108. package/dist/fields/link/component/Link.svelte +5 -5
  109. package/dist/fields/link/component/props.d.ts +2 -2
  110. package/dist/fields/link/index.d.ts +4 -1
  111. package/dist/fields/link/index.js +9 -10
  112. package/dist/fields/link/runtime.d.ts +2 -0
  113. package/dist/fields/link/runtime.js +1 -0
  114. package/dist/fields/link/{index.server.d.ts → runtime.server.d.ts} +1 -2
  115. package/dist/fields/link/{index.server.js → runtime.server.js} +2 -11
  116. package/dist/fields/number/component/Number.svelte +6 -6
  117. package/dist/fields/number/component/props.d.ts +2 -2
  118. package/dist/fields/number/index.d.ts +4 -10
  119. package/dist/fields/number/index.js +3 -4
  120. package/dist/fields/number/index.server.d.ts +1 -2
  121. package/dist/fields/number/index.server.js +1 -10
  122. package/dist/fields/radio/component/Radio.svelte +6 -7
  123. package/dist/fields/radio/component/props.d.ts +2 -2
  124. package/dist/fields/radio/index.server.d.ts +1 -2
  125. package/dist/fields/radio/index.server.js +2 -11
  126. package/dist/fields/relation/component/Relation.svelte +18 -14
  127. package/dist/fields/relation/component/Relation.svelte.d.ts +2 -2
  128. package/dist/fields/relation/index.d.ts +7 -4
  129. package/dist/fields/relation/index.js +8 -47
  130. package/dist/fields/relation/runtime.d.ts +5 -0
  131. package/dist/fields/relation/runtime.js +4 -0
  132. package/dist/fields/relation/runtime.server.d.ts +8 -0
  133. package/dist/fields/relation/runtime.server.js +49 -0
  134. package/dist/fields/rich-text/component/RichText.svelte +5 -5
  135. package/dist/fields/rich-text/component/props.d.ts +2 -2
  136. package/dist/fields/rich-text/core/features/fields/fields.svelte +2 -2
  137. package/dist/fields/rich-text/index.d.ts +2 -0
  138. package/dist/fields/rich-text/index.js +3 -0
  139. package/dist/fields/rich-text/index.server.d.ts +1 -2
  140. package/dist/fields/rich-text/index.server.js +1 -10
  141. package/dist/fields/select/component/Select.svelte +16 -16
  142. package/dist/fields/select/component/props.d.ts +2 -2
  143. package/dist/fields/select/index.d.ts +2 -0
  144. package/dist/fields/select/index.js +3 -0
  145. package/dist/fields/select/index.server.d.ts +1 -2
  146. package/dist/fields/select/index.server.js +2 -17
  147. package/dist/fields/slug/component/Slug.svelte +14 -10
  148. package/dist/fields/slug/component/Slug.svelte.d.ts +2 -2
  149. package/dist/fields/slug/index.d.ts +5 -2
  150. package/dist/fields/slug/index.js +3 -0
  151. package/dist/fields/slug/index.server.d.ts +1 -2
  152. package/dist/fields/slug/index.server.js +1 -10
  153. package/dist/fields/tabs/component/Tabs.svelte +15 -15
  154. package/dist/fields/tabs/component/Tabs.svelte.d.ts +2 -2
  155. package/dist/fields/tabs/index.d.ts +4 -16
  156. package/dist/fields/tabs/index.js +1 -8
  157. package/dist/fields/tabs/index.server.js +3 -3
  158. package/dist/fields/text/component/Text.svelte +5 -5
  159. package/dist/fields/text/component/props.d.ts +2 -3
  160. package/dist/fields/text/index.d.ts +4 -10
  161. package/dist/fields/text/index.js +3 -4
  162. package/dist/fields/text/index.server.d.ts +1 -2
  163. package/dist/fields/text/index.server.js +1 -10
  164. package/dist/fields/textarea/component/TextArea.svelte +3 -3
  165. package/dist/fields/textarea/component/props.d.ts +2 -2
  166. package/dist/fields/textarea/index.d.ts +4 -1
  167. package/dist/fields/textarea/index.js +3 -0
  168. package/dist/fields/textarea/index.server.d.ts +1 -2
  169. package/dist/fields/textarea/index.server.js +1 -10
  170. package/dist/fields/time/component/Time.svelte +5 -5
  171. package/dist/fields/time/component/Time.svelte.d.ts +1 -1
  172. package/dist/fields/time/component/props.d.ts +2 -2
  173. package/dist/fields/time/index.d.ts +2 -0
  174. package/dist/fields/time/index.js +3 -0
  175. package/dist/fields/time/index.server.d.ts +1 -2
  176. package/dist/fields/time/index.server.js +1 -10
  177. package/dist/fields/toggle/component/Toggle.svelte +3 -3
  178. package/dist/fields/toggle/component/Toggle.svelte.d.ts +1 -1
  179. package/dist/fields/toggle/component/props.d.ts +2 -2
  180. package/dist/fields/toggle/index.d.ts +2 -1
  181. package/dist/fields/toggle/index.server.d.ts +1 -2
  182. package/dist/fields/toggle/index.server.js +1 -10
  183. package/dist/fields/tree/component/AddItemButton.svelte +1 -2
  184. package/dist/fields/tree/component/Tree.svelte +6 -6
  185. package/dist/fields/tree/component/TreeBlock.svelte +5 -12
  186. package/dist/fields/tree/component/props.d.ts +3 -3
  187. package/dist/fields/tree/index.d.ts +3 -1
  188. package/dist/fields/tree/index.js +2 -2
  189. package/dist/fields/types.d.ts +11 -5
  190. package/dist/panel/components/fields/FieldsPreview.svelte +4 -5
  191. package/dist/panel/components/fields/Hint.svelte +5 -4
  192. package/dist/panel/components/fields/Hint.svelte.d.ts +3 -2
  193. package/dist/panel/components/fields/Label.svelte +6 -11
  194. package/dist/panel/components/fields/Label.svelte.d.ts +3 -2
  195. package/dist/panel/components/fields/LabelFor.svelte +4 -4
  196. package/dist/panel/components/fields/LabelFor.svelte.d.ts +2 -1
  197. package/dist/panel/components/fields/RenderFields.svelte +11 -16
  198. package/dist/panel/components/fields/{root.svelte.d.ts → fieldset.svelte.d.ts} +1 -1
  199. package/dist/panel/components/fields/{root.svelte.js → fieldset.svelte.js} +1 -1
  200. package/dist/panel/components/fields/index.d.ts +5 -5
  201. package/dist/panel/components/fields/index.js +2 -2
  202. package/dist/panel/components/sections/document/AuthFooter.svelte +2 -7
  203. package/dist/panel/components/sections/live/LiveEditPanel.svelte +2 -2
  204. package/dist/panel/context/collection.svelte.js +9 -9
  205. package/dist/panel/context/documentForm.svelte.d.ts +8 -21
  206. package/dist/panel/context/documentForm.svelte.js +45 -52
  207. package/dist/panel/context/form.svelte.d.ts +4 -3
  208. package/dist/panel/context/form.svelte.js +14 -16
  209. package/dist/panel/pages/auth/fields.d.ts +4 -4
  210. package/dist/panel/pages/auth/fields.js +6 -22
  211. package/dist/panel/pages/auth/reset-password/ResetPassword.svelte +3 -10
  212. package/dist/util/doc.js +15 -17
  213. package/package.json +3 -2
  214. package/dist/fields/relation/index.server.d.ts +0 -4
  215. package/dist/fields/relation/index.server.js +0 -13
@@ -2,12 +2,14 @@ import { isAuthConfig } from '../../collections/auth/util.js';
2
2
  import cache from '../../dev/cache/index.server.js';
3
3
  import { isFormField } from '../../fields/util.js';
4
4
  import { logger } from '../../logger/index.server.js';
5
- import { isBlocksFieldRaw } from '../../../fields/blocks/index.js';
6
- import { isGroupFieldRaw } from '../../../fields/group/index.js';
7
- import { isRelationField } from '../../../fields/relation/index.js';
8
- import { isSelectField } from '../../../fields/select/index.js';
9
- import { isTabsFieldRaw } from '../../../fields/tabs/index.js';
10
- import { isTreeFieldRaw } from '../../../fields/tree/index.js';
5
+ import { withoutDirectoriesSuffix, withoutVersionsSuffix } from '../../naming.js';
6
+ import { BlocksBuilder } from '../../../fields/blocks/index.js';
7
+ import { GroupFieldBuilder } from '../../../fields/group/index.js';
8
+ import { RelationFieldBuilder } from '../../../fields/relation/index.js';
9
+ import { SelectFieldBuilder } from '../../../fields/select/index.js';
10
+ import { TabsBuilder } from '../../../fields/tabs/index.js';
11
+ import { TreeBuilder } from '../../../fields/tree/index.js';
12
+ import { isCamelCase } from '../../../util/string.js';
11
13
  function hasDuplicates(arr) {
12
14
  return [...new Set(arr.filter((e, i, a) => a.indexOf(e) !== i))];
13
15
  }
@@ -29,6 +31,24 @@ function hasDuplicateSlug(config) {
29
31
  }
30
32
  return [];
31
33
  }
34
+ /**
35
+ * Check that all area/collection slugs are camelCase
36
+ */
37
+ function validateSlugs(config) {
38
+ const errors = [];
39
+ const slugs = [
40
+ ...(config.collections || []).map((c) => c.slug),
41
+ ...(config.areas || []).map((a) => a.slug)
42
+ ]
43
+ .map(withoutVersionsSuffix)
44
+ .map(withoutDirectoriesSuffix);
45
+ for (const slug of slugs) {
46
+ if (!isCamelCase(slug)) {
47
+ errors.push(`Slug ${slug} is not a valid prototype slug`);
48
+ }
49
+ }
50
+ return errors;
51
+ }
32
52
  /**
33
53
  * Prevent the panel user collection slug
34
54
  * to be used elsewhere
@@ -64,14 +84,14 @@ const validateDocumentFields = (documentConfig, config) => {
64
84
  const isCollection = (documentConfig) => documentConfig.type === 'collection';
65
85
  const isAuth = isCollection(documentConfig) && isAuthConfig(documentConfig);
66
86
  const registeredBlocks = {};
67
- const fieldsCompiled = documentConfig.fields.map((f) => f.compile());
87
+ // const fieldsCompiled = documentConfig.fields.map((f) => f.compile());
68
88
  if (isAuth) {
69
- const rolesField = fieldsCompiled
89
+ const rolesField = documentConfig.fields
70
90
  .filter(isFormField)
71
91
  .filter((f) => f.name === 'roles')
72
- .filter((f) => isSelectField(f))[0];
73
- const nameField = fieldsCompiled.filter(isFormField).filter((f) => f.name === 'name')[0];
74
- const emailField = fieldsCompiled
92
+ .filter((f) => f instanceof SelectFieldBuilder)[0];
93
+ const nameField = documentConfig.fields.filter(isFormField).filter((f) => f.name === 'name')[0];
94
+ const emailField = documentConfig.fields
75
95
  .filter(isFormField)
76
96
  .find((f) => f.name === 'email' && f.type === 'email');
77
97
  if (!rolesField)
@@ -80,7 +100,7 @@ const validateDocumentFields = (documentConfig, config) => {
80
100
  errors.push(`Field email is missing in collection ${documentConfig.slug}`);
81
101
  if (!nameField)
82
102
  errors.push(`Field name is missing in collection ${documentConfig.slug}`);
83
- if (!rolesField.many)
103
+ if (!rolesField.get.many)
84
104
  errors.push(`Field roles must have "many" enabled : select('roles').options(...).many(), even with a single option`);
85
105
  }
86
106
  const validateBlockField = (fields, blockType) => {
@@ -96,8 +116,8 @@ const validateDocumentFields = (documentConfig, config) => {
96
116
  };
97
117
  const validateRelationField = (field) => {
98
118
  const collectionsSlugs = (config.collections || []).map((c) => c.slug);
99
- if (!collectionsSlugs.includes(field.relationTo)) {
100
- errors.push(`Relation field ${field.name} references unknown collection ${field.relationTo}, in ${documentConfig.type} ${documentConfig.slug}`);
119
+ if (!collectionsSlugs.includes(field.get.relationTo)) {
120
+ errors.push(`Relation field ${field.name} references unknown collection ${field.get.relationTo}, in ${documentConfig.type} ${documentConfig.slug}`);
101
121
  }
102
122
  };
103
123
  const validateFields = (fields) => {
@@ -116,17 +136,17 @@ const validateDocumentFields = (documentConfig, config) => {
116
136
  return pattern.test(name) && !name.includes('-') && !name.includes(' ');
117
137
  }
118
138
  function validateTabs(field) {
119
- const duplicates = hasDuplicates(field.tabs.map((t) => t.name));
139
+ const duplicates = hasDuplicates(field.get.tabs.map((t) => t.name));
120
140
  if (duplicates.length) {
121
141
  errors.push(`Dupplicate tab name ${duplicates} in ${documentConfig.slug}`);
122
142
  }
123
143
  }
124
144
  for (const field of fields) {
125
145
  // Recursive check first into Tabs since tabs are not Formfields
126
- if (isTabsFieldRaw(field)) {
146
+ if (field instanceof TabsBuilder) {
127
147
  validateTabs(field);
128
- for (const tab of field.tabs) {
129
- validateFields(tab.fields);
148
+ for (const tab of field.get.tabs) {
149
+ validateFields(tab.get.fields);
130
150
  }
131
151
  }
132
152
  // If field is not a Formfield eg. Separator then continue
@@ -134,7 +154,7 @@ const validateDocumentFields = (documentConfig, config) => {
134
154
  continue;
135
155
  }
136
156
  // Check that a field wich has field._root = true is not localized
137
- if ('_root' in field && field._root && field.localized) {
157
+ if (field.get.root && field.get.localized) {
138
158
  errors.push(`Field ${field.name} of ${documentConfig.type} ${documentConfig.slug} with _root = true, can't be localized`);
139
159
  }
140
160
  // Check for malformed field.name
@@ -142,8 +162,8 @@ const validateDocumentFields = (documentConfig, config) => {
142
162
  errors.push(`Field ${field.name} of ${documentConfig.type} ${documentConfig.slug} should be camelCase`);
143
163
  }
144
164
  // Recursive check into Blocks
145
- if (isBlocksFieldRaw(field)) {
146
- for (const block of field.blocks) {
165
+ if (field instanceof BlocksBuilder) {
166
+ for (const block of field.get.blocks) {
147
167
  if (block.name in registeredBlocks) {
148
168
  const blockDefinedButDiffer = JSON.stringify(registeredBlocks[block.name]) !== JSON.stringify(block);
149
169
  if (blockDefinedButDiffer) {
@@ -153,25 +173,25 @@ const validateDocumentFields = (documentConfig, config) => {
153
173
  else {
154
174
  registeredBlocks[block.name] = block;
155
175
  }
156
- validateFields(block.fields.filter(isFormField));
157
- validateBlockField(block.fields.filter(isFormField), block.name);
176
+ validateFields(block.get.fields.filter(isFormField));
177
+ validateBlockField(block.get.fields.filter(isFormField), block.name);
158
178
  }
159
179
  // Recursive check into Tree
160
180
  }
161
- else if (isTreeFieldRaw(field)) {
162
- validateFields(field.fields.filter(isFormField));
181
+ else if (field instanceof TreeBuilder) {
182
+ validateFields(field.get.fields.filter(isFormField));
163
183
  // Recursive check into Tabs
164
184
  }
165
- else if (isGroupFieldRaw(field)) {
166
- validateFields(field.fields.filter(isFormField));
185
+ else if (field instanceof GroupFieldBuilder) {
186
+ validateFields(field.get.fields.filter(isFormField));
167
187
  // Check relation field
168
188
  }
169
- else if (isRelationField(field)) {
189
+ else if (field instanceof RelationFieldBuilder) {
170
190
  validateRelationField(field);
171
191
  }
172
192
  }
173
193
  };
174
- validateFields(documentConfig.fields.map((f) => f.compile()));
194
+ validateFields(documentConfig.fields);
175
195
  return errors;
176
196
  };
177
197
  const hasDatabase = (config) => {
@@ -192,9 +212,9 @@ function validateAuthCollections(config) {
192
212
  return errors;
193
213
  }
194
214
  function validate(config) {
195
- logger.debug('Validating config...');
196
215
  const validateFunctions = [
197
216
  hasDuplicateSlug,
217
+ validateSlugs,
198
218
  hasUsersSlug,
199
219
  validateFields,
200
220
  hasDatabase,
@@ -1,29 +1,29 @@
1
1
  import { FormFieldBuilder } from '../../fields/builders/form-field-builder.js';
2
- import { isGroupField } from '../../../fields/group/index.js';
2
+ import { GroupFieldBuilder } from '../../../fields/group/index.js';
3
3
  import { RelationFieldBuilder } from '../../../fields/relation/index.js';
4
4
  import { TabsBuilder } from '../../../fields/tabs/index.js';
5
5
  export function findThumbnailField(fields = [], basePath = '') {
6
6
  for (const field of fields) {
7
7
  // Direct check for isThumbnail
8
8
  if (field instanceof RelationFieldBuilder &&
9
- 'isThumbnail' in field.raw &&
10
- field.raw.isThumbnail === true) {
11
- const path = basePath ? `${basePath}.${field.raw.name}` : field.raw.name;
9
+ 'isThumbnail' in field.get &&
10
+ field.get.isThumbnail === true) {
11
+ const path = basePath ? `${basePath}.${field.name}` : field.name;
12
12
  return { field, path };
13
13
  }
14
14
  // Check in group
15
- if (isGroupField(field.raw) && field.raw.fields) {
16
- const groupPath = basePath ? `${basePath}.${field.raw.name}` : field.raw.name;
17
- const found = findThumbnailField(field.raw.fields, groupPath);
15
+ if (field instanceof GroupFieldBuilder && field.get.fields) {
16
+ const groupPath = basePath ? `${basePath}.${field.name}` : field.name;
17
+ const found = findThumbnailField(field.get.fields, groupPath);
18
18
  if (found)
19
19
  return found;
20
20
  }
21
21
  // Check in tabs
22
- if (field instanceof TabsBuilder && field.raw.tabs) {
23
- for (const tab of field.raw.tabs) {
24
- if (tab.raw.fields) {
25
- const tabPath = basePath ? `${basePath}.${tab.raw.name}` : tab.raw.name;
26
- const found = findThumbnailField(tab.raw.fields, tabPath);
22
+ if (field instanceof TabsBuilder && field.get.tabs) {
23
+ for (const tab of field.get.tabs) {
24
+ if (tab.get.fields) {
25
+ const tabPath = basePath ? `${basePath}.${tab.name}` : tab.name;
26
+ const found = findThumbnailField(tab.get.fields, tabPath);
27
27
  if (found)
28
28
  return found;
29
29
  }
@@ -1,30 +1,30 @@
1
1
  import { FormFieldBuilder } from '../../fields/builders/form-field-builder.js';
2
- import { isGroupField } from '../../../fields/group/index.js';
2
+ import { GroupFieldBuilder } from '../../../fields/group/index.js';
3
3
  import { TabsBuilder } from '../../../fields/tabs/index.js';
4
4
  export const hasMaybeTitle = (field) => ['text', 'date', 'slug', 'email', 'richText'].includes(field.type);
5
5
  export function findTitleField(fields = [], basePath = '') {
6
6
  for (const field of fields) {
7
7
  // Direct check for isTitle
8
8
  if (field instanceof FormFieldBuilder &&
9
- hasMaybeTitle(field.raw) &&
10
- 'isTitle' in field.raw &&
11
- field.raw.isTitle === true) {
12
- const path = basePath ? `${basePath}.${field.raw.name}` : field.raw.name;
9
+ hasMaybeTitle(field.get) &&
10
+ 'isTitle' in field.get &&
11
+ field.get.isTitle === true) {
12
+ const path = basePath ? `${basePath}.${field.name}` : field.name;
13
13
  return { field, path };
14
14
  }
15
15
  // Check in group
16
- if (isGroupField(field.raw) && field.raw.fields) {
17
- const groupPath = basePath ? `${basePath}.${field.raw.name}` : field.raw.name;
18
- const found = findTitleField(field.raw.fields, groupPath);
16
+ if (field instanceof GroupFieldBuilder && field.get.fields) {
17
+ const groupPath = basePath ? `${basePath}.${field.name}` : field.name;
18
+ const found = findTitleField(field.get.fields, groupPath);
19
19
  if (found)
20
20
  return found;
21
21
  }
22
22
  // Check in tabs
23
- if (field instanceof TabsBuilder && field.raw.tabs) {
24
- for (const tab of field.raw.tabs) {
25
- if (tab.raw.fields) {
26
- const tabPath = basePath ? `${basePath}.${tab.raw.name}` : tab.raw.name;
27
- const found = findTitleField(tab.raw.fields, tabPath);
23
+ if (field instanceof TabsBuilder && field.get.tabs) {
24
+ for (const tab of field.get.tabs) {
25
+ if (tab.get.fields) {
26
+ const tabPath = basePath ? `${basePath}.${tab.name}` : tab.name;
27
+ const found = findTitleField(tab.get.fields, tabPath);
28
28
  if (found)
29
29
  return found;
30
30
  }
@@ -10,7 +10,7 @@ export function makeUploadDirectoriesCollectionClient(collection) {
10
10
  const slug = withDirectoriesSuffix(collection.slug);
11
11
  const directoriesConfig = collection.upload.directories;
12
12
  // else create the directory collection
13
- let directoriesCollection = {
13
+ const directoriesCollection = {
14
14
  slug: slug,
15
15
  kebab: withDirectoriesSuffix(collection.kebab),
16
16
  versions: undefined,
@@ -1 +1,2 @@
1
1
  export declare const PACKAGE_NAME = "rimecms";
2
+ export declare const RIME_DEV_CACHE_DIR: string;
@@ -1 +1,3 @@
1
+ import path from 'path';
1
2
  export const PACKAGE_NAME = 'rimecms';
3
+ export const RIME_DEV_CACHE_DIR = path.resolve(process.cwd(), 'node_modules', '.rime');
@@ -1,12 +1,12 @@
1
+ import { RIME_DEV_CACHE_DIR } from '../../constant.server.js';
1
2
  import fs from 'fs';
2
3
  import path from 'path';
3
4
  const dev = process.env.NODE_ENV === 'development';
4
- const cachePath = path.resolve(process.cwd(), '.rime');
5
- if (!fs.existsSync(cachePath) && dev) {
6
- fs.mkdirSync(cachePath);
5
+ if (!fs.existsSync(RIME_DEV_CACHE_DIR) && dev) {
6
+ fs.mkdirSync(RIME_DEV_CACHE_DIR);
7
7
  }
8
8
  function get(key) {
9
- const keyPath = path.join(cachePath, key + '.txt');
9
+ const keyPath = path.join(RIME_DEV_CACHE_DIR, key + '.txt');
10
10
  const exist = fs.existsSync(keyPath);
11
11
  if (exist) {
12
12
  return fs.readFileSync(keyPath).toString();
@@ -14,20 +14,20 @@ function get(key) {
14
14
  return false;
15
15
  }
16
16
  function set(key, value) {
17
- if (!fs.existsSync(cachePath)) {
18
- fs.mkdirSync(cachePath);
17
+ if (!fs.existsSync(RIME_DEV_CACHE_DIR)) {
18
+ fs.mkdirSync(RIME_DEV_CACHE_DIR);
19
19
  }
20
- const keyPath = path.join(cachePath, key + '.txt');
20
+ const keyPath = path.join(RIME_DEV_CACHE_DIR, key + '.txt');
21
21
  fs.writeFileSync(keyPath, value);
22
22
  }
23
23
  function del(key) {
24
- const keyPath = path.join(cachePath, key + '.txt');
24
+ const keyPath = path.join(RIME_DEV_CACHE_DIR, key + '.txt');
25
25
  if (fs.existsSync(keyPath)) {
26
26
  fs.rmSync(keyPath, { force: true });
27
27
  }
28
28
  }
29
29
  function clear() {
30
- fs.rmSync(cachePath, { recursive: true });
30
+ fs.rmSync(RIME_DEV_CACHE_DIR, { recursive: true });
31
31
  }
32
32
  export default {
33
33
  get,
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { logger } from '../../../logger/index.server.js';
3
3
  import chalk from 'chalk';
4
+ import { spawnSync } from 'child_process';
4
5
  import { copyFileSync, cpSync, existsSync, mkdirSync, renameSync, rmSync, writeFileSync } from 'fs';
5
6
  import { getInvokingPackageManager } from '../util/package-manager.server.js';
6
7
  import { envProduction, polkaServer } from './templates.js';
@@ -22,8 +23,7 @@ export const build = (args) => {
22
23
  rmSync('./app', { recursive: true, force: true });
23
24
  }
24
25
  // Build
25
- mkdirSync('./build', { recursive: true });
26
- // spawnSync('./node_modules/.bin/vite', ['build'], { stdio: 'inherit' });
26
+ spawnSync('./node_modules/.bin/vite', ['build'], { stdio: 'inherit' });
27
27
  console.log('');
28
28
  // Create app directory
29
29
  mkdirSync('./app', { recursive: true });
@@ -1,3 +1,4 @@
1
+ import { RIME_DEV_CACHE_DIR } from '../../../constant.server.js';
1
2
  import { logger } from '../../../logger/index.server.js';
2
3
  import { rmSync } from 'node:fs';
3
4
  import path from 'node:path';
@@ -24,7 +25,7 @@ export const clear = async (args) => {
24
25
  return logger.info('Operation cancelled. Great!');
25
26
  }
26
27
  // Remove directories
27
- rmSync(path.join('.rime'), { recursive: true, force: true });
28
+ rmSync(RIME_DEV_CACHE_DIR, { recursive: true, force: true });
28
29
  rmSync(path.join('src', 'routes', '(rime)'), { recursive: true, force: true });
29
30
  rmSync(path.join('src', 'lib', INPUT_DIR), { recursive: true, force: true });
30
31
  rmSync(path.join('src', 'lib', OUTPUT_DIR), { recursive: true, force: true });
@@ -1,3 +1,4 @@
1
+ import { RIME_DEV_CACHE_DIR } from '../../../constant.server.js';
1
2
  import cache from '../../cache/index.server.js';
2
3
  import { sanitize } from '../../generate/sanitize/index.server.js';
3
4
  import { ensureGeneratedConfig, ensureUserConfigExist } from '../../../ensure.server.js';
@@ -12,8 +13,8 @@ export const generate = async (args) => {
12
13
  */
13
14
  function clearConfigCache() {
14
15
  try {
15
- rmSync(path.join(process.cwd(), '.rime'), { recursive: true, force: true });
16
- mkdirSync(path.join(process.cwd(), '.rime'));
16
+ rmSync(RIME_DEV_CACHE_DIR, { recursive: true, force: true });
17
+ mkdirSync(RIME_DEV_CACHE_DIR);
17
18
  }
18
19
  catch (err) {
19
20
  logger.error(err.message);
@@ -83,7 +83,7 @@ export const init = async ({ force, name: incomingName, skipInstall }) => {
83
83
  return;
84
84
  }
85
85
  let gitignoreContent = readFileSync(gitignorePath, 'utf-8');
86
- const updates = ['\\.rime', '\\.cache', '/logs', '/db', '\\+rime.generated'];
86
+ const updates = ['\\.cache', '/logs', '/db', '\\+rime.generated'];
87
87
  if (!gitignoreContent.includes('# rime'))
88
88
  gitignoreContent += '\n# rime';
89
89
  for (const line of updates) {
@@ -37,8 +37,8 @@ function generateRoutes(config) {
37
37
  }
38
38
  }
39
39
  // 4. Write the [slug=collection]/[slug=area] param matchers
40
- fs.writeFileSync(path.join(paramsDir, 'collection.ts'), paramMatcher((config.collections || []).map((c) => c.slug)));
41
- fs.writeFileSync(path.join(paramsDir, 'area.ts'), paramMatcher((config.areas || []).map((a) => a.slug)));
40
+ fs.writeFileSync(path.join(paramsDir, 'collection.ts'), paramMatcher((config.collections || []).map((c) => c.kebab)));
41
+ fs.writeFileSync(path.join(paramsDir, 'area.ts'), paramMatcher((config.areas || []).map((a) => a.kebab)));
42
42
  // 5. Handle custom routes from config
43
43
  const customRoutes = config.panel?.routes;
44
44
  if (customRoutes) {
@@ -171,50 +171,50 @@ export async function generateTypesString(config) {
171
171
  for (const field of fields) {
172
172
  if (field instanceof BlocksBuilder) {
173
173
  {
174
- for (const block of field.raw.blocks) {
175
- if (!registeredBlocks.includes(block.raw.name)) {
176
- const templates = await buildFieldsTypes(block.raw.fields
174
+ for (const block of field.get.blocks) {
175
+ if (!registeredBlocks.includes(block.name)) {
176
+ const templates = await buildFieldsTypes(block.get.fields
177
177
  .filter((field) => field instanceof FormFieldBuilder)
178
178
  .filter((field) => field.name !== 'type'));
179
- blocksTypes.push(makeBlockType(block.raw.name, templates.join('\n\t')));
180
- registeredBlocks.push(block.raw.name);
181
- buildblocksTypes(block.raw.fields);
179
+ blocksTypes.push(makeBlockType(block.name, templates.join('\n\t')));
180
+ registeredBlocks.push(block.name);
181
+ buildblocksTypes(block.get.fields);
182
182
  }
183
183
  }
184
184
  }
185
185
  }
186
186
  else if (field instanceof TabsBuilder) {
187
- for (const tab of field.raw.tabs) {
188
- await buildblocksTypes(tab.raw.fields);
187
+ for (const tab of field.get.tabs) {
188
+ await buildblocksTypes(tab.get.fields);
189
189
  }
190
190
  }
191
191
  else if (field instanceof GroupFieldBuilder) {
192
- await buildblocksTypes(field.raw.fields);
192
+ await buildblocksTypes(field.get.fields);
193
193
  }
194
194
  else if (field instanceof TreeBuilder) {
195
- await buildblocksTypes(field.raw.fields);
195
+ await buildblocksTypes(field.get.fields);
196
196
  }
197
197
  }
198
198
  };
199
199
  const buildTreeBlockTypes = async (fields) => {
200
200
  for (const field of fields) {
201
201
  if (field instanceof BlocksBuilder) {
202
- for (const block of field.raw.blocks) {
203
- await buildTreeBlockTypes(block.raw.fields);
202
+ for (const block of field.get.blocks) {
203
+ await buildTreeBlockTypes(block.get.fields);
204
204
  }
205
205
  }
206
206
  else if (field instanceof TabsBuilder) {
207
- for (const tab of field.raw.tabs) {
208
- await buildTreeBlockTypes(tab.raw.fields);
207
+ for (const tab of field.get.tabs) {
208
+ await buildTreeBlockTypes(tab.get.fields);
209
209
  }
210
210
  }
211
211
  else if (field instanceof GroupFieldBuilder) {
212
- await buildTreeBlockTypes(field.raw.fields);
212
+ await buildTreeBlockTypes(field.get.fields);
213
213
  }
214
214
  else if (field instanceof TreeBuilder) {
215
215
  const treeBlockTypeName = `Tree${toPascalCase(field.name)}`;
216
216
  if (!registeredTreeBlocks.includes(treeBlockTypeName)) {
217
- const treeFieldsTypes = await buildFieldsTypes(field.raw.fields.filter((field) => field instanceof FormFieldBuilder));
217
+ const treeFieldsTypes = await buildFieldsTypes(field.get.fields.filter((field) => field instanceof FormFieldBuilder));
218
218
  const treeBlockType = makeTreeBlockType(treeBlockTypeName, treeFieldsTypes.join('\n'));
219
219
  treeBlocksTypes.push(treeBlockType);
220
220
  registeredTreeBlocks.push(treeBlockTypeName);
@@ -227,7 +227,7 @@ export async function generateTypesString(config) {
227
227
  if (isUploadConfig(collection) && collection.upload.imageSizes?.length) {
228
228
  fields = collection.fields
229
229
  .filter((f) => f instanceof FormFieldBuilder)
230
- .filter((field) => !collection.upload.imageSizes.some((size) => size.name === field.raw.name));
230
+ .filter((field) => !collection.upload.imageSizes.some((size) => size.name === field.name));
231
231
  }
232
232
  const fieldsTypesList = await buildFieldsTypes(fields);
233
233
  if (collection.versions) {
@@ -1,6 +1,7 @@
1
1
  import dotenv from 'dotenv';
2
2
  import { existsSync, rmSync } from 'node:fs';
3
3
  import path from 'node:path';
4
+ import { RIME_DEV_CACHE_DIR } from '../../constant.server.js';
4
5
  import { ensureHasInit } from '../../ensure.server.js';
5
6
  import { logger } from '../../logger/index.server.js';
6
7
  import { INPUT_DIR, OUTPUT_DIR } from '../constants.js';
@@ -10,6 +11,13 @@ const dev = process.env.NODE_ENV === 'development';
10
11
  export function rime() {
11
12
  const VCoreId = '$rime/config';
12
13
  const VSchemaId = '$rime/schema';
14
+ /** General-purpose server/browser split, usable anywhere in the app (not just rime's own
15
+ * field code — see relation/index.ts for the first user). `import { x } from '$rime/runtime'`
16
+ * resolves to a sibling `server.ts` (server builds) or `browser.ts` (browser builds) next
17
+ * to whichever file does the importing — the importer's path travels encoded in the
18
+ * resolved id since `load()` only receives the id, not the importer. */
19
+ const VRuntimeId = '$rime/runtime';
20
+ const VRuntimeMarker = `\0${VRuntimeId}::`;
13
21
  const resolvedVModule = (name) => '\0' + name;
14
22
  return {
15
23
  name: 'virtual-rime',
@@ -19,10 +27,9 @@ export function rime() {
19
27
  dev && ensureHasInit();
20
28
  // Check if we need to rebuild
21
29
  const shouldRebuild = process.argv.includes('--rebuild');
22
- const rimeDevCacheDir = path.resolve(process.cwd(), '.rime');
23
- if (shouldRebuild && existsSync(rimeDevCacheDir)) {
24
- rmSync(rimeDevCacheDir, { recursive: true, force: true });
25
- logger.info('--rebuild : .rime folder deleted');
30
+ if (shouldRebuild && existsSync(RIME_DEV_CACHE_DIR)) {
31
+ rmSync(RIME_DEV_CACHE_DIR, { recursive: true, force: true });
32
+ logger.info('--rebuild : node_modules/.rime folder deleted');
26
33
  }
27
34
  });
28
35
  // Add a watcher for sanitizing config changes
@@ -86,13 +93,16 @@ export function rime() {
86
93
  return [module];
87
94
  }
88
95
  },
89
- resolveId(id) {
96
+ resolveId(id, importer) {
90
97
  if (id === VCoreId) {
91
98
  return resolvedVModule(id);
92
99
  }
93
100
  if (id === VSchemaId) {
94
101
  return resolvedVModule(id);
95
102
  }
103
+ if (id === VRuntimeId && importer) {
104
+ return `${VRuntimeMarker}${importer}`;
105
+ }
96
106
  return null;
97
107
  },
98
108
  load(id) {
@@ -108,6 +118,12 @@ export function rime() {
108
118
  return `export * from '${modulePath}'; export { default } from '${modulePath}';`;
109
119
  }
110
120
  }
121
+ if (id.startsWith(VRuntimeMarker)) {
122
+ const importer = id.slice(VRuntimeMarker.length);
123
+ const dir = path.dirname(importer);
124
+ const target = path.join(dir, isServer ? 'runtime.server.ts' : 'runtime.ts');
125
+ return `export * from '${target.replace(/\.ts$/, '.js')}';`;
126
+ }
111
127
  return null;
112
128
  }
113
129
  };
@@ -1,4 +1,5 @@
1
1
  import type { DefaultValueFn, FieldValidationFunc, FormField } from '../../../fields/types.js';
2
+ import type { DataType } from './form-field-builder.js';
2
3
  import { FormFieldBuilder } from './form-field-builder.js';
3
4
  type BooleanField = FormField & {
4
5
  type: any;
@@ -6,9 +7,10 @@ type BooleanField = FormField & {
6
7
  defaultValue?: boolean | DefaultValueFn<boolean>;
7
8
  validate?: FieldValidationFunc<BooleanField>;
8
9
  };
9
- export declare class BooleanFieldBuilder<T extends BooleanField> extends FormFieldBuilder<T> {
10
+ export declare class BooleanFieldBuilder<T extends BooleanField = BooleanField> extends FormFieldBuilder<T> {
10
11
  constructor(name: string, type: string);
11
12
  defaultValue(value: boolean | DefaultValueFn<boolean>): this;
13
+ get dataType(): DataType;
12
14
  compile(): import("../../../util/types.js").WithoutBuilders<T> & {
13
15
  component: import("svelte").Component<any>;
14
16
  cell?: import("svelte").Component<{
@@ -8,6 +8,9 @@ export class BooleanFieldBuilder extends FormFieldBuilder {
8
8
  this.field.defaultValue = value;
9
9
  return this;
10
10
  }
11
+ get dataType() {
12
+ return 'boolean';
13
+ }
11
14
  compile() {
12
15
  if (!this.field.validate) {
13
16
  this.field.validate = (value) => typeof value === 'boolean' || 'Should be true/false';
@@ -1,10 +1,22 @@
1
1
  import type { WithoutBuilders } from '../../../util/types.js';
2
2
  import type { Component } from 'svelte';
3
- import type { Field } from '../../../fields/types.js';
3
+ import type { Field, FieldAccess } from '../../../fields/types.js';
4
+ /** Method-syntax (not `foo: () => ...` property syntax) so subtype checks
5
+ * like `FormFieldBuilder<SlugField> -> FormFieldBuilder<FormField>` — used
6
+ * all over the panel, where a concrete field builder flows into a
7
+ * generically-typed prop — stay bivariant on their params, exactly like the
8
+ * class methods this replaced. Property syntax would make TS check those
9
+ * params strictly/contravariantly and break that assignability. */
10
+ export type FieldRun = {
11
+ canRead(...args: Parameters<FieldAccess>): boolean;
12
+ canCreate(...args: Parameters<FieldAccess>): boolean;
13
+ canUpdate(...args: Parameters<FieldAccess>): boolean;
14
+ };
4
15
  export declare class FieldBuilder<T extends Field = Field> {
5
16
  field: T;
6
17
  _metaUrl?: string;
7
18
  constructor(type: string);
19
+ get name(): string;
8
20
  className(str: string): this;
9
21
  compile(): WithoutBuilders<T> & {
10
22
  component: Component<any>;
@@ -14,7 +26,28 @@ export declare class FieldBuilder<T extends Field = Field> {
14
26
  };
15
27
  live(bool: boolean): this;
16
28
  get type(): string;
17
- get raw(): T;
29
+ /**
30
+ * Raw field data, plus the couple of properties that a bare `this.field`
31
+ * read can't give you: `localized`/`root` default to `false` here since
32
+ * only FormFieldBuilder fields ever set them — container fields like Tabs
33
+ * answer `false` rather than making every caller check
34
+ * `instanceof FormFieldBuilder` first just to ask this one question.
35
+ * Everything else on `T` (Tabs' `tabs`, Blocks' `blocks`, ...) comes
36
+ * through unchanged via the spread — no per-subclass override needed.
37
+ */
38
+ get get(): T & {
39
+ localized: boolean;
40
+ root: boolean;
41
+ };
42
+ /** Behavior the builder runs on your behalf (invoking a stored function) —
43
+ * see `.get` for plain data reads. Fields without an access concept
44
+ * (Tabs) default every check to allowed, matching how the field-less case
45
+ * already behaved. Params are unused here but must match FormFieldBuilder's
46
+ * override signature — TS checks generic-constraint satisfaction
47
+ * (`T extends FieldBuilder<any>`) strictly, not with the bivariant
48
+ * leniency normal overrides get, so a param-less base signature breaks
49
+ * assignability everywhere. */
50
+ get run(): FieldRun;
18
51
  get component(): Component<any> | null;
19
52
  get cell(): Component<{
20
53
  value: any;