rimecms 0.28.9 → 0.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/README.md +3 -3
  2. package/dist/adapter-sqlite/generate-schema/{util.d.ts → util.server.d.ts} +2 -2
  3. package/dist/adapter-sqlite/generate-schema/{util.js → util.server.js} +2 -2
  4. package/dist/adapter-sqlite/generate-schema/write.server.js +1 -1
  5. package/dist/adapter-sqlite/index.server.d.ts +2 -1
  6. package/dist/adapter-sqlite/index.server.js +2 -0
  7. package/dist/adapter-sqlite/transform.server.js +1 -1
  8. package/dist/adapter-sqlite/with.server.js +1 -1
  9. package/dist/core/areas/{api → rest}/get.server.d.ts +4 -2
  10. package/dist/core/areas/rest/get.server.js +45 -0
  11. package/dist/core/areas/rest/index.server.d.ts +6 -0
  12. package/dist/core/areas/rest/index.server.js +3 -0
  13. package/dist/core/areas/{api → rest}/update.server.d.ts +4 -2
  14. package/dist/core/areas/rest/update.server.js +43 -0
  15. package/dist/core/collections/auth/hooks/before-upsert/augment-fields-password.server.d.ts +1 -1
  16. package/dist/core/collections/config/augment-panel.d.ts +1 -1
  17. package/dist/core/collections/local-api.server.js +2 -1
  18. package/dist/core/collections/operations/duplicate.js +2 -2
  19. package/dist/core/collections/{api → rest}/create.server.d.ts +4 -2
  20. package/dist/core/collections/rest/create.server.js +37 -0
  21. package/dist/core/collections/{api → rest}/delete.server.d.ts +4 -2
  22. package/dist/core/collections/rest/delete.server.js +37 -0
  23. package/dist/core/collections/{api → rest}/deleteById.server.d.ts +4 -2
  24. package/dist/core/collections/rest/deleteById.server.js +21 -0
  25. package/dist/core/collections/{api → rest}/duplicate.server.d.ts +1 -1
  26. package/dist/core/collections/rest/duplicate.server.js +16 -0
  27. package/dist/core/collections/{api → rest}/get.server.d.ts +4 -2
  28. package/dist/core/collections/rest/get.server.js +50 -0
  29. package/dist/core/collections/{api → rest}/getById.server.d.ts +4 -2
  30. package/dist/core/collections/rest/getById.server.js +35 -0
  31. package/dist/core/collections/rest/index.server.d.ts +16 -0
  32. package/dist/core/collections/rest/index.server.js +16 -0
  33. package/dist/core/collections/{api → rest}/updateById.server.d.ts +4 -2
  34. package/dist/core/collections/rest/updateById.server.js +44 -0
  35. package/dist/core/collections/upload/hooks/convert-base64.server.d.ts +1 -1
  36. package/dist/core/collections/upload/hooks/extract-path.server.d.ts +1 -1
  37. package/dist/core/collections/upload/hooks/handle-path-creation.server.d.ts +1 -1
  38. package/dist/core/collections/upload/hooks/process-file-upload.server.d.ts +1 -1
  39. package/dist/core/config/auth/better-auth.server.d.ts +2 -2
  40. package/dist/core/config/client/augment-directories.js +1 -1
  41. package/dist/core/config/config-context.server.d.ts +3 -3
  42. package/dist/core/config/server/augment-directories.server.js +1 -1
  43. package/dist/core/config/server/augment-panel-access.server.d.ts +1 -1
  44. package/dist/core/config/server/build-config.server.d.ts +11 -11
  45. package/dist/core/config/server/validate.server.js +3 -3
  46. package/dist/core/config/shared/find-thumbnail.js +1 -1
  47. package/dist/core/constant.d.ts +1 -1
  48. package/dist/core/constant.js +1 -1
  49. package/dist/core/dev/cli/build/index.d.ts +1 -0
  50. package/dist/core/dev/cli/build/index.js +39 -10
  51. package/dist/core/dev/cli/build/templates.d.ts +1 -0
  52. package/dist/core/dev/cli/build/templates.js +24 -0
  53. package/dist/core/dev/cli/clear/index.server.js +1 -1
  54. package/dist/core/dev/cli/index.js +20 -0
  55. package/dist/core/dev/cli/init/index.server.js +3 -3
  56. package/dist/core/dev/cli/init/templates.d.ts +1 -1
  57. package/dist/core/dev/cli/init/templates.js +2 -2
  58. package/dist/core/dev/cli/util/log.server.d.ts +1 -0
  59. package/dist/core/dev/cli/util/log.server.js +4 -0
  60. package/dist/core/dev/cli/util/package-manager.server.d.ts +9 -0
  61. package/dist/core/dev/cli/{init/package-manager-util.server.js → util/package-manager.server.js} +15 -0
  62. package/dist/core/dev/cli/util/package.server.d.ts +9 -0
  63. package/dist/core/dev/cli/{init/get-package-info.server.js → util/package.server.js} +10 -0
  64. package/dist/core/dev/generate/routes/common.server.d.ts +10 -1
  65. package/dist/core/dev/generate/routes/common.server.js +248 -29
  66. package/dist/core/dev/generate/routes/index.server.d.ts +7 -1
  67. package/dist/core/dev/generate/routes/index.server.js +16 -55
  68. package/dist/core/dev/generate/routes/util.server.d.ts +6 -16
  69. package/dist/core/dev/generate/routes/util.server.js +8 -21
  70. package/dist/core/dev/generate/types/index.server.js +5 -3
  71. package/dist/core/dev/vite/index.server.js +1 -1
  72. package/dist/core/errors/handler.server.d.ts +22 -1
  73. package/dist/core/errors/handler.server.js +25 -2
  74. package/dist/core/errors/index.d.ts +0 -1
  75. package/dist/core/errors/index.js +0 -1
  76. package/dist/core/fields/util.d.ts +1 -1
  77. package/dist/core/handlers/routes.server.d.ts +70 -1
  78. package/dist/core/handlers/routes.server.js +55 -1
  79. package/dist/core/operations/hooks/before-upsert/data-config-map.server.d.ts +1 -1
  80. package/dist/core/operations/hooks/before-upsert/handle-new-version.server.d.ts +1 -1
  81. package/dist/core/operations/hooks/before-upsert/original-config-map.server.d.ts +1 -1
  82. package/dist/core/operations/hooks/before-upsert/set-default-values.server.d.ts +1 -1
  83. package/dist/core/operations/hooks/before-upsert/validate-fields.server.d.ts +1 -1
  84. package/dist/core/plugins/api-init/index.server.js +10 -5
  85. package/dist/core/plugins/cache/cache.server.js +1 -1
  86. package/dist/core/rime.server.d.ts +10 -10
  87. package/dist/core/rime.server.js +5 -1
  88. package/dist/fields/checkbox/index.server.js +1 -1
  89. package/dist/fields/combobox/index.server.js +1 -1
  90. package/dist/fields/date/index.server.js +1 -1
  91. package/dist/fields/email/index.js +1 -1
  92. package/dist/fields/email/index.server.js +1 -1
  93. package/dist/fields/link/component/RessourceInput.svelte +1 -1
  94. package/dist/fields/link/index.d.ts +1 -1
  95. package/dist/fields/link/index.js +1 -1
  96. package/dist/fields/link/index.server.js +1 -1
  97. package/dist/fields/number/index.server.js +1 -1
  98. package/dist/fields/radio/index.server.js +1 -1
  99. package/dist/fields/relation/client.d.ts +1 -1
  100. package/dist/fields/relation/client.js +1 -1
  101. package/dist/fields/relation/component/Cell.svelte +1 -1
  102. package/dist/fields/relation/component/Relation.svelte +1 -1
  103. package/dist/fields/relation/component/upload/Browse.svelte +1 -1
  104. package/dist/fields/relation/index.d.ts +1 -1
  105. package/dist/fields/relation/index.js +2 -2
  106. package/dist/fields/relation/index.server.js +1 -1
  107. package/dist/fields/rich-text/core/features/fields/extension.d.ts +2 -2
  108. package/dist/fields/rich-text/core/features/link/component/link-selector.svelte +1 -1
  109. package/dist/fields/rich-text/core/features/resource/resource-extension.d.ts +1 -1
  110. package/dist/fields/rich-text/core/features/resource/resource.svelte +1 -1
  111. package/dist/fields/rich-text/core/features/upload/upload-extension.d.ts +1 -1
  112. package/dist/fields/rich-text/core/features/upload/upload.svelte +1 -1
  113. package/dist/fields/rich-text/index.js +4 -2
  114. package/dist/fields/rich-text/index.server.js +1 -1
  115. package/dist/fields/select/index.server.js +1 -1
  116. package/dist/fields/slug/index.server.js +1 -1
  117. package/dist/fields/text/index.server.js +1 -1
  118. package/dist/fields/textarea/index.server.js +1 -1
  119. package/dist/fields/time/index.server.js +1 -1
  120. package/dist/fields/toggle/index.server.js +1 -1
  121. package/dist/index.d.ts +8 -3
  122. package/dist/index.js +7 -3
  123. package/dist/panel/components/sections/collection/folder/FolderWithActions.svelte +1 -1
  124. package/dist/panel/components/sections/document/ButtonStatus.svelte +1 -1
  125. package/dist/panel/components/sections/document/CurrentlyEdited.svelte +1 -1
  126. package/dist/panel/components/sections/document/Settings.svelte +1 -1
  127. package/dist/panel/context/collection.svelte.js +1 -1
  128. package/dist/panel/context/documentForm.svelte.js +1 -2
  129. package/dist/panel/context/form.svelte.d.ts +2 -0
  130. package/dist/panel/context/form.svelte.js +8 -2
  131. package/dist/panel/context/live.svelte.js +1 -1
  132. package/dist/panel/index.d.ts +9 -1
  133. package/dist/panel/index.js +7 -1
  134. package/dist/panel/pages/area/actions.server.d.ts +2 -21
  135. package/dist/panel/pages/area/actions.server.js +28 -27
  136. package/dist/panel/pages/area/load.server.d.ts +2 -17
  137. package/dist/panel/pages/area/load.server.js +37 -46
  138. package/dist/panel/pages/auth/sign-in/SignIn.svelte +7 -1
  139. package/dist/panel/pages/collection/load.server.d.ts +6 -6
  140. package/dist/panel/pages/collection/load.server.js +70 -72
  141. package/dist/panel/pages/collection-document/actions.server.d.ts +1 -1
  142. package/dist/panel/pages/collection-document/actions.server.js +78 -70
  143. package/dist/panel/pages/collection-document/load.server.d.ts +5 -20
  144. package/dist/panel/pages/collection-document/load.server.js +80 -82
  145. package/dist/server.d.ts +7 -0
  146. package/dist/server.js +7 -0
  147. package/dist/types.d.ts +1 -0
  148. package/dist/util/index.d.ts +9 -1
  149. package/dist/util/index.js +12 -1
  150. package/package.json +6 -49
  151. package/dist/core/api/index.d.ts +0 -7
  152. package/dist/core/api/index.js +0 -10
  153. package/dist/core/api/index.server.d.ts +0 -3
  154. package/dist/core/api/index.server.js +0 -3
  155. package/dist/core/areas/api/get.server.js +0 -36
  156. package/dist/core/areas/api/index.server.d.ts +0 -7
  157. package/dist/core/areas/api/index.server.js +0 -4
  158. package/dist/core/areas/api/update.server.js +0 -33
  159. package/dist/core/collections/api/create.server.js +0 -29
  160. package/dist/core/collections/api/delete.server.js +0 -32
  161. package/dist/core/collections/api/deleteById.server.js +0 -16
  162. package/dist/core/collections/api/duplicate.server.js +0 -18
  163. package/dist/core/collections/api/get.server.js +0 -45
  164. package/dist/core/collections/api/getById.server.js +0 -30
  165. package/dist/core/collections/api/index.server.d.ts +0 -17
  166. package/dist/core/collections/api/index.server.js +0 -9
  167. package/dist/core/collections/api/updateById.server.js +0 -38
  168. package/dist/core/dev/cli/init/get-package-info.server.d.ts +0 -1
  169. package/dist/core/dev/cli/init/package-manager-util.server.d.ts +0 -3
  170. package/dist/core/dev/generate/routes/area.server.d.ts +0 -7
  171. package/dist/core/dev/generate/routes/area.server.js +0 -69
  172. package/dist/core/dev/generate/routes/collection.server.d.ts +0 -14
  173. package/dist/core/dev/generate/routes/collection.server.js +0 -129
  174. package/dist/live.d.ts +0 -4
  175. package/dist/live.js +0 -4
  176. package/dist/panel/index.server.d.ts +0 -4
  177. package/dist/panel/index.server.js +0 -4
  178. package/dist/panel/pages/auth/index.d.ts +0 -4
  179. package/dist/panel/pages/auth/index.js +0 -4
  180. package/dist/panel/pages/auth/index.server.d.ts +0 -18
  181. package/dist/panel/pages/auth/index.server.js +0 -12
  182. package/dist/panel/pages/index.actions.server.d.ts +0 -13
  183. package/dist/panel/pages/index.actions.server.js +0 -10
  184. package/dist/panel/pages/index.load.server.d.ts +0 -23
  185. package/dist/panel/pages/index.load.server.js +0 -16
  186. package/dist/panel/ui.d.ts +0 -4
  187. package/dist/panel/ui.js +0 -5
  188. /package/dist/core/dev/cli/{util.server.d.ts → util/prompt.server.d.ts} +0 -0
  189. /package/dist/core/dev/cli/{util.server.js → util/prompt.server.js} +0 -0
