@aphexcms/cms-core 5.0.3 → 5.1.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 (56) hide show
  1. package/dist/components/AdminApp.svelte +3 -9
  2. package/dist/components/AdminApp.svelte.d.ts.map +1 -1
  3. package/dist/components/admin/DocumentEditor.svelte +7 -3
  4. package/dist/components/admin/DocumentEditor.svelte.d.ts.map +1 -1
  5. package/dist/components/admin/ObjectModal.svelte +1 -1
  6. package/dist/components/admin/fields/ArrayField.svelte +23 -14
  7. package/dist/components/admin/fields/ArrayField.svelte.d.ts.map +1 -1
  8. package/dist/components/admin/fields/FileField.svelte +15 -4
  9. package/dist/components/admin/fields/FileField.svelte.d.ts.map +1 -1
  10. package/dist/components/admin/fields/ImageField.svelte +19 -4
  11. package/dist/components/admin/fields/ImageField.svelte.d.ts.map +1 -1
  12. package/dist/components/admin/fields/ReferenceField.svelte +26 -9
  13. package/dist/components/admin/fields/ReferenceField.svelte.d.ts.map +1 -1
  14. package/dist/hooks.d.ts +11 -0
  15. package/dist/hooks.d.ts.map +1 -1
  16. package/dist/hooks.js +39 -22
  17. package/dist/lib/hooks.d.ts +11 -0
  18. package/dist/lib/hooks.d.ts.map +1 -1
  19. package/dist/lib/hooks.js +39 -22
  20. package/dist/lib/hooks.js.map +1 -1
  21. package/dist/lib/schema-utils/validator.d.ts.map +1 -1
  22. package/dist/lib/schema-utils/validator.js +10 -7
  23. package/dist/lib/schema-utils/validator.js.map +1 -1
  24. package/dist/lib/server/api/routes/organizations-members.d.ts.map +1 -1
  25. package/dist/lib/server/api/routes/organizations-members.js +11 -0
  26. package/dist/lib/server/api/routes/organizations-members.js.map +1 -1
  27. package/dist/lib/server/index.d.ts +1 -1
  28. package/dist/lib/server/index.d.ts.map +1 -1
  29. package/dist/lib/server/index.js +1 -1
  30. package/dist/lib/server/index.js.map +1 -1
  31. package/dist/lib/types/schemas.d.ts +2 -0
  32. package/dist/lib/types/schemas.d.ts.map +1 -1
  33. package/dist/lib/utils/preview.d.ts +20 -0
  34. package/dist/lib/utils/preview.d.ts.map +1 -0
  35. package/dist/lib/utils/preview.js +68 -0
  36. package/dist/lib/utils/preview.js.map +1 -0
  37. package/dist/lib/vite/index.d.ts +86 -0
  38. package/dist/lib/vite/index.d.ts.map +1 -0
  39. package/dist/lib/vite/index.js +270 -0
  40. package/dist/lib/vite/index.js.map +1 -0
  41. package/dist/schema-utils/validator.d.ts.map +1 -1
  42. package/dist/schema-utils/validator.js +10 -7
  43. package/dist/server/api/routes/organizations-members.d.ts.map +1 -1
  44. package/dist/server/api/routes/organizations-members.js +11 -0
  45. package/dist/server/index.d.ts +1 -1
  46. package/dist/server/index.d.ts.map +1 -1
  47. package/dist/server/index.js +1 -1
  48. package/dist/types/schemas.d.ts +2 -0
  49. package/dist/types/schemas.d.ts.map +1 -1
  50. package/dist/utils/preview.d.ts +20 -0
  51. package/dist/utils/preview.d.ts.map +1 -0
  52. package/dist/utils/preview.js +67 -0
  53. package/dist/vite/index.d.ts +86 -0
  54. package/dist/vite/index.d.ts.map +1 -0
  55. package/dist/vite/index.js +269 -0
  56. package/package.json +5 -1
