fimo 0.7.0-staging.1 → 0.7.0-staging.2

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 (143) hide show
  1. package/README.md +3 -2
  2. package/assets/skills/fimo/SKILL.md +1 -1
  3. package/assets/skills/fimo/references/assets.md +2 -2
  4. package/assets/skills/fimo/references/content.md +1 -1
  5. package/assets/skills/fimo/references/design.md +1 -1
  6. package/assets/skills/fimo-cli/SKILL.md +1 -1
  7. package/assets/skills/fimo-cli/references/assets.md +7 -24
  8. package/assets/skills/fimo-cli/references/content.md +2 -2
  9. package/assets/skills/fimo-cli/references/domains.md +1 -1
  10. package/assets/skills/fimo-cli/references/media.md +132 -142
  11. package/assets/skills/fimo-studio/references/custom-domains.md +1 -1
  12. package/dist/cli/bundle.json +3 -2
  13. package/dist/cli/index.js +1203 -110677
  14. package/dist/runtime/content/client/createContentClient.d.ts +5 -0
  15. package/dist/runtime/content/client/createContentClient.js +300 -0
  16. package/dist/runtime/content/client/createSingletonClient.d.ts +5 -0
  17. package/dist/runtime/content/client/createSingletonClient.js +108 -0
  18. package/dist/runtime/content/client/internal.d.ts +44 -0
  19. package/dist/runtime/content/client/internal.js +236 -0
  20. package/dist/runtime/content/client/types.d.ts +136 -0
  21. package/dist/runtime/content/client/useQueryLocale.d.ts +2 -0
  22. package/dist/runtime/content/client/useQueryLocale.js +6 -0
  23. package/dist/runtime/index.d.ts +3 -0
  24. package/dist/runtime/index.js +2 -0
  25. package/package.json +31 -13
  26. package/templates/react-router/package.json +1 -1
  27. package/templates/react-router/src/pages/Index.tsx +1 -1
  28. package/dist/build/vite/index.d.ts.map +0 -1
  29. package/dist/build/vite/plugins/content-sync.d.ts.map +0 -1
  30. package/dist/build/vite/plugins/content-sync.test.d.ts +0 -2
  31. package/dist/build/vite/plugins/content-sync.test.d.ts.map +0 -1
  32. package/dist/build/vite/plugins/content-sync.test.js +0 -64
  33. package/dist/build/vite/plugins/data-id.d.ts.map +0 -1
  34. package/dist/build/vite/plugins/fimo-config.d.ts.map +0 -1
  35. package/dist/build/vite/plugins/fimo-config.test.d.ts +0 -2
  36. package/dist/build/vite/plugins/fimo-config.test.d.ts.map +0 -1
  37. package/dist/build/vite/plugins/fimo-config.test.js +0 -46
  38. package/dist/build/vite/plugins/overlay.d.ts.map +0 -1
  39. package/dist/build/vite/plugins/robots.d.ts.map +0 -1
  40. package/dist/build/vite/plugins/seo.d.ts.map +0 -1
  41. package/dist/build/vite/plugins/server-config.d.ts.map +0 -1
  42. package/dist/build/vite/plugins/sitemap.d.ts.map +0 -1
  43. package/dist/build/vite/plugins/translations.d.ts.map +0 -1
  44. package/dist/build/vite/plugins/translations.test.d.ts +0 -2
  45. package/dist/build/vite/plugins/translations.test.d.ts.map +0 -1
  46. package/dist/build/vite/plugins/translations.test.js +0 -266
  47. package/dist/runtime/app/FimoProviders.d.ts.map +0 -1
  48. package/dist/runtime/app/FimoScripts.d.ts.map +0 -1
  49. package/dist/runtime/app/index.d.ts.map +0 -1
  50. package/dist/runtime/app/prefetch.d.ts.map +0 -1
  51. package/dist/runtime/content/DataSourcesProvider.d.ts.map +0 -1
  52. package/dist/runtime/content/RefreshContentProvider.d.ts.map +0 -1
  53. package/dist/runtime/content/RefreshContentProvider.test.d.ts +0 -2
  54. package/dist/runtime/content/RefreshContentProvider.test.d.ts.map +0 -1
  55. package/dist/runtime/content/RefreshContentProvider.test.js +0 -33
  56. package/dist/runtime/content/parseCollectionResponse.d.ts.map +0 -1
  57. package/dist/runtime/content/parseCollectionResponse.test.d.ts +0 -2
  58. package/dist/runtime/content/parseCollectionResponse.test.d.ts.map +0 -1
  59. package/dist/runtime/content/parseCollectionResponse.test.js +0 -20
  60. package/dist/runtime/content/utils/retrieve-data-sources.d.ts.map +0 -1
  61. package/dist/runtime/core/AppErrorBoundary.d.ts.map +0 -1
  62. package/dist/runtime/core/ViteLifecycles.d.ts.map +0 -1
  63. package/dist/runtime/i18n/FimoLocaleContext.d.ts.map +0 -1
  64. package/dist/runtime/i18n/locale.d.ts.map +0 -1
  65. package/dist/runtime/i18n/locale.test.d.ts +0 -2
  66. package/dist/runtime/i18n/locale.test.d.ts.map +0 -1
  67. package/dist/runtime/i18n/locale.test.js +0 -58
  68. package/dist/runtime/iframe/ConsoleErrorProvider.d.ts.map +0 -1
  69. package/dist/runtime/iframe/ScreenshotProvider.d.ts.map +0 -1
  70. package/dist/runtime/iframe/runtime/overlay-hmr.d.ts.map +0 -1
  71. package/dist/runtime/iframe/runtime/overlay-runtime.d.ts.map +0 -1
  72. package/dist/runtime/index.d.ts.map +0 -1
  73. package/dist/runtime/paths/get-fimo-paths.d.ts.map +0 -1
  74. package/dist/runtime/paths/get-fimo-paths.test.d.ts +0 -2
  75. package/dist/runtime/paths/get-fimo-paths.test.d.ts.map +0 -1
  76. package/dist/runtime/paths/get-fimo-paths.test.js +0 -69
  77. package/dist/runtime/paths/index.d.ts.map +0 -1
  78. package/dist/runtime/paths/types.d.ts.map +0 -1
  79. package/dist/runtime/primitives/components/Boolean.d.ts.map +0 -1
  80. package/dist/runtime/primitives/components/Date.d.ts.map +0 -1
  81. package/dist/runtime/primitives/components/Image.d.ts.map +0 -1
  82. package/dist/runtime/primitives/components/RichText.d.ts.map +0 -1
  83. package/dist/runtime/primitives/components/StaticImage.d.ts.map +0 -1
  84. package/dist/runtime/primitives/components/Text.d.ts.map +0 -1
  85. package/dist/runtime/primitives/components/Video.d.ts.map +0 -1
  86. package/dist/runtime/primitives/components/index.d.ts.map +0 -1
  87. package/dist/runtime/primitives/index.d.ts.map +0 -1
  88. package/dist/runtime/primitives/lib/image-optimization.d.ts.map +0 -1
  89. package/dist/runtime/primitives/lib/index.d.ts.map +0 -1
  90. package/dist/runtime/primitives/lib/primitives.d.ts.map +0 -1
  91. package/dist/runtime/primitives/lib/query.d.ts.map +0 -1
  92. package/dist/runtime/primitives/lib/template.d.ts.map +0 -1
  93. package/dist/runtime/primitives/lib/useFimoLiveValue.d.ts.map +0 -1
  94. package/dist/runtime/primitives/public-surface.test.d.ts +0 -2
  95. package/dist/runtime/primitives/public-surface.test.d.ts.map +0 -1
  96. package/dist/runtime/primitives/public-surface.test.js +0 -49
  97. package/dist/runtime/primitives/translations.d.ts.map +0 -1
  98. package/dist/runtime/react-router/index.d.ts.map +0 -1
  99. package/dist/runtime/react-router/navigation-utils.d.ts.map +0 -1
  100. package/dist/runtime/react-router/navigation.d.ts.map +0 -1
  101. package/dist/runtime/react-router/navigation.test.d.ts +0 -2
  102. package/dist/runtime/react-router/navigation.test.d.ts.map +0 -1
  103. package/dist/runtime/react-router/navigation.test.js +0 -35
  104. package/dist/runtime/react-router/routes.d.ts.map +0 -1
  105. package/dist/runtime/react-router/routes.test.d.ts +0 -2
  106. package/dist/runtime/react-router/routes.test.d.ts.map +0 -1
  107. package/dist/runtime/react-router/routes.test.js +0 -67
  108. package/dist/runtime/routing/AppResetScrollOnNavigate.d.ts.map +0 -1
  109. package/dist/runtime/routing/AppRoutesProvider.d.ts.map +0 -1
  110. package/dist/runtime/seo/buildSeoForPath.d.ts.map +0 -1
  111. package/dist/runtime/seo/htmlProps.d.ts.map +0 -1
  112. package/dist/runtime/seo/index.d.ts.map +0 -1
  113. package/dist/runtime/seo/resolver.d.ts.map +0 -1
  114. package/dist/runtime/shared/fimo-config.server.d.ts.map +0 -1
  115. package/dist/runtime/shared/fimo-config.types.d.ts.map +0 -1
  116. package/dist/runtime/t/OptionalTracking.d.ts.map +0 -1
  117. package/dist/runtime/t/OptionalTracking.test.d.ts +0 -2
  118. package/dist/runtime/t/OptionalTracking.test.d.ts.map +0 -1
  119. package/dist/runtime/t/OptionalTracking.test.js +0 -11
  120. package/dist/runtime/t/Pageview.d.ts.map +0 -1
  121. package/dist/runtime/templates.d.ts.map +0 -1
  122. package/dist/scripts/generated-types.test.js +0 -212
  123. package/dist/scripts/lint-translation-keys.test.d.ts +0 -1
  124. package/dist/scripts/lint-translation-keys.test.js +0 -16
  125. package/dist/scripts/sync-schemas.test.d.ts +0 -1
  126. package/dist/scripts/sync-schemas.test.js +0 -144
  127. package/dist/scripts/validate-route-metadata.test.d.ts +0 -1
  128. package/dist/scripts/validate-route-metadata.test.js +0 -116
  129. package/dist/scripts/validate-schemas.test.d.ts +0 -1
  130. package/dist/scripts/validate-schemas.test.js +0 -263
  131. package/scripts/add-ext.mjs +0 -47
  132. package/scripts/bump-version.mjs +0 -58
  133. package/scripts/bundle-cli.mjs +0 -123
  134. package/scripts/install-cli.mjs +0 -36
  135. package/scripts/lib/channels.mjs +0 -70
  136. package/scripts/lib/dev-release-state.mjs +0 -44
  137. package/scripts/lib/dev-release-state.test.ts +0 -36
  138. package/scripts/lib/postinstall-onboarding.test.ts +0 -82
  139. package/scripts/lib/release-core.mjs +0 -225
  140. package/scripts/lib/release-core.test.ts +0 -147
  141. package/scripts/migration-qa-gate.test.ts +0 -155
  142. package/scripts/publish-npm.mjs +0 -180
  143. /package/dist/{scripts/generated-types.test.d.ts → runtime/content/client/types.js} +0 -0
