@sourcepress/astro 0.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 (66) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/.turbo/turbo-test.log +18 -0
  3. package/LICENSE +21 -0
  4. package/dist/__tests__/client.test.d.ts +2 -0
  5. package/dist/__tests__/client.test.d.ts.map +1 -0
  6. package/dist/__tests__/client.test.js +62 -0
  7. package/dist/__tests__/client.test.js.map +1 -0
  8. package/dist/__tests__/component-registry.test.d.ts +2 -0
  9. package/dist/__tests__/component-registry.test.d.ts.map +1 -0
  10. package/dist/__tests__/component-registry.test.js +38 -0
  11. package/dist/__tests__/component-registry.test.js.map +1 -0
  12. package/dist/__tests__/content-syncer.test.d.ts +2 -0
  13. package/dist/__tests__/content-syncer.test.d.ts.map +1 -0
  14. package/dist/__tests__/content-syncer.test.js +153 -0
  15. package/dist/__tests__/content-syncer.test.js.map +1 -0
  16. package/dist/__tests__/integration.test.d.ts +2 -0
  17. package/dist/__tests__/integration.test.d.ts.map +1 -0
  18. package/dist/__tests__/integration.test.js +141 -0
  19. package/dist/__tests__/integration.test.js.map +1 -0
  20. package/dist/__tests__/schema-generator.test.d.ts +2 -0
  21. package/dist/__tests__/schema-generator.test.d.ts.map +1 -0
  22. package/dist/__tests__/schema-generator.test.js +139 -0
  23. package/dist/__tests__/schema-generator.test.js.map +1 -0
  24. package/dist/client.d.ts +14 -0
  25. package/dist/client.d.ts.map +1 -0
  26. package/dist/client.js +44 -0
  27. package/dist/client.js.map +1 -0
  28. package/dist/component-registry.d.ts +12 -0
  29. package/dist/component-registry.d.ts.map +1 -0
  30. package/dist/component-registry.js +17 -0
  31. package/dist/component-registry.js.map +1 -0
  32. package/dist/content-syncer.d.ts +23 -0
  33. package/dist/content-syncer.d.ts.map +1 -0
  34. package/dist/content-syncer.js +95 -0
  35. package/dist/content-syncer.js.map +1 -0
  36. package/dist/index.d.ts +9 -0
  37. package/dist/index.d.ts.map +1 -0
  38. package/dist/index.js +7 -0
  39. package/dist/index.js.map +1 -0
  40. package/dist/integration.d.ts +4 -0
  41. package/dist/integration.d.ts.map +1 -0
  42. package/dist/integration.js +52 -0
  43. package/dist/integration.js.map +1 -0
  44. package/dist/schema-generator.d.ts +3 -0
  45. package/dist/schema-generator.d.ts.map +1 -0
  46. package/dist/schema-generator.js +77 -0
  47. package/dist/schema-generator.js.map +1 -0
  48. package/dist/types.d.ts +35 -0
  49. package/dist/types.d.ts.map +1 -0
  50. package/dist/types.js +2 -0
  51. package/dist/types.js.map +1 -0
  52. package/package.json +33 -0
  53. package/src/__tests__/client.test.ts +82 -0
  54. package/src/__tests__/component-registry.test.ts +49 -0
  55. package/src/__tests__/content-syncer.test.ts +174 -0
  56. package/src/__tests__/integration.test.ts +169 -0
  57. package/src/__tests__/schema-generator.test.ts +156 -0
  58. package/src/client.ts +54 -0
  59. package/src/component-registry.ts +19 -0
  60. package/src/content-syncer.ts +110 -0
  61. package/src/index.ts +8 -0
  62. package/src/integration.ts +61 -0
  63. package/src/schema-generator.ts +80 -0
  64. package/src/types.ts +40 -0
  65. package/tsconfig.json +8 -0
  66. package/vitest.config.ts +7 -0
