fimo 0.8.0 → 0.9.0-experimental.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.
- package/assets/content-templates/hooks-template.eta +4 -2
- package/assets/content-templates/types-template.eta +66 -1
- package/assets/skills/fimo/SKILL.md +1 -1
- package/assets/skills/fimo/references/content.md +86 -15
- package/assets/skills/fimo-cli/SKILL.md +6 -2
- package/assets/skills/fimo-cli/references/content.md +61 -2
- package/assets/skills/fimo-cli/references/integrations/firecrawl.md +20 -4
- package/assets/skills/fimo-cli/references/integrations.md +5 -1
- package/assets/skills/fimo-cli/references/webhooks.md +162 -0
- package/assets/skills/fimo-migration/SKILL.md +22 -2
- package/assets/skills/fimo-migration/references/content.md +24 -0
- package/assets/skills/fimo-migration/references/manifest.md +35 -0
- package/assets/skills/fimo-migration/references/qa.md +24 -2
- package/assets/skills/fimo-migration/references/workflow.md +12 -1
- package/assets/skills/fimo-migration/references/wrap.md +617 -0
- package/assets/skills/fimo-studio/SKILL.md +5 -3
- package/assets/skills/fimo-studio/references/cms.md +9 -1
- package/assets/skills/fimo-studio/references/visual-editing.md +5 -3
- package/assets/skills/fimo-studio/references/webhooks.md +42 -0
- package/dist/build/vite/plugins/translations.d.ts +2 -8
- package/dist/build/vite/plugins/translations.js +3 -121
- package/dist/cli/bundle.json +1 -1
- package/dist/cli/index.js +1051 -144
- package/dist/runtime/app/FimoProviders.d.ts +1 -11
- package/dist/runtime/app/FimoProviders.js +2 -23
- package/dist/runtime/astro/index.d.ts +2 -0
- package/dist/runtime/astro/index.js +3 -0
- package/dist/runtime/astro/server.d.ts +3 -0
- package/dist/runtime/astro/server.js +6 -0
- package/dist/runtime/content/client/internal.js +1 -0
- package/dist/runtime/content/client/types.d.ts +16 -0
- package/dist/runtime/i18n/FimoLocaleContext.js +1 -0
- package/dist/runtime/next/FimoNextProviders.d.ts +24 -0
- package/dist/runtime/next/FimoNextProviders.js +20 -0
- package/dist/runtime/next/FimoNextScripts.d.ts +10 -0
- package/dist/runtime/next/FimoNextScripts.js +19 -0
- package/dist/runtime/next/index.d.ts +14 -0
- package/dist/runtime/next/index.js +14 -0
- package/dist/runtime/next/server.d.ts +2 -0
- package/dist/runtime/next/server.js +4 -0
- package/dist/runtime/nuxt/composables.d.ts +9 -0
- package/dist/runtime/nuxt/composables.js +57 -0
- package/dist/runtime/nuxt/index.d.ts +3 -0
- package/dist/runtime/nuxt/index.js +6 -0
- package/dist/runtime/nuxt/server.d.ts +3 -0
- package/dist/runtime/nuxt/server.js +6 -0
- package/dist/runtime/primitives/labels-hook.d.ts +33 -0
- package/dist/runtime/primitives/labels-hook.js +41 -0
- package/dist/runtime/primitives/labels-store.d.ts +12 -0
- package/dist/runtime/primitives/labels-store.js +60 -0
- package/dist/runtime/primitives/lib/useFimoLiveValue.d.ts +5 -3
- package/dist/runtime/primitives/lib/useFimoLiveValue.js +11 -4
- package/dist/runtime/primitives/translations.d.ts +1 -27
- package/dist/runtime/primitives/translations.js +7 -85
- package/dist/runtime/react/FimoSpaProviders.d.ts +36 -0
- package/dist/runtime/react/FimoSpaProviders.js +63 -0
- package/dist/runtime/react/index.d.ts +33 -0
- package/dist/runtime/react/index.js +39 -0
- package/dist/runtime/remix/FimoRemixProviders.d.ts +16 -0
- package/dist/runtime/remix/FimoRemixProviders.js +12 -0
- package/dist/runtime/remix/FimoRemixScripts.d.ts +10 -0
- package/dist/runtime/remix/FimoRemixScripts.js +19 -0
- package/dist/runtime/remix/index.d.ts +12 -0
- package/dist/runtime/remix/index.js +11 -0
- package/dist/runtime/remix/server.d.ts +2 -0
- package/dist/runtime/remix/server.js +2 -0
- package/dist/runtime/shared/display-routes.d.ts +14 -0
- package/dist/runtime/shared/display-routes.js +25 -0
- package/dist/runtime/shared/fimo-config.server.js +1 -0
- package/dist/runtime/shared/fimo-config.types.d.ts +2 -0
- package/dist/runtime/shared/i18n-messages.d.ts +29 -0
- package/dist/runtime/shared/i18n-messages.js +79 -0
- package/dist/runtime/shared/labels-fetch.pure.d.ts +17 -0
- package/dist/runtime/shared/labels-fetch.pure.js +71 -0
- package/dist/runtime/shared/labels-fetch.server.d.ts +7 -0
- package/dist/runtime/shared/labels-fetch.server.js +97 -0
- package/dist/runtime/shared/labels-t.pure.d.ts +2 -0
- package/dist/runtime/shared/labels-t.pure.js +10 -0
- package/dist/runtime/strapi/client.d.ts +30 -0
- package/dist/runtime/strapi/client.js +89 -0
- package/dist/runtime/strapi/index.d.ts +5 -0
- package/dist/runtime/strapi/index.js +6 -0
- package/dist/runtime/strapi/reshape.d.ts +46 -0
- package/dist/runtime/strapi/reshape.js +114 -0
- package/dist/runtime/svelte/index.d.ts +3 -0
- package/dist/runtime/svelte/index.js +7 -0
- package/dist/runtime/svelte/server.d.ts +3 -0
- package/dist/runtime/svelte/server.js +6 -0
- package/dist/runtime/vue/index.d.ts +3 -0
- package/dist/runtime/vue/index.js +5 -0
- package/dist/runtime/vue/server.d.ts +3 -0
- package/dist/runtime/vue/server.js +6 -0
- package/dist/runtime/wrapped/FimoFileLink.d.ts +17 -0
- package/dist/runtime/wrapped/FimoFileLink.js +19 -0
- package/dist/runtime/wrapped/FimoMediaImage.d.ts +14 -0
- package/dist/runtime/wrapped/FimoMediaImage.js +20 -0
- package/dist/runtime/wrapped/FimoMediaVideo.d.ts +14 -0
- package/dist/runtime/wrapped/FimoMediaVideo.js +20 -0
- package/dist/runtime/wrapped/FimoRichTextBlock.d.ts +23 -0
- package/dist/runtime/wrapped/FimoRichTextBlock.js +22 -0
- package/dist/runtime/wrapped/FimoText.d.ts +22 -0
- package/dist/runtime/wrapped/FimoText.js +20 -0
- package/dist/runtime/wrapped/WrappedContentContext.d.ts +28 -0
- package/dist/runtime/wrapped/WrappedContentContext.js +30 -0
- package/dist/runtime/wrapped/WrappedProviders.d.ts +33 -0
- package/dist/runtime/wrapped/WrappedProviders.js +101 -0
- package/dist/runtime/wrapped/dom.d.ts +4 -0
- package/dist/runtime/wrapped/dom.js +23 -0
- package/dist/runtime/wrapped/server.d.ts +77 -0
- package/dist/runtime/wrapped/server.js +237 -0
- package/dist/scripts/apply-wrap-templates.d.ts +61 -0
- package/dist/scripts/apply-wrap-templates.js +132 -0
- package/dist/scripts/apply-wrap.d.ts +46 -0
- package/dist/scripts/apply-wrap.js +278 -0
- package/dist/scripts/cms/discover.d.ts +2 -0
- package/dist/scripts/cms/discover.js +17 -0
- package/dist/scripts/cms/example-content.d.ts +33 -0
- package/dist/scripts/cms/example-content.js +163 -0
- package/dist/scripts/cms/strapi/detect.d.ts +2 -0
- package/dist/scripts/cms/strapi/detect.js +186 -0
- package/dist/scripts/cms/strapi/index.d.ts +3 -0
- package/dist/scripts/cms/strapi/index.js +25 -0
- package/dist/scripts/cms/strapi/list-source.d.ts +17 -0
- package/dist/scripts/cms/strapi/list-source.js +90 -0
- package/dist/scripts/cms/strapi/schema-map.d.ts +9 -0
- package/dist/scripts/cms/strapi/schema-map.js +279 -0
- package/dist/scripts/cms/strapi/shapes.d.ts +23 -0
- package/dist/scripts/cms/strapi/shapes.js +38 -0
- package/dist/scripts/cms/strapi/touchpoints.d.ts +31 -0
- package/dist/scripts/cms/strapi/touchpoints.js +145 -0
- package/dist/scripts/cms/strapi/wire-client.d.ts +15 -0
- package/dist/scripts/cms/strapi/wire-client.js +107 -0
- package/dist/scripts/cms/strapi/wiring.d.ts +17 -0
- package/dist/scripts/cms/strapi/wiring.js +46 -0
- package/dist/scripts/cms/types.d.ts +145 -0
- package/dist/scripts/cms/types.js +11 -0
- package/dist/scripts/detect-framework.d.ts +39 -0
- package/dist/scripts/detect-framework.js +133 -0
- package/dist/scripts/draft-rows.d.ts +19 -0
- package/dist/scripts/draft-rows.js +135 -0
- package/dist/scripts/draft-schemas.d.ts +27 -0
- package/dist/scripts/draft-schemas.js +188 -0
- package/dist/scripts/extract-translations.js +16 -11
- package/dist/scripts/frameworks/astro/routes.d.ts +3 -0
- package/dist/scripts/frameworks/astro/routes.js +55 -0
- package/dist/scripts/frameworks/astro/template-style.d.ts +7 -0
- package/dist/scripts/frameworks/astro/template-style.js +19 -0
- package/dist/scripts/frameworks/discover.d.ts +70 -0
- package/dist/scripts/frameworks/discover.js +178 -0
- package/dist/scripts/frameworks/next/rewire.d.ts +30 -0
- package/dist/scripts/frameworks/next/rewire.js +258 -0
- package/dist/scripts/frameworks/next/routes.d.ts +17 -0
- package/dist/scripts/frameworks/next/routes.js +134 -0
- package/dist/scripts/frameworks/next/wiring.d.ts +33 -0
- package/dist/scripts/frameworks/next/wiring.js +186 -0
- package/dist/scripts/frameworks/nuxt/routes.d.ts +3 -0
- package/dist/scripts/frameworks/nuxt/routes.js +54 -0
- package/dist/scripts/frameworks/nuxt/template-style.d.ts +9 -0
- package/dist/scripts/frameworks/nuxt/template-style.js +27 -0
- package/dist/scripts/frameworks/remix/routes.d.ts +3 -0
- package/dist/scripts/frameworks/remix/routes.js +50 -0
- package/dist/scripts/frameworks/support.d.ts +75 -0
- package/dist/scripts/frameworks/support.js +165 -0
- package/dist/scripts/frameworks/sveltekit/routes.d.ts +3 -0
- package/dist/scripts/frameworks/sveltekit/routes.js +50 -0
- package/dist/scripts/frameworks/sveltekit/template-style.d.ts +9 -0
- package/dist/scripts/frameworks/sveltekit/template-style.js +54 -0
- package/dist/scripts/frameworks/vite/routes.d.ts +15 -0
- package/dist/scripts/frameworks/vite/routes.js +93 -0
- package/dist/scripts/frameworks/vite/wiring.d.ts +10 -0
- package/dist/scripts/frameworks/vite/wiring.js +99 -0
- package/dist/scripts/i18n-namespace.d.ts +27 -0
- package/dist/scripts/i18n-namespace.js +155 -0
- package/dist/scripts/lib/validation-report.d.ts +1 -0
- package/dist/scripts/lib/validation-report.js +3 -0
- package/dist/scripts/render-parity/capture.d.ts +56 -0
- package/dist/scripts/render-parity/capture.js +366 -0
- package/dist/scripts/render-parity/compare.d.ts +59 -0
- package/dist/scripts/render-parity/compare.js +0 -0
- package/dist/scripts/render-parity/normalize-html.d.ts +13 -0
- package/dist/scripts/render-parity/normalize-html.js +223 -0
- package/dist/scripts/render-parity/types.d.ts +41 -0
- package/dist/scripts/render-parity/types.js +1 -0
- package/dist/scripts/scan-wrappable.d.ts +196 -0
- package/dist/scripts/scan-wrappable.js +1232 -0
- package/dist/scripts/validate-route-metadata.js +11 -0
- package/dist/scripts/validate-schemas.js +42 -1
- package/package.json +84 -4
- package/release.json +2 -2
- package/templates/react-router/package.json +1 -1
|
@@ -42,7 +42,7 @@ When you open a Collection, the entry list provides several tools:
|
|
|
42
42
|
2. Click the **+** (plus) icon button at the top of the Collection (labeled **New entry** on hover). If the Collection is empty, use the **Create entry** button in the center of the empty state instead.
|
|
43
43
|
3. Fill in the form fields (text, images, dates, whatever the collection defines).
|
|
44
44
|
|
|
45
|
-
Changes save automatically as you fill in each field (the save is debounced), so there is no Save button. The save status appears in the top bar (Saving / Saved).
|
|
45
|
+
Changes save automatically as you fill in each field (the save is debounced), so there is no Save button. The save status appears in the top bar (Saving / Saved). An incomplete new entry waits until its required fields are valid before it becomes part of the Collection. If the Collection is wired to a page on your site, new content shows up automatically.
|
|
46
46
|
|
|
47
47
|
## Editing an Entry
|
|
48
48
|
|
|
@@ -51,6 +51,14 @@ Changes save automatically as you fill in each field (the save is debounced), so
|
|
|
51
51
|
|
|
52
52
|
Your edits save automatically as you change each field (the save is debounced), so there is no Save button. Watch the top bar for the save status (Saving / Saved). The entry editor's only header actions are delete (trash icon) and copy link.
|
|
53
53
|
|
|
54
|
+
If a field is invalid, the editor keeps the change unsaved and pins a status bar below the header. Choose **Review issues** to jump to the first invalid field, then **Next issue** to move through the remaining fields. Collapsed blocks open automatically. Once every issue is fixed, the editor confirms that all fields are valid and resumes saving.
|
|
55
|
+
|
|
56
|
+
## Editing Text
|
|
57
|
+
|
|
58
|
+
- Short text such as titles, names, and slugs uses one compact line.
|
|
59
|
+
- Plain multiline text such as summaries and descriptions starts taller and grows as you write.
|
|
60
|
+
- Formatted content uses the rich-text editor for headings, links, lists, and media.
|
|
61
|
+
|
|
54
62
|
## Bulk Operations
|
|
55
63
|
|
|
56
64
|
Need to update or remove several entries at once?
|
|
@@ -12,7 +12,9 @@ For text elements, the side panel shows editable fields where you can change the
|
|
|
12
12
|
|
|
13
13
|
### Editing Styles
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
Style controls are only available on projects created before July 2026. Newer projects edit styles through the AI chat instead (for example: "make the hero title larger and dark blue"). If the user does not see the style controls described below, their project is a newer one -- point them to the chat.
|
|
16
|
+
|
|
17
|
+
On projects that have them, the side panel organizes style controls into these categories:
|
|
16
18
|
|
|
17
19
|
- **Typography** -- Font family, font size, font weight, line height, letter spacing, text alignment, and bold/italic/underline/strikethrough toggles.
|
|
18
20
|
- **Color** -- Text and foreground colors.
|
|
@@ -31,5 +33,5 @@ Click the **Edit mode** toggle again or close the side panel. The side editor cl
|
|
|
31
33
|
|
|
32
34
|
## When to Use Edit Mode vs. Chat
|
|
33
35
|
|
|
34
|
-
- **Edit mode** is best for
|
|
35
|
-
- **Chat** is better for
|
|
36
|
+
- **Edit mode** is best for content changes -- updating text (including bold, italic, underline, and links), and replacing images. On older projects it also covers quick style tweaks like colors and spacing.
|
|
37
|
+
- **Chat** is better for style and structural changes -- changing colors or spacing (on newer projects), adding new sections, restructuring a page layout, or building new functionality.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Webhooks
|
|
2
|
+
|
|
3
|
+
> **Beta:** Test each destination and review its delivery history before depending on it in production.
|
|
4
|
+
|
|
5
|
+
Webhooks send project activity to an external HTTPS endpoint. Use them for focused reactions such as adding a waitlist submission to an email tool, notifying Slack after a publish, or starting a GitHub workflow after an agent review.
|
|
6
|
+
|
|
7
|
+
Only project members with Full Access can see Webhooks in Settings or manage its destinations and delivery history.
|
|
8
|
+
|
|
9
|
+
## Create one
|
|
10
|
+
|
|
11
|
+
1. Open the project and choose **Settings**.
|
|
12
|
+
2. Select **Webhooks**.
|
|
13
|
+
3. Choose **New webhook**.
|
|
14
|
+
4. Name it, select one event, and enter the destination URL.
|
|
15
|
+
5. Optionally narrow form, agent, media, or entry events with the filter shown for that event.
|
|
16
|
+
6. Review the request and select **Save**.
|
|
17
|
+
|
|
18
|
+
The event groups are Entries, Forms, Publish, Agents, Analytics, and Media. Webhooks belong to the project, with up to 20 configurations. They listen to main by default or can include every environment.
|
|
19
|
+
|
|
20
|
+
Entry webhooks show **Combine rapid changes**. The default waits 5 seconds after direct editing stops and sends one delivery with the combined changes. Immediate, 30-second, and 1-minute windows are also available. Bulk edits and environment merges already produce batches and send immediately.
|
|
21
|
+
|
|
22
|
+
## Configure the request
|
|
23
|
+
|
|
24
|
+
The default payload is the complete Fimo event, including its type, project, environment, timestamp, and event-specific data. Keep this when the destination can accept it.
|
|
25
|
+
|
|
26
|
+
Choose **Custom template** when a service expects a specific JSON shape. Use **Insert variable** to pick fields for the selected event. Variables use paths such as `{{ event.data.submission.data.email }}`. The preview catches invalid JSON and missing variables before save.
|
|
27
|
+
|
|
28
|
+
When Studio recognizes a Resend, Slack, or GitHub URL, it offers a request setup for that service. The suggestion never changes the request automatically. Accept it to prefill relevant headers and JSON, then review every field.
|
|
29
|
+
|
|
30
|
+
## Add authentication
|
|
31
|
+
|
|
32
|
+
Under **Headers**, add a header name and choose its value type. Prefer a project secret for API keys and tokens; choose whether the destination needs the raw secret, a `Bearer ` prefix, or a `token ` prefix. Fixed values are suitable only for non-sensitive headers.
|
|
33
|
+
|
|
34
|
+
Fimo signs requests by default. Save the signing secret shown after creation so a custom receiver can verify `X-Fimo-Signature`. Rotate it from the webhook configuration if it is exposed.
|
|
35
|
+
|
|
36
|
+
## Test and monitor
|
|
37
|
+
|
|
38
|
+
Use **Send test** before depending on a workflow. Tests use documented sample data and travel through the same delivery path as real events.
|
|
39
|
+
|
|
40
|
+
Open **Deliveries** to see the event ID, masked destination, request metadata and payload excerpt, queue message ID, status, HTTP response, duration, and individual attempts. Fimo automatically retries temporary failures. After all automatic retries are exhausted, open the failed delivery and choose **Retry now**. A delivery accepts up to five manual retries.
|
|
41
|
+
|
|
42
|
+
Destination credentials are masked in configuration and delivery details. A successful test means the destination returned a successful HTTP response; it does not necessarily mean the provider completed its downstream action, so check the provider when that distinction matters.
|
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
import type { Plugin } from 'vite';
|
|
2
|
-
|
|
3
|
-
dictionaries: Record<string, Record<string, string>>;
|
|
4
|
-
defaultLocale: string;
|
|
5
|
-
locales: string[];
|
|
6
|
-
updatedAt: string | null;
|
|
7
|
-
}
|
|
2
|
+
import { loadLabelBundle } from '../../../runtime/shared/labels-fetch.server.js';
|
|
8
3
|
export default function translationsPlugin(): Plugin;
|
|
9
|
-
export
|
|
10
|
-
export {};
|
|
4
|
+
export { loadLabelBundle };
|
|
11
5
|
//# sourceMappingURL=translations.d.ts.map
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
|
-
import { Buffer } from 'node:buffer';
|
|
3
2
|
import { readFile } from 'node:fs/promises';
|
|
4
3
|
import { homedir } from 'node:os';
|
|
5
4
|
import { join } from 'node:path';
|
|
6
|
-
import {
|
|
7
|
-
import { getConfigServer } from '../../../runtime/shared/fimo-config.server.js';
|
|
5
|
+
import { emptyLabelBundle, labelSignature, loadLabelBundle, readProjectEnv, resolveTenantApiUrl, serializeBundle, } from '../../../runtime/shared/labels-fetch.server.js';
|
|
8
6
|
const VIRTUAL_ID = 'virtual:translations';
|
|
9
7
|
const RESOLVED_ID = '\0' + VIRTUAL_ID;
|
|
10
8
|
export default function translationsPlugin() {
|
|
@@ -145,7 +143,7 @@ export default function translationsPlugin() {
|
|
|
145
143
|
};
|
|
146
144
|
async function connectLabelEvents(root, onLabelsChanged) {
|
|
147
145
|
const env = await readProjectEnv(root);
|
|
148
|
-
const apiUrl = env
|
|
146
|
+
const apiUrl = resolveTenantApiUrl(env);
|
|
149
147
|
if (!apiUrl) {
|
|
150
148
|
return [];
|
|
151
149
|
}
|
|
@@ -229,24 +227,6 @@ function parseContentChangePayload(payload) {
|
|
|
229
227
|
updatedAt: typeof source.updatedAt === 'string' ? source.updatedAt : undefined,
|
|
230
228
|
};
|
|
231
229
|
}
|
|
232
|
-
function serializeBundle(bundle) {
|
|
233
|
-
return JSON.stringify({
|
|
234
|
-
dictionaries: bundle.dictionaries,
|
|
235
|
-
defaultLocale: bundle.defaultLocale,
|
|
236
|
-
locales: bundle.locales,
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
|
-
function emptyLabelBundle(rootDir) {
|
|
240
|
-
const config = getConfigServer(rootDir);
|
|
241
|
-
const defaultLocale = getFimoDefaultLocale(config);
|
|
242
|
-
const locales = getFimoLocales(config);
|
|
243
|
-
return {
|
|
244
|
-
dictionaries: Object.fromEntries(locales.map((locale) => [locale, {}])),
|
|
245
|
-
defaultLocale,
|
|
246
|
-
locales,
|
|
247
|
-
updatedAt: null,
|
|
248
|
-
};
|
|
249
|
-
}
|
|
250
230
|
function findVirtualTranslationModules(server) {
|
|
251
231
|
const direct = server.moduleGraph.getModuleById(RESOLVED_ID);
|
|
252
232
|
const matches = new Set(direct ? [direct] : []);
|
|
@@ -257,73 +237,13 @@ function findVirtualTranslationModules(server) {
|
|
|
257
237
|
}
|
|
258
238
|
return [...matches];
|
|
259
239
|
}
|
|
260
|
-
function labelSignature(bundle) {
|
|
261
|
-
return Buffer.from(serializeBundle(bundle)).toString('base64');
|
|
262
|
-
}
|
|
263
240
|
function labelUpdatePayload(bundle) {
|
|
264
241
|
return {
|
|
265
242
|
...bundle,
|
|
266
243
|
signature: labelSignature(bundle),
|
|
267
244
|
};
|
|
268
245
|
}
|
|
269
|
-
export
|
|
270
|
-
const config = getConfigServer(rootDir);
|
|
271
|
-
const defaultLocale = getFimoDefaultLocale(config);
|
|
272
|
-
const locales = getFimoLocales(config);
|
|
273
|
-
const env = await readProjectEnv(rootDir);
|
|
274
|
-
const apiUrl = env.VITE_API_URL;
|
|
275
|
-
if (!apiUrl) {
|
|
276
|
-
return {
|
|
277
|
-
dictionaries: Object.fromEntries(locales.map((locale) => [locale, {}])),
|
|
278
|
-
defaultLocale,
|
|
279
|
-
locales,
|
|
280
|
-
updatedAt: null,
|
|
281
|
-
};
|
|
282
|
-
}
|
|
283
|
-
try {
|
|
284
|
-
const loaded = await Promise.all(locales.map((locale) => fetchLabelDictionary(apiUrl, locale).catch(() => ({ locale, labels: {}, updatedAt: null }))));
|
|
285
|
-
const updatedAt = loaded
|
|
286
|
-
.map((entry) => entry.updatedAt)
|
|
287
|
-
.filter((value) => typeof value === 'string')
|
|
288
|
-
.sort()
|
|
289
|
-
.at(-1);
|
|
290
|
-
return {
|
|
291
|
-
dictionaries: Object.fromEntries(loaded.map((entry) => [entry.locale, entry.labels])),
|
|
292
|
-
defaultLocale,
|
|
293
|
-
locales,
|
|
294
|
-
updatedAt: updatedAt ?? null,
|
|
295
|
-
};
|
|
296
|
-
}
|
|
297
|
-
catch {
|
|
298
|
-
return {
|
|
299
|
-
dictionaries: Object.fromEntries(locales.map((locale) => [locale, {}])),
|
|
300
|
-
defaultLocale,
|
|
301
|
-
locales,
|
|
302
|
-
updatedAt: null,
|
|
303
|
-
};
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
async function fetchLabelDictionary(apiUrl, locale) {
|
|
307
|
-
const url = new URL('/labels', apiUrl);
|
|
308
|
-
url.searchParams.set('locale', locale);
|
|
309
|
-
const response = await fetchWithTimeout(url, 4000);
|
|
310
|
-
if (!response.ok) {
|
|
311
|
-
return { locale, labels: {}, updatedAt: null };
|
|
312
|
-
}
|
|
313
|
-
const body = (await response.json());
|
|
314
|
-
if (Array.isArray(body.data)) {
|
|
315
|
-
return {
|
|
316
|
-
locale,
|
|
317
|
-
labels: Object.fromEntries(body.data.map((row) => [row.key, row.value ?? row.defaultValue ?? ''])),
|
|
318
|
-
updatedAt: null,
|
|
319
|
-
};
|
|
320
|
-
}
|
|
321
|
-
return {
|
|
322
|
-
locale,
|
|
323
|
-
labels: body.data?.labels ?? {},
|
|
324
|
-
updatedAt: body.data?.updatedAt ?? null,
|
|
325
|
-
};
|
|
326
|
-
}
|
|
246
|
+
export { loadLabelBundle };
|
|
327
247
|
async function loadRuntimeConfig(apiUrl) {
|
|
328
248
|
try {
|
|
329
249
|
const response = await fetchWithTimeout(new URL('/runtime-config', apiUrl), 2000);
|
|
@@ -358,44 +278,6 @@ async function fetchWithTimeout(url, timeoutMs) {
|
|
|
358
278
|
clearTimeout(timeout);
|
|
359
279
|
}
|
|
360
280
|
}
|
|
361
|
-
async function readProjectEnv(rootDir) {
|
|
362
|
-
const values = {
|
|
363
|
-
...(await readEnvFile(join(rootDir, '.env'))),
|
|
364
|
-
...(await readEnvFile(join(rootDir, '.env.local'))),
|
|
365
|
-
};
|
|
366
|
-
for (const key of ['VITE_API_URL']) {
|
|
367
|
-
if (process.env[key]) {
|
|
368
|
-
values[key] = process.env[key];
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
return values;
|
|
372
|
-
}
|
|
373
|
-
async function readEnvFile(filePath) {
|
|
374
|
-
try {
|
|
375
|
-
const content = await readFile(filePath, 'utf8');
|
|
376
|
-
const values = {};
|
|
377
|
-
for (const line of content.split(/\r?\n/)) {
|
|
378
|
-
const trimmed = line.trim();
|
|
379
|
-
if (!trimmed || trimmed.startsWith('#')) {
|
|
380
|
-
continue;
|
|
381
|
-
}
|
|
382
|
-
const index = trimmed.indexOf('=');
|
|
383
|
-
if (index === -1) {
|
|
384
|
-
continue;
|
|
385
|
-
}
|
|
386
|
-
const key = trimmed.slice(0, index).trim();
|
|
387
|
-
const value = trimmed
|
|
388
|
-
.slice(index + 1)
|
|
389
|
-
.trim()
|
|
390
|
-
.replace(/^['"]|['"]$/g, '');
|
|
391
|
-
values[key] = value;
|
|
392
|
-
}
|
|
393
|
-
return values;
|
|
394
|
-
}
|
|
395
|
-
catch {
|
|
396
|
-
return {};
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
281
|
async function readProjectSettings(rootDir) {
|
|
400
282
|
try {
|
|
401
283
|
const raw = await readFile(join(rootDir, '.fimo.settings.json'), 'utf8');
|