@@ -9,7 +9,7 @@ const DOLLAR_LIB = '$lib';
9
9
  */
10
10
  const mainLayout = () => `
11
11
  import type { ServerLoadEvent } from '@sveltejs/kit';
12
- export const load = async ({ locals, url }: ServerLoadEvent) => {
12
+ export const load = async ({ locals }: ServerLoadEvent) => {
13
13
  return { user: locals.user };
14
14
  };`;
15
15
  /**
@@ -50,8 +50,8 @@ const error = () => `
50
50
  const rootLayout = () => `
51
51
  <script lang="ts">
52
52
  import type { Snippet } from 'svelte';
53
- import type { Dictionaries } from '${PACKAGE_NAME}/i18n';
54
- import i18n from '${PACKAGE_NAME}/i18n';
53
+ import type { Dictionaries } from '${PACKAGE_NAME}';
54
+ import { i18n } from '${PACKAGE_NAME}';
55
55
  import '${PACKAGE_NAME}/panel/style/index.css';
56
56
 
57
57
  type Props = { children: Snippet; data: { translations: Dictionaries } };
@@ -71,7 +71,7 @@ const rootLayout = () => `
71
71
  */
72
72
  const rootLayoutServer = () => `
73
73
  import type { ServerLoadEvent } from '@sveltejs/kit';
74
- import { registerTranslation } from '${PACKAGE_NAME}/i18n/register.server.js';
74
+ import { registerTranslation } from '${PACKAGE_NAME}/server';
75
75
 
76
76
  export const ssr = false;
77
77
 
@@ -85,8 +85,8 @@ export const load = async ({ locals }: ServerLoadEvent) => {
85
85
  * (rime)/panel/sign-in/+page.svelte
86
86
  */
87
87
  const signInPage = () => `
