@codefast/cli 0.9.0 → 0.10.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/CHANGELOG.md +28 -0
- package/README.md +329 -149
- package/dist/arrange/analyze.d.ts +10 -0
- package/dist/arrange/cli-schema.d.ts +50 -0
- package/dist/arrange/command.d.ts +7 -0
- package/dist/arrange/domain/analyze-service.d.ts +18 -0
- package/dist/arrange/domain/ast/ast-node.d.ts +394 -0
- package/dist/arrange/domain/ast/collectors-cn.d.ts +26 -0
- package/dist/arrange/domain/ast/collectors-jsx.d.ts +8 -0
- package/dist/arrange/domain/ast/collectors-tv.d.ts +34 -0
- package/dist/arrange/domain/ast/helpers.d.ts +36 -0
- package/dist/arrange/domain/ast/helpers.js +1 -0
- package/dist/arrange/domain/ast/simplify-targets.d.ts +22 -0
- package/dist/arrange/domain/ast/targets.d.ts +20 -0
- package/dist/arrange/domain/constants.d.ts +111 -0
- package/dist/arrange/domain/grouping-service.d.ts +100 -0
- package/dist/arrange/domain/grouping.d.ts +21 -0
- package/dist/arrange/domain/imports.d.ts +14 -0
- package/dist/arrange/domain/source-text-formatters.d.ts +33 -0
- package/dist/arrange/domain/tailwind-token.d.ts +24 -0
- package/dist/arrange/domain/token-classifier.d.ts +47 -0
- package/dist/arrange/domain/types.d.ts +208 -0
- package/dist/arrange/output.d.ts +26 -0
- package/dist/arrange/process-file.d.ts +11 -0
- package/dist/arrange/resolve-target.d.ts +10 -0
- package/dist/arrange/resolve-target.js +3 -16
- package/dist/arrange/scan-target.d.ts +7 -0
- package/dist/arrange/simplify-process-file.d.ts +11 -0
- package/dist/arrange/simplify-sync.d.ts +13 -0
- package/dist/arrange/source-parse.d.ts +7 -0
- package/dist/arrange/suggest.d.ts +8 -0
- package/dist/arrange/sync.d.ts +11 -0
- package/dist/arrange/typescript-ast-translator.d.ts +31 -0
- package/dist/arrange/workspace.d.ts +13 -0
- package/dist/arrange/workspace.js +2 -2
- package/dist/audit/cli-schema.d.ts +93 -0
- package/dist/audit/cli-schema.js +3 -3
- package/dist/audit/command.d.ts +8 -0
- package/dist/audit/command.js +12 -12
- package/dist/audit/domain/audit-file.d.ts +7 -0
- package/dist/audit/domain/comment-content.d.ts +26 -0
- package/dist/audit/domain/comment-dividers.d.ts +62 -0
- package/dist/audit/domain/display-names.d.ts +11 -0
- package/dist/audit/domain/import-policy.d.ts +34 -0
- package/dist/audit/domain/import-policy.js +147 -0
- package/dist/audit/domain/link-references.d.ts +40 -0
- package/dist/audit/domain/mappings.d.ts +45 -0
- package/dist/audit/domain/markdown-links.d.ts +44 -0
- package/dist/audit/domain/since-versions.d.ts +26 -0
- package/dist/audit/domain/tokenize.d.ts +14 -0
- package/dist/audit/domain/tsdoc-syntax.d.ts +20 -0
- package/dist/audit/domain/types.d.ts +171 -0
- package/dist/audit/output.d.ts +91 -0
- package/dist/audit/output.js +11 -11
- package/dist/audit/prepare.d.ts +70 -0
- package/dist/audit/prepare.js +11 -11
- package/dist/audit/run-comments.d.ts +17 -0
- package/dist/audit/run-display-names.d.ts +14 -0
- package/dist/audit/run-imports.d.ts +14 -0
- package/dist/audit/{run-react.js → run-imports.js} +15 -5
- package/dist/audit/run-links.d.ts +14 -0
- package/dist/audit/run.d.ts +14 -0
- package/dist/bin.d.ts +2 -0
- package/dist/cli.d.ts +6 -0
- package/dist/core/cli/format-error.d.ts +7 -0
- package/dist/core/cli/global-options.d.ts +15 -0
- package/dist/core/cli/positional.d.ts +6 -0
- package/dist/core/cli/result-handle.d.ts +19 -0
- package/dist/core/config/define-config.d.ts +7 -0
- package/dist/core/config/define-config.js +8 -0
- package/dist/core/config/loader.d.ts +18 -0
- package/dist/core/config/loader.js +2 -7
- package/dist/core/config/schema.d.ts +99 -0
- package/dist/core/config/schema.js +7 -85
- package/dist/core/config/warnings.d.ts +6 -0
- package/dist/core/config.d.ts +12 -0
- package/dist/core/errors.d.ts +25 -0
- package/dist/core/exit-codes.d.ts +18 -0
- package/dist/core/filesystem/node.d.ts +7 -0
- package/dist/core/filesystem/node.js +1 -0
- package/dist/core/filesystem/port.d.ts +44 -0
- package/dist/core/glob.d.ts +19 -0
- package/dist/core/logger.d.ts +9 -0
- package/dist/core/result.d.ts +30 -0
- package/dist/core/schema-parse.d.ts +9 -0
- package/dist/core/source-text-edit.d.ts +33 -0
- package/dist/core/verbose-diagnostics.d.ts +6 -0
- package/dist/core/workspace/ancestor-directories.d.ts +12 -0
- package/dist/core/workspace/ancestor-directories.js +30 -0
- package/dist/core/workspace/markdown-walk.d.ts +7 -0
- package/dist/core/workspace/markdown-walk.js +2 -20
- package/dist/core/workspace/package-version.d.ts +9 -0
- package/dist/core/workspace/package-version.js +8 -12
- package/dist/core/workspace/resolver.d.ts +39 -0
- package/dist/core/workspace/resolver.js +58 -75
- package/dist/core/workspace/skip-directories.d.ts +6 -0
- package/dist/core/workspace/source-walk.d.ts +16 -0
- package/dist/core/workspace/source-walk.js +2 -19
- package/dist/core/workspace/typescript-walk.d.ts +7 -0
- package/dist/core/workspace/typescript-walk.js +2 -23
- package/dist/core/workspace/walk-files.d.ts +7 -0
- package/dist/core/workspace/walk-files.js +27 -0
- package/dist/core/workspace/well-known-files.d.ts +18 -0
- package/dist/core/workspace/well-known-files.js +18 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +5 -0
- package/dist/mirror/cli-result.d.ts +13 -0
- package/dist/mirror/cli-schema.d.ts +8 -0
- package/dist/mirror/command.d.ts +7 -0
- package/dist/mirror/dist-filesystem-impl.d.ts +8 -0
- package/dist/mirror/domain/constants.d.ts +18 -0
- package/dist/mirror/domain/constants.js +0 -12
- package/dist/mirror/domain/dirent-guard.d.ts +10 -0
- package/dist/mirror/domain/dist-filesystem.d.ts +9 -0
- package/dist/mirror/domain/errors.d.ts +24 -0
- package/dist/mirror/domain/exports.d.ts +36 -0
- package/dist/mirror/domain/package-display-name.d.ts +8 -0
- package/dist/mirror/domain/path-normalizer.d.ts +6 -0
- package/dist/mirror/domain/types.d.ts +131 -0
- package/dist/mirror/output.d.ts +23 -0
- package/dist/mirror/package-path.d.ts +19 -0
- package/dist/mirror/prepare.d.ts +15 -0
- package/dist/mirror/prepare.js +2 -2
- package/dist/mirror/supplement-exports.d.ts +27 -0
- package/dist/mirror/supplement-exports.js +2 -2
- package/dist/mirror/sync-reporter.d.ts +60 -0
- package/dist/mirror/sync-reporter.js +4 -0
- package/dist/mirror/sync-types.d.ts +43 -0
- package/dist/mirror/sync-workspace-package.d.ts +9 -0
- package/dist/mirror/sync-workspace-package.js +3 -3
- package/dist/mirror/sync.d.ts +12 -0
- package/dist/mirror/sync.js +5 -3
- package/dist/mirror/write-exports.d.ts +15 -0
- package/dist/pack-slim/cli-result.d.ts +13 -0
- package/dist/pack-slim/cli-schema.d.ts +17 -0
- package/dist/pack-slim/command.d.ts +7 -0
- package/dist/pack-slim/command.js +2 -2
- package/dist/pack-slim/domain/transform.d.ts +69 -0
- package/dist/pack-slim/domain/types.d.ts +46 -0
- package/dist/pack-slim/output.d.ts +15 -0
- package/dist/pack-slim/sync.d.ts +23 -0
- package/dist/pack-slim/sync.js +4 -4
- package/dist/pack-slim/working-tree.d.ts +20 -0
- package/dist/tag/cli-result.d.ts +7 -0
- package/dist/tag/cli-schema.d.ts +8 -0
- package/dist/tag/command.d.ts +7 -0
- package/dist/tag/domain/types.d.ts +111 -0
- package/dist/tag/output.d.ts +17 -0
- package/dist/tag/prepare.d.ts +13 -0
- package/dist/tag/prepare.js +2 -2
- package/dist/tag/resolve-target-path.d.ts +10 -0
- package/dist/tag/since-writer.d.ts +32 -0
- package/dist/tag/sync.d.ts +42 -0
- package/dist/tag/target-candidates.d.ts +8 -0
- package/dist/tag/target-candidates.js +1 -1
- package/dist/tag/target-runner.d.ts +8 -0
- package/dist/tag/version-resolver.d.ts +7 -0
- package/package.json +12 -1
- package/dist/audit/domain/react-imports.js +0 -91
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
/**
|
|
3
|
+
* Each directory from `fromDirectory` up to and including the filesystem root.
|
|
4
|
+
*
|
|
5
|
+
* @since 0.10.0
|
|
6
|
+
*/
|
|
7
|
+
export function* ancestorDirectories(fromDirectory) {
|
|
8
|
+
let directoryPath = path.resolve(fromDirectory);
|
|
9
|
+
for (;;) {
|
|
10
|
+
yield directoryPath;
|
|
11
|
+
const parent = path.dirname(directoryPath);
|
|
12
|
+
if (parent === directoryPath) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
directoryPath = parent;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The nearest ancestor directory (starting at `fromDirectory`) the predicate accepts, or undefined at the filesystem root.
|
|
20
|
+
*
|
|
21
|
+
* @since 0.10.0
|
|
22
|
+
*/
|
|
23
|
+
export function findNearestAncestor(fromDirectory, isMatch) {
|
|
24
|
+
for (const directoryPath of ancestorDirectories(fromDirectory)) {
|
|
25
|
+
if (isMatch(directoryPath)) {
|
|
26
|
+
return directoryPath;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { FilesystemPort } from "#/core/filesystem/port";
|
|
2
|
+
/**
|
|
3
|
+
* Every markdown file under a root, skipping build output and vendored trees.
|
|
4
|
+
*
|
|
5
|
+
* @since 0.5.0
|
|
6
|
+
*/
|
|
7
|
+
export declare function walkMarkdownFiles(rootDirectoryPath: string, fs: FilesystemPort): Array<string>;
|
|
@@ -1,27 +1,9 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { defaultSkipDirectoryNames } from "#/core/workspace/skip-directories";
|
|
1
|
+
import { walkFiles } from "#/core/workspace/walk-files";
|
|
3
2
|
/**
|
|
4
3
|
* Every markdown file under a root, skipping build output and vendored trees.
|
|
5
4
|
*
|
|
6
5
|
* @since 0.5.0
|
|
7
6
|
*/
|
|
8
7
|
export function walkMarkdownFiles(rootDirectoryPath, fs) {
|
|
9
|
-
|
|
10
|
-
visitMarkdownPaths(result, rootDirectoryPath, fs);
|
|
11
|
-
return result;
|
|
12
|
-
}
|
|
13
|
-
function visitMarkdownPaths(result, entryPath, fs) {
|
|
14
|
-
const entryStats = fs.statSync(entryPath);
|
|
15
|
-
if (entryStats.isDirectory()) {
|
|
16
|
-
for (const childName of fs.readdirSync(entryPath)) {
|
|
17
|
-
if (defaultSkipDirectoryNames.has(childName)) {
|
|
18
|
-
continue;
|
|
19
|
-
}
|
|
20
|
-
visitMarkdownPaths(result, path.join(entryPath, childName), fs);
|
|
21
|
-
}
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
if (entryPath.endsWith(".md")) {
|
|
25
|
-
result.push(entryPath);
|
|
26
|
-
}
|
|
8
|
+
return walkFiles(rootDirectoryPath, fs, (filePath) => filePath.endsWith(".md"));
|
|
27
9
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { FilesystemPort } from "#/core/filesystem/port";
|
|
2
|
+
/**
|
|
3
|
+
* Finds the `version` of the nearest enclosing `package.json`, or null when the first
|
|
4
|
+
* one found declares none (the private workspace root is version-less by design).
|
|
5
|
+
*
|
|
6
|
+
* @since 0.8.0
|
|
7
|
+
*/
|
|
8
|
+
declare function findNearestPackageVersion(fs: FilesystemPort, targetPath: string): string | null;
|
|
9
|
+
export { findNearestPackageVersion };
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
+
import { findNearestAncestor } from "#/core/workspace/ancestor-directories";
|
|
3
|
+
import { packageJsonFileName } from "#/core/workspace/well-known-files";
|
|
2
4
|
/**
|
|
3
5
|
* Finds the `version` of the nearest enclosing `package.json`, or null when the first
|
|
4
6
|
* one found declares none (the private workspace root is version-less by design).
|
|
@@ -7,18 +9,12 @@ import path from "node:path";
|
|
|
7
9
|
*/
|
|
8
10
|
function findNearestPackageVersion(fs, targetPath) {
|
|
9
11
|
const resolved = path.resolve(targetPath);
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const version = JSON.parse(fs.readFileSync(packageJsonPath, "utf8")).version;
|
|
15
|
-
return typeof version === "string" && version.length > 0 ? version : null;
|
|
16
|
-
}
|
|
17
|
-
const parent = path.dirname(current);
|
|
18
|
-
if (parent === current) {
|
|
19
|
-
return null;
|
|
20
|
-
}
|
|
21
|
-
current = parent;
|
|
12
|
+
const startDirectory = fs.statSync(resolved).isDirectory() ? resolved : path.dirname(resolved);
|
|
13
|
+
const packageDirectory = findNearestAncestor(startDirectory, (directoryPath) => fs.existsSync(path.join(directoryPath, packageJsonFileName)));
|
|
14
|
+
if (packageDirectory === undefined) {
|
|
15
|
+
return null;
|
|
22
16
|
}
|
|
17
|
+
const version = JSON.parse(fs.readFileSync(path.join(packageDirectory, packageJsonFileName), "utf8")).version;
|
|
18
|
+
return typeof version === "string" && version.length > 0 ? version : null;
|
|
23
19
|
}
|
|
24
20
|
export { findNearestPackageVersion };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { FilesystemPort } from "#/core/filesystem/port";
|
|
2
|
+
/**
|
|
3
|
+
* A resolved project root and whether it is a pnpm workspace or a standalone single package.
|
|
4
|
+
*
|
|
5
|
+
* @since 0.10.0
|
|
6
|
+
*/
|
|
7
|
+
export type ResolvedProjectRoot = {
|
|
8
|
+
readonly rootDir: string;
|
|
9
|
+
readonly mode: "workspace" | "single-package";
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Resolves the project root: the `pnpm-workspace.yaml` directory, or the nearest `package.json` for a single package.
|
|
13
|
+
*
|
|
14
|
+
* @since 0.10.0
|
|
15
|
+
*/
|
|
16
|
+
export declare function resolveProjectRoot(fromDirectory: string, fs: FilesystemPort): ResolvedProjectRoot;
|
|
17
|
+
/**
|
|
18
|
+
* Where the workspace package patterns came from.
|
|
19
|
+
*
|
|
20
|
+
* @since 0.3.16-canary.0
|
|
21
|
+
*/
|
|
22
|
+
type WorkspacePackageLayoutSource = "pnpm-workspace-yaml" | "default-patterns" | "declared-empty" | "single-package";
|
|
23
|
+
/**
|
|
24
|
+
* The discovered workspace package directories together with how the layout was determined.
|
|
25
|
+
*
|
|
26
|
+
* @since 0.3.16-canary.0
|
|
27
|
+
*/
|
|
28
|
+
export type WorkspacePackageLayoutOutcome = {
|
|
29
|
+
readonly packageDirectoryPathsAbsolute: Array<string>;
|
|
30
|
+
readonly layoutSource: WorkspacePackageLayoutSource;
|
|
31
|
+
readonly hasPnpmWorkspaceYamlFile: boolean;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Lists the workspace's package directories per `pnpm-workspace.yaml`, falling back to default patterns.
|
|
35
|
+
*
|
|
36
|
+
* @since 0.3.16-canary.0
|
|
37
|
+
*/
|
|
38
|
+
export declare function listWorkspacePackageDirectories(rootDirectoryPathAbsolute: string, fs: FilesystemPort, suppressGlobPermissionDiagnostics?: boolean): Promise<WorkspacePackageLayoutOutcome>;
|
|
39
|
+
export {};
|
|
@@ -1,35 +1,28 @@
|
|
|
1
|
-
import { globSync } from "node:fs";
|
|
2
1
|
import path from "node:path";
|
|
3
|
-
import { fileURLToPath } from "node:url";
|
|
4
2
|
import { parse as parseYaml } from "yaml";
|
|
5
3
|
import { messageFrom } from "#/core/errors";
|
|
6
4
|
import { createAnyGlobMatcher } from "#/core/glob";
|
|
7
5
|
import { logger } from "#/core/logger";
|
|
6
|
+
import { findNearestAncestor } from "#/core/workspace/ancestor-directories";
|
|
7
|
+
import { packageJsonFileName, workspaceYamlFileName } from "#/core/workspace/well-known-files";
|
|
8
8
|
/**
|
|
9
|
-
* Resolves the
|
|
9
|
+
* Resolves the project root: the `pnpm-workspace.yaml` directory, or the nearest `package.json` for a single package.
|
|
10
10
|
*
|
|
11
|
-
* @since 0.
|
|
11
|
+
* @since 0.10.0
|
|
12
12
|
*/
|
|
13
|
-
export function
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
if (fs.existsSync(path.join(dir, "pnpm-workspace.yaml"))) {
|
|
19
|
-
return dir;
|
|
20
|
-
}
|
|
21
|
-
const parent = path.dirname(dir);
|
|
22
|
-
if (parent === dir) {
|
|
23
|
-
break;
|
|
24
|
-
}
|
|
25
|
-
dir = parent;
|
|
26
|
-
}
|
|
13
|
+
export function resolveProjectRoot(fromDirectory, fs) {
|
|
14
|
+
// Resolution follows where the user is (cwd), not where the CLI is installed.
|
|
15
|
+
const workspaceRoot = findNearestAncestor(fromDirectory, (directoryPath) => fs.existsSync(path.join(directoryPath, workspaceYamlFileName)));
|
|
16
|
+
if (workspaceRoot !== undefined) {
|
|
17
|
+
return { rootDir: workspaceRoot, mode: "workspace" };
|
|
27
18
|
}
|
|
28
|
-
|
|
19
|
+
const packageRoot = findNearestAncestor(fromDirectory, (directoryPath) => fs.existsSync(path.join(directoryPath, packageJsonFileName)));
|
|
20
|
+
if (packageRoot !== undefined) {
|
|
21
|
+
return { rootDir: packageRoot, mode: "single-package" };
|
|
22
|
+
}
|
|
23
|
+
throw new Error(`Could not locate a project root (no pnpm-workspace.yaml and no package.json found from: ${fromDirectory})`);
|
|
29
24
|
}
|
|
30
|
-
const workspaceYamlFileName = "pnpm-workspace.yaml";
|
|
31
25
|
const defaultIncludePatterns = ["packages/*"];
|
|
32
|
-
const packageJsonFileName = "package.json";
|
|
33
26
|
function toPosix(filePath) {
|
|
34
27
|
return filePath.split(path.sep).join("/");
|
|
35
28
|
}
|
|
@@ -71,33 +64,28 @@ function splitPnpmWorkspacePackagesArray(raw) {
|
|
|
71
64
|
return { include, exclude };
|
|
72
65
|
}
|
|
73
66
|
function parsePnpmWorkspaceDocument(doc) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
throw new Error(`${wf} root document must be an object (got empty or null)`);
|
|
77
|
-
}
|
|
78
|
-
if (typeof doc !== "object" || Array.isArray(doc)) {
|
|
79
|
-
throw new Error(`${wf} root must be a mapping, not an array or scalar`);
|
|
67
|
+
if (doc === null || typeof doc !== "object" || Array.isArray(doc)) {
|
|
68
|
+
throw new Error(`${workspaceYamlFileName} root must be a mapping, not an array or scalar`);
|
|
80
69
|
}
|
|
81
70
|
const parsedDoc = doc;
|
|
82
71
|
if (!Object.prototype.hasOwnProperty.call(parsedDoc, "packages")) {
|
|
83
72
|
return { include: [], exclude: [], hasPackagesKey: false, isEmptyPackagesArray: false };
|
|
84
73
|
}
|
|
85
|
-
const
|
|
86
|
-
if (!Array.isArray(
|
|
87
|
-
throw new Error(`${
|
|
74
|
+
const packagesField = parsedDoc.packages;
|
|
75
|
+
if (!Array.isArray(packagesField)) {
|
|
76
|
+
throw new Error(`${workspaceYamlFileName} field "packages" must be an array`);
|
|
88
77
|
}
|
|
89
|
-
if (
|
|
78
|
+
if (packagesField.length === 0) {
|
|
90
79
|
return { include: [], exclude: [], hasPackagesKey: true, isEmptyPackagesArray: true };
|
|
91
80
|
}
|
|
92
81
|
return {
|
|
93
|
-
...splitPnpmWorkspacePackagesArray(
|
|
82
|
+
...splitPnpmWorkspacePackagesArray(packagesField),
|
|
94
83
|
hasPackagesKey: true,
|
|
95
84
|
isEmptyPackagesArray: false,
|
|
96
85
|
};
|
|
97
86
|
}
|
|
98
87
|
async function readWorkspaceYaml(rootDir, fs) {
|
|
99
|
-
const
|
|
100
|
-
const workspaceYamlPath = path.join(rootDir, wf);
|
|
88
|
+
const workspaceYamlPath = path.join(rootDir, workspaceYamlFileName);
|
|
101
89
|
if (!fs.existsSync(workspaceYamlPath)) {
|
|
102
90
|
return { exists: false };
|
|
103
91
|
}
|
|
@@ -106,7 +94,7 @@ async function readWorkspaceYaml(rootDir, fs) {
|
|
|
106
94
|
raw = await fs.readFile(workspaceYamlPath, "utf8");
|
|
107
95
|
}
|
|
108
96
|
catch (caughtReadError) {
|
|
109
|
-
throw new Error(`Failed to read ${
|
|
97
|
+
throw new Error(`Failed to read ${workspaceYamlFileName}: ${messageFrom(caughtReadError)}`, {
|
|
110
98
|
cause: caughtReadError,
|
|
111
99
|
});
|
|
112
100
|
}
|
|
@@ -115,12 +103,12 @@ async function readWorkspaceYaml(rootDir, fs) {
|
|
|
115
103
|
doc = parseYaml(raw);
|
|
116
104
|
}
|
|
117
105
|
catch (caughtYamlParseError) {
|
|
118
|
-
throw new Error(`Failed to parse ${
|
|
106
|
+
throw new Error(`Failed to parse ${workspaceYamlFileName}: ${messageFrom(caughtYamlParseError)}`, {
|
|
119
107
|
cause: caughtYamlParseError,
|
|
120
108
|
});
|
|
121
109
|
}
|
|
122
110
|
if (doc === null || doc === undefined) {
|
|
123
|
-
throw new Error(`${
|
|
111
|
+
throw new Error(`${workspaceYamlFileName} must define a mapping at the document root`);
|
|
124
112
|
}
|
|
125
113
|
return { exists: true, doc };
|
|
126
114
|
}
|
|
@@ -131,47 +119,42 @@ async function readWorkspaceYaml(rootDir, fs) {
|
|
|
131
119
|
*/
|
|
132
120
|
export async function listWorkspacePackageDirectories(rootDirectoryPathAbsolute, fs, suppressGlobPermissionDiagnostics) {
|
|
133
121
|
const workspaceYaml = await readWorkspaceYaml(rootDirectoryPathAbsolute, fs);
|
|
134
|
-
|
|
122
|
+
if (!workspaceYaml.exists) {
|
|
123
|
+
// No pnpm-workspace.yaml: treat the nearest package as the whole workspace.
|
|
124
|
+
const rootPackageJsonPath = path.join(rootDirectoryPathAbsolute, packageJsonFileName);
|
|
125
|
+
return {
|
|
126
|
+
packageDirectoryPathsAbsolute: fs.existsSync(rootPackageJsonPath) ? [rootDirectoryPathAbsolute] : [],
|
|
127
|
+
layoutSource: "single-package",
|
|
128
|
+
hasPnpmWorkspaceYamlFile: false,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
135
131
|
let include;
|
|
136
132
|
let exclude;
|
|
137
133
|
let layoutSource;
|
|
138
|
-
const
|
|
139
|
-
if (!
|
|
140
|
-
include = [...
|
|
134
|
+
const parsed = parsePnpmWorkspaceDocument(workspaceYaml.doc);
|
|
135
|
+
if (!parsed.hasPackagesKey) {
|
|
136
|
+
include = [...defaultIncludePatterns];
|
|
141
137
|
exclude = [];
|
|
142
138
|
layoutSource = "default-patterns";
|
|
143
139
|
}
|
|
140
|
+
else if (parsed.isEmptyPackagesArray) {
|
|
141
|
+
return {
|
|
142
|
+
packageDirectoryPathsAbsolute: [],
|
|
143
|
+
layoutSource: "declared-empty",
|
|
144
|
+
hasPnpmWorkspaceYamlFile: true,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
144
147
|
else {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
exclude = [];
|
|
149
|
-
layoutSource = "default-patterns";
|
|
150
|
-
}
|
|
151
|
-
else if (parsed.isEmptyPackagesArray) {
|
|
152
|
-
return {
|
|
153
|
-
packageDirectoryPathsAbsolute: [],
|
|
154
|
-
layoutSource: "declared-empty",
|
|
155
|
-
hasPnpmWorkspaceYamlFile: true,
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
else {
|
|
159
|
-
include = parsed.include;
|
|
160
|
-
exclude = parsed.exclude;
|
|
161
|
-
layoutSource = "pnpm-workspace-yaml";
|
|
162
|
-
}
|
|
148
|
+
include = parsed.include;
|
|
149
|
+
exclude = parsed.exclude;
|
|
150
|
+
layoutSource = "pnpm-workspace-yaml";
|
|
163
151
|
}
|
|
164
152
|
const foundRelativePosixPackageRoots = new Set();
|
|
165
|
-
const globOpts = {
|
|
166
|
-
cwd: rootDirectoryPathAbsolute,
|
|
167
|
-
posix: true,
|
|
168
|
-
...(path.sep === "\\" ? { windowsPathsNoEscape: true } : {}),
|
|
169
|
-
};
|
|
170
153
|
for (const pattern of include) {
|
|
171
|
-
const
|
|
154
|
+
const packageJsonGlob = workspacePatternToPackageJsonGlob(pattern);
|
|
172
155
|
let matches;
|
|
173
156
|
try {
|
|
174
|
-
matches = globSync(
|
|
157
|
+
matches = fs.globSync(packageJsonGlob, { cwd: rootDirectoryPathAbsolute });
|
|
175
158
|
}
|
|
176
159
|
catch (caughtGlobError) {
|
|
177
160
|
if (isGlobPermissionError(caughtGlobError)) {
|
|
@@ -184,26 +167,26 @@ export async function listWorkspacePackageDirectories(rootDirectoryPathAbsolute,
|
|
|
184
167
|
cause: caughtGlobError,
|
|
185
168
|
});
|
|
186
169
|
}
|
|
170
|
+
const suffix = `/${packageJsonFileName}`;
|
|
187
171
|
for (const matchedPath of matches) {
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
if (!posix.endsWith(suffix)) {
|
|
172
|
+
const posixPath = toPosix(matchedPath);
|
|
173
|
+
if (!posixPath.endsWith(suffix)) {
|
|
191
174
|
continue;
|
|
192
175
|
}
|
|
193
|
-
const
|
|
194
|
-
if (!
|
|
176
|
+
const relativeRoot = posixPath.slice(0, -suffix.length);
|
|
177
|
+
if (!relativeRoot) {
|
|
195
178
|
continue;
|
|
196
179
|
}
|
|
197
|
-
foundRelativePosixPackageRoots.add(
|
|
180
|
+
foundRelativePosixPackageRoots.add(relativeRoot);
|
|
198
181
|
}
|
|
199
182
|
}
|
|
200
183
|
const isExcluded = createAnyGlobMatcher(exclude, { dot: true });
|
|
201
|
-
const filteredRelative = [...foundRelativePosixPackageRoots].filter((
|
|
184
|
+
const filteredRelative = [...foundRelativePosixPackageRoots].filter((relativeRoot) => !isExcluded(relativeRoot));
|
|
202
185
|
filteredRelative.sort((a, b) => a.localeCompare(b));
|
|
203
|
-
const packageDirectoryPathsAbsolute = filteredRelative.map((
|
|
186
|
+
const packageDirectoryPathsAbsolute = filteredRelative.map((relativeRoot) => path.resolve(rootDirectoryPathAbsolute, relativeRoot.split("/").join(path.sep)));
|
|
204
187
|
return {
|
|
205
188
|
packageDirectoryPathsAbsolute,
|
|
206
189
|
layoutSource,
|
|
207
|
-
hasPnpmWorkspaceYamlFile,
|
|
190
|
+
hasPnpmWorkspaceYamlFile: true,
|
|
208
191
|
};
|
|
209
192
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { FilesystemPort } from "#/core/filesystem/port";
|
|
2
|
+
/**
|
|
3
|
+
* Every hand-written source file a comment convention applies to — `.ts`, `.tsx`, `.css`, and ignore files.
|
|
4
|
+
*
|
|
5
|
+
* @remarks Emitted declarations are excluded: they carry whatever the compiler copied over,
|
|
6
|
+
* and rewriting them would be undone by the next build.
|
|
7
|
+
*
|
|
8
|
+
* @since 0.6.0
|
|
9
|
+
*/
|
|
10
|
+
export declare function walkSourceFiles(rootDirectoryPath: string, fs: FilesystemPort): Array<string>;
|
|
11
|
+
/**
|
|
12
|
+
* Which comment syntax a path is written in, or `null` when the convention does not cover it.
|
|
13
|
+
*
|
|
14
|
+
* @since 0.6.0
|
|
15
|
+
*/
|
|
16
|
+
export declare function sourceCommentLanguage(filePath: string): "css" | "ignore" | "js" | null;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
|
-
import {
|
|
2
|
+
import { walkFiles } from "#/core/workspace/walk-files";
|
|
3
3
|
// Ignore files carry the divider convention over `#` comments — the content rules stay code-only.
|
|
4
4
|
const ignoreFileNames = new Set([
|
|
5
5
|
".gitignore",
|
|
@@ -17,9 +17,7 @@ const ignoreFileNames = new Set([
|
|
|
17
17
|
* @since 0.6.0
|
|
18
18
|
*/
|
|
19
19
|
export function walkSourceFiles(rootDirectoryPath, fs) {
|
|
20
|
-
|
|
21
|
-
visitSourcePaths(result, rootDirectoryPath, fs);
|
|
22
|
-
return result;
|
|
20
|
+
return walkFiles(rootDirectoryPath, fs, (filePath) => sourceCommentLanguage(filePath) !== null);
|
|
23
21
|
}
|
|
24
22
|
/**
|
|
25
23
|
* Which comment syntax a path is written in, or `null` when the convention does not cover it.
|
|
@@ -37,19 +35,4 @@ export function sourceCommentLanguage(filePath) {
|
|
|
37
35
|
return "css";
|
|
38
36
|
}
|
|
39
37
|
return ignoreFileNames.has(path.basename(filePath)) ? "ignore" : null;
|
|
40
|
-
}
|
|
41
|
-
function visitSourcePaths(result, entryPath, fs) {
|
|
42
|
-
const entryStats = fs.statSync(entryPath);
|
|
43
|
-
if (entryStats.isDirectory()) {
|
|
44
|
-
for (const childName of fs.readdirSync(entryPath)) {
|
|
45
|
-
if (defaultSkipDirectoryNames.has(childName)) {
|
|
46
|
-
continue;
|
|
47
|
-
}
|
|
48
|
-
visitSourcePaths(result, path.join(entryPath, childName), fs);
|
|
49
|
-
}
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
if (sourceCommentLanguage(entryPath) !== null) {
|
|
53
|
-
result.push(entryPath);
|
|
54
|
-
}
|
|
55
38
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { FilesystemPort } from "#/core/filesystem/port";
|
|
2
|
+
/**
|
|
3
|
+
* Recursively collects the `.ts`/`.tsx` file paths under a root, skipping `.d.ts` and skip-listed directories.
|
|
4
|
+
*
|
|
5
|
+
* @since 0.3.16-canary.0
|
|
6
|
+
*/
|
|
7
|
+
export declare function walkTsxFiles(rootDirectoryPath: string, fs: FilesystemPort): Array<string>;
|
|
@@ -1,30 +1,9 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { defaultSkipDirectoryNames } from "#/core/workspace/skip-directories";
|
|
1
|
+
import { walkFiles } from "#/core/workspace/walk-files";
|
|
3
2
|
/**
|
|
4
3
|
* Recursively collects the `.ts`/`.tsx` file paths under a root, skipping `.d.ts` and skip-listed directories.
|
|
5
4
|
*
|
|
6
5
|
* @since 0.3.16-canary.0
|
|
7
6
|
*/
|
|
8
7
|
export function walkTsxFiles(rootDirectoryPath, fs) {
|
|
9
|
-
|
|
10
|
-
visitTsxPaths(result, rootDirectoryPath, fs);
|
|
11
|
-
return result;
|
|
12
|
-
}
|
|
13
|
-
function visitTsxPaths(result, entryPath, fs) {
|
|
14
|
-
const entryStats = fs.statSync(entryPath);
|
|
15
|
-
if (entryStats.isDirectory()) {
|
|
16
|
-
for (const childName of fs.readdirSync(entryPath)) {
|
|
17
|
-
if (defaultSkipDirectoryNames.has(childName)) {
|
|
18
|
-
continue;
|
|
19
|
-
}
|
|
20
|
-
visitTsxPaths(result, path.join(entryPath, childName), fs);
|
|
21
|
-
}
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
if (entryPath.endsWith(".d.ts")) {
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
if (entryPath.endsWith(".tsx") || entryPath.endsWith(".ts")) {
|
|
28
|
-
result.push(entryPath);
|
|
29
|
-
}
|
|
8
|
+
return walkFiles(rootDirectoryPath, fs, (filePath) => !filePath.endsWith(".d.ts") && (filePath.endsWith(".ts") || filePath.endsWith(".tsx")));
|
|
30
9
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { FilesystemPort } from "#/core/filesystem/port";
|
|
2
|
+
/**
|
|
3
|
+
* Every file under a root the predicate accepts, skipping build output and vendored trees.
|
|
4
|
+
*
|
|
5
|
+
* @since 0.10.0
|
|
6
|
+
*/
|
|
7
|
+
export declare function walkFiles(rootDirectoryPath: string, fs: FilesystemPort, shouldInclude: (filePath: string) => boolean): Array<string>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { defaultSkipDirectoryNames } from "#/core/workspace/skip-directories";
|
|
3
|
+
/**
|
|
4
|
+
* Every file under a root the predicate accepts, skipping build output and vendored trees.
|
|
5
|
+
*
|
|
6
|
+
* @since 0.10.0
|
|
7
|
+
*/
|
|
8
|
+
export function walkFiles(rootDirectoryPath, fs, shouldInclude) {
|
|
9
|
+
const result = [];
|
|
10
|
+
visit(result, rootDirectoryPath, fs, shouldInclude);
|
|
11
|
+
return result;
|
|
12
|
+
}
|
|
13
|
+
function visit(result, entryPath, fs, shouldInclude) {
|
|
14
|
+
const entryStats = fs.statSync(entryPath);
|
|
15
|
+
if (entryStats.isDirectory()) {
|
|
16
|
+
for (const childName of fs.readdirSync(entryPath)) {
|
|
17
|
+
if (defaultSkipDirectoryNames.has(childName)) {
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
visit(result, path.join(entryPath, childName), fs, shouldInclude);
|
|
21
|
+
}
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (shouldInclude(entryPath)) {
|
|
25
|
+
result.push(entryPath);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The manifest file name that marks a package directory.
|
|
3
|
+
*
|
|
4
|
+
* @since 0.10.0
|
|
5
|
+
*/
|
|
6
|
+
export declare const packageJsonFileName = "package.json";
|
|
7
|
+
/**
|
|
8
|
+
* The pnpm workspace manifest file name that marks a workspace root.
|
|
9
|
+
*
|
|
10
|
+
* @since 0.10.0
|
|
11
|
+
*/
|
|
12
|
+
export declare const workspaceYamlFileName = "pnpm-workspace.yaml";
|
|
13
|
+
/**
|
|
14
|
+
* The build output directory name packages emit to.
|
|
15
|
+
*
|
|
16
|
+
* @since 0.10.0
|
|
17
|
+
*/
|
|
18
|
+
export declare const distDirName = "dist";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The manifest file name that marks a package directory.
|
|
3
|
+
*
|
|
4
|
+
* @since 0.10.0
|
|
5
|
+
*/
|
|
6
|
+
export const packageJsonFileName = "package.json";
|
|
7
|
+
/**
|
|
8
|
+
* The pnpm workspace manifest file name that marks a workspace root.
|
|
9
|
+
*
|
|
10
|
+
* @since 0.10.0
|
|
11
|
+
*/
|
|
12
|
+
export const workspaceYamlFileName = "pnpm-workspace.yaml";
|
|
13
|
+
/**
|
|
14
|
+
* The build output directory name packages emit to.
|
|
15
|
+
*
|
|
16
|
+
* @since 0.10.0
|
|
17
|
+
*/
|
|
18
|
+
export const distDirName = "dist";
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `@codefast/cli` public API: run the CLI in-process, and author a typed `codefast.config.*`.
|
|
3
|
+
*/
|
|
4
|
+
export { runCli } from "#/cli";
|
|
5
|
+
export { defineConfig } from "#/core/config/define-config";
|
|
6
|
+
export type { CodefastAfterWriteHook, CodefastArrangeConfig, CodefastConfig, CodefastTagConfig, MirrorConfig, } from "#/core/config/schema";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { GlobalStats } from "#/mirror/domain/types";
|
|
2
|
+
/**
|
|
3
|
+
* Maps a mirror run's stats to the process exit code.
|
|
4
|
+
*
|
|
5
|
+
* @since 0.3.16-canary.0
|
|
6
|
+
*/
|
|
7
|
+
export declare function exitCodeForMirrorSyncResult(stats: GlobalStats): number;
|
|
8
|
+
/**
|
|
9
|
+
* Serializes a mirror run's stats as the single-line JSON summary printed under `--json`.
|
|
10
|
+
*
|
|
11
|
+
* @since 0.3.16-canary.0
|
|
12
|
+
*/
|
|
13
|
+
export declare function formatMirrorSyncJsonOutput(stats: GlobalStats, elapsedSeconds: number, write?: boolean): string;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { MirrorSyncRunRequest } from "#/mirror/sync-types";
|
|
3
|
+
/**
|
|
4
|
+
* Zod schema validating a `MirrorSyncRunRequest`.
|
|
5
|
+
*
|
|
6
|
+
* @since 0.3.16-canary.0
|
|
7
|
+
*/
|
|
8
|
+
export declare const mirrorSyncRunRequestSchema: z.ZodType<MirrorSyncRunRequest>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FilesystemPort } from "#/core/filesystem/port";
|
|
2
|
+
import type { DistFilesystem } from "#/mirror/domain/dist-filesystem";
|
|
3
|
+
/**
|
|
4
|
+
* Creates the `DistFilesystem` the mirror scan uses, backed by a `FilesystemPort`.
|
|
5
|
+
*
|
|
6
|
+
* @since 0.3.16-canary.0
|
|
7
|
+
*/
|
|
8
|
+
export declare function createMirrorDistFilesystem(fs: FilesystemPort): DistFilesystem;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The JavaScript extensions accepted as runtime entries in `dist/`.
|
|
3
|
+
*
|
|
4
|
+
* @since 0.3.16-canary.0
|
|
5
|
+
*/
|
|
6
|
+
export declare const VALID_JS_EXTENSIONS: ReadonlySet<string>;
|
|
7
|
+
/**
|
|
8
|
+
* The declaration-file extensions accepted as type entries in `dist/`.
|
|
9
|
+
*
|
|
10
|
+
* @since 0.3.16-canary.0
|
|
11
|
+
*/
|
|
12
|
+
export declare const VALID_DTS_EXTENSIONS: ReadonlySet<string>;
|
|
13
|
+
/**
|
|
14
|
+
* The `package.json` self-export specifier every generated map includes.
|
|
15
|
+
*
|
|
16
|
+
* @since 0.3.16-canary.0
|
|
17
|
+
*/
|
|
18
|
+
export declare const PACKAGE_JSON_EXPORT = "./package.json";
|
|
@@ -1,15 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The build output directory the mirror scan reads.
|
|
3
|
-
*
|
|
4
|
-
* @since 0.3.16-canary.0
|
|
5
|
-
*/
|
|
6
|
-
export const DIST_DIR = "dist";
|
|
7
|
-
/**
|
|
8
|
-
* The manifest file name the mirror rewrites.
|
|
9
|
-
*
|
|
10
|
-
* @since 0.3.16-canary.0
|
|
11
|
-
*/
|
|
12
|
-
export const PACKAGE_JSON = "package.json";
|
|
13
1
|
/**
|
|
14
2
|
* The JavaScript extensions accepted as runtime entries in `dist/`.
|
|
15
3
|
*
|