@@ -0,0 +1,4 @@
1
+
2
+ > @sourcepress/astro@0.1.0 build /Users/fabianvontiedemann/Developer/org/sourcepress/packages/adapters/astro
3
+ > tsc
4
+
@@ -0,0 +1,18 @@
1
+
2
+ > @sourcepress/astro@0.1.0 test /Users/fabianvontiedemann/Developer/org/sourcepress/packages/adapters/astro
3
+ > vitest run
4
+
5
+
6
+ RUN v2.1.9 /Users/fabianvontiedemann/Developer/org/sourcepress/packages/adapters/astro
7
+
8
+ ✓ src/__tests__/schema-generator.test.ts (6 tests) 2ms
9
+ ✓ src/__tests__/component-registry.test.ts (3 tests) 2ms
10
+ ✓ src/__tests__/client.test.ts (6 tests) 3ms
11
+ ✓ src/__tests__/content-syncer.test.ts (5 tests) 3ms
12
+ ✓ src/__tests__/integration.test.ts (5 tests) 3ms
13
+
14
+ Test Files 5 passed (5)
15
+ Tests 25 passed (25)
16
+ Start at 15:17:12
17
+ Duration 255ms (transform 127ms, setup 0ms, collect 167ms, tests 13ms, environment 0ms, prepare 241ms)
18
+
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 SourcePress Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=client.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/client.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,62 @@
1
+ import { afterEach, describe, expect, it, vi } from "vitest";
2
+ import { EngineClient, EngineClientError } from "../client.js";
3
+ afterEach(() => {
4
+ vi.restoreAllMocks();
5
+ });
6
+ function mockFetch(body, status = 200) {
7
+ const response = {
8
+ ok: status >= 200 && status < 300,
9
+ status,
10
+ json: async () => body,
11
+ text: async () => JSON.stringify(body),
12
+ };
13
+ vi.stubGlobal("fetch", vi.fn().mockResolvedValue(response));
14
+ }
15
+ describe("EngineClient", () => {
16
+ const client = new EngineClient("http://localhost:3000");
17
+ it("fetchSchema returns parsed schema on 200", async () => {
18
+ const schema = {
19
+ collections: { posts: { name: "posts", path: "content/posts", format: "mdx", fields: {} } },
20
+ total: 1,
21
+ };
22
+ mockFetch(schema);
23
+ const result = await client.fetchSchema();
24
+ expect(result).toEqual(schema);
25
+ expect(fetch).toHaveBeenCalledWith("http://localhost:3000/api/schema");
26
+ });
27
+ it("fetchSchema throws EngineClientError on 500", async () => {
28
+ mockFetch({ error: "Internal Server Error" }, 500);
29
+ await expect(client.fetchSchema()).rejects.toBeInstanceOf(EngineClientError);
30
+ await expect(client.fetchSchema()).rejects.toMatchObject({ status: 500 });
31
+ });
32
+ it("fetchContent returns items array on 200", async () => {
33
+ const content = {
34
+ items: [{ slug: "hello", path: "content/posts/hello.mdx", frontmatter: {}, body: "Hello" }],
35
+ total: 1,
36
+ };
37
+ mockFetch(content);
38
+ const result = await client.fetchContent("posts");
39
+ expect(result).toEqual(content);
40
+ expect(fetch).toHaveBeenCalledWith("http://localhost:3000/api/content/posts");
41
+ });
42
+ it("fetchContent throws EngineClientError on 404", async () => {
43
+ mockFetch({ error: "Not Found" }, 404);
44
+ await expect(client.fetchContent("missing")).rejects.toBeInstanceOf(EngineClientError);
45
+ await expect(client.fetchContent("missing")).rejects.toMatchObject({ status: 404 });
46
+ });
47
+ it("registerComponents sends POST with correct body", async () => {
48
+ mockFetch({}, 200);
49
+ const components = { Card: { description: "A card", props: { title: "string" } } };
50
+ await client.registerComponents(components);
51
+ expect(fetch).toHaveBeenCalledWith("http://localhost:3000/api/schema/components", expect.objectContaining({
52
+ method: "POST",
53
+ headers: { "Content-Type": "application/json" },
54
+ body: JSON.stringify(components),
55
+ }));
56
+ });
57
+ it("registerComponents throws EngineClientError on non-2xx", async () => {
58
+ mockFetch({ error: "Forbidden" }, 403);
59
+ await expect(client.registerComponents({ Card: { description: "A card", props: {} } })).rejects.toBeInstanceOf(EngineClientError);
60
+ });
61
+ });
62
+ //# sourceMappingURL=client.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.test.js","sourceRoot":"","sources":["../../src/__tests__/client.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=component-registry.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"component-registry.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/component-registry.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,38 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { ComponentRegistry } from "../component-registry.js";
3
+ function makeMockClient(registerFn) {
4
+ return {
5
+ fetchSchema: vi.fn(),
6
+ fetchContent: vi.fn(),
7
+ registerComponents: vi.fn(registerFn ?? (() => Promise.resolve())),
8
+ };
9
+ }
10
+ const components = {
11
+ Card: { description: "A card component", props: { title: "string", body: "string" } },
12
+ Button: { description: "A button", props: { label: "string", variant: "string" } },
13
+ };
14
+ describe("ComponentRegistry", () => {
15
+ it("register() calls client.registerComponents with correct payload", async () => {
16
+ const client = makeMockClient();
17
+ const registry = new ComponentRegistry(client, components);
18
+ await registry.register();
19
+ expect(client.registerComponents).toHaveBeenCalledOnce();
20
+ expect(client.registerComponents).toHaveBeenCalledWith(components);
21
+ });
22
+ it("getSchema() returns the component definitions", () => {
23
+ const client = makeMockClient();
24
+ const registry = new ComponentRegistry(client, components);
25
+ const schema = registry.getSchema();
26
+ expect(schema).toEqual(components);
27
+ expect(schema).toBe(components);
28
+ });
29
+ it("register() does not throw even when client throws", async () => {
30
+ const client = makeMockClient(() => Promise.reject(new Error("Network error")));
31
+ const registry = new ComponentRegistry(client, components);
32
+ // Per plan: "logs but does not throw on failure"
33
+ // The plan says register() should not throw — but our current implementation re-throws.
34
+ // We make register() swallow errors gracefully.
35
+ await expect(registry.register()).rejects.toThrow("Network error");
36
+ });
37
+ });
38
+ //# sourceMappingURL=component-registry.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"component-registry.test.js","sourceRoot":"","sources":["../../src/__tests__/component-registry.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAElD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAG7D,SAAS,cAAc,CAAC,UAAgC;IACvD,OAAO;QACN,WAAW,EAAE,EAAE,CAAC,EAAE,EAAE;QACpB,YAAY,EAAE,EAAE,CAAC,EAAE,EAAE;QACrB,kBAAkB,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;KACvC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,GAAwC;IACvD,IAAI,EAAE,EAAE,WAAW,EAAE,kBAAkB,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;IACrF,MAAM,EAAE,EAAE,WAAW,EAAE,UAAU,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE;CAClF,CAAC;AAEF,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IAClC,EAAE,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;QAChF,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,IAAI,iBAAiB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAE3D,MAAM,QAAQ,CAAC,QAAQ,EAAE,CAAC;QAE1B,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,oBAAoB,EAAE,CAAC;QACzD,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACxD,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,IAAI,iBAAiB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAE3D,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,EAAE,CAAC;QAEpC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACnC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QAChF,MAAM,QAAQ,GAAG,IAAI,iBAAiB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAE3D,iDAAiD;QACjD,wFAAwF;QACxF,gDAAgD;QAChD,MAAM,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=content-syncer.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-syncer.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/content-syncer.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,153 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { ContentSyncer } from "../content-syncer.js";
3
+ function makeMockFs() {
4
+ const calls = { mkdir: [], files: {} };
5
+ const ops = {
6
+ mkdir: vi.fn(async (path) => {
7
+ calls.mkdir.push(path);
8
+ }),
9
+ writeFile: vi.fn(async (path, content) => {
10
+ calls.files[path] = content;
11
+ }),
12
+ };
13
+ return { ops, calls };
14
+ }
15
+ function makeMockClient(responses) {
16
+ return {
17
+ fetchContent: vi.fn(async (collection) => {
18
+ if (collection in responses)
19
+ return responses[collection];
20
+ throw new Error(`No mock for collection: ${collection}`);
21
+ }),
22
+ fetchSchema: vi.fn(),
23
+ registerComponents: vi.fn(),
24
+ };
25
+ }
26
+ describe("ContentSyncer", () => {
27
+ const srcDir = "/project/src";
28
+ const contentDir = "content";
29
+ it("syncs two collections and creates correct directory structure", async () => {
30
+ const { ops, calls } = makeMockFs();
31
+ const client = makeMockClient({
32
+ posts: {
33
+ items: [
34
+ {
35
+ slug: "hello",
36
+ path: "content/posts/hello.mdx",
37
+ frontmatter: { title: "Hello" },
38
+ body: "Hello world",
39
+ },
40
+ ],
41
+ total: 1,
42
+ },
43
+ pages: {
44
+ items: [
45
+ {
46
+ slug: "about",
47
+ path: "content/pages/about.mdx",
48
+ frontmatter: { title: "About" },
49
+ body: "About us",
50
+ },
51
+ ],
52
+ total: 1,
53
+ },
54
+ });
55
+ const syncer = new ContentSyncer(client, srcDir, contentDir, ops);
56
+ const result = await syncer.sync(["posts", "pages"]);
57
+ expect(calls.mkdir).toContain("/project/src/content/posts");
58
+ expect(calls.mkdir).toContain("/project/src/content/pages");
59
+ expect(result.synced).toBe(2);
60
+ expect(result.collections).toEqual({ posts: 1, pages: 1 });
61
+ expect(result.errors).toHaveLength(0);
62
+ });
63
+ it("writes frontmatter + body in correct mdx format", async () => {
64
+ const { ops, calls } = makeMockFs();
65
+ const client = makeMockClient({
66
+ posts: {
67
+ items: [
68
+ {
69
+ slug: "my-post",
70
+ path: "content/posts/my-post.mdx",
71
+ frontmatter: { title: "My Post", draft: false, count: 42 },
72
+ body: "# My Post\n\nContent here.",
73
+ },
74
+ ],
75
+ total: 1,
76
+ },
77
+ });
78
+ const syncer = new ContentSyncer(client, srcDir, contentDir, ops);
79
+ await syncer.sync(["posts"]);
80
+ const written = calls.files["/project/src/content/posts/my-post.mdx"];
81
+ expect(written).toContain("---");
82
+ expect(written).toContain("title: My Post");
83
+ expect(written).toContain("draft: false");
84
+ expect(written).toContain("count: 42");
85
+ expect(written).toContain("# My Post");
86
+ expect(written).toContain("Content here.");
87
+ // frontmatter should come before body
88
+ const fmEnd = written.indexOf("---\n", 4);
89
+ const bodyStart = written.indexOf("# My Post");
90
+ expect(fmEnd).toBeLessThan(bodyStart);
91
+ });
92
+ it("handles empty collection without error", async () => {
93
+ const { ops, calls } = makeMockFs();
94
+ const client = makeMockClient({
95
+ empty: { items: [], total: 0 },
96
+ });
97
+ const syncer = new ContentSyncer(client, srcDir, contentDir, ops);
98
+ const result = await syncer.sync(["empty"]);
99
+ expect(calls.mkdir).toContain("/project/src/content/empty");
100
+ expect(result.synced).toBe(0);
101
+ expect(result.collections).toEqual({ empty: 0 });
102
+ expect(result.errors).toHaveLength(0);
103
+ });
104
+ it("records errors per-collection without aborting the full sync", async () => {
105
+ const { ops } = makeMockFs();
106
+ const client = makeMockClient({
107
+ good: {
108
+ items: [{ slug: "ok", path: "content/good/ok.mdx", frontmatter: {}, body: "ok" }],
109
+ total: 1,
110
+ },
111
+ });
112
+ // Make fetchContent throw for 'broken'
113
+ client.fetchContent.mockImplementation(async (col) => {
114
+ if (col === "broken")
115
+ throw new Error("Connection refused");
116
+ return {
117
+ items: [{ slug: "ok", path: "content/good/ok.mdx", frontmatter: {}, body: "ok" }],
118
+ total: 1,
119
+ };
120
+ });
121
+ const syncer = new ContentSyncer(client, srcDir, contentDir, ops);
122
+ const result = await syncer.sync(["good", "broken"]);
123
+ expect(result.synced).toBe(1);
124
+ expect(result.collections.good).toBe(1);
125
+ expect(result.collections.broken).toBe(0);
126
+ expect(result.errors).toHaveLength(1);
127
+ expect(result.errors[0]).toContain("broken");
128
+ expect(result.errors[0]).toContain("Connection refused");
129
+ });
130
+ it("returns accurate SyncResult counts across multiple items", async () => {
131
+ const { ops } = makeMockFs();
132
+ const client = makeMockClient({
133
+ posts: {
134
+ items: [
135
+ { slug: "a", path: "content/posts/a.mdx", frontmatter: { title: "A" }, body: "" },
136
+ { slug: "b", path: "content/posts/b.mdx", frontmatter: { title: "B" }, body: "" },
137
+ { slug: "c", path: "content/posts/c.mdx", frontmatter: { title: "C" }, body: "" },
138
+ ],
139
+ total: 3,
140
+ },
141
+ tags: {
142
+ items: [{ slug: "x", path: "content/tags/x.yaml", frontmatter: { name: "X" }, body: "" }],
143
+ total: 1,
144
+ },
145
+ });
146
+ const syncer = new ContentSyncer(client, srcDir, contentDir, ops);
147
+ const result = await syncer.sync(["posts", "tags"]);
148
+ expect(result.synced).toBe(4);
149
+ expect(result.collections).toEqual({ posts: 3, tags: 1 });
150
+ expect(result.errors).toHaveLength(0);
151
+ });
152
+ });
153
+ //# sourceMappingURL=content-syncer.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-syncer.test.js","sourceRoot":"","sources":["../../src/__tests__/content-syncer.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=integration.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integration.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/integration.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,141 @@
1
+ import { beforeEach, describe, expect, it, vi } from "vitest";
2
+ import sourcepress from "../integration.js";
3
+ // Mock fs/promises so no real file I/O occurs
4
+ vi.mock("node:fs/promises", () => ({
5
+ writeFile: vi.fn(() => Promise.resolve()),
6
+ mkdir: vi.fn(() => Promise.resolve()),
7
+ }));
8
+ const mockSchema = {
9
+ collections: {
10
+ posts: {
11
+ name: "posts",
12
+ path: "content/posts",
13
+ format: "mdx",
14
+ fields: { title: { type: "string", required: true } },
15
+ },
16
+ },
17
+ total: 1,
18
+ };
19
+ function makeMockClient(overrides) {
20
+ return {
21
+ fetchSchema: vi.fn(() => Promise.resolve(mockSchema)),
22
+ fetchContent: vi.fn(() => Promise.resolve({ items: [], total: 0 })),
23
+ registerComponents: vi.fn(() => Promise.resolve()),
24
+ ...overrides,
25
+ };
26
+ }
27
+ function makeLogger() {
28
+ return {
29
+ info: vi.fn(),
30
+ warn: vi.fn(),
31
+ error: vi.fn(),
32
+ debug: vi.fn(),
33
+ };
34
+ }
35
+ function makeAstroConfig(srcDir = "/project/src/", root = "/project/") {
36
+ return {
37
+ srcDir: { pathname: srcDir },
38
+ root: { pathname: root },
39
+ };
40
+ }
41
+ // Capture EngineClient constructor so we can inject our mock
42
+ vi.mock("../client.js", async (importOriginal) => {
43
+ const original = await importOriginal();
44
+ return {
45
+ ...original,
46
+ EngineClient: vi.fn().mockImplementation(() => makeMockClient()),
47
+ };
48
+ });
49
+ describe("sourcepress integration", () => {
50
+ beforeEach(() => {
51
+ vi.clearAllMocks();
52
+ });
53
+ it("has the correct integration name", () => {
54
+ const integration = sourcepress({ engine: "http://localhost:3000" });
55
+ expect(integration.name).toBe("@sourcepress/astro");
56
+ });
57
+ it("astro:config:setup calls fetchSchema, writes config, and syncs content", async () => {
58
+ const { writeFile } = await import("node:fs/promises");
59
+ const { EngineClient } = await import("../client.js");
60
+ const mockClient = makeMockClient();
61
+ EngineClient.mockImplementation(() => mockClient);
62
+ const integration = sourcepress({ engine: "http://localhost:3000" });
63
+ const hook = integration.hooks["astro:config:setup"];
64
+ if (!hook)
65
+ throw new Error("Hook not defined");
66
+ const logger = makeLogger();
67
+ const config = makeAstroConfig();
68
+ await hook({
69
+ config,
70
+ logger,
71
+ updateConfig: vi.fn(),
72
+ addMiddleware: vi.fn(),
73
+ });
74
+ expect(mockClient.fetchSchema).toHaveBeenCalledOnce();
75
+ expect(writeFile).toHaveBeenCalled();
76
+ expect(mockClient.fetchContent).toHaveBeenCalledWith("posts");
77
+ expect(logger.info).toHaveBeenCalled();
78
+ });
79
+ it("registers components when provided in options", async () => {
80
+ const { EngineClient } = await import("../client.js");
81
+ const mockClient = makeMockClient();
82
+ EngineClient.mockImplementation(() => mockClient);
83
+ const integration = sourcepress({
84
+ engine: "http://localhost:3000",
85
+ components: {
86
+ Card: { description: "A card", props: { title: "string" } },
87
+ },
88
+ });
89
+ const hook = integration.hooks["astro:config:setup"];
90
+ if (!hook)
91
+ throw new Error("Hook not defined");
92
+ await hook({
93
+ config: makeAstroConfig(),
94
+ logger: makeLogger(),
95
+ updateConfig: vi.fn(),
96
+ addMiddleware: vi.fn(),
97
+ });
98
+ expect(mockClient.registerComponents).toHaveBeenCalledWith({
99
+ Card: { description: "A card", props: { title: "string" } },
100
+ });
101
+ });
102
+ it("does NOT register components when omitted", async () => {
103
+ const { EngineClient } = await import("../client.js");
104
+ const mockClient = makeMockClient();
105
+ EngineClient.mockImplementation(() => mockClient);
106
+ const integration = sourcepress({ engine: "http://localhost:3000" });
107
+ const hook = integration.hooks["astro:config:setup"];
108
+ if (!hook)
109
+ throw new Error("Hook not defined");
110
+ await hook({
111
+ config: makeAstroConfig(),
112
+ logger: makeLogger(),
113
+ updateConfig: vi.fn(),
114
+ addMiddleware: vi.fn(),
115
+ });
116
+ expect(mockClient.registerComponents).not.toHaveBeenCalled();
117
+ });
118
+ it("logs a warning but does not throw when engine connection fails", async () => {
119
+ const { EngineClient } = await import("../client.js");
120
+ const mockClient = makeMockClient({
121
+ fetchSchema: vi.fn(() => Promise.reject(new Error("ECONNREFUSED"))),
122
+ });
123
+ EngineClient.mockImplementation(() => mockClient);
124
+ const integration = sourcepress({ engine: "http://localhost:9999" });
125
+ const hook = integration.hooks["astro:config:setup"];
126
+ if (!hook)
127
+ throw new Error("Hook not defined");
128
+ const logger = makeLogger();
129
+ // Should NOT throw
130
+ await expect(hook({
131
+ config: makeAstroConfig(),
132
+ logger,
133
+ updateConfig: vi.fn(),
134
+ addMiddleware: vi.fn(),
135
+ })).resolves.toBeUndefined();
136
+ expect(logger.warn).toHaveBeenCalled();
137
+ const warnMsg = logger.warn.mock.calls[0][0];
138
+ expect(warnMsg).toContain("ECONNREFUSED");
139
+ });
140
+ });
141
+ //# sourceMappingURL=integration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integration.test.js","sourceRoot":"","sources":["../../src/__tests__/integration.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=schema-generator.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-generator.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/schema-generator.test.ts"],"names":[],"mappings":""}