88
- <script lang="ts">
89
- import { SignIn } from '${PACKAGE_NAME}/panel/auth/client';
88
+ <script>
89
+ import { SignIn } from '${PACKAGE_NAME}/panel';
90
90
  const { data } = $props();
91
91
  </script>
92
92
 
@@ -96,10 +96,12 @@ const signInPage = () => `
96
96
  * (rime)/auth/sign-in/+page@(rime).server.ts
97
97
  */
98
98
  const signInPageServer = () => `
99
- import { authLoads, authActions } from '${PACKAGE_NAME}/panel/auth';
99
+ import { type ServerLoadEvent, type RequestEvent } from '@sveltejs/kit';
100
100
 
101
- export const load = authLoads.signIn;
102
- export const actions = authActions.signIn;
101
+ export const load = (event: ServerLoadEvent) => event.locals.routes.panel.load.signIn(event);
102
+ export const actions = {
103
+ default: (event: RequestEvent) => event.locals.routes.panel.actions.signIn(event)
104
+ };
103
105
  `;
104
106
  /**
105
107
  * Forgot password page template
@@ -107,7 +109,7 @@ export const actions = authActions.signIn;
107
109
  */
108
110
  const forgotPasswordPage = () => `
109
111
  <script>
110
- import { ForgotPassword } from '${PACKAGE_NAME}/panel/auth/client'
112
+ import { ForgotPassword } from '${PACKAGE_NAME}/panel'
111
113
  const { data } = $props();
112
114
  </script>
113
115
  <ForgotPassword {data} />`;
@@ -116,17 +118,17 @@ const forgotPasswordPage = () => `
116
118
  * (rime)/forgot-password/+page.server.ts
117
119
  */
118
120
  const forgotPasswordPageServer = () => `
119
- import { authLoads } from '${PACKAGE_NAME}/panel/auth';
121
+ import { type ServerLoadEvent } from '@sveltejs/kit';
120
122
 
121
- export const load = authLoads.forgotPassword;
123
+ export const load = (event: ServerLoadEvent) => event.locals.routes.panel.load.forgotPassword(event);
122
124
  `;
123
125
  /**
124
126
  * Reset password page template
125
127
  * (rime)/reset-password/+page.svelte
126
128
  */