@@ -0,0 +1,269 @@
1
+ import { createRequire } from 'node:module';
2
+ const require = createRequire(import.meta.url);
3
+ /**
4
+ * Watches the CMS config and schema files in dev. When any of them change,
5
+ * the plugin re-loads `aphex.config.ts` via Vite's SSR loader (so the fresh
6
+ * module re-runs the schema imports) and hands the new config to cms-core's
7
+ * `__notifyAphexConfigChanged()` setter — the engine then re-initializes on
8
+ * the next request without restarting the Vite dev server.
9
+ *
10
+ * Why this works without races:
11
+ * - `server.ssrLoadModule` is Vite's official re-eval path, no cache-bust hacks
12
+ * - The plugin and the running SvelteKit hook share the same cms-core module
13
+ * instance through Vite's module graph, so the setter mutates the same
14
+ * `activeConfig` the hook reads on each request
15
+ * - A single mutation point (`__notifyAphexConfigChanged`) replaces the old
16
+ * global dirty-flag protocol; no two-step set-then-read race window
17
+ *
18
+ * Falls back to `server.restart()` automatically if the swap throws (e.g.
19
+ * the user introduced a syntax error in their schema). `mode: 'restart'`
20
+ * forces the slower-but-most-correct path on every change.
21
+ */
22
+ export function aphexHMR(options = {}) {
23
+ const schemaDir = options.schemaDir ?? '/schemaTypes/';
24
+ const configFile = options.configFile ?? 'aphex.config.ts';
25
+ const debounceMs = options.debounceMs ?? 150;
26
+ const mode = options.mode ?? 'swap';
27
+ return {
28
+ name: 'aphex:hmr',
29
+ configureServer(server) {
30
+ const { watcher, ws } = server;
31
+ function isReloadTarget(file) {
32
+ const normalized = file.replace(/\\/g, '/');
33
+ return ((normalized.includes(schemaDir) && normalized.endsWith('.ts')) ||
34
+ normalized.endsWith(`/${configFile}`));
35
+ }
36
+ async function swapSchemas(file) {
37
+ const start = Date.now();
38
+ const configPath = `${server.config.root}/${configFile}`;
39
+ // Invalidate the changed file + the config + the schemaTypes barrel
40
+ // so ssrLoadModule re-evaluates with the new disk contents.
41
+ for (const path of [file, configPath]) {
42
+ const mods = server.moduleGraph.getModulesByFile(path);
43
+ mods?.forEach((mod) => server.moduleGraph.invalidateModule(mod));
44
+ }
45
+ const configMod = await server.ssrLoadModule(configPath);
46
+ const freshConfig = configMod.default;
47
+ if (!freshConfig) {
48
+ throw new Error(`${configFile} did not export a default config`);
49
+ }
50
+ const cmsCore = await server.ssrLoadModule('@aphexcms/cms-core/server');
51
+ if (typeof cmsCore.__notifyAphexConfigChanged !== 'function') {
52
+ throw new Error('cms-core does not expose __notifyAphexConfigChanged — upgrade @aphexcms/cms-core');
53
+ }
54
+ cmsCore.__notifyAphexConfigChanged(freshConfig);
55
+ ws.send({ type: 'full-reload' });
56
+ console.log(`🔄 CMS schemas hot-swapped (${Date.now() - start}ms): ${file}`);
57
+ }
58
+ let pending = null;
59
+ let lastFile = '';
60
+ function scheduleReload(file) {
61
+ lastFile = file;
62
+ if (pending)
63
+ clearTimeout(pending);
64
+ pending = setTimeout(async () => {
65
+ pending = null;
66
+ if (mode === 'restart') {
67
+ console.log(`🔄 CMS schema change → restarting dev server: ${lastFile}`);
68
+ server.restart().catch((err) => {
69
+ console.error('[aphex] dev server restart failed:', err);
70
+ });
71
+ return;
72
+ }
73
+ try {
74
+ await swapSchemas(lastFile);
75
+ }
76
+ catch (err) {
77
+ console.error('[aphex] hot-swap failed, falling back to restart:', err);
78
+ server.restart().catch((err) => {
79
+ console.error('[aphex] dev server restart failed:', err);
80
+ });
81
+ }
82
+ }, debounceMs);
83
+ }
84
+ for (const event of ['change', 'add', 'unlink']) {
85
+ watcher.on(event, (file) => {
86
+ if (isReloadTarget(file))
87
+ scheduleReload(file);
88
+ });
89
+ }
90
+ }
91
+ };
92
+ }
93
+ /**
94
+ * Redirects `dayjs` and `dayjs/plugin/*` imports to dayjs's ESM build.
95
+ *
96
+ * dayjs 1.x ships a UMD `main` (`dayjs.min.js`) with no `exports` map or
97
+ * `module` field. When imports originate inside a package excluded from
98
+ * Vite's pre-bundling (e.g. `@aphexcms/cms-core`), Vite serves the raw UMD
99
+ * — which has no ESM `default` export — and the browser blows up with
100
+ * "does not provide an export named 'default'". This alias guarantees every
101
+ * dayjs import resolves to the proper ESM build.
102
+ */
103
+ function aphexDayjsAlias() {
104
+ return {
105
+ name: 'aphex:dayjs-alias',
106
+ config() {
107
+ const dayjsEsm = require.resolve('dayjs/esm/index.js');
108
+ const dayjsEsmPluginDir = dayjsEsm.replace(/\/index\.js$/, '/plugin');
109
+ return {
110
+ resolve: {
111
+ alias: [
112
+ { find: /^dayjs$/, replacement: dayjsEsm },
113
+ {
114
+ find: /^dayjs\/plugin\/([^/]+?)(\.js)?$/,
115
+ replacement: `${dayjsEsmPluginDir}/$1/index.js`
116
+ }
117
+ ]
118
+ }
119
+ };
120
+ }
121
+ };
122
+ }
123
+ /**
124
+ * SSR config: cms-core and ui packages re-export `.svelte` components through
125
+ * their entry barrels — Vite must bundle them for SSR. If they are externalised,
126
+ * Node's native ESM loader tries to resolve the raw `.svelte` files directly
127
+ * and throws ERR_UNKNOWN_FILE_EXTENSION (the `svelte` export condition is only
128
+ * honoured by Vite, not by Node).
129
+ *
130
+ * sharp/graphql/graphql-yoga are native or large CJS deps that should stay
131
+ * external — bundling them breaks Node's native bindings or balloons the SSR
132
+ * bundle.
133
+ */
134
+ function aphexSSR() {
135
+ return {
136
+ name: 'aphex:ssr',
137
+ config() {
138
+ return {
139
+ ssr: {
140
+ noExternal: ['@aphexcms/ui', '@aphexcms/cms-core'],
141
+ external: ['sharp', 'graphql', 'graphql-yoga']
142
+ }
143
+ };
144
+ }
145
+ };
146
+ }
147
+ /**
148
+ * optimizeDeps tuning: exclude the Aphex Svelte packages from esbuild
149
+ * pre-bundling (esbuild can't transform `.svelte` files; vite-plugin-svelte
150
+ * handles them at transform time instead), and pre-bundle their transitive
151
+ * deps that Vite would otherwise discover lazily at runtime — which causes
152
+ * full-page reloads when the user first navigates to a route that triggers
153
+ * a new dep.
154
+ */
155
+ function aphexOptimizeDeps() {
156
+ return {
157
+ name: 'aphex:optimize-deps',
158
+ config() {
159
+ return {
160
+ optimizeDeps: {
161
+ exclude: ['sharp', '@aphexcms/ui', '@aphexcms/cms-core'],
162
+ include: [
163
+ 'tailwind-variants',
164
+ 'tailwind-merge',
165
+ '@internationalized/date',
166
+ 'bits-ui',
167
+ 'dayjs',
168
+ 'dayjs/plugin/customParseFormat',
169
+ 'dayjs/plugin/utc',
170
+ '@lucide/svelte',
171
+ '@lucide/svelte/icons/panel-left',
172
+ '@lucide/svelte/icons/minus',
173
+ '@lucide/svelte/icons/circle',
174
+ '@lucide/svelte/icons/chevron-right',
175
+ '@lucide/svelte/icons/search',
176
+ '@lucide/svelte/icons/bot',
177
+ '@lucide/svelte/icons/calendar',
178
+ '@lucide/svelte/icons/check',
179
+ '@lucide/svelte/icons/chevron-down',
180
+ '@lucide/svelte/icons/chevron-left',
181
+ '@lucide/svelte/icons/chevron-up',
182
+ '@lucide/svelte/icons/chevrons-up-down',
183
+ '@lucide/svelte/icons/circle-check',
184
+ '@lucide/svelte/icons/info',
185
+ '@lucide/svelte/icons/loader-2',
186
+ '@lucide/svelte/icons/octagon-x',
187
+ '@lucide/svelte/icons/plus',
188
+ '@lucide/svelte/icons/triangle-alert',
189
+ '@lucide/svelte/icons/x',
190
+ 'better-auth/client/plugins',
191
+ 'better-auth/svelte',
192
+ 'mode-watcher',
193
+ 'svelte-sonner',
194
+ '@aphexcms/cms-core > @dnd-kit/helpers',
195
+ '@aphexcms/cms-core > @dnd-kit/svelte',
196
+ '@aphexcms/cms-core > @dnd-kit/svelte/sortable',
197
+ '@aphexcms/cms-core > dayjs',
198
+ '@aphexcms/cms-core > dayjs/plugin/customParseFormat',
199
+ '@aphexcms/cms-core > dayjs/plugin/utc'
200
+ ]
201
+ }
202
+ };
203
+ }
204
+ };
205
+ }
206
+ /**
207
+ * Vite's default watcher ignores `node_modules`. In a workspace setup where
208
+ * Aphex packages are linked from `node_modules/@aphexcms/*`, edits to those
209
+ * source files won't trigger HMR unless we explicitly un-ignore them.
210
+ */
211
+ function aphexWatchUnfilter() {
212
+ return {
213
+ name: 'aphex:watch-unfilter',
214
+ config() {
215
+ return {
216
+ server: {
217
+ watch: {
218
+ ignored: [
219
+ '!**/node_modules/@aphexcms/cms-core/**',
220
+ '!**/node_modules/@aphexcms/ui/**'
221
+ ]
222
+ }
223
+ }
224
+ };
225
+ }
226
+ };
227
+ }
228
+ /**
229
+ * One-stop Vite plugin for AphexCMS apps. Bundles:
230
+ *
231
+ * - schema HMR (restart-on-change)
232
+ * - dayjs ESM alias redirect
233
+ * - SSR noExternal/external defaults for cms-core/ui packages
234
+ * - optimizeDeps tuning so first-render isn't slowed by lazy dep discovery
235
+ * - watcher un-ignore for in-monorepo Aphex package edits
236
+ *
237
+ * Each piece can be opted out individually. Returns an array of plugins so
238
+ * Vite can attach each one separately and keep diagnostics readable.
239
+ *
240
+ * Usage:
241
+ *
242
+ * ```ts
243
+ * // vite.config.ts
244
+ * import { aphex } from '@aphexcms/cms-core/vite';
245
+ *
246
+ * export default defineConfig({
247
+ * plugins: [tailwindcss(), sveltekit(), aphex()]
248
+ * });
249
+ * ```
250
+ */
251
+ export function aphex(options = {}) {
252
+ const plugins = [];
253
+ if (options.hmr !== false) {
254
+ plugins.push(aphexHMR(options.hmr ?? {}));
255
+ }
256
+ if (options.dayjs !== false) {
257
+ plugins.push(aphexDayjsAlias());
258
+ }
259
+ if (options.ssr !== false) {
260
+ plugins.push(aphexSSR());
261
+ }
262
+ if (options.optimizeDeps !== false) {
263
+ plugins.push(aphexOptimizeDeps());
264
+ }
265
+ if (options.watch !== false) {
266
+ plugins.push(aphexWatchUnfilter());
267
+ }
268
+ return plugins;
269
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aphexcms/cms-core",
3
- "version": "5.0.3",
3
+ "version": "5.1.0",
4
4
  "description": "Aphex CMS Core - A Sanity-style CMS with ports and adapters architecture",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -36,6 +36,10 @@
36
36
  "types": "./dist/schema/index.d.ts",
37
37
  "default": "./dist/schema/index.js"
38
38
  },
39
+ "./vite": {
40
+ "types": "./dist/vite/index.d.ts",
41
+ "default": "./dist/vite/index.js"
42
+ },
39
43
  "./app-augment": {
40
44
  "types": "./dist/app-augment.d.ts",
41
45
  "default": "./dist/app-augment.js"