@larkiny/astro-github-loader 0.11.3 → 0.12.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 (51) hide show
  1. package/README.md +28 -55
  2. package/dist/github.assets.d.ts +70 -0
  3. package/dist/github.assets.js +253 -0
  4. package/dist/github.auth.js +13 -9
  5. package/dist/github.cleanup.d.ts +3 -2
  6. package/dist/github.cleanup.js +30 -23
  7. package/dist/github.constants.d.ts +0 -16
  8. package/dist/github.constants.js +0 -16
  9. package/dist/github.content.d.ts +5 -131
  10. package/dist/github.content.js +152 -794
  11. package/dist/github.dryrun.d.ts +9 -5
  12. package/dist/github.dryrun.js +46 -25
  13. package/dist/github.link-transform.d.ts +2 -2
  14. package/dist/github.link-transform.js +65 -57
  15. package/dist/github.loader.js +30 -46
  16. package/dist/github.logger.d.ts +2 -2
  17. package/dist/github.logger.js +33 -24
  18. package/dist/github.paths.d.ts +76 -0
  19. package/dist/github.paths.js +190 -0
  20. package/dist/github.storage.d.ts +15 -0
  21. package/dist/github.storage.js +109 -0
  22. package/dist/github.types.d.ts +34 -4
  23. package/dist/index.d.ts +8 -6
  24. package/dist/index.js +3 -6
  25. package/dist/test-helpers.d.ts +130 -0
  26. package/dist/test-helpers.js +194 -0
  27. package/package.json +3 -1
  28. package/src/github.assets.spec.ts +717 -0
  29. package/src/github.assets.ts +365 -0
  30. package/src/github.auth.spec.ts +245 -0
  31. package/src/github.auth.ts +24 -10
  32. package/src/github.cleanup.spec.ts +380 -0
  33. package/src/github.cleanup.ts +91 -47
  34. package/src/github.constants.ts +0 -17
  35. package/src/github.content.spec.ts +305 -454
  36. package/src/github.content.ts +259 -957
  37. package/src/github.dryrun.spec.ts +586 -0
  38. package/src/github.dryrun.ts +105 -54
  39. package/src/github.link-transform.spec.ts +1345 -0
  40. package/src/github.link-transform.ts +174 -95
  41. package/src/github.loader.spec.ts +75 -50
  42. package/src/github.loader.ts +101 -76
  43. package/src/github.logger.spec.ts +795 -0
  44. package/src/github.logger.ts +77 -35
  45. package/src/github.paths.spec.ts +523 -0
  46. package/src/github.paths.ts +259 -0
  47. package/src/github.storage.spec.ts +367 -0
  48. package/src/github.storage.ts +127 -0
  49. package/src/github.types.ts +48 -9
  50. package/src/index.ts +43 -6
  51. package/src/test-helpers.ts +215 -0
