blodemd 0.0.4 → 0.0.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.
- package/README.md +12 -1
- package/dev-server/app/[[...slug]]/page.tsx +139 -0
- package/dev-server/app/blodemd-dev/invalidate/route.ts +12 -0
- package/dev-server/app/blodemd-dev/static/[...path]/route.ts +32 -0
- package/dev-server/app/blodemd-dev/version/route.ts +14 -0
- package/dev-server/app/blodemd-internal/proxy/route.ts +86 -0
- package/dev-server/app/error.tsx +24 -0
- package/dev-server/app/globals.css +4 -0
- package/dev-server/app/layout.tsx +38 -0
- package/dev-server/app/not-found.tsx +18 -0
- package/dev-server/app/search/route.ts +17 -0
- package/dev-server/components/dev-reload-script.tsx +86 -0
- package/dev-server/components/providers.tsx +15 -0
- package/dev-server/lib/dev-state.ts +8 -0
- package/dev-server/lib/local-content-source.ts +103 -0
- package/dev-server/lib/local-runtime.tsx +558 -0
- package/dev-server/next.config.js +46 -0
- package/dev-server/package.json +57 -0
- package/dev-server/postcss.config.mjs +7 -0
- package/dev-server/public/glide-variable.woff2 +0 -0
- package/dev-server/tsconfig.json +49 -0
- package/dist/cli.mjs +299 -26
- package/dist/cli.mjs.map +1 -1
- package/docs/app/globals.css +455 -0
- package/docs/components/api/api-playground.tsx +295 -0
- package/docs/components/api/api-reference.tsx +121 -0
- package/docs/components/content/collection-index.tsx +114 -0
- package/docs/components/docs/contextual-menu.tsx +406 -0
- package/docs/components/docs/copy-page-menu.tsx +255 -0
- package/docs/components/docs/doc-header.tsx +192 -0
- package/docs/components/docs/doc-shell.tsx +289 -0
- package/docs/components/docs/doc-sidebar.tsx +206 -0
- package/docs/components/docs/doc-toc.tsx +45 -0
- package/docs/components/docs/mobile-nav.tsx +207 -0
- package/docs/components/mdx/accordion.tsx +83 -0
- package/docs/components/mdx/badge.tsx +79 -0
- package/docs/components/mdx/callout.tsx +88 -0
- package/docs/components/mdx/card.tsx +104 -0
- package/docs/components/mdx/code-block.tsx +75 -0
- package/docs/components/mdx/code-group.tsx +94 -0
- package/docs/components/mdx/color.tsx +87 -0
- package/docs/components/mdx/columns.tsx +25 -0
- package/docs/components/mdx/expandable.tsx +45 -0
- package/docs/components/mdx/field-layout.tsx +77 -0
- package/docs/components/mdx/frame.tsx +23 -0
- package/docs/components/mdx/get-text-content.ts +18 -0
- package/docs/components/mdx/icon.tsx +56 -0
- package/docs/components/mdx/index.tsx +96 -0
- package/docs/components/mdx/installer.tsx +20 -0
- package/docs/components/mdx/panel.tsx +11 -0
- package/docs/components/mdx/param-field.tsx +56 -0
- package/docs/components/mdx/preview.tsx +36 -0
- package/docs/components/mdx/prompt.tsx +63 -0
- package/docs/components/mdx/request-example.tsx +27 -0
- package/docs/components/mdx/response-field.tsx +42 -0
- package/docs/components/mdx/steps.tsx +92 -0
- package/docs/components/mdx/tabs.tsx +88 -0
- package/docs/components/mdx/tile.tsx +43 -0
- package/docs/components/mdx/tooltip.tsx +71 -0
- package/docs/components/mdx/tree.tsx +120 -0
- package/docs/components/mdx/type-table.tsx +71 -0
- package/docs/components/mdx/update.tsx +44 -0
- package/docs/components/mdx/video.tsx +12 -0
- package/docs/components/mdx/view.tsx +66 -0
- package/docs/components/providers.tsx +15 -0
- package/docs/components/ui/breadcrumb.tsx +92 -0
- package/docs/components/ui/button.tsx +90 -0
- package/docs/components/ui/card.tsx +92 -0
- package/docs/components/ui/command.tsx +139 -0
- package/docs/components/ui/dialog.tsx +97 -0
- package/docs/components/ui/field.tsx +237 -0
- package/docs/components/ui/input.tsx +105 -0
- package/docs/components/ui/label.tsx +22 -0
- package/docs/components/ui/popover.tsx +72 -0
- package/docs/components/ui/search.tsx +380 -0
- package/docs/components/ui/separator.tsx +26 -0
- package/docs/components/ui/sheet.tsx +104 -0
- package/docs/components/ui/sidebar.tsx +433 -0
- package/docs/components/ui/theme-toggle.tsx +62 -0
- package/docs/components/ui/tooltip.tsx +53 -0
- package/docs/lib/contextual-options.ts +193 -0
- package/docs/lib/docs-collection.ts +22 -0
- package/docs/lib/mdx.ts +90 -0
- package/docs/lib/navigation.ts +288 -0
- package/docs/lib/openapi.ts +158 -0
- package/docs/lib/routes.ts +10 -0
- package/docs/lib/server-cache.ts +83 -0
- package/docs/lib/shiki.ts +35 -0
- package/docs/lib/theme.ts +29 -0
- package/docs/lib/toc.ts +2 -0
- package/docs/lib/utils.ts +5 -0
- package/package.json +34 -3
- package/packages/@repo/common/dist/index.d.ts +9 -0
- package/packages/@repo/common/dist/index.d.ts.map +1 -0
- package/packages/@repo/common/dist/index.js +42 -0
- package/packages/@repo/common/package.json +34 -0
- package/packages/@repo/common/src/common.unit.test.ts +55 -0
- package/packages/@repo/common/src/index.ts +51 -0
- package/packages/@repo/contracts/dist/api-key.d.ts +30 -0
- package/packages/@repo/contracts/dist/api-key.d.ts.map +1 -0
- package/packages/@repo/contracts/dist/api-key.js +20 -0
- package/packages/@repo/contracts/dist/dates.d.ts +4 -0
- package/packages/@repo/contracts/dist/dates.d.ts.map +1 -0
- package/packages/@repo/contracts/dist/dates.js +2 -0
- package/packages/@repo/contracts/dist/deployment.d.ts +71 -0
- package/packages/@repo/contracts/dist/deployment.d.ts.map +1 -0
- package/packages/@repo/contracts/dist/deployment.js +46 -0
- package/packages/@repo/contracts/dist/domain.d.ts +94 -0
- package/packages/@repo/contracts/dist/domain.d.ts.map +1 -0
- package/packages/@repo/contracts/dist/domain.js +36 -0
- package/packages/@repo/contracts/dist/ids.d.ts +14 -0
- package/packages/@repo/contracts/dist/ids.d.ts.map +1 -0
- package/packages/@repo/contracts/dist/ids.js +10 -0
- package/packages/@repo/contracts/dist/index.d.ts +10 -0
- package/packages/@repo/contracts/dist/index.d.ts.map +1 -0
- package/packages/@repo/contracts/dist/index.js +11 -0
- package/packages/@repo/contracts/dist/pagination.d.ts +23 -0
- package/packages/@repo/contracts/dist/pagination.d.ts.map +1 -0
- package/packages/@repo/contracts/dist/pagination.js +15 -0
- package/packages/@repo/contracts/dist/project.d.ts +25 -0
- package/packages/@repo/contracts/dist/project.d.ts.map +1 -0
- package/packages/@repo/contracts/dist/project.js +23 -0
- package/packages/@repo/contracts/dist/tenant.d.ts +99 -0
- package/packages/@repo/contracts/dist/tenant.d.ts.map +1 -0
- package/packages/@repo/contracts/dist/tenant.js +36 -0
- package/packages/@repo/contracts/dist/user.d.ts +9 -0
- package/packages/@repo/contracts/dist/user.d.ts.map +1 -0
- package/packages/@repo/contracts/dist/user.js +9 -0
- package/packages/@repo/contracts/package.json +37 -0
- package/packages/@repo/contracts/src/api-key.ts +27 -0
- package/packages/@repo/contracts/src/dates.ts +4 -0
- package/packages/@repo/contracts/src/deployment.ts +73 -0
- package/packages/@repo/contracts/src/domain.ts +51 -0
- package/packages/@repo/contracts/src/ids.ts +22 -0
- package/packages/@repo/contracts/src/index.ts +11 -0
- package/packages/@repo/contracts/src/pagination.ts +21 -0
- package/packages/@repo/contracts/src/project.ts +30 -0
- package/packages/@repo/contracts/src/tenant.ts +54 -0
- package/packages/@repo/contracts/src/user.ts +12 -0
- package/packages/@repo/models/dist/docs-config.d.ts +985 -0
- package/packages/@repo/models/dist/docs-config.d.ts.map +1 -0
- package/packages/@repo/models/dist/docs-config.js +548 -0
- package/packages/@repo/models/dist/index.d.ts +3 -0
- package/packages/@repo/models/dist/index.d.ts.map +1 -0
- package/packages/@repo/models/dist/index.js +3 -0
- package/packages/@repo/models/dist/tenant.d.ts +25 -0
- package/packages/@repo/models/dist/tenant.d.ts.map +1 -0
- package/packages/@repo/models/dist/tenant.js +1 -0
- package/packages/@repo/models/package.json +37 -0
- package/packages/@repo/models/src/docs-config.ts +648 -0
- package/packages/@repo/models/src/index.ts +3 -0
- package/packages/@repo/models/src/tenant.ts +29 -0
- package/packages/@repo/prebuild/dist/index.d.ts +2 -0
- package/packages/@repo/prebuild/dist/index.d.ts.map +1 -0
- package/packages/@repo/prebuild/dist/index.js +2 -0
- package/packages/@repo/prebuild/dist/openapi.d.ts +43 -0
- package/packages/@repo/prebuild/dist/openapi.d.ts.map +1 -0
- package/packages/@repo/prebuild/dist/openapi.js +58 -0
- package/packages/@repo/prebuild/package.json +39 -0
- package/packages/@repo/prebuild/src/index.ts +2 -0
- package/packages/@repo/prebuild/src/openapi.ts +116 -0
- package/packages/@repo/previewing/dist/blob-source.d.ts +16 -0
- package/packages/@repo/previewing/dist/blob-source.d.ts.map +1 -0
- package/packages/@repo/previewing/dist/blob-source.js +110 -0
- package/packages/@repo/previewing/dist/content-source.d.ts +12 -0
- package/packages/@repo/previewing/dist/content-source.d.ts.map +1 -0
- package/packages/@repo/previewing/dist/content-source.js +1 -0
- package/packages/@repo/previewing/dist/fs-source.d.ts +11 -0
- package/packages/@repo/previewing/dist/fs-source.d.ts.map +1 -0
- package/packages/@repo/previewing/dist/fs-source.js +79 -0
- package/packages/@repo/previewing/dist/index.d.ts +120 -0
- package/packages/@repo/previewing/dist/index.d.ts.map +1 -0
- package/packages/@repo/previewing/dist/index.js +984 -0
- package/packages/@repo/previewing/package.json +41 -0
- package/packages/@repo/previewing/src/blob-source.ts +167 -0
- package/packages/@repo/previewing/src/content-source.ts +12 -0
- package/packages/@repo/previewing/src/fs-source.ts +111 -0
- package/packages/@repo/previewing/src/index.ts +1490 -0
- package/packages/@repo/previewing/src/index.unit.test.ts +290 -0
- package/packages/@repo/validation/dist/index.d.ts +12 -0
- package/packages/@repo/validation/dist/index.d.ts.map +1 -0
- package/packages/@repo/validation/dist/index.js +30 -0
- package/packages/@repo/validation/package.json +37 -0
- package/packages/@repo/validation/src/index.ts +59 -0
- package/packages/@repo/validation/src/mintlify-docs-schema.json +5016 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@repo/previewing",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./src/index.ts",
|
|
9
|
+
"import": "./dist/index.js",
|
|
10
|
+
"default": "./dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"./*": {
|
|
13
|
+
"types": "./src/*.ts",
|
|
14
|
+
"import": "./dist/*.js",
|
|
15
|
+
"default": "./dist/*.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "rm -rf dist && tsc",
|
|
20
|
+
"check-types": "tsc --noEmit",
|
|
21
|
+
"lint": "oxlint .",
|
|
22
|
+
"lint:fix": "oxlint --fix .",
|
|
23
|
+
"format": "oxfmt --write .",
|
|
24
|
+
"format:check": "oxfmt ."
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@repo/common": "*",
|
|
28
|
+
"@repo/models": "*",
|
|
29
|
+
"@repo/prebuild": "*",
|
|
30
|
+
"@repo/validation": "*",
|
|
31
|
+
"yaml": "^2.8.3"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@repo/typescript-config": "*",
|
|
35
|
+
"@types/node": "^22.19.15",
|
|
36
|
+
"oxfmt": "^0.42.0",
|
|
37
|
+
"oxlint": "^1.57.0",
|
|
38
|
+
"typescript": "6.0.2",
|
|
39
|
+
"ultracite": "^7.3.2"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
|
|
3
|
+
import { normalizePath } from "@repo/common";
|
|
4
|
+
|
|
5
|
+
import type { CompiledMdxResult, ContentSource } from "./content-source.js";
|
|
6
|
+
|
|
7
|
+
interface BlobManifestFile {
|
|
8
|
+
path: string;
|
|
9
|
+
url: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface BlobManifest {
|
|
13
|
+
files: BlobManifestFile[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
type FetchInitWithNext = RequestInit & {
|
|
17
|
+
next?: {
|
|
18
|
+
revalidate?: number;
|
|
19
|
+
tags?: string[];
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const isRecord = (value: unknown): value is Record<string, unknown> =>
|
|
24
|
+
typeof value === "object" && value !== null;
|
|
25
|
+
|
|
26
|
+
const isBlobManifest = (value: unknown): value is BlobManifest => {
|
|
27
|
+
if (!isRecord(value) || !Array.isArray(value.files)) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return value.files.every((file) => {
|
|
32
|
+
if (!isRecord(file)) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return typeof file.path === "string" && typeof file.url === "string";
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const normalizeDirectory = (directory: string) => {
|
|
41
|
+
const normalized = normalizePath(path.posix.normalize(directory));
|
|
42
|
+
if (!normalized || normalized === ".") {
|
|
43
|
+
return "";
|
|
44
|
+
}
|
|
45
|
+
return normalized ? `${normalized}/` : "";
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const normalizeRelativePath = (value: string) =>
|
|
49
|
+
normalizePath(path.posix.normalize(value));
|
|
50
|
+
|
|
51
|
+
export class BlobContentSource implements ContentSource {
|
|
52
|
+
private readonly manifestUrl: string;
|
|
53
|
+
private readonly cacheTag?: string;
|
|
54
|
+
private manifestPromise?: Promise<Map<string, string>>;
|
|
55
|
+
|
|
56
|
+
constructor(manifestUrl: string, cacheTag?: string) {
|
|
57
|
+
this.manifestUrl = manifestUrl;
|
|
58
|
+
this.cacheTag = cacheTag;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private getFetchOptions(): FetchInitWithNext {
|
|
62
|
+
if (!this.cacheTag) {
|
|
63
|
+
return { cache: "no-store" };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
next: {
|
|
68
|
+
revalidate: 3600,
|
|
69
|
+
tags: [this.cacheTag],
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private async loadManifest(): Promise<Map<string, string>> {
|
|
75
|
+
if (!this.manifestPromise) {
|
|
76
|
+
this.manifestPromise = (async () => {
|
|
77
|
+
const response = await fetch(this.manifestUrl, this.getFetchOptions());
|
|
78
|
+
if (!response.ok) {
|
|
79
|
+
throw new Error(
|
|
80
|
+
`Failed to load deployment manifest: ${response.status}`
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const manifest = (await response.json()) as unknown;
|
|
85
|
+
if (!isBlobManifest(manifest)) {
|
|
86
|
+
throw new Error("Deployment manifest is invalid.");
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return new Map(
|
|
90
|
+
manifest.files.map((file) => [
|
|
91
|
+
normalizeRelativePath(file.path),
|
|
92
|
+
file.url,
|
|
93
|
+
])
|
|
94
|
+
);
|
|
95
|
+
})();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return await this.manifestPromise;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async readFile(relativePath: string): Promise<string> {
|
|
102
|
+
const url = await this.resolveUrl(relativePath);
|
|
103
|
+
if (!url) {
|
|
104
|
+
throw new Error(`Content file "${relativePath}" not found.`);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const response = await fetch(url, this.getFetchOptions());
|
|
108
|
+
if (!response.ok) {
|
|
109
|
+
throw new Error(`Failed to load content file: ${response.status}`);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return await response.text();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async listFiles(directory: string): Promise<string[]> {
|
|
116
|
+
const manifest = await this.loadManifest();
|
|
117
|
+
const prefix = normalizeDirectory(directory);
|
|
118
|
+
|
|
119
|
+
const files = [...manifest.keys()].filter((file) =>
|
|
120
|
+
prefix ? file.startsWith(prefix) : true
|
|
121
|
+
);
|
|
122
|
+
// oxlint-disable-next-line eslint-plugin-unicorn/no-array-sort
|
|
123
|
+
files.sort();
|
|
124
|
+
return files;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async exists(relativePath: string): Promise<boolean> {
|
|
128
|
+
const manifest = await this.loadManifest();
|
|
129
|
+
return manifest.has(normalizeRelativePath(relativePath));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
async resolveUrl(relativePath: string): Promise<string | null> {
|
|
133
|
+
const manifest = await this.loadManifest();
|
|
134
|
+
return manifest.get(normalizeRelativePath(relativePath)) ?? null;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
async readCompiledMdx(
|
|
138
|
+
relativePath: string
|
|
139
|
+
): Promise<CompiledMdxResult | null> {
|
|
140
|
+
const compiledPath = `_compiled/${normalizeRelativePath(relativePath)}.json`;
|
|
141
|
+
const url = await this.resolveUrl(compiledPath);
|
|
142
|
+
if (!url) {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
try {
|
|
147
|
+
const response = await fetch(url, this.getFetchOptions());
|
|
148
|
+
if (!response.ok) {
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const data = (await response.json()) as CompiledMdxResult;
|
|
153
|
+
if (!data.compiledSource || data.version !== 1) {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return data;
|
|
158
|
+
} catch {
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export const createBlobSource = (
|
|
165
|
+
manifestUrl: string,
|
|
166
|
+
cacheTag?: string
|
|
167
|
+
): ContentSource => new BlobContentSource(manifestUrl, cacheTag);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface CompiledMdxResult {
|
|
2
|
+
compiledSource: string;
|
|
3
|
+
version: number;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export interface ContentSource {
|
|
7
|
+
readFile(relativePath: string): Promise<string>;
|
|
8
|
+
listFiles(directory: string): Promise<string[]>;
|
|
9
|
+
exists(relativePath: string): Promise<boolean>;
|
|
10
|
+
resolveUrl?(relativePath: string): Promise<string | null> | string | null;
|
|
11
|
+
readCompiledMdx?(relativePath: string): Promise<CompiledMdxResult | null>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
|
|
4
|
+
import { normalizePath } from "@repo/common";
|
|
5
|
+
|
|
6
|
+
import type { ContentSource } from "./content-source.js";
|
|
7
|
+
|
|
8
|
+
const IGNORED_DIRECTORIES = new Set([
|
|
9
|
+
"app",
|
|
10
|
+
"components",
|
|
11
|
+
"content",
|
|
12
|
+
"lib",
|
|
13
|
+
"node_modules",
|
|
14
|
+
"public",
|
|
15
|
+
]);
|
|
16
|
+
const IGNORED_ROOT_FILES = new Set(["AGENTS.md", "README.md"]);
|
|
17
|
+
|
|
18
|
+
const isNotFoundError = (error: unknown) =>
|
|
19
|
+
Boolean(
|
|
20
|
+
error &&
|
|
21
|
+
typeof error === "object" &&
|
|
22
|
+
"code" in error &&
|
|
23
|
+
(error as { code?: string }).code === "ENOENT"
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
const isWithinRoot = (root: string, candidate: string) =>
|
|
27
|
+
candidate === root || candidate.startsWith(`${root}${path.sep}`);
|
|
28
|
+
|
|
29
|
+
const resolveWithinRoot = (root: string, relativePath: string) => {
|
|
30
|
+
const normalized = normalizePath(relativePath);
|
|
31
|
+
const absolutePath = path.resolve(root, normalized);
|
|
32
|
+
|
|
33
|
+
if (!isWithinRoot(root, absolutePath)) {
|
|
34
|
+
throw new Error(`Path "${relativePath}" escapes the content source root.`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return absolutePath;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const walkFiles = async (
|
|
41
|
+
directory: string,
|
|
42
|
+
prefix: string
|
|
43
|
+
): Promise<string[]> => {
|
|
44
|
+
const entries = await fs.readdir(directory, { withFileTypes: true });
|
|
45
|
+
const files: string[] = [];
|
|
46
|
+
|
|
47
|
+
for (const entry of entries) {
|
|
48
|
+
if (entry.name.startsWith(".")) {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const absolutePath = path.join(directory, entry.name);
|
|
53
|
+
const relativePath = prefix ? path.join(prefix, entry.name) : entry.name;
|
|
54
|
+
|
|
55
|
+
if (entry.isDirectory()) {
|
|
56
|
+
if (IGNORED_DIRECTORIES.has(entry.name)) {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
files.push(...(await walkFiles(absolutePath, relativePath)));
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (entry.isFile()) {
|
|
64
|
+
if (!prefix && IGNORED_ROOT_FILES.has(entry.name)) {
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
files.push(normalizePath(relativePath));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return files;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export class FsContentSource implements ContentSource {
|
|
75
|
+
private readonly root: string;
|
|
76
|
+
|
|
77
|
+
constructor(root: string) {
|
|
78
|
+
this.root = path.resolve(root);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async readFile(relativePath: string): Promise<string> {
|
|
82
|
+
return await fs.readFile(
|
|
83
|
+
resolveWithinRoot(this.root, relativePath),
|
|
84
|
+
"utf8"
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async listFiles(directory: string): Promise<string[]> {
|
|
89
|
+
return await walkFiles(resolveWithinRoot(this.root, directory), "");
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async exists(relativePath: string): Promise<boolean> {
|
|
93
|
+
try {
|
|
94
|
+
await fs.access(resolveWithinRoot(this.root, relativePath));
|
|
95
|
+
return true;
|
|
96
|
+
} catch (error) {
|
|
97
|
+
if (isNotFoundError(error)) {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
throw error;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// oxlint-disable-next-line eslint/class-methods-use-this
|
|
105
|
+
resolveUrl(): string | null {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export const createFsSource = (root: string): ContentSource =>
|
|
111
|
+
new FsContentSource(root);
|