create-m5kdev 0.29.0 → 0.31.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.
- package/dist/src/catalog.cjs +139 -0
- package/dist/src/catalog.cjs.map +1 -0
- package/dist/src/catalog.d.cts +30 -0
- package/dist/src/changes.cjs +70 -0
- package/dist/src/changes.cjs.map +1 -0
- package/dist/src/changes.d.cts +26 -0
- package/dist/src/create.cjs +37 -23
- package/dist/src/create.cjs.map +1 -1
- package/dist/src/diagnostics.cjs +33 -0
- package/dist/src/diagnostics.cjs.map +1 -0
- package/dist/src/diagnostics.d.cts +20 -0
- package/dist/src/doctor.cjs +245 -0
- package/dist/src/doctor.cjs.map +1 -0
- package/dist/src/doctor.d.cts +13 -0
- package/dist/src/fs.cjs +56 -26
- package/dist/src/fs.cjs.map +1 -1
- package/dist/src/fs.d.cts +11 -4
- package/dist/src/init.cjs +110 -0
- package/dist/src/init.cjs.map +1 -0
- package/dist/src/init.d.cts +36 -0
- package/dist/src/migrations/ast.cjs +49 -0
- package/dist/src/migrations/ast.cjs.map +1 -0
- package/dist/src/migrations/ast.d.cts +10 -0
- package/dist/src/migrations/registry.cjs +41 -0
- package/dist/src/migrations/registry.cjs.map +1 -0
- package/dist/src/migrations/registry.d.cts +12 -0
- package/dist/src/migrations/types.cjs +0 -0
- package/dist/src/migrations/types.d.cts +22 -0
- package/dist/src/prompts.cjs +1 -1
- package/dist/src/prompts.cjs.map +1 -1
- package/dist/src/reconcile.cjs +361 -0
- package/dist/src/reconcile.cjs.map +1 -0
- package/dist/src/reconcile.d.cts +26 -0
- package/dist/src/runCli.cjs +155 -27
- package/dist/src/runCli.cjs.map +1 -1
- package/dist/src/state.cjs +104 -0
- package/dist/src/state.cjs.map +1 -0
- package/dist/src/state.d.cts +50 -0
- package/dist/src/template.cjs +45 -0
- package/dist/src/template.cjs.map +1 -0
- package/dist/src/template.d.cts +10 -0
- package/dist/src/types.d.cts +20 -1
- package/dist/src/update.cjs +91 -0
- package/dist/src/update.cjs.map +1 -0
- package/dist/src/update.d.cts +33 -0
- package/package.json +12 -4
- package/templates/minimal-app/README.md.tpl +18 -3
- package/templates/minimal-app/apps/email/src/emails/accountDeletionEmail.tsx.tpl +36 -35
- package/templates/minimal-app/apps/email/src/emails/organizationInviteEmail.tsx.tpl +35 -34
- package/templates/minimal-app/apps/email/src/emails/passwordResetEmail.tsx.tpl +36 -35
- package/templates/minimal-app/apps/email/src/emails/verificationEmail.tsx.tpl +38 -37
- package/templates/minimal-app/apps/email/src/emails/waitlistEmails.tsx.tpl +88 -87
- package/templates/minimal-app/apps/email/src/index.ts.tpl +74 -72
- package/templates/minimal-app/apps/email/tsconfig.json.tpl +11 -16
- package/templates/minimal-app/apps/server/tsconfig.json.tpl +13 -20
- package/templates/minimal-app/apps/shared/tsconfig.json.tpl +12 -16
- package/templates/minimal-app/apps/webapp/src/modules/posts/hooks/usePostsList.ts.tpl +98 -98
- package/templates/minimal-app/biome.json.tpl +9 -2
- package/templates/minimal-app/pnpm-workspace.yaml.tpl +61 -63
- package/templates/minimal-app/template.manifest.json +30 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
|
|
3
|
+
let node_fs = require("node:fs");
|
|
4
|
+
node_fs = require_runtime.__toESM(node_fs);
|
|
5
|
+
let node_path = require("node:path");
|
|
6
|
+
node_path = require_runtime.__toESM(node_path);
|
|
7
|
+
let yaml = require("yaml");
|
|
8
|
+
//#region src/catalog.ts
|
|
9
|
+
const DEPENDENCY_FIELDS = [
|
|
10
|
+
"dependencies",
|
|
11
|
+
"devDependencies",
|
|
12
|
+
"peerDependencies",
|
|
13
|
+
"optionalDependencies"
|
|
14
|
+
];
|
|
15
|
+
function walkPackageJsonFiles(directory, out = []) {
|
|
16
|
+
for (const entry of node_fs.default.readdirSync(directory, { withFileTypes: true })) {
|
|
17
|
+
if (entry.name === "node_modules" || entry.name === ".git") continue;
|
|
18
|
+
const entryPath = node_path.default.join(directory, entry.name);
|
|
19
|
+
if (entry.isDirectory()) walkPackageJsonFiles(entryPath, out);
|
|
20
|
+
else if (entry.isFile() && entry.name === "package.json") out.push(entryPath);
|
|
21
|
+
}
|
|
22
|
+
return out;
|
|
23
|
+
}
|
|
24
|
+
function readJson(filePath) {
|
|
25
|
+
return JSON.parse(node_fs.default.readFileSync(filePath, "utf8"));
|
|
26
|
+
}
|
|
27
|
+
function collectConsumerDependencyNames(packageFiles) {
|
|
28
|
+
const names = /* @__PURE__ */ new Set();
|
|
29
|
+
for (const filePath of packageFiles) {
|
|
30
|
+
const manifest = readJson(filePath);
|
|
31
|
+
for (const field of DEPENDENCY_FIELDS) {
|
|
32
|
+
const dependencies = manifest[field];
|
|
33
|
+
for (const [name, specifier] of Object.entries(dependencies ?? {})) if (specifier.startsWith("catalog:") || name.startsWith("@m5kdev/") && specifier.startsWith("workspace:")) names.add(name);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return [...names].sort((left, right) => left.localeCompare(right));
|
|
37
|
+
}
|
|
38
|
+
function buildConsumerCatalog(options) {
|
|
39
|
+
const workspacePath = node_path.default.join(options.repoRoot, "pnpm-workspace.yaml");
|
|
40
|
+
const sourceCatalog = (0, yaml.parse)(node_fs.default.readFileSync(workspacePath, "utf8")).catalog ?? {};
|
|
41
|
+
const names = collectConsumerDependencyNames([...walkPackageJsonFiles(options.starterDirectory), node_path.default.join(options.rootTemplatesDirectory, "package.json.tpl")]);
|
|
42
|
+
const catalog = {};
|
|
43
|
+
const missing = [];
|
|
44
|
+
for (const name of names) {
|
|
45
|
+
if (name.startsWith("@m5kdev/")) {
|
|
46
|
+
const packageName = name.slice(8);
|
|
47
|
+
const packagePath = node_path.default.join(options.repoRoot, "packages", packageName, "package.json");
|
|
48
|
+
if (!node_fs.default.existsSync(packagePath)) {
|
|
49
|
+
missing.push(name);
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const packageManifest = readJson(packagePath);
|
|
53
|
+
if (typeof packageManifest.version !== "string") {
|
|
54
|
+
missing.push(name);
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
catalog[name] = packageManifest.version;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
const version = sourceCatalog[name];
|
|
61
|
+
if (version === void 0) {
|
|
62
|
+
missing.push(name);
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
catalog[name] = String(version);
|
|
66
|
+
}
|
|
67
|
+
if (missing.length > 0) throw new Error(`Missing consumer catalog versions for: ${missing.join(", ")}`);
|
|
68
|
+
return catalog;
|
|
69
|
+
}
|
|
70
|
+
function renderConsumerWorkspace(source, catalog) {
|
|
71
|
+
const workspace = (0, yaml.parse)(source);
|
|
72
|
+
workspace.catalog = Object.fromEntries(Object.entries(catalog).sort(([left], [right]) => left.localeCompare(right)));
|
|
73
|
+
return (0, yaml.stringify)(workspace, { lineWidth: 0 });
|
|
74
|
+
}
|
|
75
|
+
function readCatalog(source) {
|
|
76
|
+
const workspace = (0, yaml.parse)(source);
|
|
77
|
+
return Object.fromEntries(Object.entries(workspace.catalog ?? {}).map(([name, version]) => [name, String(version)]));
|
|
78
|
+
}
|
|
79
|
+
function assertCatalogKeys(catalog, expectedNames, label = "consumer catalog") {
|
|
80
|
+
const expected = new Set(expectedNames);
|
|
81
|
+
const missing = expectedNames.filter((name) => !(name in catalog));
|
|
82
|
+
const obsolete = Object.keys(catalog).filter((name) => !expected.has(name));
|
|
83
|
+
if (missing.length > 0 || obsolete.length > 0) {
|
|
84
|
+
const details = [missing.length > 0 ? `missing: ${missing.join(", ")}` : void 0, obsolete.length > 0 ? `obsolete: ${obsolete.join(", ")}` : void 0].filter(Boolean);
|
|
85
|
+
throw new Error(`Invalid ${label} (${details.join("; ")})`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function mergeManagedCatalog(options) {
|
|
89
|
+
const document = (0, yaml.parseDocument)(options.source);
|
|
90
|
+
const local = readCatalog(options.source);
|
|
91
|
+
const conflicts = [];
|
|
92
|
+
const names = new Set([...Object.keys(options.base), ...Object.keys(options.target)]);
|
|
93
|
+
for (const name of [...names].sort((left, right) => left.localeCompare(right))) {
|
|
94
|
+
const base = options.base[name];
|
|
95
|
+
const current = local[name];
|
|
96
|
+
const target = options.target[name];
|
|
97
|
+
if (base === void 0) {
|
|
98
|
+
if (current === void 0) document.setIn(["catalog", name], target);
|
|
99
|
+
else if (current !== target) conflicts.push({
|
|
100
|
+
name,
|
|
101
|
+
local: current,
|
|
102
|
+
target
|
|
103
|
+
});
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (target === void 0) {
|
|
107
|
+
if (current === base) document.deleteIn(["catalog", name]);
|
|
108
|
+
else if (current !== void 0) conflicts.push({
|
|
109
|
+
name,
|
|
110
|
+
base,
|
|
111
|
+
local: current
|
|
112
|
+
});
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
if (current === base) document.setIn(["catalog", name], target);
|
|
116
|
+
else if (current !== target && target !== base) conflicts.push({
|
|
117
|
+
name,
|
|
118
|
+
base,
|
|
119
|
+
local: current,
|
|
120
|
+
target
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
const merged = document.toString({ lineWidth: 0 });
|
|
124
|
+
return {
|
|
125
|
+
source: merged,
|
|
126
|
+
changed: merged !== options.source,
|
|
127
|
+
conflicts
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
//#endregion
|
|
131
|
+
exports.assertCatalogKeys = assertCatalogKeys;
|
|
132
|
+
exports.buildConsumerCatalog = buildConsumerCatalog;
|
|
133
|
+
exports.collectConsumerDependencyNames = collectConsumerDependencyNames;
|
|
134
|
+
exports.mergeManagedCatalog = mergeManagedCatalog;
|
|
135
|
+
exports.readCatalog = readCatalog;
|
|
136
|
+
exports.renderConsumerWorkspace = renderConsumerWorkspace;
|
|
137
|
+
exports.walkPackageJsonFiles = walkPackageJsonFiles;
|
|
138
|
+
|
|
139
|
+
//# sourceMappingURL=catalog.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.cjs","names":["fs","path"],"sources":["../../src/catalog.ts"],"sourcesContent":["import fs from \"node:fs\";\r\nimport path from \"node:path\";\r\nimport { parse, parseDocument, stringify } from \"yaml\";\r\n\r\nconst DEPENDENCY_FIELDS = [\r\n \"dependencies\",\r\n \"devDependencies\",\r\n \"peerDependencies\",\r\n \"optionalDependencies\",\r\n] as const;\r\n\r\nexport type ConsumerCatalog = Record<string, string>;\r\n\r\nexport function walkPackageJsonFiles(directory: string, out: string[] = []): string[] {\r\n for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {\r\n if (entry.name === \"node_modules\" || entry.name === \".git\") continue;\r\n const entryPath = path.join(directory, entry.name);\r\n if (entry.isDirectory()) {\r\n walkPackageJsonFiles(entryPath, out);\r\n } else if (entry.isFile() && entry.name === \"package.json\") {\r\n out.push(entryPath);\r\n }\r\n }\r\n return out;\r\n}\r\n\r\nfunction readJson(filePath: string): Record<string, unknown> {\r\n return JSON.parse(fs.readFileSync(filePath, \"utf8\")) as Record<string, unknown>;\r\n}\r\n\r\nexport function collectConsumerDependencyNames(packageFiles: readonly string[]): string[] {\r\n const names = new Set<string>();\r\n\r\n for (const filePath of packageFiles) {\r\n const manifest = readJson(filePath);\r\n for (const field of DEPENDENCY_FIELDS) {\r\n const dependencies = manifest[field] as Record<string, string> | undefined;\r\n for (const [name, specifier] of Object.entries(dependencies ?? {})) {\r\n if (\r\n specifier.startsWith(\"catalog:\") ||\r\n (name.startsWith(\"@m5kdev/\") && specifier.startsWith(\"workspace:\"))\r\n ) {\r\n names.add(name);\r\n }\r\n }\r\n }\r\n }\r\n\r\n return [...names].sort((left, right) => left.localeCompare(right));\r\n}\r\n\r\nexport function buildConsumerCatalog(options: {\r\n repoRoot: string;\r\n starterDirectory: string;\r\n rootTemplatesDirectory: string;\r\n}): ConsumerCatalog {\r\n const workspacePath = path.join(options.repoRoot, \"pnpm-workspace.yaml\");\r\n const workspace = parse(fs.readFileSync(workspacePath, \"utf8\")) as {\r\n catalog?: Record<string, string | number>;\r\n };\r\n const sourceCatalog = workspace.catalog ?? {};\r\n const packageFiles = [\r\n ...walkPackageJsonFiles(options.starterDirectory),\r\n path.join(options.rootTemplatesDirectory, \"package.json.tpl\"),\r\n ];\r\n const names = collectConsumerDependencyNames(packageFiles);\r\n const catalog: ConsumerCatalog = {};\r\n const missing: string[] = [];\r\n\r\n for (const name of names) {\r\n if (name.startsWith(\"@m5kdev/\")) {\r\n const packageName = name.slice(\"@m5kdev/\".length);\r\n const packagePath = path.join(options.repoRoot, \"packages\", packageName, \"package.json\");\r\n if (!fs.existsSync(packagePath)) {\r\n missing.push(name);\r\n continue;\r\n }\r\n const packageManifest = readJson(packagePath);\r\n if (typeof packageManifest.version !== \"string\") {\r\n missing.push(name);\r\n continue;\r\n }\r\n catalog[name] = packageManifest.version;\r\n continue;\r\n }\r\n\r\n const version = sourceCatalog[name];\r\n if (version === undefined) {\r\n missing.push(name);\r\n continue;\r\n }\r\n catalog[name] = String(version);\r\n }\r\n\r\n if (missing.length > 0) {\r\n throw new Error(`Missing consumer catalog versions for: ${missing.join(\", \")}`);\r\n }\r\n\r\n return catalog;\r\n}\r\n\r\nexport function renderConsumerWorkspace(source: string, catalog: ConsumerCatalog): string {\r\n const workspace = parse(source) as Record<string, unknown>;\r\n workspace.catalog = Object.fromEntries(\r\n Object.entries(catalog).sort(([left], [right]) => left.localeCompare(right))\r\n );\r\n return stringify(workspace, { lineWidth: 0 });\r\n}\r\n\r\nexport function readCatalog(source: string): ConsumerCatalog {\r\n const workspace = parse(source) as { catalog?: Record<string, string | number> };\r\n return Object.fromEntries(\r\n Object.entries(workspace.catalog ?? {}).map(([name, version]) => [name, String(version)])\r\n );\r\n}\r\n\r\nexport function assertCatalogKeys(\r\n catalog: ConsumerCatalog,\r\n expectedNames: readonly string[],\r\n label = \"consumer catalog\"\r\n): void {\r\n const expected = new Set(expectedNames);\r\n const missing = expectedNames.filter((name) => !(name in catalog));\r\n const obsolete = Object.keys(catalog).filter((name) => !expected.has(name));\r\n if (missing.length > 0 || obsolete.length > 0) {\r\n const details = [\r\n missing.length > 0 ? `missing: ${missing.join(\", \")}` : undefined,\r\n obsolete.length > 0 ? `obsolete: ${obsolete.join(\", \")}` : undefined,\r\n ].filter(Boolean);\r\n throw new Error(`Invalid ${label} (${details.join(\"; \")})`);\r\n }\r\n}\r\n\r\nexport interface CatalogMergeConflict {\r\n name: string;\r\n base?: string;\r\n local?: string;\r\n target?: string;\r\n}\r\n\r\nexport function mergeManagedCatalog(options: {\r\n source: string;\r\n base: ConsumerCatalog;\r\n target: ConsumerCatalog;\r\n}): { source: string; changed: boolean; conflicts: CatalogMergeConflict[] } {\r\n const document = parseDocument(options.source);\r\n const local = readCatalog(options.source);\r\n const conflicts: CatalogMergeConflict[] = [];\r\n const names = new Set([...Object.keys(options.base), ...Object.keys(options.target)]);\r\n\r\n for (const name of [...names].sort((left, right) => left.localeCompare(right))) {\r\n const base = options.base[name];\r\n const current = local[name];\r\n const target = options.target[name];\r\n\r\n if (base === undefined) {\r\n if (current === undefined) document.setIn([\"catalog\", name], target);\r\n else if (current !== target) conflicts.push({ name, local: current, target });\r\n continue;\r\n }\r\n if (target === undefined) {\r\n if (current === base) document.deleteIn([\"catalog\", name]);\r\n else if (current !== undefined) conflicts.push({ name, base, local: current });\r\n continue;\r\n }\r\n if (current === base) document.setIn([\"catalog\", name], target);\r\n else if (current !== target && target !== base) {\r\n conflicts.push({ name, base, local: current, target });\r\n }\r\n }\r\n\r\n const merged = document.toString({ lineWidth: 0 });\r\n return { source: merged, changed: merged !== options.source, conflicts };\r\n}\r\n"],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//#region src/catalog.d.ts
|
|
2
|
+
type ConsumerCatalog = Record<string, string>;
|
|
3
|
+
declare function walkPackageJsonFiles(directory: string, out?: string[]): string[];
|
|
4
|
+
declare function collectConsumerDependencyNames(packageFiles: readonly string[]): string[];
|
|
5
|
+
declare function buildConsumerCatalog(options: {
|
|
6
|
+
repoRoot: string;
|
|
7
|
+
starterDirectory: string;
|
|
8
|
+
rootTemplatesDirectory: string;
|
|
9
|
+
}): ConsumerCatalog;
|
|
10
|
+
declare function renderConsumerWorkspace(source: string, catalog: ConsumerCatalog): string;
|
|
11
|
+
declare function readCatalog(source: string): ConsumerCatalog;
|
|
12
|
+
declare function assertCatalogKeys(catalog: ConsumerCatalog, expectedNames: readonly string[], label?: string): void;
|
|
13
|
+
interface CatalogMergeConflict {
|
|
14
|
+
name: string;
|
|
15
|
+
base?: string;
|
|
16
|
+
local?: string;
|
|
17
|
+
target?: string;
|
|
18
|
+
}
|
|
19
|
+
declare function mergeManagedCatalog(options: {
|
|
20
|
+
source: string;
|
|
21
|
+
base: ConsumerCatalog;
|
|
22
|
+
target: ConsumerCatalog;
|
|
23
|
+
}): {
|
|
24
|
+
source: string;
|
|
25
|
+
changed: boolean;
|
|
26
|
+
conflicts: CatalogMergeConflict[];
|
|
27
|
+
};
|
|
28
|
+
//#endregion
|
|
29
|
+
export { CatalogMergeConflict, ConsumerCatalog, assertCatalogKeys, buildConsumerCatalog, collectConsumerDependencyNames, mergeManagedCatalog, readCatalog, renderConsumerWorkspace, walkPackageJsonFiles };
|
|
30
|
+
//# sourceMappingURL=catalog.d.cts.map
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_runtime = require("../_virtual/_rolldown/runtime.cjs");
|
|
3
|
+
let node_path = require("node:path");
|
|
4
|
+
node_path = require_runtime.__toESM(node_path);
|
|
5
|
+
let node_fs_promises = require("node:fs/promises");
|
|
6
|
+
node_fs_promises = require_runtime.__toESM(node_fs_promises);
|
|
7
|
+
//#region src/changes.ts
|
|
8
|
+
function safePath(repoRoot, relativePath) {
|
|
9
|
+
if (node_path.default.isAbsolute(relativePath)) throw new Error(`Absolute change path is not allowed: ${relativePath}`);
|
|
10
|
+
const normalized = node_path.default.posix.normalize(relativePath.split("\\").join("/"));
|
|
11
|
+
if (normalized === ".." || normalized.startsWith("../")) throw new Error(`Change path escapes the repository: ${relativePath}`);
|
|
12
|
+
const resolved = node_path.default.resolve(repoRoot, normalized);
|
|
13
|
+
if (resolved !== repoRoot && !resolved.startsWith(`${repoRoot}${node_path.default.sep}`)) throw new Error(`Change path escapes the repository: ${relativePath}`);
|
|
14
|
+
return resolved;
|
|
15
|
+
}
|
|
16
|
+
async function findRepositorySymlink(repoRoot, relativePath) {
|
|
17
|
+
safePath(repoRoot, relativePath);
|
|
18
|
+
const normalized = node_path.default.posix.normalize(relativePath.split("\\").join("/"));
|
|
19
|
+
let current = node_path.default.resolve(repoRoot);
|
|
20
|
+
let currentRelative = "";
|
|
21
|
+
for (const segment of normalized.split("/")) {
|
|
22
|
+
current = node_path.default.join(current, segment);
|
|
23
|
+
currentRelative = currentRelative ? `${currentRelative}/${segment}` : segment;
|
|
24
|
+
const stat = await node_fs_promises.default.lstat(current).catch(() => null);
|
|
25
|
+
if (!stat) return void 0;
|
|
26
|
+
if (stat.isSymbolicLink()) return currentRelative;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
var ChangeSet = class {
|
|
30
|
+
constructor(repoRoot) {
|
|
31
|
+
this.repoRoot = repoRoot;
|
|
32
|
+
this.changes = /* @__PURE__ */ new Map();
|
|
33
|
+
this.conflicts = [];
|
|
34
|
+
}
|
|
35
|
+
addChange(change) {
|
|
36
|
+
safePath(this.repoRoot, change.path);
|
|
37
|
+
this.changes.set(change.path, change);
|
|
38
|
+
}
|
|
39
|
+
addConflict(conflict) {
|
|
40
|
+
safePath(this.repoRoot, conflict.path);
|
|
41
|
+
this.conflicts.push(conflict);
|
|
42
|
+
}
|
|
43
|
+
async read(pathName) {
|
|
44
|
+
const planned = this.changes.get(pathName);
|
|
45
|
+
if (planned) return planned.kind === "delete" ? void 0 : planned.content;
|
|
46
|
+
const symlink = await findRepositorySymlink(this.repoRoot, pathName);
|
|
47
|
+
if (symlink) throw new Error(`Refusing to read through symlink: ${symlink}`);
|
|
48
|
+
return node_fs_promises.default.readFile(safePath(this.repoRoot, pathName)).catch(() => void 0);
|
|
49
|
+
}
|
|
50
|
+
async apply() {
|
|
51
|
+
if (this.conflicts.length > 0) throw new Error("Cannot apply a change set with conflicts.");
|
|
52
|
+
const changes = [...this.changes.values()].sort((left, right) => left.path.localeCompare(right.path));
|
|
53
|
+
for (const change of changes) {
|
|
54
|
+
const target = safePath(this.repoRoot, change.path);
|
|
55
|
+
const symlink = await findRepositorySymlink(this.repoRoot, change.path);
|
|
56
|
+
if (symlink) throw new Error(`Refusing to write through symlink: ${symlink}`);
|
|
57
|
+
if (change.kind === "delete") {
|
|
58
|
+
await node_fs_promises.default.rm(target, { force: true });
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
await node_fs_promises.default.mkdir(node_path.default.dirname(target), { recursive: true });
|
|
62
|
+
await node_fs_promises.default.writeFile(target, change.content ?? Buffer.alloc(0));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
//#endregion
|
|
67
|
+
exports.ChangeSet = ChangeSet;
|
|
68
|
+
exports.findRepositorySymlink = findRepositorySymlink;
|
|
69
|
+
|
|
70
|
+
//# sourceMappingURL=changes.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"changes.cjs","names":["path","fs"],"sources":["../../src/changes.ts"],"sourcesContent":["import fs from \"node:fs/promises\";\r\nimport path from \"node:path\";\r\n\r\nexport type PlannedChangeKind = \"add\" | \"modify\" | \"delete\";\r\n\r\nexport interface PlannedChange {\r\n kind: PlannedChangeKind;\r\n path: string;\r\n content?: Buffer;\r\n reason: string;\r\n}\r\n\r\nexport interface PlannedConflict {\r\n path: string;\r\n reason: string;\r\n}\r\n\r\nfunction safePath(repoRoot: string, relativePath: string): string {\r\n if (path.isAbsolute(relativePath))\r\n throw new Error(`Absolute change path is not allowed: ${relativePath}`);\r\n const normalized = path.posix.normalize(relativePath.split(\"\\\\\").join(\"/\"));\r\n if (normalized === \"..\" || normalized.startsWith(\"../\")) {\r\n throw new Error(`Change path escapes the repository: ${relativePath}`);\r\n }\r\n const resolved = path.resolve(repoRoot, normalized);\r\n if (resolved !== repoRoot && !resolved.startsWith(`${repoRoot}${path.sep}`)) {\r\n throw new Error(`Change path escapes the repository: ${relativePath}`);\r\n }\r\n return resolved;\r\n}\r\n\r\nexport async function findRepositorySymlink(\r\n repoRoot: string,\r\n relativePath: string\r\n): Promise<string | undefined> {\r\n safePath(repoRoot, relativePath);\r\n const normalized = path.posix.normalize(relativePath.split(\"\\\\\").join(\"/\"));\r\n let current = path.resolve(repoRoot);\r\n let currentRelative = \"\";\r\n for (const segment of normalized.split(\"/\")) {\r\n current = path.join(current, segment);\r\n currentRelative = currentRelative ? `${currentRelative}/${segment}` : segment;\r\n const stat = await fs.lstat(current).catch(() => null);\r\n if (!stat) return undefined;\r\n if (stat.isSymbolicLink()) return currentRelative;\r\n }\r\n return undefined;\r\n}\r\n\r\nexport class ChangeSet {\r\n readonly changes = new Map<string, PlannedChange>();\r\n readonly conflicts: PlannedConflict[] = [];\r\n\r\n constructor(readonly repoRoot: string) {}\r\n\r\n addChange(change: PlannedChange): void {\r\n safePath(this.repoRoot, change.path);\r\n this.changes.set(change.path, change);\r\n }\r\n\r\n addConflict(conflict: PlannedConflict): void {\r\n safePath(this.repoRoot, conflict.path);\r\n this.conflicts.push(conflict);\r\n }\r\n\r\n async read(pathName: string): Promise<Buffer | undefined> {\r\n const planned = this.changes.get(pathName);\r\n if (planned) return planned.kind === \"delete\" ? undefined : planned.content;\r\n const symlink = await findRepositorySymlink(this.repoRoot, pathName);\r\n if (symlink) throw new Error(`Refusing to read through symlink: ${symlink}`);\r\n return fs.readFile(safePath(this.repoRoot, pathName)).catch(() => undefined);\r\n }\r\n\r\n async apply(): Promise<void> {\r\n if (this.conflicts.length > 0) throw new Error(\"Cannot apply a change set with conflicts.\");\r\n const changes = [...this.changes.values()].sort((left, right) =>\r\n left.path.localeCompare(right.path)\r\n );\r\n for (const change of changes) {\r\n const target = safePath(this.repoRoot, change.path);\r\n const symlink = await findRepositorySymlink(this.repoRoot, change.path);\r\n if (symlink) throw new Error(`Refusing to write through symlink: ${symlink}`);\r\n if (change.kind === \"delete\") {\r\n await fs.rm(target, { force: true });\r\n continue;\r\n }\r\n await fs.mkdir(path.dirname(target), { recursive: true });\r\n await fs.writeFile(target, change.content ?? Buffer.alloc(0));\r\n }\r\n }\r\n}\r\n"],"mappings":";;;;;;;AAiBA,SAAS,SAAS,UAAkB,cAA8B;AAChE,KAAIA,UAAAA,QAAK,WAAW,aAAa,CAC/B,OAAM,IAAI,MAAM,wCAAwC,eAAe;CACzE,MAAM,aAAaA,UAAAA,QAAK,MAAM,UAAU,aAAa,MAAM,KAAK,CAAC,KAAK,IAAI,CAAC;AAC3E,KAAI,eAAe,QAAQ,WAAW,WAAW,MAAM,CACrD,OAAM,IAAI,MAAM,uCAAuC,eAAe;CAExE,MAAM,WAAWA,UAAAA,QAAK,QAAQ,UAAU,WAAW;AACnD,KAAI,aAAa,YAAY,CAAC,SAAS,WAAW,GAAG,WAAWA,UAAAA,QAAK,MAAM,CACzE,OAAM,IAAI,MAAM,uCAAuC,eAAe;AAExE,QAAO;;AAGT,eAAsB,sBACpB,UACA,cAC6B;AAC7B,UAAS,UAAU,aAAa;CAChC,MAAM,aAAaA,UAAAA,QAAK,MAAM,UAAU,aAAa,MAAM,KAAK,CAAC,KAAK,IAAI,CAAC;CAC3E,IAAI,UAAUA,UAAAA,QAAK,QAAQ,SAAS;CACpC,IAAI,kBAAkB;AACtB,MAAK,MAAM,WAAW,WAAW,MAAM,IAAI,EAAE;AAC3C,YAAUA,UAAAA,QAAK,KAAK,SAAS,QAAQ;AACrC,oBAAkB,kBAAkB,GAAG,gBAAgB,GAAG,YAAY;EACtE,MAAM,OAAO,MAAMC,iBAAAA,QAAG,MAAM,QAAQ,CAAC,YAAY,KAAK;AACtD,MAAI,CAAC,KAAM,QAAO,KAAA;AAClB,MAAI,KAAK,gBAAgB,CAAE,QAAO;;;AAKtC,IAAa,YAAb,MAAuB;CAIrB,YAAY,UAA2B;AAAlB,OAAA,WAAA;iCAHF,IAAI,KAA4B;mBACX,EAAE;;CAI1C,UAAU,QAA6B;AACrC,WAAS,KAAK,UAAU,OAAO,KAAK;AACpC,OAAK,QAAQ,IAAI,OAAO,MAAM,OAAO;;CAGvC,YAAY,UAAiC;AAC3C,WAAS,KAAK,UAAU,SAAS,KAAK;AACtC,OAAK,UAAU,KAAK,SAAS;;CAG/B,MAAM,KAAK,UAA+C;EACxD,MAAM,UAAU,KAAK,QAAQ,IAAI,SAAS;AAC1C,MAAI,QAAS,QAAO,QAAQ,SAAS,WAAW,KAAA,IAAY,QAAQ;EACpE,MAAM,UAAU,MAAM,sBAAsB,KAAK,UAAU,SAAS;AACpE,MAAI,QAAS,OAAM,IAAI,MAAM,qCAAqC,UAAU;AAC5E,SAAOA,iBAAAA,QAAG,SAAS,SAAS,KAAK,UAAU,SAAS,CAAC,CAAC,YAAY,KAAA,EAAU;;CAG9E,MAAM,QAAuB;AAC3B,MAAI,KAAK,UAAU,SAAS,EAAG,OAAM,IAAI,MAAM,4CAA4C;EAC3F,MAAM,UAAU,CAAC,GAAG,KAAK,QAAQ,QAAQ,CAAC,CAAC,MAAM,MAAM,UACrD,KAAK,KAAK,cAAc,MAAM,KAAK,CACpC;AACD,OAAK,MAAM,UAAU,SAAS;GAC5B,MAAM,SAAS,SAAS,KAAK,UAAU,OAAO,KAAK;GACnD,MAAM,UAAU,MAAM,sBAAsB,KAAK,UAAU,OAAO,KAAK;AACvE,OAAI,QAAS,OAAM,IAAI,MAAM,sCAAsC,UAAU;AAC7E,OAAI,OAAO,SAAS,UAAU;AAC5B,UAAMA,iBAAAA,QAAG,GAAG,QAAQ,EAAE,OAAO,MAAM,CAAC;AACpC;;AAEF,SAAMA,iBAAAA,QAAG,MAAMD,UAAAA,QAAK,QAAQ,OAAO,EAAE,EAAE,WAAW,MAAM,CAAC;AACzD,SAAMC,iBAAAA,QAAG,UAAU,QAAQ,OAAO,WAAW,OAAO,MAAM,EAAE,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//#region src/changes.d.ts
|
|
2
|
+
type PlannedChangeKind = "add" | "modify" | "delete";
|
|
3
|
+
interface PlannedChange {
|
|
4
|
+
kind: PlannedChangeKind;
|
|
5
|
+
path: string;
|
|
6
|
+
content?: Buffer;
|
|
7
|
+
reason: string;
|
|
8
|
+
}
|
|
9
|
+
interface PlannedConflict {
|
|
10
|
+
path: string;
|
|
11
|
+
reason: string;
|
|
12
|
+
}
|
|
13
|
+
declare function findRepositorySymlink(repoRoot: string, relativePath: string): Promise<string | undefined>;
|
|
14
|
+
declare class ChangeSet {
|
|
15
|
+
readonly repoRoot: string;
|
|
16
|
+
readonly changes: Map<string, PlannedChange>;
|
|
17
|
+
readonly conflicts: PlannedConflict[];
|
|
18
|
+
constructor(repoRoot: string);
|
|
19
|
+
addChange(change: PlannedChange): void;
|
|
20
|
+
addConflict(conflict: PlannedConflict): void;
|
|
21
|
+
read(pathName: string): Promise<Buffer | undefined>;
|
|
22
|
+
apply(): Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
export { ChangeSet, PlannedChange, PlannedChangeKind, PlannedConflict, findRepositorySymlink };
|
|
26
|
+
//# sourceMappingURL=changes.d.cts.map
|
package/dist/src/create.cjs
CHANGED
|
@@ -5,40 +5,54 @@ const require_src_strings = require("./strings.cjs");
|
|
|
5
5
|
const require_src_fs = require("./fs.cjs");
|
|
6
6
|
const require_src_paths = require("./paths.cjs");
|
|
7
7
|
const require_src_prompts = require("./prompts.cjs");
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
const require_src_template = require("./template.cjs");
|
|
9
|
+
const require_src_state = require("./state.cjs");
|
|
10
10
|
let node_path = require("node:path");
|
|
11
11
|
node_path = require_runtime.__toESM(node_path);
|
|
12
|
+
let node_fs_promises = require("node:fs/promises");
|
|
13
|
+
node_fs_promises = require_runtime.__toESM(node_fs_promises);
|
|
12
14
|
//#region src/create.ts
|
|
13
|
-
function loadFeatureManifest(templateDirectory) {
|
|
14
|
-
const manifestPath = node_path.default.join(templateDirectory, "template.manifest.json");
|
|
15
|
-
if (!node_fs.default.existsSync(manifestPath)) return { features: {} };
|
|
16
|
-
return JSON.parse(node_fs.default.readFileSync(manifestPath, "utf8"));
|
|
17
|
-
}
|
|
18
15
|
async function scaffoldProject(initialOptions) {
|
|
19
16
|
const options = await require_src_prompts.resolveCreateCommandOptions(initialOptions);
|
|
20
|
-
const
|
|
21
|
-
|
|
17
|
+
const { appName, appDescription, targetDirectory: targetDirectoryOption } = options;
|
|
18
|
+
if (!appName || !appDescription || !targetDirectoryOption) throw new Error("Unable to resolve the required create options.");
|
|
19
|
+
const appSlug = require_src_strings.slugifyAppName(appName);
|
|
20
|
+
const targetDirectory = node_path.default.resolve(process.cwd(), targetDirectoryOption);
|
|
22
21
|
const templateDirectory = require_src_paths.getTemplateRoot();
|
|
23
22
|
const context = {
|
|
24
|
-
appName
|
|
25
|
-
appDescription
|
|
23
|
+
appName,
|
|
24
|
+
appDescription,
|
|
26
25
|
appSlug,
|
|
27
26
|
packageScope: require_src_strings.derivePackageScope(appSlug),
|
|
28
27
|
betterAuthSecret: require_src_strings.createBetterAuthSecret()
|
|
29
28
|
};
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
29
|
+
const enabledFeatures = require_src_template.getEnabledFeatures(options.platform ?? "web", Boolean(options.testHarness));
|
|
30
|
+
const manifest = require_src_template.loadTemplateManifest(templateDirectory);
|
|
31
|
+
const excludePrefixes = require_src_template.getExcludedFeaturePaths(manifest, enabledFeatures);
|
|
32
|
+
const createdTargetDirectory = await require_src_fs.ensureDirectoryState(targetDirectory, options.force);
|
|
33
|
+
try {
|
|
34
|
+
await require_src_fs.copyTemplateDirectory(templateDirectory, targetDirectory, context, {
|
|
35
|
+
excludePrefixes,
|
|
36
|
+
enabledFeatures
|
|
37
|
+
});
|
|
38
|
+
const renderedFiles = await require_src_fs.collectTemplateFiles(templateDirectory, context, {
|
|
39
|
+
excludePrefixes,
|
|
40
|
+
enabledFeatures
|
|
41
|
+
});
|
|
42
|
+
await require_src_state.writeManagedState(targetDirectory, require_src_state.createManagedState({
|
|
43
|
+
templateVersion: require_src_state.getCliVersion(),
|
|
44
|
+
enabledFeatures,
|
|
45
|
+
context,
|
|
46
|
+
renderedFiles,
|
|
47
|
+
manifest
|
|
48
|
+
}));
|
|
49
|
+
} catch (error) {
|
|
50
|
+
if (createdTargetDirectory) await node_fs_promises.default.rm(targetDirectory, {
|
|
51
|
+
recursive: true,
|
|
52
|
+
force: true
|
|
53
|
+
});
|
|
54
|
+
throw error;
|
|
55
|
+
}
|
|
42
56
|
if (!options.skipGit) await require_src_fs.runGitInit(targetDirectory);
|
|
43
57
|
if (!options.skipInstall) await require_src_fs.runInstall(targetDirectory);
|
|
44
58
|
return {
|
package/dist/src/create.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.cjs","names":["path","
|
|
1
|
+
{"version":3,"file":"create.cjs","names":["resolveCreateCommandOptions","slugifyAppName","path","getTemplateRoot","derivePackageScope","createBetterAuthSecret","getEnabledFeatures","loadTemplateManifest","getExcludedFeaturePaths","ensureDirectoryState","copyTemplateDirectory","collectTemplateFiles","writeManagedState","createManagedState","getCliVersion","fs","runGitInit","runInstall","TEMPLATE_NAME"],"sources":["../../src/create.ts"],"sourcesContent":["import fs from \"node:fs/promises\";\r\nimport path from \"node:path\";\r\nimport { TEMPLATE_NAME } from \"./constants\";\r\nimport {\r\n collectTemplateFiles,\r\n copyTemplateDirectory,\r\n ensureDirectoryState,\r\n runGitInit,\r\n runInstall,\r\n} from \"./fs\";\r\nimport { getTemplateRoot } from \"./paths\";\r\nimport { resolveCreateCommandOptions } from \"./prompts\";\r\nimport { createManagedState, getCliVersion, writeManagedState } from \"./state\";\r\nimport { createBetterAuthSecret, derivePackageScope, slugifyAppName } from \"./strings\";\r\nimport { getEnabledFeatures, getExcludedFeaturePaths, loadTemplateManifest } from \"./template\";\r\nimport type { CreateCommandOptions, TemplateContext } from \"./types\";\r\n\r\nexport interface ScaffoldResult {\r\n context: TemplateContext;\r\n targetDirectory: string;\r\n templateName: string;\r\n}\r\n\r\nexport async function scaffoldProject(\r\n initialOptions: CreateCommandOptions\r\n): Promise<ScaffoldResult> {\r\n const options = await resolveCreateCommandOptions(initialOptions);\r\n const { appName, appDescription, targetDirectory: targetDirectoryOption } = options;\r\n if (!appName || !appDescription || !targetDirectoryOption) {\r\n throw new Error(\"Unable to resolve the required create options.\");\r\n }\r\n const appSlug = slugifyAppName(appName);\r\n const targetDirectory = path.resolve(process.cwd(), targetDirectoryOption);\r\n const templateDirectory = getTemplateRoot();\r\n\r\n const context: TemplateContext = {\r\n appName,\r\n appDescription,\r\n appSlug,\r\n packageScope: derivePackageScope(appSlug),\r\n betterAuthSecret: createBetterAuthSecret(),\r\n };\r\n\r\n const enabledFeatures = getEnabledFeatures(\r\n options.platform ?? \"web\",\r\n Boolean(options.testHarness)\r\n );\r\n const manifest = loadTemplateManifest(templateDirectory);\r\n const excludePrefixes = getExcludedFeaturePaths(manifest, enabledFeatures);\r\n\r\n const createdTargetDirectory = await ensureDirectoryState(targetDirectory, options.force);\r\n try {\r\n await copyTemplateDirectory(templateDirectory, targetDirectory, context, {\r\n excludePrefixes,\r\n enabledFeatures,\r\n });\r\n const renderedFiles = await collectTemplateFiles(templateDirectory, context, {\r\n excludePrefixes,\r\n enabledFeatures,\r\n });\r\n await writeManagedState(\r\n targetDirectory,\r\n createManagedState({\r\n templateVersion: getCliVersion(),\r\n enabledFeatures,\r\n context,\r\n renderedFiles,\r\n manifest,\r\n })\r\n );\r\n } catch (error) {\r\n if (createdTargetDirectory) {\r\n await fs.rm(targetDirectory, { recursive: true, force: true });\r\n }\r\n throw error;\r\n }\r\n\r\n if (!options.skipGit) {\r\n await runGitInit(targetDirectory);\r\n }\r\n\r\n if (!options.skipInstall) {\r\n await runInstall(targetDirectory);\r\n }\r\n\r\n return {\r\n context,\r\n targetDirectory,\r\n templateName: TEMPLATE_NAME,\r\n };\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;AAuBA,eAAsB,gBACpB,gBACyB;CACzB,MAAM,UAAU,MAAMA,oBAAAA,4BAA4B,eAAe;CACjE,MAAM,EAAE,SAAS,gBAAgB,iBAAiB,0BAA0B;AAC5E,KAAI,CAAC,WAAW,CAAC,kBAAkB,CAAC,sBAClC,OAAM,IAAI,MAAM,iDAAiD;CAEnE,MAAM,UAAUC,oBAAAA,eAAe,QAAQ;CACvC,MAAM,kBAAkBC,UAAAA,QAAK,QAAQ,QAAQ,KAAK,EAAE,sBAAsB;CAC1E,MAAM,oBAAoBC,kBAAAA,iBAAiB;CAE3C,MAAM,UAA2B;EAC/B;EACA;EACA;EACA,cAAcC,oBAAAA,mBAAmB,QAAQ;EACzC,kBAAkBC,oBAAAA,wBAAwB;EAC3C;CAED,MAAM,kBAAkBC,qBAAAA,mBACtB,QAAQ,YAAY,OACpB,QAAQ,QAAQ,YAAY,CAC7B;CACD,MAAM,WAAWC,qBAAAA,qBAAqB,kBAAkB;CACxD,MAAM,kBAAkBC,qBAAAA,wBAAwB,UAAU,gBAAgB;CAE1E,MAAM,yBAAyB,MAAMC,eAAAA,qBAAqB,iBAAiB,QAAQ,MAAM;AACzF,KAAI;AACF,QAAMC,eAAAA,sBAAsB,mBAAmB,iBAAiB,SAAS;GACvE;GACA;GACD,CAAC;EACF,MAAM,gBAAgB,MAAMC,eAAAA,qBAAqB,mBAAmB,SAAS;GAC3E;GACA;GACD,CAAC;AACF,QAAMC,kBAAAA,kBACJ,iBACAC,kBAAAA,mBAAmB;GACjB,iBAAiBC,kBAAAA,eAAe;GAChC;GACA;GACA;GACA;GACD,CAAC,CACH;UACM,OAAO;AACd,MAAI,uBACF,OAAMC,iBAAAA,QAAG,GAAG,iBAAiB;GAAE,WAAW;GAAM,OAAO;GAAM,CAAC;AAEhE,QAAM;;AAGR,KAAI,CAAC,QAAQ,QACX,OAAMC,eAAAA,WAAW,gBAAgB;AAGnC,KAAI,CAAC,QAAQ,YACX,OAAMC,eAAAA,WAAW,gBAAgB;AAGnC,QAAO;EACL;EACA;EACA,cAAcC,sBAAAA;EACf"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/diagnostics.ts
|
|
3
|
+
function createDiagnosticReport(diagnostics) {
|
|
4
|
+
return {
|
|
5
|
+
ok: !diagnostics.some((diagnostic) => diagnostic.severity === "error"),
|
|
6
|
+
diagnostics
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
function printDiagnosticReport(report) {
|
|
10
|
+
for (const [severity, title] of [
|
|
11
|
+
["error", "Errors"],
|
|
12
|
+
["warning", "Warnings"],
|
|
13
|
+
["info", "Information"]
|
|
14
|
+
]) {
|
|
15
|
+
const entries = report.diagnostics.filter((diagnostic) => diagnostic.severity === severity);
|
|
16
|
+
if (entries.length === 0) continue;
|
|
17
|
+
console.log(`${title}:`);
|
|
18
|
+
for (const diagnostic of entries) {
|
|
19
|
+
const location = diagnostic.path ? ` (${diagnostic.path})` : "";
|
|
20
|
+
console.log(` [${diagnostic.code}] ${diagnostic.message}${location}`);
|
|
21
|
+
if (diagnostic.migrationId) console.log(` migration: ${diagnostic.migrationId}`);
|
|
22
|
+
if (diagnostic.guide) console.log(` guide: ${diagnostic.guide}`);
|
|
23
|
+
if (diagnostic.suggestion) console.log(` ${diagnostic.suggestion}`);
|
|
24
|
+
}
|
|
25
|
+
console.log("");
|
|
26
|
+
}
|
|
27
|
+
if (report.diagnostics.length === 0) console.log("No issues found.");
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
exports.createDiagnosticReport = createDiagnosticReport;
|
|
31
|
+
exports.printDiagnosticReport = printDiagnosticReport;
|
|
32
|
+
|
|
33
|
+
//# sourceMappingURL=diagnostics.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnostics.cjs","names":[],"sources":["../../src/diagnostics.ts"],"sourcesContent":["export type DiagnosticSeverity = \"error\" | \"warning\" | \"info\";\r\n\r\nexport interface Diagnostic {\r\n code: string;\r\n severity: DiagnosticSeverity;\r\n message: string;\r\n path?: string;\r\n suggestion?: string;\r\n migrationId?: string;\r\n guide?: string;\r\n}\r\n\r\nexport interface DiagnosticReport {\r\n ok: boolean;\r\n diagnostics: Diagnostic[];\r\n}\r\n\r\nexport function createDiagnosticReport(diagnostics: Diagnostic[]): DiagnosticReport {\r\n return {\r\n ok: !diagnostics.some((diagnostic) => diagnostic.severity === \"error\"),\r\n diagnostics,\r\n };\r\n}\r\n\r\nexport function printDiagnosticReport(report: DiagnosticReport): void {\r\n const groups: Array<[DiagnosticSeverity, string]> = [\r\n [\"error\", \"Errors\"],\r\n [\"warning\", \"Warnings\"],\r\n [\"info\", \"Information\"],\r\n ];\r\n\r\n for (const [severity, title] of groups) {\r\n const entries = report.diagnostics.filter((diagnostic) => diagnostic.severity === severity);\r\n if (entries.length === 0) continue;\r\n console.log(`${title}:`);\r\n for (const diagnostic of entries) {\r\n const location = diagnostic.path ? ` (${diagnostic.path})` : \"\";\r\n console.log(` [${diagnostic.code}] ${diagnostic.message}${location}`);\r\n if (diagnostic.migrationId) console.log(` migration: ${diagnostic.migrationId}`);\r\n if (diagnostic.guide) console.log(` guide: ${diagnostic.guide}`);\r\n if (diagnostic.suggestion) console.log(` ${diagnostic.suggestion}`);\r\n }\r\n console.log(\"\");\r\n }\r\n\r\n if (report.diagnostics.length === 0) console.log(\"No issues found.\");\r\n}\r\n"],"mappings":";;AAiBA,SAAgB,uBAAuB,aAA6C;AAClF,QAAO;EACL,IAAI,CAAC,YAAY,MAAM,eAAe,WAAW,aAAa,QAAQ;EACtE;EACD;;AAGH,SAAgB,sBAAsB,QAAgC;AAOpE,MAAK,MAAM,CAAC,UAAU,UAN8B;EAClD,CAAC,SAAS,SAAS;EACnB,CAAC,WAAW,WAAW;EACvB,CAAC,QAAQ,cAAc;EACxB,EAEuC;EACtC,MAAM,UAAU,OAAO,YAAY,QAAQ,eAAe,WAAW,aAAa,SAAS;AAC3F,MAAI,QAAQ,WAAW,EAAG;AAC1B,UAAQ,IAAI,GAAG,MAAM,GAAG;AACxB,OAAK,MAAM,cAAc,SAAS;GAChC,MAAM,WAAW,WAAW,OAAO,KAAK,WAAW,KAAK,KAAK;AAC7D,WAAQ,IAAI,MAAM,WAAW,KAAK,IAAI,WAAW,UAAU,WAAW;AACtE,OAAI,WAAW,YAAa,SAAQ,IAAI,kBAAkB,WAAW,cAAc;AACnF,OAAI,WAAW,MAAO,SAAQ,IAAI,cAAc,WAAW,QAAQ;AACnE,OAAI,WAAW,WAAY,SAAQ,IAAI,OAAO,WAAW,aAAa;;AAExE,UAAQ,IAAI,GAAG;;AAGjB,KAAI,OAAO,YAAY,WAAW,EAAG,SAAQ,IAAI,mBAAmB"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//#region src/diagnostics.d.ts
|
|
2
|
+
type DiagnosticSeverity = "error" | "warning" | "info";
|
|
3
|
+
interface Diagnostic {
|
|
4
|
+
code: string;
|
|
5
|
+
severity: DiagnosticSeverity;
|
|
6
|
+
message: string;
|
|
7
|
+
path?: string;
|
|
8
|
+
suggestion?: string;
|
|
9
|
+
migrationId?: string;
|
|
10
|
+
guide?: string;
|
|
11
|
+
}
|
|
12
|
+
interface DiagnosticReport {
|
|
13
|
+
ok: boolean;
|
|
14
|
+
diagnostics: Diagnostic[];
|
|
15
|
+
}
|
|
16
|
+
declare function createDiagnosticReport(diagnostics: Diagnostic[]): DiagnosticReport;
|
|
17
|
+
declare function printDiagnosticReport(report: DiagnosticReport): void;
|
|
18
|
+
//#endregion
|
|
19
|
+
export { Diagnostic, DiagnosticReport, DiagnosticSeverity, createDiagnosticReport, printDiagnosticReport };
|
|
20
|
+
//# sourceMappingURL=diagnostics.d.cts.map
|