@rafters/veneer 0.0.1 → 0.0.2
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/bin.d.mts +1 -0
- package/dist/bin.mjs +20 -0
- package/dist/check-DxTxqBre.mjs +156 -0
- package/dist/index.mjs +2 -155
- package/package.json +4 -1
package/dist/bin.d.mts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {}
|
package/dist/bin.mjs
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { t as check } from "./check-DxTxqBre.mjs";
|
|
3
|
+
//#region src/bin.ts
|
|
4
|
+
const [root, ...rest] = process.argv.slice(2);
|
|
5
|
+
if (root?.startsWith("-") || rest.length > 0) {
|
|
6
|
+
process.stderr.write("usage: rafters-check [root]\n");
|
|
7
|
+
process.exitCode = 1;
|
|
8
|
+
} else {
|
|
9
|
+
const result = await check(root ?? process.cwd());
|
|
10
|
+
if (result.ok) {
|
|
11
|
+
process.stdout.write(result.report);
|
|
12
|
+
for (const { message } of result.notices) process.stderr.write(`${message}\n`);
|
|
13
|
+
process.exitCode = result.diagnostics.some(({ severity }) => severity === "error") ? 1 : 0;
|
|
14
|
+
} else {
|
|
15
|
+
for (const { message } of result.errors) process.stderr.write(`${message}\n`);
|
|
16
|
+
process.exitCode = 1;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { a as ProjectError, i as resolveComponents, n as report, o as openProject, r as compareCodePoints, s as readConfig, t as lint } from "./lint-BabXVYQJ.mjs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { mkdir, rename, rm, writeFile } from "node:fs/promises";
|
|
4
|
+
import { lstatSync } from "node:fs";
|
|
5
|
+
//#region src/docs.ts
|
|
6
|
+
function propLine(prop) {
|
|
7
|
+
return {
|
|
8
|
+
name: prop.name,
|
|
9
|
+
type: prop.type,
|
|
10
|
+
optional: prop.optional,
|
|
11
|
+
...prop.default !== void 0 && { default: prop.default },
|
|
12
|
+
...prop.values !== void 0 && { values: prop.values },
|
|
13
|
+
...prop.doc !== void 0 && { doc: prop.doc },
|
|
14
|
+
file: prop.file,
|
|
15
|
+
line: prop.line,
|
|
16
|
+
column: prop.column
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function componentLine(component) {
|
|
20
|
+
return {
|
|
21
|
+
kind: "component",
|
|
22
|
+
name: component.name,
|
|
23
|
+
file: component.file,
|
|
24
|
+
resolved: component.resolved,
|
|
25
|
+
...component.reason !== void 0 && { reason: component.reason },
|
|
26
|
+
...component.description !== void 0 && { description: component.description },
|
|
27
|
+
tags: component.tags,
|
|
28
|
+
props: component.props.map(propLine),
|
|
29
|
+
inherited: component.inherited,
|
|
30
|
+
inheritedDefaults: component.inheritedDefaults
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function docsText(intent, components) {
|
|
34
|
+
return [{
|
|
35
|
+
kind: "project",
|
|
36
|
+
intent
|
|
37
|
+
}, ...components.map(componentLine)].map((line) => `${JSON.stringify(line)}\n`).join("");
|
|
38
|
+
}
|
|
39
|
+
async function writeWhole(docsPath, text) {
|
|
40
|
+
const temporary = `${docsPath}.tmp`;
|
|
41
|
+
await mkdir(path.dirname(docsPath), { recursive: true });
|
|
42
|
+
try {
|
|
43
|
+
await rm(temporary, { force: true });
|
|
44
|
+
await writeFile(temporary, text, { flag: "wx" });
|
|
45
|
+
await rename(temporary, docsPath);
|
|
46
|
+
} catch (error) {
|
|
47
|
+
await rm(temporary, { force: true });
|
|
48
|
+
throw error;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async function openOrError(root, unsaved) {
|
|
52
|
+
try {
|
|
53
|
+
return await openProject(root, { unsaved });
|
|
54
|
+
} catch (error) {
|
|
55
|
+
if (error instanceof ProjectError && error.code === "tsconfig-missing") return {
|
|
56
|
+
code: error.code,
|
|
57
|
+
message: error.message
|
|
58
|
+
};
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function outputSymlinkError(root) {
|
|
63
|
+
const symlink = [".rafters", ".rafters/veneer"].find((folder) => lstatSync(path.join(root, folder), { throwIfNoEntry: false })?.isSymbolicLink());
|
|
64
|
+
if (!symlink) return void 0;
|
|
65
|
+
return {
|
|
66
|
+
code: "output-symlink",
|
|
67
|
+
message: `${symlink} is a symbolic link; veneer writes only inside the project`
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function sortedNotices(notices) {
|
|
71
|
+
return notices.toSorted((a, b) => compareCodePoints(a.code, b.code) || compareCodePoints(a.message, b.message));
|
|
72
|
+
}
|
|
73
|
+
async function writeDocsFrom(project, config) {
|
|
74
|
+
const { components, notices } = await resolveComponents(project, config.componentFolders);
|
|
75
|
+
const docsPath = path.join(project.root, ".rafters/veneer/docs.jsonl");
|
|
76
|
+
await writeWhole(docsPath, docsText(config.intent, components));
|
|
77
|
+
return {
|
|
78
|
+
docsPath,
|
|
79
|
+
notices: sortedNotices([...config.notices, ...notices])
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
async function writeDocs(projectRoot) {
|
|
83
|
+
const root = path.resolve(projectRoot);
|
|
84
|
+
const config = await readConfig(root);
|
|
85
|
+
if (!config.ok) return {
|
|
86
|
+
ok: false,
|
|
87
|
+
errors: config.errors
|
|
88
|
+
};
|
|
89
|
+
const symlink = outputSymlinkError(root);
|
|
90
|
+
if (symlink) return {
|
|
91
|
+
ok: false,
|
|
92
|
+
errors: [symlink]
|
|
93
|
+
};
|
|
94
|
+
const project = await openOrError(root);
|
|
95
|
+
if ("code" in project) return {
|
|
96
|
+
ok: false,
|
|
97
|
+
errors: [project]
|
|
98
|
+
};
|
|
99
|
+
try {
|
|
100
|
+
return {
|
|
101
|
+
ok: true,
|
|
102
|
+
...await writeDocsFrom(project, config)
|
|
103
|
+
};
|
|
104
|
+
} finally {
|
|
105
|
+
project.close();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
//#endregion
|
|
109
|
+
//#region src/check.ts
|
|
110
|
+
function outsideProgram(file) {
|
|
111
|
+
return {
|
|
112
|
+
code: "outside-program",
|
|
113
|
+
message: `${file} is not in the tsconfig's files, so it was not checked`
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
async function check(projectRoot, options = {}) {
|
|
117
|
+
const root = path.resolve(projectRoot);
|
|
118
|
+
const config = await readConfig(root);
|
|
119
|
+
if (!config.ok) return {
|
|
120
|
+
ok: false,
|
|
121
|
+
errors: config.errors
|
|
122
|
+
};
|
|
123
|
+
const unsaved = options.unsaved ?? {};
|
|
124
|
+
const unsavedFiles = Object.keys(unsaved);
|
|
125
|
+
const isSave = options.save === true && unsavedFiles.length === 0;
|
|
126
|
+
const symlink = isSave ? outputSymlinkError(root) : void 0;
|
|
127
|
+
if (symlink) return {
|
|
128
|
+
ok: false,
|
|
129
|
+
errors: [symlink]
|
|
130
|
+
};
|
|
131
|
+
const project = await openOrError(root, unsaved);
|
|
132
|
+
if ("code" in project) return {
|
|
133
|
+
ok: false,
|
|
134
|
+
errors: [project]
|
|
135
|
+
};
|
|
136
|
+
try {
|
|
137
|
+
const roots = project.checker.getRootFileNames();
|
|
138
|
+
const outside = unsavedFiles.filter((file) => !roots.includes(path.join(root, file)));
|
|
139
|
+
const asked = options.paths ?? (unsavedFiles.length > 0 ? unsavedFiles : void 0);
|
|
140
|
+
const diagnostics = await lint(project, {
|
|
141
|
+
componentFolders: config.componentFolders,
|
|
142
|
+
files: isSave ? void 0 : asked?.filter((file) => !outside.includes(file))
|
|
143
|
+
});
|
|
144
|
+
const written = isSave ? await writeDocsFrom(project, config) : void 0;
|
|
145
|
+
return {
|
|
146
|
+
ok: true,
|
|
147
|
+
diagnostics,
|
|
148
|
+
report: report(diagnostics),
|
|
149
|
+
...written ?? { notices: sortedNotices([...config.notices, ...outside.map(outsideProgram)]) }
|
|
150
|
+
};
|
|
151
|
+
} finally {
|
|
152
|
+
project.close();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
//#endregion
|
|
156
|
+
export { writeDocs as n, check as t };
|
package/dist/index.mjs
CHANGED
|
@@ -1,156 +1,3 @@
|
|
|
1
|
-
import { a as ProjectError,
|
|
2
|
-
import
|
|
3
|
-
import { mkdir, rename, rm, writeFile } from "node:fs/promises";
|
|
4
|
-
import { lstatSync } from "node:fs";
|
|
5
|
-
//#region src/docs.ts
|
|
6
|
-
function propLine(prop) {
|
|
7
|
-
return {
|
|
8
|
-
name: prop.name,
|
|
9
|
-
type: prop.type,
|
|
10
|
-
optional: prop.optional,
|
|
11
|
-
...prop.default !== void 0 && { default: prop.default },
|
|
12
|
-
...prop.values !== void 0 && { values: prop.values },
|
|
13
|
-
...prop.doc !== void 0 && { doc: prop.doc },
|
|
14
|
-
file: prop.file,
|
|
15
|
-
line: prop.line,
|
|
16
|
-
column: prop.column
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
function componentLine(component) {
|
|
20
|
-
return {
|
|
21
|
-
kind: "component",
|
|
22
|
-
name: component.name,
|
|
23
|
-
file: component.file,
|
|
24
|
-
resolved: component.resolved,
|
|
25
|
-
...component.reason !== void 0 && { reason: component.reason },
|
|
26
|
-
...component.description !== void 0 && { description: component.description },
|
|
27
|
-
tags: component.tags,
|
|
28
|
-
props: component.props.map(propLine),
|
|
29
|
-
inherited: component.inherited,
|
|
30
|
-
inheritedDefaults: component.inheritedDefaults
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
function docsText(intent, components) {
|
|
34
|
-
return [{
|
|
35
|
-
kind: "project",
|
|
36
|
-
intent
|
|
37
|
-
}, ...components.map(componentLine)].map((line) => `${JSON.stringify(line)}\n`).join("");
|
|
38
|
-
}
|
|
39
|
-
async function writeWhole(docsPath, text) {
|
|
40
|
-
const temporary = `${docsPath}.tmp`;
|
|
41
|
-
await mkdir(path.dirname(docsPath), { recursive: true });
|
|
42
|
-
try {
|
|
43
|
-
await rm(temporary, { force: true });
|
|
44
|
-
await writeFile(temporary, text, { flag: "wx" });
|
|
45
|
-
await rename(temporary, docsPath);
|
|
46
|
-
} catch (error) {
|
|
47
|
-
await rm(temporary, { force: true });
|
|
48
|
-
throw error;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
async function openOrError(root, unsaved) {
|
|
52
|
-
try {
|
|
53
|
-
return await openProject(root, { unsaved });
|
|
54
|
-
} catch (error) {
|
|
55
|
-
if (error instanceof ProjectError && error.code === "tsconfig-missing") return {
|
|
56
|
-
code: error.code,
|
|
57
|
-
message: error.message
|
|
58
|
-
};
|
|
59
|
-
throw error;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
function outputSymlinkError(root) {
|
|
63
|
-
const symlink = [".rafters", ".rafters/veneer"].find((folder) => lstatSync(path.join(root, folder), { throwIfNoEntry: false })?.isSymbolicLink());
|
|
64
|
-
if (!symlink) return void 0;
|
|
65
|
-
return {
|
|
66
|
-
code: "output-symlink",
|
|
67
|
-
message: `${symlink} is a symbolic link; veneer writes only inside the project`
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
function sortedNotices(notices) {
|
|
71
|
-
return notices.toSorted((a, b) => compareCodePoints(a.code, b.code) || compareCodePoints(a.message, b.message));
|
|
72
|
-
}
|
|
73
|
-
async function writeDocsFrom(project, config) {
|
|
74
|
-
const { components, notices } = await resolveComponents(project, config.componentFolders);
|
|
75
|
-
const docsPath = path.join(project.root, ".rafters/veneer/docs.jsonl");
|
|
76
|
-
await writeWhole(docsPath, docsText(config.intent, components));
|
|
77
|
-
return {
|
|
78
|
-
docsPath,
|
|
79
|
-
notices: sortedNotices([...config.notices, ...notices])
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
async function writeDocs(projectRoot) {
|
|
83
|
-
const root = path.resolve(projectRoot);
|
|
84
|
-
const config = await readConfig(root);
|
|
85
|
-
if (!config.ok) return {
|
|
86
|
-
ok: false,
|
|
87
|
-
errors: config.errors
|
|
88
|
-
};
|
|
89
|
-
const symlink = outputSymlinkError(root);
|
|
90
|
-
if (symlink) return {
|
|
91
|
-
ok: false,
|
|
92
|
-
errors: [symlink]
|
|
93
|
-
};
|
|
94
|
-
const project = await openOrError(root);
|
|
95
|
-
if ("code" in project) return {
|
|
96
|
-
ok: false,
|
|
97
|
-
errors: [project]
|
|
98
|
-
};
|
|
99
|
-
try {
|
|
100
|
-
return {
|
|
101
|
-
ok: true,
|
|
102
|
-
...await writeDocsFrom(project, config)
|
|
103
|
-
};
|
|
104
|
-
} finally {
|
|
105
|
-
project.close();
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
//#endregion
|
|
109
|
-
//#region src/check.ts
|
|
110
|
-
function outsideProgram(file) {
|
|
111
|
-
return {
|
|
112
|
-
code: "outside-program",
|
|
113
|
-
message: `${file} is not in the tsconfig's files, so it was not checked`
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
async function check(projectRoot, options = {}) {
|
|
117
|
-
const root = path.resolve(projectRoot);
|
|
118
|
-
const config = await readConfig(root);
|
|
119
|
-
if (!config.ok) return {
|
|
120
|
-
ok: false,
|
|
121
|
-
errors: config.errors
|
|
122
|
-
};
|
|
123
|
-
const unsaved = options.unsaved ?? {};
|
|
124
|
-
const unsavedFiles = Object.keys(unsaved);
|
|
125
|
-
const isSave = options.save === true && unsavedFiles.length === 0;
|
|
126
|
-
const symlink = isSave ? outputSymlinkError(root) : void 0;
|
|
127
|
-
if (symlink) return {
|
|
128
|
-
ok: false,
|
|
129
|
-
errors: [symlink]
|
|
130
|
-
};
|
|
131
|
-
const project = await openOrError(root, unsaved);
|
|
132
|
-
if ("code" in project) return {
|
|
133
|
-
ok: false,
|
|
134
|
-
errors: [project]
|
|
135
|
-
};
|
|
136
|
-
try {
|
|
137
|
-
const roots = project.checker.getRootFileNames();
|
|
138
|
-
const outside = unsavedFiles.filter((file) => !roots.includes(path.join(root, file)));
|
|
139
|
-
const asked = options.paths ?? (unsavedFiles.length > 0 ? unsavedFiles : void 0);
|
|
140
|
-
const diagnostics = await lint(project, {
|
|
141
|
-
componentFolders: config.componentFolders,
|
|
142
|
-
files: isSave ? void 0 : asked?.filter((file) => !outside.includes(file))
|
|
143
|
-
});
|
|
144
|
-
const written = isSave ? await writeDocsFrom(project, config) : void 0;
|
|
145
|
-
return {
|
|
146
|
-
ok: true,
|
|
147
|
-
diagnostics,
|
|
148
|
-
report: report(diagnostics),
|
|
149
|
-
...written ?? { notices: sortedNotices([...config.notices, ...outside.map(outsideProgram)]) }
|
|
150
|
-
};
|
|
151
|
-
} finally {
|
|
152
|
-
project.close();
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
//#endregion
|
|
1
|
+
import { a as ProjectError, n as report, o as openProject, t as lint } from "./lint-BabXVYQJ.mjs";
|
|
2
|
+
import { n as writeDocs, t as check } from "./check-DxTxqBre.mjs";
|
|
156
3
|
export { ProjectError, check, lint, openProject, report, writeDocs };
|
package/package.json
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rafters/veneer",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "Docs, rafters check and the composite compile for rafters projects",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "https://github.com/rafters-studio/veneer"
|
|
9
9
|
},
|
|
10
|
+
"bin": {
|
|
11
|
+
"rafters-check": "./dist/bin.mjs"
|
|
12
|
+
},
|
|
10
13
|
"files": [
|
|
11
14
|
"dist"
|
|
12
15
|
],
|