127
129
  const resetPasswordPage = () => `
128
- <script lang="ts">
129
- import { ResetPassword } from '${PACKAGE_NAME}/panel/auth/client';
130
+ <script>
131
+ import { ResetPassword } from '${PACKAGE_NAME}/panel';
130
132
  const { data } = $props();
131
133
  </script>
132
134
 
@@ -136,9 +138,9 @@ const resetPasswordPage = () => `
136
138
  * (rime)/reset-password/+page.server.ts
137
139
  */
138
140
  const resetPasswordPageServer = () => `
139
- import { authLoads } from '${PACKAGE_NAME}/panel/auth';
141
+ import { type ServerLoadEvent } from '@sveltejs/kit';
140
142
 
141
- export const load = authLoads.resetPassword;
143
+ export const load = (event: ServerLoadEvent) => event.locals.routes.panel.load.resetPassword(event);
142
144
  `;
143
145
  /**
144
146
  * Panel layout template
@@ -146,7 +148,7 @@ export const load = authLoads.resetPassword;
146
148
  */
147
149
  const panelLayout = () => `
148
150
  <script>
149
- import { Panel } from '${PACKAGE_NAME}/panel/client';
151
+ import { Panel } from '${PACKAGE_NAME}/panel';
150
152
  import config from '${DOLLAR_LIB}/${OUTPUT_DIR}/rime.config.js';
151
153
 
152
154
  const { children, data } = $props();
@@ -168,8 +170,8 @@ const panelLayoutServer = () => `
168
170
  import { type ServerLoadEvent } from '@sveltejs/kit';
169
171
 
170
172
  export const load = async ({ locals }: ServerLoadEvent) => {
171
- const { user, locale, routes } = locals;
172
- return { user, locale, routes };
173
+ const { user, locale, navigation } = locals;
174
+ return { user, locale, routes: navigation };
173
175
  };`;
174
176
  /**
175
177
  * Panel page template
@@ -177,7 +179,7 @@ export const load = async ({ locals }: ServerLoadEvent) => {
177
179
  */
178
180
  const panelPage = () => `
179
181
  <script>
180
- import { Dashboard } from '${PACKAGE_NAME}/panel/client';
182
+ import { Dashboard } from '${PACKAGE_NAME}/panel';
181
183
  const { data } = $props();
182
184
  </script>
183
185
 
@@ -187,18 +189,17 @@ const panelPage = () => `
187
189
  * (rime)/panel/+page.server.ts
188
190
  */
189
191
  const panelPageServer = () => `
190
- import { pagesLoad } from '${PACKAGE_NAME}/panel';
192
+ import { type ServerLoadEvent } from '@sveltejs/kit';
191
193
 
192
- export const load = pagesLoad.dashboard;`;
194
+ export const load = (event: ServerLoadEvent) => event.locals.routes.panel.load.dashboard(event);`;
193
195
  /**
194
196
  * Live page template
195
197
  * (rime)/live/+page.svelte
196
198
  */
197
199
  const livePage = () => `
198
- <script lang="ts">
199
- import { Live } from '${PACKAGE_NAME}/panel/client';
200
-
201
- import config from '../../../../lib/${OUTPUT_DIR}/rime.config.js';
200
+ <script>
201
+ import { Live } from '${PACKAGE_NAME}/panel';
202
+ import config from '${DOLLAR_LIB}/${OUTPUT_DIR}/rime.config.js';
202
203
 
203
204
  const { data } = $props();
204
205
  </script>
@@ -210,9 +211,192 @@ const livePage = () => `
210
211
  * (rime)/live/+page.server.ts
211
212
  */