package/dist/index.js CHANGED
@@ -1,6 +1,3 @@
1
- export * from './github.auth.js';
2
- export * from './github.constants.js';
3
- export * from './github.content.js';
4
- export * from './github.loader.js';
5
- export * from './github.types.js';
6
- export * from './github.link-transform.js';
1
+ // Public API — functions
2
+ export { githubLoader } from "./github.loader.js";
3
+ export { createAuthenticatedOctokit, createOctokitFromEnv, } from "./github.auth.js";
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Creates a mock Astro LoaderContext with all required properties.
3
+ * The returned store is a real Map wrapped in the store interface,
4
+ * so tests can inspect stored entries directly.
5
+ */
6
+ export declare function createMockContext(): {
7
+ store: {
8
+ set: (entry: any) => any;
9
+ get: (id: string) => any;
10
+ delete: (id: string) => boolean;
11
+ clear: () => void;
12
+ entries: () => MapIterator<[string, any]>;
13
+ keys: () => MapIterator<string>;
14
+ values: () => MapIterator<any>;
15
+ };
16
+ meta: Map<string, string>;
17
+ logger: {
18
+ info: import("vitest").Mock<(...args: any[]) => any>;
19
+ warn: import("vitest").Mock<(...args: any[]) => any>;
20
+ error: import("vitest").Mock<(...args: any[]) => any>;
21
+ debug: import("vitest").Mock<(...args: any[]) => any>;
22
+ verbose: import("vitest").Mock<(...args: any[]) => any>;
23
+ logFileProcessing: import("vitest").Mock<(...args: any[]) => any>;
24
+ logImportSummary: import("vitest").Mock<(...args: any[]) => any>;
25
+ logAssetProcessing: import("vitest").Mock<(...args: any[]) => any>;
26
+ withSpinner: (_msg: string, fn: () => Promise<any>) => Promise<any>;
27
+ getLevel: () => "default";
28
+ };
29
+ config: {};
30
+ entryTypes: Map<string, {
31
+ getEntryInfo: ({ contents, }: {
32
+ contents: string;
33
+ fileUrl: URL;
34
+ }) => Promise<{
35
+ body: string;
36
+ data: {};
37
+ }>;
38
+ }>;
39
+ generateDigest: (content: string) => string;
40
+ parseData: (data: any) => Promise<any>;
41
+ /** Direct access to the underlying store Map for assertions */
42
+ _store: Map<string, any>;
43
+ /** Direct access to the underlying meta Map for assertions */
44
+ _meta: Map<string, string>;
45
+ };
46
+ /** Standard mock commit used across tests */
47
+ export declare const MOCK_COMMIT: {
48
+ sha: string;
49
+ commit: {
50
+ tree: {
51
+ sha: string;
52
+ };
53
+ message: string;
54
+ author: {
55
+ name: string;
56
+ email: string;
57
+ date: string;
58
+ };
59
+ committer: {
60
+ name: string;
61
+ email: string;
62
+ date: string;
63
+ };
64
+ };
65
+ };
66
+ /** Mock tree data representing a typical repository structure */
67
+ export declare const MOCK_TREE_DATA: {
68
+ sha: string;
69
+ url: string;
70
+ tree: ({
71
+ path: string;
72
+ mode: string;
73
+ type: string;
74
+ sha: string;
75
+ size: number;
76
+ url: string;
77
+ } | {
78
+ path: string;
79
+ mode: string;
80
+ type: string;
81
+ sha: string;
82
+ url: string;
83
+ size?: undefined;
84
+ })[];
85
+ truncated: boolean;
86
+ };
87
+ /**
88
+ * Creates an Octokit instance with mocked API methods for listCommits and getTree.
89
+ * Returns both the instance and the spies for assertions.
90
+ */
91
+ export declare function createMockOctokit(options?: {
92
+ treeData?: typeof MOCK_TREE_DATA;
93
+ commitData?: typeof MOCK_COMMIT;
94
+ }): {
95
+ octokit: import("@octokit/core").Octokit & {
96
+ paginate: import("@octokit/plugin-paginate-rest").PaginateInterface;
97
+ } & import("@octokit/plugin-paginate-graphql").paginateGraphQLInterface & import("@octokit/plugin-rest-endpoint-methods").Api & {
98
+ retry: {
99
+ retryRequest: (error: import("octokit").RequestError, retries: number, retryAfter: number) => import("octokit").RequestError;
100
+ };
101
+ };
102
+ spies: {
103
+ listCommitsSpy: import("vitest").MockInstance<{
104
+ (params?: import("@octokit/plugin-rest-endpoint-methods").RestEndpointMethodTypes["repos"]["listCommits"]["parameters"]): Promise<import("@octokit/plugin-rest-endpoint-methods").RestEndpointMethodTypes["repos"]["listCommits"]["response"]>;
105
+ defaults: import("@octokit/types").RequestInterface["defaults"];
106
+ endpoint: import("@octokit/types").EndpointInterface<{
107
+ url: string;
108
+ }>;
109
+ }>;
110
+ getTreeSpy: import("vitest").MockInstance<{
111
+ (params?: import("@octokit/plugin-rest-endpoint-methods").RestEndpointMethodTypes["git"]["getTree"]["parameters"]): Promise<import("@octokit/plugin-rest-endpoint-methods").RestEndpointMethodTypes["git"]["getTree"]["response"]>;
112
+ defaults: import("@octokit/types").RequestInterface["defaults"];
113
+ endpoint: import("@octokit/types").EndpointInterface<{
114
+ url: string;
115
+ }>;
116
+ }>;
117
+ getContentSpy: import("vitest").MockInstance<{
118
+ (params?: import("@octokit/plugin-rest-endpoint-methods").RestEndpointMethodTypes["repos"]["getContent"]["parameters"]): Promise<import("@octokit/plugin-rest-endpoint-methods").RestEndpointMethodTypes["repos"]["getContent"]["response"]>;
119
+ defaults: import("@octokit/types").RequestInterface["defaults"];
120
+ endpoint: import("@octokit/types").EndpointInterface<{
121
+ url: string;
122
+ }>;
123
+ }>;
124
+ };
125
+ };
126
+ /**
127
+ * Sets up a global fetch mock that returns markdown content.
128
+ * Returns the mock for assertions.
129
+ */
130
+ export declare function mockFetch(content?: string): import("vitest").Mock<(...args: any[]) => any>;
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Shared test helpers for astro-github-loader test suite.
3
+ * Provides factory functions for creating mock Astro loader contexts,
4
+ * Octokit instances with pre-configured spies, and common fixtures.
5
+ */
6
+ import { vi } from "vitest";
7
+ import { Octokit } from "octokit";
8
+ /**
9
+ * Creates a mock Astro LoaderContext with all required properties.
10
+ * The returned store is a real Map wrapped in the store interface,
11
+ * so tests can inspect stored entries directly.
12
+ */
13
+ export function createMockContext() {
14
+ const store = new Map();
15
+ const meta = new Map();
16
+ return {
17
+ store: {
18
+ set: (entry) => {
19
+ store.set(entry.id, entry);
20
+ return entry;
21
+ },
22
+ get: (id) => store.get(id),
23
+ delete: (id) => store.delete(id),
24
+ clear: () => store.clear(),
25
+ entries: () => store.entries(),
26
+ keys: () => store.keys(),
27
+ values: () => store.values(),
28
+ },
29
+ meta,
30
+ logger: {
31
+ info: vi.fn(),
32
+ warn: vi.fn(),
33
+ error: vi.fn(),
34
+ debug: vi.fn(),
35
+ verbose: vi.fn(),
36
+ logFileProcessing: vi.fn(),
37
+ logImportSummary: vi.fn(),
38
+ logAssetProcessing: vi.fn(),
39
+ withSpinner: async (_msg, fn) => await fn(),
40
+ getLevel: () => "default",
41
+ },
42
+ config: {},
43
+ entryTypes: new Map([
44
+ [
45
+ ".md",
46
+ {
47
+ getEntryInfo: async ({ contents, }) => ({
48
+ body: contents,
49
+ data: {},
50
+ }),
51
+ },
52
+ ],
53
+ ]),
54
+ generateDigest: (content) => String(content.length),
55
+ parseData: async (data) => data,
56
+ /** Direct access to the underlying store Map for assertions */
57
+ _store: store,
58
+ /** Direct access to the underlying meta Map for assertions */
59
+ _meta: meta,
60
+ };
61
+ }
62
+ /** Standard mock commit used across tests */
63
+ export const MOCK_COMMIT = {
64
+ sha: "abc123def456",
65
+ commit: {
66
+ tree: { sha: "tree123abc456" },
67
+ message: "Test commit",
68
+ author: {
69
+ name: "Test Author",
70
+ email: "test@example.com",
71
+ date: "2024-01-01T00:00:00Z",
72
+ },
73
+ committer: {
74
+ name: "Test Committer",
75
+ email: "test@example.com",
76
+ date: "2024-01-01T00:00:00Z",
77
+ },
78
+ },
79
+ };
80
+ /** Mock tree data representing a typical repository structure */
81
+ export const MOCK_TREE_DATA = {
82
+ sha: "tree123abc456",
83
+ url: "https://api.github.com/repos/test/repo/git/trees/tree123abc456",
84
+ tree: [
85
+ {
86
+ path: "docs/algokit.md",
87
+ mode: "100644",
88
+ type: "blob",
89
+ sha: "file1sha",
90
+ size: 1234,
91
+ url: "https://api.github.com/repos/test/repo/git/blobs/file1sha",
92
+ },
93
+ {
94
+ path: "docs/features",
95
+ mode: "040000",
96
+ type: "tree",
97
+ sha: "dir1sha",
98
+ url: "https://api.github.com/repos/test/repo/git/trees/dir1sha",
99
+ },
100
+ {
101
+ path: "docs/features/accounts.md",
102
+ mode: "100644",
103
+ type: "blob",
104
+ sha: "file2sha",
105
+ size: 2345,
106
+ url: "https://api.github.com/repos/test/repo/git/blobs/file2sha",
107
+ },
108
+ {
109
+ path: "docs/features/tasks.md",
110
+ mode: "100644",
111
+ type: "blob",
112
+ sha: "file3sha",
113
+ size: 3456,
114
+ url: "https://api.github.com/repos/test/repo/git/blobs/file3sha",
115
+ },
116
+ {
117
+ path: "docs/features/generate.md",
118
+ mode: "100644",
119
+ type: "blob",
120
+ sha: "file4sha",
121
+ size: 4567,
122
+ url: "https://api.github.com/repos/test/repo/git/blobs/file4sha",
123
+ },
124
+ {
125
+ path: "docs/cli/index.md",
126
+ mode: "100644",
127
+ type: "blob",
128
+ sha: "file5sha",
129
+ size: 5678,
130
+ url: "https://api.github.com/repos/test/repo/git/blobs/file5sha",
131
+ },
132
+ {
133
+ path: "README.md",
134
+ mode: "100644",
135
+ type: "blob",
136
+ sha: "file6sha",
137
+ size: 678,
138
+ url: "https://api.github.com/repos/test/repo/git/blobs/file6sha",
139
+ },
140
+ {
141
+ path: "package.json",
142
+ mode: "100644",
143
+ type: "blob",
144
+ sha: "file7sha",
145
+ size: 789,
146
+ url: "https://api.github.com/repos/test/repo/git/blobs/file7sha",
147
+ },
148
+ ],
149
+ truncated: false,
150
+ };
151
+ /**
152
+ * Creates an Octokit instance with mocked API methods for listCommits and getTree.
153
+ * Returns both the instance and the spies for assertions.
154
+ */
155
+ export function createMockOctokit(options) {
156
+ const octokit = new Octokit({ auth: "mock-token" });
157
+ const commit = options?.commitData ?? MOCK_COMMIT;
158
+ const tree = options?.treeData ?? MOCK_TREE_DATA;
159
+ const listCommitsSpy = vi
160
+ .spyOn(octokit.rest.repos, "listCommits")
161
+ .mockResolvedValue({
162
+ data: [commit],
163
+ status: 200,
164
+ url: "",
165
+ headers: {},
166
+ });
167
+ const getTreeSpy = vi.spyOn(octokit.rest.git, "getTree").mockResolvedValue({
168
+ data: tree,
169
+ status: 200,
170
+ url: "",
171
+ headers: {},
172
+ });
173
+ const getContentSpy = vi
174
+ .spyOn(octokit.rest.repos, "getContent")
175
+ .mockResolvedValue({ data: [], status: 200, url: "", headers: {} });
176
+ return {
177
+ octokit,
178
+ spies: { listCommitsSpy, getTreeSpy, getContentSpy },
179
+ };
180
+ }
181
+ /**
182
+ * Sets up a global fetch mock that returns markdown content.
183
+ * Returns the mock for assertions.
184
+ */
185
+ export function mockFetch(content = "# Test Content\n\nThis is test markdown content.") {
186
+ const fetchMock = vi.fn().mockResolvedValue({
187
+ ok: true,
188
+ status: 200,
189
+ headers: new Headers(),
190
+ text: async () => content,
191
+ });
192
+ global.fetch = fetchMock;
193
+ return fetchMock;
194
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@larkiny/astro-github-loader",
3
3
  "type": "module",
4
- "version": "0.11.3",
4
+ "version": "0.12.0",
5
5
  "description": "Load content from GitHub repositories into Astro content collections with asset management and content transformations",
6
6
  "keywords": [
7
7
  "astro",
@@ -38,6 +38,7 @@
38
38
  "build": "tsc",
39
39
  "test": "vitest run",
40
40
  "test:watch": "vitest",
41
+ "test:coverage": "vitest run --coverage",
41
42
  "lint": "eslint .",
42
43
  "prettier": "prettier --check .",
43
44
  "preview": "astro preview",
@@ -57,6 +58,7 @@
57
58
  "@types/node": "^22.14.0",
58
59
  "@types/picomatch": "^4.0.0",
59
60
  "@typescript-eslint/parser": "^8.29.0",
61
+ "@vitest/coverage-v8": "^3.2.4",
60
62
  "eslint": "^9.24.0",
61
63
  "eslint-plugin-astro": "^1.3.1",
62
64
  "prettier": "3.5.3",