@@ -1,46 +0,0 @@
1
- import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
2
- import { tmpdir } from 'node:os';
3
- import { join } from 'node:path';
4
- import { afterEach, describe, expect, it } from 'vitest';
5
- import fimoConfigPlugin from './fimo-config';
6
- let scratch = null;
7
- const pluginContext = {
8
- meta: {},
9
- error: (error) => {
10
- throw error;
11
- },
12
- info: () => undefined,
13
- warn: () => undefined,
14
- debug: () => undefined,
15
- };
16
- afterEach(() => {
17
- if (scratch) {
18
- rmSync(scratch, { recursive: true, force: true });
19
- scratch = null;
20
- }
21
- });
22
- function createPluginWithConfig(config) {
23
- scratch = mkdtempSync(join(tmpdir(), 'fimo-config-plugin-'));
24
- writeFileSync(join(scratch, 'fimo-config.json'), JSON.stringify(config, null, 2));
25
- const plugin = fimoConfigPlugin();
26
- if (typeof plugin.config === 'function') {
27
- plugin.config.call(pluginContext, { root: scratch }, { command: 'build', mode: 'production' });
28
- }
29
- return plugin;
30
- }
31
- function transformHtml(plugin, html) {
32
- if (typeof plugin.transformIndexHtml !== 'function') {
33
- throw new Error('Expected transformIndexHtml function');
34
- }
35
- return plugin.transformIndexHtml.call(pluginContext, html, {});
36
- }
37
- describe('fimoConfigPlugin', () => {
38
- it('sets html lang from i18n.defaultLocale', () => {
39
- const plugin = createPluginWithConfig({ seo: { locale: 'es_ES' }, i18n: { defaultLocale: 'fr' } });
40
- expect(transformHtml(plugin, '<html><head></head><body></body></html>')).toContain('<html lang="fr">');
41
- });
42
- it('falls back to en when i18n.defaultLocale is absent', () => {
43
- const plugin = createPluginWithConfig({ seo: { locale: 'es_ES' } });
44
- expect(transformHtml(plugin, '<html lang="fr"><head></head><body></body></html>')).toContain('<html lang="en">');
45
- });
46
- });
@@ -1 +0,0 @@
1
- {"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../../../../src/build/vite/plugins/overlay.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAoEnC,MAAM,CAAC,OAAO,UAAU,aAAa,IAAI,MAAM,CA+E9C"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"robots.d.ts","sourceRoot":"","sources":["../../../../src/build/vite/plugins/robots.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AA6BnC;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,IAAI,MAAM,CAuB7C"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"seo.d.ts","sourceRoot":"","sources":["../../../../src/build/vite/plugins/seo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AA2BnC,MAAM,CAAC,OAAO,UAAU,SAAS,IAAI,MAAM,CA2G1C"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"server-config.d.ts","sourceRoot":"","sources":["../../../../src/build/vite/plugins/server-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAEnC,MAAM,CAAC,OAAO,UAAU,kBAAkB,IAAI,MAAM,CAsBnD"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"sitemap.d.ts","sourceRoot":"","sources":["../../../../src/build/vite/plugins/sitemap.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAkDnC,MAAM,CAAC,OAAO,UAAU,aAAa,IAAI,MAAM,CA8B9C"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"translations.d.ts","sourceRoot":"","sources":["../../../../src/build/vite/plugins/translations.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAiB,MAAM,MAAM,CAAC;AAQlD,UAAU,WAAW;IACnB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACrD,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAwCD,MAAM,CAAC,OAAO,UAAU,kBAAkB,IAAI,MAAM,CAmOnD;AAoED,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAwC3E"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=translations.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"translations.test.d.ts","sourceRoot":"","sources":["../../../../src/build/vite/plugins/translations.test.ts"],"names":[],"mappings":""}
@@ -1,266 +0,0 @@
1
- import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
2
- import { tmpdir } from 'node:os';
3
- import { join } from 'node:path';
4
- import { afterEach, describe, expect, it, vi } from 'vitest';
5
- import translationsPlugin from './translations';
6
- let scratch = null;
7
- let activePlugin = null;
8
- const originalFimoApiToken = process.env.FIMO_API_TOKEN;
9
- const pluginContext = {
10
- addWatchFile: vi.fn(),
11
- meta: {},
12
- error: (error) => {
13
- throw error;
14
- },
15
- info: () => undefined,
16
- warn: () => undefined,
17
- debug: () => undefined,
18
- };
19
- afterEach(() => {
20
- if (activePlugin && typeof activePlugin.closeBundle === 'function') {
21
- activePlugin.closeBundle.call(pluginContext);
22
- activePlugin = null;
23
- }
24
- if (scratch) {
25
- rmSync(scratch, { recursive: true, force: true });
26
- scratch = null;
27
- }
28
- if (originalFimoApiToken === undefined) {
29
- delete process.env.FIMO_API_TOKEN;
30
- }
31
- else {
32
- process.env.FIMO_API_TOKEN = originalFimoApiToken;
33
- }
34
- vi.unstubAllGlobals();
35
- vi.clearAllMocks();
36
- });
37
- function createProjectRoot() {
38
- scratch = mkdtempSync(join(tmpdir(), 'fimo-translations-plugin-'));
39
- writeFileSync(join(scratch, 'fimo-config.json'), JSON.stringify({ i18n: { defaultLocale: 'es', locales: ['es'] } }, null, 2));
40
- writeFileSync(join(scratch, '.env'), 'VITE_API_URL=https://tenant.example.test\n');
41
- return scratch;
42
- }
43
- function createPlugin(root, command) {
44
- const plugin = translationsPlugin();
45
- activePlugin = plugin;
46
- if (typeof plugin.configResolved === 'function') {
47
- plugin.configResolved.call(pluginContext, { root, command });
48
- }
49
- return plugin;
50
- }
51
- async function buildStart(plugin) {
52
- if (typeof plugin.buildStart !== 'function') {
53
- throw new Error('Expected buildStart hook');
54
- }
55
- await plugin.buildStart.call(pluginContext, {});
56
- }
57
- async function loadTranslations(plugin) {
58
- if (typeof plugin.resolveId !== 'function' || typeof plugin.load !== 'function') {
59
- throw new Error('Expected resolveId/load hooks');
60
- }
61
- const id = await plugin.resolveId.call(pluginContext, 'virtual:translations', undefined, {});
62
- if (typeof id !== 'string') {
63
- throw new Error('Expected virtual translations module id');
64
- }
65
- const result = await plugin.load.call(pluginContext, id, {});
66
- if (typeof result !== 'string') {
67
- throw new Error('Expected virtual translations source');
68
- }
69
- return result;
70
- }
71
- function createDevServer() {
72
- return {
73
- watcher: { add: vi.fn() },
74
- moduleGraph: {
75
- getModuleById: vi.fn(() => null),
76
- idToModuleMap: new Map(),
77
- },
78
- ws: { send: vi.fn() },
79
- };
80
- }
81
- function mockLabels(labels) {
82
- const fetchMock = vi.fn(async () => jsonResponse({ data: { labels, updatedAt: '2026-06-24T00:00:00.000Z' } }));
83
- vi.stubGlobal('fetch', fetchMock);
84
- return fetchMock;
85
- }
86
- function jsonResponse(body) {
87
- return {
88
- ok: true,
89
- json: async () => body,
90
- };
91
- }
92
- async function waitFor(condition) {
93
- const deadline = Date.now() + 1000;
94
- while (Date.now() < deadline) {
95
- if (condition()) {
96
- return;
97
- }
98
- await new Promise((resolve) => setTimeout(resolve, 10));
99
- }
100
- throw new Error('Timed out waiting for condition');
101
- }
102
- describe('translationsPlugin', () => {
103
- it('does not block dev startup on the initial label fetch', async () => {
104
- const root = createProjectRoot();
105
- const fetchMock = mockLabels({ headline: 'Hola' });
106
- const plugin = createPlugin(root, 'serve');
107
- await buildStart(plugin);
108
- expect(fetchMock).not.toHaveBeenCalled();
109
- const source = await loadTranslations(plugin);
110
- expect(source).toContain('export const translations = {};');
111
- expect(source).toContain('export const defaultLocale = "es";');
112
- });
113
- it('pushes updated labels over custom HMR without a full page reload', async () => {
114
- const root = createProjectRoot();
115
- mockLabels({ headline: 'Hola' });
116
- const plugin = createPlugin(root, 'serve');
117
- await buildStart(plugin);
118
- const server = createDevServer();
119
- if (typeof plugin.configureServer !== 'function') {
120
- throw new Error('Expected configureServer hook');
121
- }
122
- plugin.configureServer.call(pluginContext, server);
123
- await waitFor(() => server.ws.send.mock.calls.length > 0);
124
- expect(server.ws.send).toHaveBeenCalledWith({
125
- type: 'custom',
126
- event: 'fimo:labels-updated',
127
- data: expect.objectContaining({
128
- defaultLocale: 'es',
129
- dictionaries: { es: { headline: 'Hola' } },
130
- locales: ['es'],
131
- signature: expect.any(String),
132
- updatedAt: '2026-06-24T00:00:00.000Z',
133
- }),
134
- });
135
- expect(server.ws.send).not.toHaveBeenCalledWith({ type: 'full-reload', path: '*' });
136
- const source = await loadTranslations(plugin);
137
- expect(source).toContain('"headline":"Hola"');
138
- });
139
- it('discovers the events URL from tenant runtime config when env is absent', async () => {
140
- const root = createProjectRoot();
141
- const projectId = '11111111-1111-4111-8111-111111111111';
142
- writeFileSync(join(root, '.fimo.settings.json'), JSON.stringify({ projectId, apiUrl: 'https://api.example.test' }));
143
- process.env.FIMO_API_TOKEN = 'test-api-token';
144
- const socketUrls = [];
145
- vi.stubGlobal('WebSocket', class {
146
- onopen = null;
147
- onmessage = null;
148
- onclose = null;
149
- onerror = null;
150
- constructor(url) {
151
- socketUrls.push(url);
152
- }
153
- close() { }
154
- });
155
- const fetchMock = vi.fn(async (input, init) => {
156
- const url = new URL(input.toString());
157
- if (url.pathname === '/labels') {
158
- return jsonResponse({ data: { labels: {}, updatedAt: null } });
159
- }
160
- if (url.pathname === '/runtime-config') {
161
- return jsonResponse({ data: { eventsServerUrl: 'https://events.example.test' } });
162
- }
163
- if (url.pathname === '/api/auth/one-time-token/generate') {
164
- expect(init?.method).toBe('GET');
165
- return jsonResponse({ token: 'event-token' });
166
- }
167
- return { ok: false, json: async () => ({}) };
168
- });
169
- vi.stubGlobal('fetch', fetchMock);
170
- const plugin = createPlugin(root, 'serve');
171
- await buildStart(plugin);
172
- const server = createDevServer();
173
- if (typeof plugin.configureServer !== 'function') {
174
- throw new Error('Expected configureServer hook');
175
- }
176
- plugin.configureServer.call(pluginContext, server);
177
- await waitFor(() => socketUrls.length > 0);
178
- expect(socketUrls[0]).toContain(`wss://events.example.test/parties/events/${projectId}`);
179
- expect(socketUrls[0]).toContain('authToken=event-token');
180
- });
181
- it('forwards content changes over custom HMR without a full page reload', async () => {
182
- const root = createProjectRoot();
183
- const projectId = '11111111-1111-4111-8111-111111111111';
184
- writeFileSync(join(root, '.fimo.settings.json'), JSON.stringify({ projectId, apiUrl: 'https://api.example.test' }));
185
- process.env.FIMO_API_TOKEN = 'test-api-token';
186
- const sockets = [];
187
- vi.stubGlobal('WebSocket', class {
188
- onopen = null;
189
- onmessage = null;
190
- onclose = null;
191
- onerror = null;
192
- constructor(_url) {
193
- sockets.push(this);
194
- }
195
- close() { }
196
- });
197
- vi.stubGlobal('fetch', vi.fn(async (input) => {
198
- const url = new URL(input.toString());
199
- if (url.pathname === '/labels') {
200
- return jsonResponse({ data: { labels: {}, updatedAt: null } });
201
- }
202
- if (url.pathname === '/runtime-config') {
203
- return jsonResponse({ data: { eventsServerUrl: 'https://events.example.test' } });
204
- }
205
- if (url.pathname === '/api/auth/one-time-token/generate') {
206
- return jsonResponse({ data: { token: 'event-token' } });
207
- }
208
- return { ok: false, json: async () => ({}) };
209
- }));
210
- const plugin = createPlugin(root, 'serve');
211
- await buildStart(plugin);
212
- const server = createDevServer();
213
- if (typeof plugin.configureServer !== 'function') {
214
- throw new Error('Expected configureServer hook');
215
- }
216
- plugin.configureServer.call(pluginContext, server);
217
- await waitFor(() => sockets.length > 0);
218
- sockets[0].onmessage?.({
219
- data: JSON.stringify({
220
- type: 'content:changed',
221
- payload: {
222
- changes: [{ action: 'update', contentType: 'LiveNote', id: 'entry-1', locale: 'en' }],
223
- updatedAt: '2026-06-24T00:00:00.000Z',
224
- },
225
- }),
226
- });
227
- expect(server.ws.send).toHaveBeenCalledWith({
228
- type: 'custom',
229
- event: 'fimo:content-updated',
230
- data: {
231
- changes: [{ action: 'update', contentType: 'LiveNote', id: 'entry-1', locale: 'en' }],
232
- updatedAt: '2026-06-24T00:00:00.000Z',
233
- },
234
- });
235
- expect(server.ws.send).not.toHaveBeenCalledWith({ type: 'full-reload', path: '*' });
236
- });
237
- it('still waits for labels during production builds', async () => {
238
- const root = createProjectRoot();
239
- const fetchMock = mockLabels({ headline: 'Hola' });
240
- const plugin = createPlugin(root, 'build');
241
- await buildStart(plugin);
242
- expect(fetchMock).toHaveBeenCalled();
243
- const source = await loadTranslations(plugin);
244
- expect(source).toContain('"headline":"Hola"');
245
- });
246
- it('loads one dictionary per configured locale', async () => {
247
- const root = createProjectRoot();
248
- writeFileSync(join(root, 'fimo-config.json'), JSON.stringify({ i18n: { defaultLocale: 'en', locales: ['en', 'es'] } }, null, 2));
249
- vi.stubGlobal('fetch', vi.fn(async (input) => {
250
- const url = new URL(input.toString());
251
- const locale = url.searchParams.get('locale');
252
- return jsonResponse({
253
- data: {
254
- labels: locale === 'es' ? { headline: 'Hola' } : { headline: 'Hello' },
255
- updatedAt: `2026-06-24T00:00:0${locale === 'es' ? '2' : '1'}.000Z`,
256
- },
257
- });
258
- }));
259
- const plugin = createPlugin(root, 'build');
260
- await buildStart(plugin);
261
- const source = await loadTranslations(plugin);
262
- expect(source).toContain('export const dictionaries = {"en":{"headline":"Hello"},"es":{"headline":"Hola"}};');
263
- expect(source).toContain('export const translations = {"headline":"Hello"};');
264
- expect(source).toContain('export const updatedAt = "2026-06-24T00:00:02.000Z";');
265
- });
266
- });
@@ -1 +0,0 @@
1
- {"version":3,"file":"FimoProviders.d.ts","sourceRoot":"","sources":["../../../src/runtime/app/FimoProviders.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoD,MAAM,OAAO,CAAC;AAezE,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CACpC;AAwFD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,kBAAkB,2CAwCrE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"FimoScripts.d.ts","sourceRoot":"","sources":["../../../src/runtime/app/FimoScripts.tsx"],"names":[],"mappings":"AAKA,OAAO,0BAA0B,CAAC;AA6BlC;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,4CAc1B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/runtime/app/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACxE,YAAY,EAAE,YAAY,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACtF,YAAY,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAC3E,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"prefetch.d.ts","sourceRoot":"","sources":["../../../src/runtime/app/prefetch.ts"],"names":[],"mappings":"AAkFA,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,6CAElD;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,CAqClG"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"DataSourcesProvider.d.ts","sourceRoot":"","sources":["../../../src/runtime/content/DataSourcesProvider.tsx"],"names":[],"mappings":"AA6CA,wBAAgB,mBAAmB,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,2CA8B9E"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"RefreshContentProvider.d.ts","sourceRoot":"","sources":["../../../src/runtime/content/RefreshContentProvider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAGnD,UAAU,qBAAqB;IAC7B,OAAO,CAAC,EAAE,KAAK,CAAC;QACd,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAYD,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAMrE;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,OAAO,GAAG,qBAAqB,GAAG,IAAI,CAWpF;AAmBD,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,SAAS,OAAO,EAAE,EAC5B,OAAO,EAAE,qBAAqB,GAAG,IAAI,GACpC,OAAO,CAUT;AAED,eAAO,MAAM,sBAAsB,EAAE,EAAE,CAAC,iBAAiB,CAiCxD,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=RefreshContentProvider.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"RefreshContentProvider.test.d.ts","sourceRoot":"","sources":["../../../src/runtime/content/RefreshContentProvider.test.ts"],"names":[],"mappings":""}
@@ -1,33 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { getContentRefreshPayload, normalizeContentQueryRoot, shouldInvalidateContentQuery, } from './RefreshContentProvider.js';
3
- describe('RefreshContentProvider content invalidation', () => {
4
- it('keeps broad invalidation when no content type is provided', () => {
5
- expect(shouldInvalidateContentQuery(['BlogPost'], null)).toBe(true);
6
- expect(shouldInvalidateContentQuery(['Author'], {})).toBe(true);
7
- });
8
- it('invalidates only matching generated content query roots', () => {
9
- const payload = { contentType: 'BlogPost', locale: 'en' };
10
- expect(shouldInvalidateContentQuery(['BlogPost', 'entry-1', 'en'], payload)).toBe(true);
11
- expect(shouldInvalidateContentQuery(['Author', 'entry-1', 'en'], payload)).toBe(false);
12
- });
13
- it('normalizes schema-style content type names to generated query roots', () => {
14
- expect(normalizeContentQueryRoot('blog-post')).toBe('BlogPost');
15
- expect(shouldInvalidateContentQuery(['BlogPost'], { contentType: 'blog-post' })).toBe(true);
16
- });
17
- it('supports events with multiple changed content types', () => {
18
- const payload = {
19
- changes: [
20
- { contentType: 'BlogPost', id: 'post-1' },
21
- { contentType: 'author-profile', id: 'author-1' },
22
- ],
23
- };
24
- expect(shouldInvalidateContentQuery(['BlogPost'], payload)).toBe(true);
25
- expect(shouldInvalidateContentQuery(['AuthorProfile'], payload)).toBe(true);
26
- expect(shouldInvalidateContentQuery(['Product'], payload)).toBe(false);
27
- });
28
- it('reads payloads from window messages and direct HMR payloads', () => {
29
- const payload = { contentType: 'BlogPost', locale: 'en' };
30
- expect(getContentRefreshPayload({ type: 'content/refresh', payload })).toEqual(payload);
31
- expect(getContentRefreshPayload(payload)).toEqual(payload);
32
- });
33
- });
@@ -1 +0,0 @@
1
- {"version":3,"file":"parseCollectionResponse.d.ts","sourceRoot":"","sources":["../../../src/runtime/content/parseCollectionResponse.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IACzC,QAAQ,CAAC,IAAI,EAAE;QACb,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;KAC3B,CAAC;CACH;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,kBAAkB,CAE1E"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=parseCollectionResponse.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"parseCollectionResponse.test.d.ts","sourceRoot":"","sources":["../../../src/runtime/content/parseCollectionResponse.test.ts"],"names":[],"mappings":""}
@@ -1,20 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { parseCollectionResponse } from './parseCollectionResponse.js';
3
- describe('parseCollectionResponse', () => {
4
- it('accepts the collection envelope used by generated clients', () => {
5
- const response = parseCollectionResponse({
6
- data: [{ id: 'post-1', title: 'Hello' }],
7
- meta: { limit: 12, offset: 24, total: 40, hasMore: true },
8
- });
9
- expect(response).toEqual({
10
- data: [{ id: 'post-1', title: 'Hello' }],
11
- meta: { limit: 12, offset: 24, total: 40, hasMore: true },
12
- });
13
- });
14
- it('rejects invalid pagination metadata', () => {
15
- expect(() => parseCollectionResponse({
16
- data: [],
17
- meta: { limit: 0, offset: -1, total: '40', hasMore: 'yes' },
18
- })).toThrow();
19
- });
20
- });
@@ -1 +0,0 @@
1
- {"version":3,"file":"retrieve-data-sources.d.ts","sourceRoot":"","sources":["../../../../src/runtime/content/utils/retrieve-data-sources.ts"],"names":[],"mappings":"AACA,KAAK,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAExC,UAAU,UAAU;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;AAgD9D;;;;GAIG;AACH,wBAAgB,0BAA0B,IAAI,kBAAkB,CAwD/D"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"AppErrorBoundary.d.ts","sourceRoot":"","sources":["../../../src/runtime/core/AppErrorBoundary.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,QAmBrC;AAGD,wBAAgB,gBAAgB,4CAM/B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ViteLifecycles.d.ts","sourceRoot":"","sources":["../../../src/runtime/core/ViteLifecycles.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AAGzC,wBAAgB,cAAc,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,2CAkCzE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"FimoLocaleContext.d.ts","sourceRoot":"","sources":["../../../src/runtime/i18n/FimoLocaleContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoC,MAAM,OAAO,CAAC;AAEzD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAExD,MAAM,MAAM,sBAAsB,GAAG,IAAI,CACvC,oBAAoB,EACpB,QAAQ,GAAG,eAAe,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,KAAK,CAC1E,CAAC;AAaF,wBAAgB,kBAAkB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;IAAE,KAAK,EAAE,sBAAsB,CAAC;IAAC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,2CAEpH;AAED,wBAAgB,SAAS,IAAI,sBAAsB,CAElD"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"locale.d.ts","sourceRoot":"","sources":["../../../src/runtime/i18n/locale.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAEjE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,eAAe,EAAE,OAAO,CAAC;IACzB,GAAG,EAAE,KAAK,GAAG,KAAK,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,GAAG,SAAS,GAAG,MAAM,CAEzF;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,GAAG,SAAS,GAAG,MAAM,EAAE,CAUrF;AAED,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,MAAM,GAAG,GAAG,GAAG,qBAAqB,EACjD,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,GAAG,SAAS,GAC3C,oBAAoB,CA8CtB;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,GAAG,SAAS,GAAG,MAAM,CAgBnH;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,KAAK,GAAG,KAAK,CAGlE;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAYpF"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=locale.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"locale.test.d.ts","sourceRoot":"","sources":["../../../src/runtime/i18n/locale.test.ts"],"names":[],"mappings":""}
@@ -1,58 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { localizeFimoPath, resolveFimoLocale } from './locale';
3
- describe('Fimo locale routing', () => {
4
- const config = {
5
- i18n: {
6
- defaultLocale: 'en',
7
- locales: ['en', 'es'],
8
- routing: {
9
- strategy: 'path-prefix',
10
- prefixDefaultLocale: false,
11
- },
12
- },
13
- };
14
- it('uses the unprefixed URL for the default locale', () => {
15
- expect(resolveFimoLocale('/pricing', config)).toMatchObject({
16
- locale: 'en',
17
- routePath: '/pricing',
18
- prefix: null,
19
- isDefaultLocale: true,
20
- });
21
- });
22
- it('strips non-default locale prefixes before route matching', () => {
23
- expect(resolveFimoLocale('/es/blog/hola-mundo', config)).toMatchObject({
24
- locale: 'es',
25
- routePath: '/blog/hola-mundo',
26
- prefix: 'es',
27
- isDefaultLocale: false,
28
- });
29
- });
30
- it('builds localized paths for enabled locales', () => {
31
- expect(localizeFimoPath('/pricing', 'en', config)).toBe('/pricing');
32
- expect(localizeFimoPath('/pricing', 'es', config)).toBe('/es/pricing');
33
- expect(localizeFimoPath('/', 'es', config)).toBe('/es');
34
- });
35
- it('can prefix the default locale when configured', () => {
36
- const prefixed = {
37
- i18n: {
38
- ...config.i18n,
39
- routing: {
40
- strategy: 'path-prefix',
41
- prefixDefaultLocale: true,
42
- },
43
- },
44
- };
45
- expect(localizeFimoPath('/pricing', 'en', prefixed)).toBe('/en/pricing');
46
- });
47
- it('canonicalizes structurally valid locale tags', () => {
48
- expect(resolveFimoLocale('/es-419/pricing', {
49
- i18n: {
50
- defaultLocale: 'en_us',
51
- locales: ['en_us', 'es-419'],
52
- },
53
- })).toMatchObject({
54
- locale: 'es-419',
55
- defaultLocale: 'en-US',
56
- });
57
- });
58
- });
@@ -1 +0,0 @@
1
- {"version":3,"file":"ConsoleErrorProvider.d.ts","sourceRoot":"","sources":["../../../src/runtime/iframe/ConsoleErrorProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAkEnD,eAAO,MAAM,oBAAoB,EAAE,EAAE,CAAC,iBAAiB,CA0CtD,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ScreenshotProvider.d.ts","sourceRoot":"","sources":["../../../src/runtime/iframe/ScreenshotProvider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAkEnD,eAAO,MAAM,kBAAkB,EAAE,EAAE,CAAC,iBAAiB,CAOpD,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"overlay-hmr.d.ts","sourceRoot":"","sources":["../../../../src/runtime/iframe/runtime/overlay-hmr.ts"],"names":[],"mappings":""}
@@ -1 +0,0 @@
1
- {"version":3,"file":"overlay-runtime.d.ts","sourceRoot":"","sources":["../../../../src/runtime/iframe/runtime/overlay-runtime.ts"],"names":[],"mappings":""}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/runtime/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AACvF,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACvE,YAAY,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAC1E,YAAY,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAG7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAC/E,YAAY,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAG/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAG1D,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAG3C,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAEpE,cAAc,uBAAuB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"get-fimo-paths.d.ts","sourceRoot":"","sources":["../../../src/runtime/paths/get-fimo-paths.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAkFhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAsB,YAAY,CAAC,IAAI,GAAE,mBAAwB,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAoGtF"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=get-fimo-paths.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"get-fimo-paths.test.d.ts","sourceRoot":"","sources":["../../../src/runtime/paths/get-fimo-paths.test.ts"],"names":[],"mappings":""}
@@ -1,69 +0,0 @@
1
- import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
2
- import { tmpdir } from 'node:os';
3
- import { join } from 'node:path';
4
- import { afterEach, describe, expect, it, vi } from 'vitest';
5
- import { getFimoPaths } from './get-fimo-paths.js';
6
- const roots = [];
7
- function createDynamicProject() {
8
- const root = mkdtempSync(join(tmpdir(), 'fimo-paths-'));
9
- roots.push(root);
10
- writeFileSync(join(root, '.env'), 'VITE_API_URL=https://tenant.example.test\n');
11
- writeFileSync(join(root, 'fimo-config.json'), JSON.stringify({
12
- routes: {
13
- 'blog/post': {
14
- path: '/blog/:slug',
15
- params: {
16
- slug: {
17
- schema: 'BlogPost',
18
- queryField: 'slug',
19
- displayField: 'title',
20
- },
21
- },
22
- },
23
- },
24
- }));
25
- return root;
26
- }
27
- function response(status, data = []) {
28
- return new Response(JSON.stringify({ data }), {
29
- status,
30
- headers: { 'Content-Type': 'application/json' },
31
- });
32
- }
33
- afterEach(() => {
34
- vi.useRealTimers();
35
- vi.unstubAllGlobals();
36
- for (const root of roots.splice(0)) {
37
- rmSync(root, { recursive: true, force: true });
38
- }
39
- });
40
- describe('getFimoPaths content fetches', () => {
41
- it.each([502, 503, 504])('recovers from a transient %s response', async (status) => {
42
- vi.useFakeTimers();
43
- const fetchMock = vi
44
- .fn()
45
- .mockResolvedValueOnce(response(status))
46
- .mockResolvedValueOnce(response(200, [{ slug: 'hello-world' }]));
47
- vi.stubGlobal('fetch', fetchMock);
48
- const resultPromise = getFimoPaths({ cwd: createDynamicProject() });
49
- await vi.runAllTimersAsync();
50
- await expect(resultPromise).resolves.toContainEqual(expect.objectContaining({ routeKey: 'blog/post', path: '/blog/hello-world' }));
51
- expect(fetchMock).toHaveBeenCalledTimes(2);
52
- });
53
- it('fails clearly after exhausting the transient retry budget', async () => {
54
- vi.useFakeTimers();
55
- const fetchMock = vi.fn().mockResolvedValue(response(503));
56
- vi.stubGlobal('fetch', fetchMock);
57
- const resultPromise = getFimoPaths({ cwd: createDynamicProject() });
58
- const rejection = expect(resultPromise).rejects.toThrow('Failed to fetch BlogPost: 503 after 3 attempts');
59
- await vi.runAllTimersAsync();
60
- await rejection;
61
- expect(fetchMock).toHaveBeenCalledTimes(3);
62
- });
63
- it('does not retry an author response', async () => {
64
- const fetchMock = vi.fn().mockResolvedValue(response(400));
65
- vi.stubGlobal('fetch', fetchMock);
66
- await expect(getFimoPaths({ cwd: createDynamicProject() })).rejects.toThrow('Failed to fetch BlogPost: 400');
67
- expect(fetchMock).toHaveBeenCalledTimes(1);
68
- });
69
- });
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/runtime/paths/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,YAAY,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC"}