212
213
  const livePageServer = () => `
213
- import { pagesLoad } from '${PACKAGE_NAME}/panel';
214
+ import { type ServerLoadEvent } from '@sveltejs/kit';
215
+
216
+ export const load = (event: ServerLoadEvent) => event.locals.routes.panel.load.live(event);`;
217
+ /****************************************************/
218
+ /* Panel /[slug=collection|area]/... and API /api/[slug=collection|area]/...
219
+ /* — fixed, generic, matcher-disambiguated routes shared by every
220
+ /* collection/area, generated once regardless of how many are configured.
221
+ /* The [slug=collection]/[slug=area] param matchers (src/params/, see
222
+ /* collectionMatcher/areaMatcher below) route each slug to the right folder
223
+ /* at the SvelteKit router level, so collection and area pages/endpoints are
224
+ /* genuinely separate routes — no runtime kind-branching inside a shared
225
+ /* component, no unauthenticated-branch union fighting the component's data
226
+ /* prop type. Each reads slug/id off event.params (a real dynamic route
227
+ /* param) via event.locals.routes, so none of these import anything from
228
+ /* rimecms besides the panel components.
229
+ /****************************************************/
230
+ /**
231
+ * Collection list page
232
+ * (rime)/panel/[slug=collection]/+page.svelte
233
+ */
234
+ const collectionListPage = () => `
235
+ <script>
236
+ import { Collection } from '${PACKAGE_NAME}/panel';
237
+ const { data } = $props();
238
+ </script>
239
+
240
+ <Collection {data} slug={data.slug} />`;
241
+ /**
242
+ * (rime)/panel/[slug=collection]/+page.server.ts
243
+ */
244
+ const collectionListPageServer = () => `
245
+ import { type ServerLoadEvent } from '@sveltejs/kit';
246
+
247
+ export const load = async (event: ServerLoadEvent) => {
248
+ const data = await event.locals.routes.panel.load.collection(event);
249
+ return { ...data, slug: event.params.slug || '' };
250
+ };`;
251
+ /**
252
+ * Area document page
253
+ * (rime)/panel/[slug=area]/+page.svelte
254
+ */
255
+ const areaDocPage = () => `
256
+ <script>
257
+ import { Area } from '${PACKAGE_NAME}/panel';
258
+ const { data } = $props();
259
+ </script>
260
+
261
+ <Area {data} />`;
262
+ /**
263
+ * (rime)/panel/[slug=area]/+page.server.ts
264
+ */
265
+ const areaDocPageServer = () => `
266
+ import type { RequestEvent, ServerLoadEvent } from '@sveltejs/kit';
267
+
268
+ export const load = (event: ServerLoadEvent) => event.locals.routes.panel.load.area(event);
269
+
270
+ export const actions = {
271
+ update: (event: RequestEvent) => event.locals.routes.panel.actions.area.update(event)
272
+ };`;
273
+ /**
274
+ * Collection document page
275
+ * (rime)/panel/[slug=collection]/[id]/+page.svelte
276
+ */
277
+ const collectionDocPage = () => `
278
+ <script>
279
+ import { CollectionDoc } from '${PACKAGE_NAME}/panel';
280
+ const { data } = $props();
281
+ </script>
282
+
283
+ <CollectionDoc {data} />`;
284
+ /**
285
+ * (rime)/panel/[slug=collection]/[id]/+page.server.ts
286
+ */
287
+ const collectionDocPageServer = () => `
288
+ import type { RequestEvent, ServerLoadEvent } from '@sveltejs/kit';
289
+
290
+ export const load = (event: ServerLoadEvent) => event.locals.routes.panel.load.document(event);
291
+
292
+ export const actions = {
293
+ create: (event: RequestEvent) => event.locals.routes.panel.actions.document.create(event),
294
+ update: (event: RequestEvent) => event.locals.routes.panel.actions.document.update(event)
295
+ };`;
296
+ /**
297
+ * Collection document versions page
298
+ * (rime)/panel/[slug=collection]/[id]/versions/+page.svelte
299
+ */
300
+ const collectionDocVersionsPage = () => `
301
+ <script>
302
+ import { CollectionDocVersions } from '${PACKAGE_NAME}/panel';
303
+ const { data } = $props();
304
+ </script>
305
+
306
+ <CollectionDocVersions data={data} />`;
307
+ /**
308
+ * (rime)/panel/[slug=collection]/[id]/versions/+page.server.ts
309
+ */
310
+ const collectionDocVersionsPageServer = () => `
311
+ import { type ServerLoadEvent } from '@sveltejs/kit';
312
+
313
+ export const load = (event: ServerLoadEvent) =>
314
+ event.locals.routes.panel.load.documentVersions(event);`;
315
+ /**
316
+ * Area document versions page
317
+ * (rime)/panel/[slug=area]/versions/+page.svelte
318
+ */
319
+ const areaVersionsPage = () => `
320
+ <script>
321
+ import { AreaVersionsDoc } from '${PACKAGE_NAME}/panel';
322
+ const { data } = $props();
323
+ </script>
324
+
325
+ <AreaVersionsDoc data={data} />`;
326
+ /**
327
+ * (rime)/panel/[slug=area]/versions/+page.server.ts
328
+ */
329
+ const areaVersionsPageServer = () => `
330
+ import { type ServerLoadEvent } from '@sveltejs/kit';
331
+
332
+ export const load = (event: ServerLoadEvent) => event.locals.routes.panel.load.areaVersions(event);`;
333
+ /**
334
+ * Collection REST endpoint (list-level)
335
+ * (rime)/api/[slug=collection]/+server.ts
336
+ */
337
+ const collectionApiServer = () => `
338
+ import { type RequestEvent } from '@sveltejs/kit';
339
+
340
+ export const GET = (event: RequestEvent) => event.locals.routes.rest.collection.get(event);
341
+ export const POST = (event: RequestEvent) => event.locals.routes.rest.collection.create(event);
342
+ export const DELETE = (event: RequestEvent) => event.locals.routes.rest.collection.delete(event);`;
343
+ /**
344
+ * Area REST endpoint — singleton, no [id] tier: GET reads it, PATCH updates
345
+ * it, no create/delete (areas are config-defined, not created/removed via API).
346
+ * (rime)/api/[slug=area]/+server.ts
347
+ */
348
+ const areaApiServer = () => `
349
+ import { type RequestEvent } from '@sveltejs/kit';
214
350
 
215
- export const load = pagesLoad.live;`;
351
+ export const GET = (event: RequestEvent) => event.locals.routes.rest.area.get(event);
352
+ export const PATCH = (event: RequestEvent) => event.locals.routes.rest.area.update(event);`;
353
+ /**
354
+ * Collection REST endpoint (id-level)
355
+ * (rime)/api/[slug=collection]/[id]/+server.ts
356
+ */
357
+ const collectionIdApiServer = () => `
358
+ import { type RequestEvent } from '@sveltejs/kit';
359
+
360
+ export const GET = (event: RequestEvent) => event.locals.routes.rest.collection.getById(event);
361
+ export const PATCH = (event: RequestEvent) => event.locals.routes.rest.collection.updateById(event);
362
+ export const DELETE = (event: RequestEvent) => event.locals.routes.rest.collection.deleteById(event);`;
363
+ /**
364
+ * Collection duplicate action
365
+ * (rime)/api/[slug=collection]/[id]/duplicate/+server.ts
366
+ */
367
+ const collectionDuplicateApiServer = () => `
368
+ import { type RequestEvent } from '@sveltejs/kit';
369
+
370
+ export const POST = (event: RequestEvent) => event.locals.routes.rest.collection.duplicate(event);`;
371
+ /**
372
+ * Param matchers backing [slug=collection]/[slug=area] — bake in the actual
373
+ * configured slug list at generation time so they stay isomorphic (no
374
+ * server-only config import; SvelteKit resolves matchers on the client too
375
+ * for client-side navigation), same approach as this repo's own hand-written
376
+ * src/params/news.ts, lang.ts.
377
+ * src/params/collection.ts, src/params/area.ts
378
+ */
379
+ const paramMatcher = (slugs) => `
380
+ import type { ParamMatcher } from '@sveltejs/kit';
381
+
382
+ const slugs = ${JSON.stringify(slugs)} as const;
383
+
384
+ export const match: ParamMatcher = (param): param is (typeof slugs)[number] =>
385
+ (slugs as readonly string[]).includes(param);`;
386
+ /**
387
+ * Catch-all so /api/* stays a literal, static-prefixed SvelteKit route —
388
+ * without it, an unmatched /api/* request (unknown slug, wrong shape) would
389
+ * fall through to the next candidate in the manifest, e.g. the public site's
390
+ * (front)/[[locale]]/[[id]] route, silently binding garbage params instead
391
+ * of 404ing.
392
+ * (rime)/api/[...rest]/+server.ts
393
+ */
394
+ const apiCatchAllServer = () => `
395
+ import { error } from '@sveltejs/kit';
396
+
397
+ export const fallback = async () => {
398
+ throw error(404);
399
+ };`;
216
400
  /**
217
401
  * Custom route template generator
218
402
  * Used for generating custom routes
@@ -276,6 +460,41 @@ export const commonRoutes = {
276
460
  '(rime)/panel/live-edit': {
277
461
  'page@(rime)': livePage,
278
462
  pageServer: livePageServer
463
+ },
464
+ '(rime)/panel/[slug=collection]': {
465
+ page: collectionListPage,
466
+ pageServer: collectionListPageServer
467
+ },
468
+ '(rime)/panel/[slug=collection]/[id]': {
469
+ page: collectionDocPage,
470
+ pageServer: collectionDocPageServer
471
+ },
472
+ '(rime)/panel/[slug=collection]/[id]/versions': {
473
+ page: collectionDocVersionsPage,
474
+ pageServer: collectionDocVersionsPageServer
475
+ },
476
+ '(rime)/panel/[slug=area]': {
477
+ page: areaDocPage,
478
+ pageServer: areaDocPageServer
479
+ },
480
+ '(rime)/panel/[slug=area]/versions': {
481
+ page: areaVersionsPage,
482
+ pageServer: areaVersionsPageServer
483
+ },
484
+ '(rime)/api/[slug=collection]': {
485
+ server: collectionApiServer
486
+ },
487
+ '(rime)/api/[slug=collection]/[id]': {
488
+ server: collectionIdApiServer
489
+ },
490
+ '(rime)/api/[slug=collection]/[id]/duplicate': {
491
+ server: collectionDuplicateApiServer
492
+ },
493
+ '(rime)/api/[slug=area]': {
494
+ server: areaApiServer
495
+ },
496
+ '(rime)/api/[...rest]': {
497
+ server: apiCatchAllServer
279
498
  }
280
499
  };
281
- export { customRoute };
500
+ export { customRoute, paramMatcher };
@@ -1,6 +1,12 @@
1
1
  import type { Config } from '../../../../types.js';
2
2
  /**
3
- * Main function to generate browser routes based on configuration
3
+ * Main function to generate browser routes based on configuration.
4
+ * commonRoutes is a fixed set of files (layout, sign-in, dashboard, the
5
+ * matcher-disambiguated /panel/[slug=collection|area]/... and
6
+ * /api/[slug=collection|area]/... dynamic routes) — it no longer varies with
7
+ * how many collections/areas are configured, so there's no per-collection/area
8
+ * loop here anymore. The src/params/collection.ts and area.ts matchers backing
9
+ * those routes DO bake in the actual slug list, so they're rewritten here too.
4
10
  */
5
11
  declare function generateRoutes<T extends Config>(config: T): void;
6
12
  export default generateRoutes;
@@ -1,20 +1,21 @@
1
1
  import { logger } from '../../../logger/index.server.js';
2
- import { withDirectoriesSuffix, withVersionsSuffix } from '../../../naming.js';
3
2
  import fs from 'fs';
4
3
  import path from 'path';
5
- import { areaAPIRoutes, areaRoutes, areaVersionsPanelRoutes } from './area.server.js';
6
- import { collectionAPIRoutes, collectionPanelRoutes, collectionVersionsPanelRoutes } from './collection.server.js';
7
- import { commonRoutes, customRoute } from './common.server.js';
4
+ import { commonRoutes, customRoute, paramMatcher } from './common.server.js';
8
5
  import { injectCustomCSS, removeCustomCSS } from './custom-css.server.js';
9
6
  import { ensureDir, shouldRegenerateRoutes, writeRouteFile } from './util.server.js';
10
7
  const projectRoot = process.cwd();
11
8
  /**
12
- * Main function to generate browser routes based on configuration
9
+ * Main function to generate browser routes based on configuration.
10
+ * commonRoutes is a fixed set of files (layout, sign-in, dashboard, the
11
+ * matcher-disambiguated /panel/[slug=collection|area]/... and
12
+ * /api/[slug=collection|area]/... dynamic routes) — it no longer varies with
13
+ * how many collections/areas are configured, so there's no per-collection/area
14
+ * loop here anymore. The src/params/collection.ts and area.ts matchers backing
15
+ * those routes DO bake in the actual slug list, so they're rewritten here too.
13
16
  */
14
17
  function generateRoutes(config) {
15
18
  logger.info('Routes generation...');
16
- const areas = (config.areas || []).filter((a) => a._generateRoutes !== false);
17
- const collections = (config.collections || []).filter((c) => c._generateRoutes !== false);
18
19
  // 1. Check if routes need to be regenerated
19
20
  if (!shouldRegenerateRoutes(config)) {
20
21
  return;
@@ -23,62 +24,22 @@ function generateRoutes(config) {
23
24
  const rootRoutes = path.resolve(projectRoot, 'src', 'routes');
24
25
  const rimeRoutes = path.join(rootRoutes, '(rime)');
25
26
  const panelRoute = path.join(rimeRoutes, 'panel');
27
+ const paramsDir = path.resolve(projectRoot, 'src', 'params');
26
28
  fs.rmSync(rimeRoutes, { recursive: true, force: true });
27
29
  ensureDir(rootRoutes);
28
30
  ensureDir(rimeRoutes);
29
31
  ensureDir(panelRoute);
30
- // Function that generate area/collection routes files from a Routes object
31
- const processRoutes = (slug, kebab, routes) => {
32
- for (const [pattern, files] of Object.entries(routes)) {
33
- const routePath = pattern.replace('{area.kebab}', kebab).replace('{collection.kebab}', kebab);
34
- // Generate each file type (page, layout, etc.)
35
- for (const [fileType, templateFn] of Object.entries(files)) {
36
- writeRouteFile(rootRoutes, routePath, fileType, templateFn(slug));
37
- }
38
- }
39
- };
40
- // 3. Process common routes
32
+ ensureDir(paramsDir);
33
+ // 3. Process common routes (now includes the matcher-disambiguated [slug=collection|area] routes)
41
34
  for (const [pattern, files] of Object.entries(commonRoutes)) {
42
35
  for (const [fileType, templateFn] of Object.entries(files)) {
43
36
  writeRouteFile(rootRoutes, pattern, fileType, templateFn());
44
37
  }
45
38
  }
46
- // 4. Process area routes
47
- for (const area of areas) {
48
- processRoutes(area.slug, area.kebab, areaRoutes);
49
- processRoutes(area.slug, area.kebab, areaAPIRoutes);
50
- if (area.versions) {
51
- processRoutes(area.slug, area.kebab, areaVersionsPanelRoutes);
52
- // Use collections API route as area_versions is a collection
53
- processRoutes(withVersionsSuffix(area.slug), withVersionsSuffix(area.kebab), collectionAPIRoutes);
54
- }
55
- }
56
- // 5. Process collection routes
57
- for (const collection of collections) {
58
- // Function that generate routes files
59
- const processRoutes = (slug, kebab, routes) => {
60
- for (const [pattern, files] of Object.entries(routes)) {
61
- const routePath = pattern.replace('{collection.kebab}', kebab);
62
- // Generate each file type (page, layout, etc.)
63
- for (const [fileType, templateFn] of Object.entries(files)) {
64
- // Check if function takes parameters before calling it
65
- const content = templateFn.length > 0 ? templateFn(slug) : templateFn();
66
- writeRouteFile(rootRoutes, routePath, fileType, content);
67
- }
68
- }
69
- };
70
- // Panel routes
71
- processRoutes(collection.slug, collection.kebab, collectionPanelRoutes);
72
- processRoutes(collection.slug, collection.kebab, collectionAPIRoutes);
73
- if (collection.versions) {
74
- processRoutes(collection.slug, collection.kebab, collectionVersionsPanelRoutes);
75
- processRoutes(withVersionsSuffix(collection.slug), withVersionsSuffix(collection.kebab), collectionAPIRoutes);
76
- }
77
- if (collection.upload) {
78
- processRoutes(withDirectoriesSuffix(collection.slug), withDirectoriesSuffix(collection.kebab), collectionAPIRoutes);
79
- }
80
- }
81
- // 6. Handle custom routes from config
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)));
42
+ // 5. Handle custom routes from config
82
43
  const customRoutes = config.panel?.routes;
83
44
  if (customRoutes) {
84
45
  for (const [route, routeConfig] of Object.entries(customRoutes)) {
@@ -86,7 +47,7 @@ function generateRoutes(config) {
86
47
  writeRouteFile(rootRoutes, routePath, 'page', customRoute(routeConfig));
87
48
  }
88
49
  }
89
- // 7. Handle custom CSS in layout file
50
+ // 6. Handle custom CSS in layout file
90
51
  const layoutPath = path.join(rimeRoutes, '+layout.svelte');
91
52
  if (fs.existsSync(layoutPath)) {
92
53
  if (config.panel?.css) {
@@ -6,13 +6,13 @@ export type RouteTemplateFunction<T extends any[] = any[]> = (...args: T) => str
6
6
  export type RouteDefinition = Record<string, RouteTemplateFunction>;
7
7
  export type Routes = Record<string, RouteDefinition>;
8
8
  /**
9
- * Check if routes need to be regenerated based on config changes
9
+ * Check if routes need to be regenerated based on config changes.
10
+ * Panel/API routes are a fixed set of dynamic-segment files (file count never
11
+ * grows with schema size), but the [slug=collection]/[slug=area] param
12
+ * matchers under src/params/ bake in the actual slug lists, so adding,
13
+ * removing, or renaming a collection/area still needs a regen to keep those
14
+ * matchers in sync — same trigger as custom routes and panel CSS.
10
15
  * @returns true if routes should be regenerated, false otherwise
11
- * @example
12
- * // Check if routes need to be regenerated
13
- * const config = { areas: [], collections: [], panel: { css: 'styles.css' } };
14
- * const needsRegeneration = shouldRegenerateRoutes(config);
15
- * // If the config has changed since last run, needsRegeneration will be true
16
16
  */
17
17
  export declare function shouldRegenerateRoutes<T extends Config>(config: T): boolean;
18
18
  /**
@@ -40,13 +40,3 @@ export declare function ensureDir(dirPath: string): void;
40
40
  * // Creates /path/to/src/routes/(rime)/panel/news/+page.svelte with the provided content
41
41
  */
42
42
  export declare function writeRouteFile(basePath: string, routePath: string, fileType: string, content: string): void;
43
- /**
44
- * Cast slug in generated templates for document with versions
45
- * in order to prevent TS error that slug_versions is not a collection/area
46
- *
47
- * @example
48
- * castVersionSlug('pages_versions')
49
- * // output : 'pages_versions' as any
50
- * export const GET = api.collection.get('pages_versions' as any)
51
- */
52
- export declare const TScastVersionSlug: (slug: string) => string;
@@ -1,29 +1,26 @@
1
1
  import cache from '../../cache/index.server.js';
2
- import { hasDirectoriesSuffix, hasVersionsSuffix } from '../../../naming.js';
3
2
  import { slugify } from '../../../../util/string.js';
4
3
  import fs from 'fs';
5
4
  import path from 'path';
6
5
  /**
7
- * Check if routes need to be regenerated based on config changes
6
+ * Check if routes need to be regenerated based on config changes.
7
+ * Panel/API routes are a fixed set of dynamic-segment files (file count never
8
+ * grows with schema size), but the [slug=collection]/[slug=area] param
9
+ * matchers under src/params/ bake in the actual slug lists, so adding,
10
+ * removing, or renaming a collection/area still needs a regen to keep those
11
+ * matchers in sync — same trigger as custom routes and panel CSS.
8
12
  * @returns true if routes should be regenerated, false otherwise
9
- * @example
10
- * // Check if routes need to be regenerated
11
- * const config = { areas: [], collections: [], panel: { css: 'styles.css' } };
12
- * const needsRegeneration = shouldRegenerateRoutes(config);
13
- * // If the config has changed since last run, needsRegeneration will be true
14
13
  */
15
14
  export function shouldRegenerateRoutes(config) {
16
- const versionsSuffix = (document) => (document.versions ? '.v' : '');
17
- const authSuffix = (collection) => collection.auth ? `.${collection.auth.type}` : '';
18
15
  const memo = `
