fimo 0.7.0-experimental.4 → 0.7.0-experimental.6

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 (34) hide show
  1. package/dist/cli/bundle.json +1 -1
  2. package/dist/cli/index.js +827 -464
  3. package/dist/runtime/strapi/client.d.ts +26 -0
  4. package/dist/runtime/strapi/client.d.ts.map +1 -0
  5. package/dist/runtime/strapi/client.js +88 -0
  6. package/dist/runtime/strapi/client.test.d.ts +2 -0
  7. package/dist/runtime/strapi/client.test.d.ts.map +1 -0
  8. package/dist/runtime/strapi/client.test.js +64 -0
  9. package/dist/runtime/strapi/index.d.ts +5 -0
  10. package/dist/runtime/strapi/index.d.ts.map +1 -0
  11. package/dist/runtime/strapi/index.js +6 -0
  12. package/dist/runtime/strapi/reshape.d.ts +28 -0
  13. package/dist/runtime/strapi/reshape.d.ts.map +1 -0
  14. package/dist/runtime/strapi/reshape.js +79 -0
  15. package/dist/runtime/strapi/reshape.test.d.ts +2 -0
  16. package/dist/runtime/strapi/reshape.test.d.ts.map +1 -0
  17. package/dist/runtime/strapi/reshape.test.js +33 -0
  18. package/dist/scripts/cms/example-content.js +22 -1
  19. package/dist/scripts/cms/example-content.test.js +11 -2
  20. package/dist/scripts/cms/strapi/detect.js +1 -0
  21. package/dist/scripts/cms/strapi/index.js +8 -0
  22. package/dist/scripts/cms/strapi/schema-map.js +11 -0
  23. package/dist/scripts/cms/strapi/schema-map.test.js +4 -0
  24. package/dist/scripts/cms/strapi/wire-client.d.ts +15 -0
  25. package/dist/scripts/cms/strapi/wire-client.js +107 -0
  26. package/dist/scripts/cms/strapi/wire-client.test.d.ts +1 -0
  27. package/dist/scripts/cms/strapi/wire-client.test.js +51 -0
  28. package/dist/scripts/cms/strapi/wiring.d.ts +17 -0
  29. package/dist/scripts/cms/strapi/wiring.js +36 -0
  30. package/dist/scripts/cms/strapi/wiring.test.d.ts +1 -0
  31. package/dist/scripts/cms/strapi/wiring.test.js +27 -0
  32. package/dist/scripts/cms/types.d.ts +18 -0
  33. package/package.json +5 -1
  34. package/templates/react-router/package.json +1 -1