19
- areas:${(config.areas || []).map((area) => `${area.slug}${versionsSuffix(area)}`).join(',')}
20
- collections:${(config.collections || []).map((collection) => `${collection.slug}${authSuffix(collection)}${versionsSuffix(collection)}`).join(',')}
21
16
  custom:${config.panel?.routes
22
17
  ? Object.entries(config.panel.routes)
23
18
  .map(([k, v]) => `${k}-${slugify(v.component.toString())}`)
24
19
  .join(',')
25
20
  : ''}
26
21
  css:${config.panel?.css ? config.panel.css : 'none'}
22
+ collections:${(config.collections || []).map((c) => c.slug).join(',')}
23
+ areas:${(config.areas || []).map((a) => a.slug).join(',')}
27
24
  `;
28
25
  const cachedMemo = cache.get('routes');
29
26
  if (cachedMemo && cachedMemo === memo) {
@@ -102,13 +99,3 @@ export function writeRouteFile(basePath, routePath, fileType, content) {
102
99
  }
103
100
  fs.writeFileSync(path.join(dir, fileName), content);
104
101
  }
105
- /**
106
- * Cast slug in generated templates for document with versions
107
- * in order to prevent TS error that slug_versions is not a collection/area
108
- *
109
- * @example
110
- * castVersionSlug('pages_versions')
111
- * // output : 'pages_versions' as any
112
- * export const GET = api.collection.get('pages_versions' as any)
113
- */
114
- export const TScastVersionSlug = (slug) => hasVersionsSuffix(slug) || hasDirectoriesSuffix(slug) ? `'${slug}' as any` : `'${slug}'`;
@@ -146,7 +146,7 @@ export async function generateTypesString(config) {
146
146
  const treeBlocksTypes = [];
147
147
  const registeredBlocks = [];
148
148
  const registeredTreeBlocks = [];
149
- let imports = new Set(['BaseDoc', 'Navigation', 'User']);
149
+ let imports = new Set(['BaseDoc', 'Navigation', 'RouteHandlers', 'User']);
150
150
  const addImport = (string) => {
151
151
  imports = new Set([...imports, string]);
152
152
  };
@@ -297,8 +297,10 @@ export async function generateTypesString(config) {
297
297
  >;
298
298
  /** Flag enabled by the core plugin rime.cache when the API cache is ON */
299
299
  cacheEnabled: boolean;
300
- /** Available in panel, routes for sidebar */
301
- routes: Navigation;
300
+ /** Available in panel, nav routes for sidebar */
301
+ navigation: Navigation;
302
+ /** Dispatch facade backing the fixed /panel/[slug]/... and /api/[slug]/... routes */
303
+ routes: RouteHandlers;
302
304
  /**
303
305
  * Current locale if applicable
304
306
  * set following this prioroty :
@@ -98,7 +98,7 @@ export function rime() {
98
98
  load(id) {
99
99
  const isServer = this.environment?.config?.consumer === 'server';
100
100
  if (id === resolvedVModule(VCoreId)) {
101
- const corePath = isServer ? 'rimecms/config/server' : 'rimecms/config/client';
101
+ const corePath = isServer ? 'rimecms/config/server' : 'rimecms/config';
102
102
  return `export * from '${corePath}';`;
103
103
  }
104
104
  if (id === resolvedVModule(VSchemaId) && isServer) {
@@ -2,13 +2,34 @@ export declare const ERROR_CONTEXT: {
2
2
  readonly ACTION: "action";
3
3
  readonly API: "api";
4
4
  readonly LOAD: "load";
5
- readonly HANDLER: "handler";
6
5
  };
7
6
  export type ErrorContext = (typeof ERROR_CONTEXT)[keyof typeof ERROR_CONTEXT];
8
7
  type ErrorHandlerOptions = {
9
8
  context: ErrorContext;
10
9
  formData?: Record<string, any>;
11
10
  };
11
+ /**
12
+ * Only called at the route boundary: +server.ts handlers, load functions,
13
+ * form actions. Everywhere else, just `throw new RimeError(...)` (centralizes
14
+ * error codes/messages) — it bubbles up and gets caught here, where `context`
15
+ * tells this function which SvelteKit primitive to translate it into:
16
+ * `error()` (api/load), `redirect()`, or `fail()` (action form errors).
17
+ *
18
+ * Always call it as `return handleError(...)`. Most branches throw internally
19
+ * (`error`/`redirect`), so `return` never runs — but the `fail()` branch (form
20
+ * errors in actions) is a real return value, so `return` is required there.
21
+ *
22
+ * @example +server.ts endpoint
23
+ * if (!id) return handleError(new RimeError(RimeError.NOT_FOUND), { context: ERROR_CONTEXT.API });
24
+ *
25
+ * @example load function
26
+ * const [err, doc] = await trycatch(() => getDoc(id));
27
+ * if (err) return handleError(err, { context: ERROR_CONTEXT.LOAD });
28
+ *
29
+ * @example form action
30
+ * const [err] = await trycatch(() => save(data));
31
+ * if (err) return handleError(err, { context: ERROR_CONTEXT.ACTION, formData: data });
32
+ */
12
33
  export declare function handleError(err: Error, options: ErrorHandlerOptions): import("@sveltejs/kit").ActionFailure<{
13
34
  form: Record<string, any>;
14
35
  errors: import("../../types.js").FormErrors;