@@ -0,0 +1,51 @@
1
+ import { mkdirSync, mkdtempSync, readFileSync, 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 { wireStrapiClient } from './wire-client.js';
6
+ let dir;
7
+ const schemas = [
8
+ {
9
+ name: 'BlogPost',
10
+ label: 'Blog Post',
11
+ isSingleton: false,
12
+ localized: false,
13
+ fields: {},
14
+ sourceUid: 'api::blog-post.blog-post',
15
+ sourcePath: '/blog-posts',
16
+ },
17
+ ];
18
+ afterEach(() => {
19
+ if (dir) {
20
+ rmSync(dir, { recursive: true, force: true });
21
+ }
22
+ });
23
+ describe('wireStrapiClient', () => {
24
+ it('generates the fimo-strapi module and swaps bare fetch calls', () => {
25
+ dir = mkdtempSync(join(tmpdir(), 'wire-strapi-'));
26
+ const clientDir = join(dir, 'src', 'lib', 'strapi-api');
27
+ mkdirSync(clientDir, { recursive: true });
28
+ writeFileSync(join(clientDir, 'base.ts'), 'export async function req(url: string, init: RequestInit) {\n const response = await fetch(url, init);\n return response;\n}\n');
29
+ writeFileSync(join(clientDir, 'other.ts'), 'export const x = 1;\n');
30
+ const result = wireStrapiClient(dir, clientDir, schemas);
31
+ expect(result.wired).toBe(true);
32
+ const generated = readFileSync(join(clientDir, 'fimo-strapi.ts'), 'utf8');
33
+ expect(generated).toContain('createFimoStrapiFetch');
34
+ expect(generated).toContain("'blog-posts': 'BlogPost',");
35
+ const base = readFileSync(join(clientDir, 'base.ts'), 'utf8');
36
+ expect(base).toContain('await fimoStrapiFetch(url, init)');
37
+ expect(base).not.toContain('await fetch(');
38
+ expect(base).toContain("import { fimoStrapiFetch } from './fimo-strapi';");
39
+ // A file with no fetch stays untouched.
40
+ expect(readFileSync(join(clientDir, 'other.ts'), 'utf8')).not.toContain('fimoStrapiFetch');
41
+ });
42
+ it('warns when no bare fetch is found', () => {
43
+ dir = mkdtempSync(join(tmpdir(), 'wire-strapi-none-'));
44
+ const clientDir = join(dir, 'client');
45
+ mkdirSync(clientDir, { recursive: true });
46
+ writeFileSync(join(clientDir, 'base.ts'), 'export const x = 1;\n');
47
+ const result = wireStrapiClient(dir, clientDir, schemas);
48
+ expect(result.wired).toBe(false);
49
+ expect(result.warnings[0]).toContain('No bare fetch()');
50
+ });
51
+ });
@@ -0,0 +1,17 @@
1
+ import type { CmsCollectionSchema } from '../types.js';
2
+ /**
3
+ * Machine-wiring for the native `fimo/strapi` read adapter. From the scaffolded
4
+ * schemas it derives the Strapi-path → Fimo-type map (+ the singletons) and
5
+ * emits a tiny repo module that instantiates the Fimo-backed fetch. The
6
+ * migration then swaps the CMS client's `fetch` for `fimoStrapiFetch` — after
7
+ * which the whole site reads scaffolded content from Fimo, deterministically.
8
+ */
9
+ export interface StrapiWiring {
10
+ /** Strapi REST path segment (pluralName) → Fimo type name. */
11
+ types: Record<string, string>;
12
+ /** Fimo type names that are single types. */
13
+ singletons: string[];
14
+ }
15
+ export declare function strapiWiring(schemas: CmsCollectionSchema[]): StrapiWiring;
16
+ /** Emit the repo module (`fimo-strapi.ts`) that wires the fetch to Fimo. */
17
+ export declare function renderFimoStrapiModule(schemas: CmsCollectionSchema[]): string;
@@ -0,0 +1,36 @@
1
+ export function strapiWiring(schemas) {
2
+ const types = {};
3
+ const singletons = [];
4
+ for (const schema of schemas) {
5
+ const pluralName = schema.sourcePath.replace(/^\/+/, '');
6
+ if (pluralName) {
7
+ types[pluralName] = schema.name;
8
+ }
9
+ if (schema.isSingleton) {
10
+ singletons.push(schema.name);
11
+ }
12
+ }
13
+ return { types, singletons };
14
+ }
15
+ /** Emit the repo module (`fimo-strapi.ts`) that wires the fetch to Fimo. */
16
+ export function renderFimoStrapiModule(schemas) {
17
+ const { types, singletons } = strapiWiring(schemas);
18
+ const typeEntries = Object.entries(types)
19
+ .map(([pluralName, typeName]) => ` '${pluralName}': '${typeName}',`)
20
+ .join('\n');
21
+ return `// AUTO-GENERATED by \`fimo migrate --scaffold-cms\`. Serves this site's Strapi
22
+ // content reads from Fimo (scaffolded example content) through fimo/strapi.
23
+ // The migration points the CMS client's fetch at \`fimoStrapiFetch\`; reads for
24
+ // scaffolded types resolve from Fimo, everything else falls through to Strapi.
25
+ import { createFimoStrapiFetch } from 'fimo/strapi';
26
+
27
+ // Strapi REST path (pluralName) -> Fimo type name.
28
+ const TYPES: Record<string, string> = {
29
+ ${typeEntries}
30
+ };
31
+
32
+ const SINGLETONS = [${singletons.map((name) => `'${name}'`).join(', ')}];
33
+
34
+ export const fimoStrapiFetch = createFimoStrapiFetch({ types: TYPES, singletons: SINGLETONS });
35
+ `;
36
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,27 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { renderFimoStrapiModule, strapiWiring } from './wiring.js';
3
+ const schema = (name, sourcePath, isSingleton = false) => ({
4
+ name,
5
+ label: name,
6
+ isSingleton,
7
+ localized: false,
8
+ fields: {},
9
+ sourceUid: `api::${name.toLowerCase()}.${name.toLowerCase()}`,
10
+ sourcePath,
11
+ });
12
+ describe('strapiWiring', () => {
13
+ it('maps pluralName paths to Fimo types and lists singletons', () => {
14
+ const wiring = strapiWiring([schema('BlogPost', '/blog-posts'), schema('Global', '/globals', true)]);
15
+ expect(wiring.types).toEqual({ 'blog-posts': 'BlogPost', globals: 'Global' });
16
+ expect(wiring.singletons).toEqual(['Global']);
17
+ });
18
+ });
19
+ describe('renderFimoStrapiModule', () => {
20
+ it('emits a module importing fimo/strapi with the type map + singletons', () => {
21
+ const src = renderFimoStrapiModule([schema('BlogPost', '/blog-posts'), schema('Global', '/globals', true)]);
22
+ expect(src).toContain("import { createFimoStrapiFetch } from 'fimo/strapi';");
23
+ expect(src).toContain("'blog-posts': 'BlogPost',");
24
+ expect(src).toContain("const SINGLETONS = ['Global'];");
25
+ expect(src).toContain('export const fimoStrapiFetch = createFimoStrapiFetch({ types: TYPES, singletons: SINGLETONS });');
26
+ });
27
+ });
@@ -38,6 +38,10 @@ export interface CmsCollectionSchema {
38
38
  /** The CMS marks this type as localized → seed per configured locale. */
39
39
  readonly localized: boolean;
40
40
  readonly fields: Record<string, FimoFieldDef>;
41
+ /** Pre-computed example values for fields the generic generator can't shape
42
+ * from the Fimo field type alone (dynamic zones must be arrays, components
43
+ * objects). Keyed by field name; the generator uses these verbatim. */
44
+ readonly examples?: Record<string, unknown>;
41
45
  /** Source CMS uid for provenance (e.g. `api::blog-post.blog-post`). */
42
46
  readonly sourceUid: string;
43
47
  /** Source REST path (e.g. `/blog-posts`) — informational for later rewire. */
@@ -51,6 +55,9 @@ export interface CmsDetection {
51
55
  readonly host: string;
52
56
  /** Absolute path to the CMS app root when co-located (monorepo), else null. */
53
57
  readonly appDir: string | null;
58
+ /** Absolute path to the frontend's CMS client module dir (where the fetch
59
+ * lives), for machine-wiring the reads to Fimo. Null if not found. */
60
+ readonly clientDir: string | null;
54
61
  /** Repo-relative files/signals that evidenced the detection. */
55
62
  readonly evidence: string[];
56
63
  /** Locales configured in the CMS, when discoverable (may be empty). */
@@ -73,4 +80,15 @@ export interface CmsConnector {
73
80
  * `fetchEntries` from.
74
81
  */
75
82
  renderListSource?(schemas: CmsCollectionSchema[], serverImport: string): string | null;
83
+ /**
84
+ * Machine-wire the frontend's CMS reads to Fimo: emit the adapter module and
85
+ * swap the client's fetch, so the whole site reads scaffolded content from
86
+ * Fimo. Deterministic — no agent step.
87
+ */
88
+ wireClient?(cwd: string, schemas: CmsCollectionSchema[]): CmsWireResult;
89
+ }
90
+ export interface CmsWireResult {
91
+ changes: string[];
92
+ warnings: string[];
93
+ wired: boolean;
76
94
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fimo",
3
- "version": "0.7.0-experimental.4",
3
+ "version": "0.7.0-experimental.6",
4
4
  "description": "Fimo CLI - create, deploy, and manage Fimo projects",
5
5
  "bin": {
6
6
  "fimo": "dist/cli/index.js"
@@ -52,6 +52,10 @@
52
52
  "types": "./dist/runtime/templates.d.ts",
53
53
  "import": "./dist/runtime/templates.js"
54
54
  },
55
+ "./strapi": {
56
+ "types": "./dist/runtime/strapi/index.d.ts",
57
+ "import": "./dist/runtime/strapi/index.js"
58
+ },
55
59
  "./remix": {
56
60
  "types": "./dist/runtime/remix/index.d.ts",
57
61
  "import": "./dist/runtime/remix/index.js"
@@ -21,7 +21,7 @@
21
21
  "cmdk": "^1.1.1",
22
22
  "date-fns": "^4.1.0",
23
23
  "embla-carousel-react": "^8.6.0",
24
- "fimo": "0.7.0-experimental.4",
24
+ "fimo": "0.7.0-experimental.6",
25
25
  "input-otp": "^1.4.2",
26
26
  "isbot": "^5",
27
27
  "lucide-react": "^0.577.0",