readyup 0.0.0 → 0.13.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/LICENSE +21 -0
- package/README.md +123 -0
- package/bin/rdy.js +11 -0
- package/dist/esm/.cache +1 -0
- package/dist/esm/assertIsPreflightCollection.d.ts +2 -0
- package/dist/esm/assertIsPreflightCollection.js +27 -0
- package/dist/esm/assertIsRdyKit.d.ts +2 -0
- package/dist/esm/assertIsRdyKit.js +27 -0
- package/dist/esm/authoring.d.ts +6 -0
- package/dist/esm/authoring.js +22 -0
- package/dist/esm/bin/preflight.d.ts +1 -0
- package/dist/esm/bin/preflight.js +12 -0
- package/dist/esm/bin/rdy.d.ts +1 -0
- package/dist/esm/bin/rdy.js +12 -0
- package/dist/esm/bin/route.d.ts +1 -0
- package/dist/esm/bin/route.js +202 -0
- package/dist/esm/check-utils/filesystem.d.ts +4 -0
- package/dist/esm/check-utils/filesystem.js +26 -0
- package/dist/esm/check-utils/index.d.ts +3 -0
- package/dist/esm/check-utils/index.js +14 -0
- package/dist/esm/check-utils/package-json.d.ts +6 -0
- package/dist/esm/check-utils/package-json.js +40 -0
- package/dist/esm/check-utils/semver.d.ts +1 -0
- package/dist/esm/check-utils/semver.js +12 -0
- package/dist/esm/cli.d.ts +36 -0
- package/dist/esm/cli.js +285 -0
- package/dist/esm/compile/compileCommand.d.ts +1 -0
- package/dist/esm/compile/compileCommand.js +121 -0
- package/dist/esm/compile/compileConfig.d.ts +5 -0
- package/dist/esm/compile/compileConfig.js +52 -0
- package/dist/esm/compile/validateCompiledOutput.d.ts +1 -0
- package/dist/esm/compile/validateCompiledOutput.js +29 -0
- package/dist/esm/config.d.ts +2 -0
- package/dist/esm/config.js +28 -0
- package/dist/esm/expandGitHubShorthand.d.ts +1 -0
- package/dist/esm/expandGitHubShorthand.js +26 -0
- package/dist/esm/formatCombinedSummary.d.ts +2 -0
- package/dist/esm/formatCombinedSummary.js +40 -0
- package/dist/esm/formatJsonError.d.ts +1 -0
- package/dist/esm/formatJsonError.js +6 -0
- package/dist/esm/formatJsonReport.d.ts +10 -0
- package/dist/esm/formatJsonReport.js +90 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +37 -0
- package/dist/esm/init/initCommand.d.ts +6 -0
- package/dist/esm/init/initCommand.js +33 -0
- package/dist/esm/init/scaffold.d.ts +11 -0
- package/dist/esm/init/scaffold.js +15 -0
- package/dist/esm/init/templates.d.ts +2 -0
- package/dist/esm/init/templates.js +37 -0
- package/dist/esm/isRecord.d.ts +1 -0
- package/dist/esm/isRecord.js +6 -0
- package/dist/esm/jitiImport.d.ts +1 -0
- package/dist/esm/jitiImport.js +23 -0
- package/dist/esm/loadConfig.d.ts +2 -0
- package/dist/esm/loadConfig.js +74 -0
- package/dist/esm/loadRemoteCollection.d.ts +6 -0
- package/dist/esm/loadRemoteCollection.js +40 -0
- package/dist/esm/loadRemoteKit.d.ts +6 -0
- package/dist/esm/loadRemoteKit.js +40 -0
- package/dist/esm/parseArgs.d.ts +15 -0
- package/dist/esm/parseArgs.js +93 -0
- package/dist/esm/reportPreflight.d.ts +7 -0
- package/dist/esm/reportPreflight.js +105 -0
- package/dist/esm/reportRdy.d.ts +7 -0
- package/dist/esm/reportRdy.js +105 -0
- package/dist/esm/resolveCollectionExports.d.ts +1 -0
- package/dist/esm/resolveCollectionExports.js +20 -0
- package/dist/esm/resolveGitHubToken.d.ts +1 -0
- package/dist/esm/resolveGitHubToken.js +22 -0
- package/dist/esm/resolveKitExports.d.ts +1 -0
- package/dist/esm/resolveKitExports.js +20 -0
- package/dist/esm/resolveRequestedNames.d.ts +2 -0
- package/dist/esm/resolveRequestedNames.js +38 -0
- package/dist/esm/runPreflight.d.ts +7 -0
- package/dist/esm/runPreflight.js +157 -0
- package/dist/esm/runRdy.d.ts +7 -0
- package/dist/esm/runRdy.js +157 -0
- package/dist/esm/terminal.d.ts +6 -0
- package/dist/esm/terminal.js +55 -0
- package/dist/esm/types.d.ts +139 -0
- package/dist/esm/types.js +10 -0
- package/dist/esm/validateCollection.d.ts +2 -0
- package/dist/esm/validateCollection.js +27 -0
- package/dist/esm/validateKit.d.ts +2 -0
- package/dist/esm/validateKit.js +27 -0
- package/dist/esm/version.d.ts +1 -0
- package/dist/esm/version.js +4 -0
- package/dist/esm/writeFileWithCheck.d.ts +10 -0
- package/dist/esm/writeFileWithCheck.js +41 -0
- package/package.json +56 -10
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
function printStep(message) {
|
|
2
|
+
console.info(`
|
|
3
|
+
> ${message}`);
|
|
4
|
+
}
|
|
5
|
+
function printSuccess(message) {
|
|
6
|
+
console.info(` \u2705 ${message}`);
|
|
7
|
+
}
|
|
8
|
+
function printSkip(message) {
|
|
9
|
+
console.info(` \u26A0\uFE0F ${message}`);
|
|
10
|
+
}
|
|
11
|
+
function printError(message) {
|
|
12
|
+
console.error(` \u274C ${message}`);
|
|
13
|
+
}
|
|
14
|
+
function reportWriteResult(result, dryRun) {
|
|
15
|
+
switch (result.outcome) {
|
|
16
|
+
case "created":
|
|
17
|
+
if (dryRun) {
|
|
18
|
+
printSuccess(`[dry-run] Would create ${result.filePath}`);
|
|
19
|
+
} else {
|
|
20
|
+
printSuccess(`Created ${result.filePath}`);
|
|
21
|
+
}
|
|
22
|
+
break;
|
|
23
|
+
case "overwritten":
|
|
24
|
+
if (dryRun) {
|
|
25
|
+
printSuccess(`[dry-run] Would overwrite ${result.filePath}`);
|
|
26
|
+
} else {
|
|
27
|
+
printSuccess(`Overwrote ${result.filePath}`);
|
|
28
|
+
}
|
|
29
|
+
break;
|
|
30
|
+
case "up-to-date":
|
|
31
|
+
printSuccess(`${result.filePath} (up to date)`);
|
|
32
|
+
break;
|
|
33
|
+
case "skipped":
|
|
34
|
+
if (result.error) {
|
|
35
|
+
printSkip(`${result.filePath} (could not read for comparison: ${result.error})`);
|
|
36
|
+
} else {
|
|
37
|
+
printSkip(`${result.filePath} (already exists)`);
|
|
38
|
+
}
|
|
39
|
+
break;
|
|
40
|
+
case "failed":
|
|
41
|
+
if (result.error) {
|
|
42
|
+
printError(`Failed to write ${result.filePath}: ${result.error}`);
|
|
43
|
+
} else {
|
|
44
|
+
printError(`Failed to write ${result.filePath}`);
|
|
45
|
+
}
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export {
|
|
50
|
+
printError,
|
|
51
|
+
printSkip,
|
|
52
|
+
printStep,
|
|
53
|
+
printSuccess,
|
|
54
|
+
reportWriteResult
|
|
55
|
+
};
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
export type Severity = 'error' | 'warn' | 'recommend';
|
|
2
|
+
export type SkipResult = false | string;
|
|
3
|
+
export type FixLocation = 'inline' | 'end';
|
|
4
|
+
export interface FractionProgress {
|
|
5
|
+
type: 'fraction';
|
|
6
|
+
passedCount: number;
|
|
7
|
+
count: number;
|
|
8
|
+
}
|
|
9
|
+
export interface PercentProgress {
|
|
10
|
+
type: 'percent';
|
|
11
|
+
percent: number;
|
|
12
|
+
}
|
|
13
|
+
export type Progress = FractionProgress | PercentProgress;
|
|
14
|
+
export declare function isPercentProgress(progress: Progress): progress is PercentProgress;
|
|
15
|
+
export interface CheckOutcome {
|
|
16
|
+
ok: boolean;
|
|
17
|
+
detail?: string;
|
|
18
|
+
progress?: Progress;
|
|
19
|
+
}
|
|
20
|
+
export type CheckReturnValue = boolean | CheckOutcome;
|
|
21
|
+
export interface RdyCheck {
|
|
22
|
+
name: string;
|
|
23
|
+
check: () => CheckReturnValue | Promise<CheckReturnValue>;
|
|
24
|
+
severity?: Severity;
|
|
25
|
+
skip?: () => SkipResult | Promise<SkipResult>;
|
|
26
|
+
fix?: string;
|
|
27
|
+
checks?: RdyCheck[];
|
|
28
|
+
}
|
|
29
|
+
interface RdyResultBase {
|
|
30
|
+
name: string;
|
|
31
|
+
severity: Severity;
|
|
32
|
+
detail: string | null;
|
|
33
|
+
fix: string | null;
|
|
34
|
+
error: Error | null;
|
|
35
|
+
progress: Progress | null;
|
|
36
|
+
durationMs: number;
|
|
37
|
+
depth: number;
|
|
38
|
+
}
|
|
39
|
+
export interface PassedResult extends RdyResultBase {
|
|
40
|
+
status: 'passed';
|
|
41
|
+
ok: true;
|
|
42
|
+
}
|
|
43
|
+
export interface FailedResult extends RdyResultBase {
|
|
44
|
+
status: 'failed';
|
|
45
|
+
ok: false;
|
|
46
|
+
}
|
|
47
|
+
export interface SkippedResult extends RdyResultBase {
|
|
48
|
+
status: 'skipped';
|
|
49
|
+
ok: null;
|
|
50
|
+
skipReason: 'n/a' | 'precondition';
|
|
51
|
+
}
|
|
52
|
+
export type RdyResult = PassedResult | FailedResult | SkippedResult;
|
|
53
|
+
export interface RdyReport {
|
|
54
|
+
results: RdyResult[];
|
|
55
|
+
passed: boolean;
|
|
56
|
+
durationMs: number;
|
|
57
|
+
}
|
|
58
|
+
export interface ChecklistSummary {
|
|
59
|
+
name: string;
|
|
60
|
+
passed: number;
|
|
61
|
+
failed: number;
|
|
62
|
+
skipped: number;
|
|
63
|
+
allPassed: boolean;
|
|
64
|
+
durationMs: number;
|
|
65
|
+
}
|
|
66
|
+
export interface RdyChecklist {
|
|
67
|
+
name: string;
|
|
68
|
+
preconditions?: RdyCheck[];
|
|
69
|
+
checks: RdyCheck[];
|
|
70
|
+
fixLocation?: FixLocation;
|
|
71
|
+
}
|
|
72
|
+
export interface RdyStagedChecklist {
|
|
73
|
+
name: string;
|
|
74
|
+
preconditions?: RdyCheck[];
|
|
75
|
+
groups: RdyCheck[][];
|
|
76
|
+
fixLocation?: FixLocation;
|
|
77
|
+
}
|
|
78
|
+
export declare function isFlatChecklist(checklist: RdyChecklist | RdyStagedChecklist): checklist is RdyChecklist;
|
|
79
|
+
export interface RdyKit {
|
|
80
|
+
checklists: Array<RdyChecklist | RdyStagedChecklist>;
|
|
81
|
+
suites?: Record<string, string[]>;
|
|
82
|
+
defaultSeverity?: Severity;
|
|
83
|
+
failOn?: Severity;
|
|
84
|
+
reportOn?: Severity;
|
|
85
|
+
fixLocation?: FixLocation;
|
|
86
|
+
}
|
|
87
|
+
export interface RdyConfig {
|
|
88
|
+
compile?: {
|
|
89
|
+
srcDir?: string;
|
|
90
|
+
outDir?: string;
|
|
91
|
+
include?: string;
|
|
92
|
+
};
|
|
93
|
+
internal?: {
|
|
94
|
+
dir?: string;
|
|
95
|
+
extension?: string;
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
export interface ResolvedRdyConfig {
|
|
99
|
+
compile: {
|
|
100
|
+
srcDir: string;
|
|
101
|
+
outDir: string;
|
|
102
|
+
include: string | undefined;
|
|
103
|
+
};
|
|
104
|
+
internal: {
|
|
105
|
+
dir: string;
|
|
106
|
+
extension: string;
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
export interface JsonCheckEntry {
|
|
110
|
+
name: string;
|
|
111
|
+
status: 'passed' | 'failed' | 'skipped';
|
|
112
|
+
ok: true | false | null;
|
|
113
|
+
severity: Severity;
|
|
114
|
+
skipReason: 'n/a' | 'precondition' | null;
|
|
115
|
+
detail: string | null;
|
|
116
|
+
fix: string | null;
|
|
117
|
+
error: string | null;
|
|
118
|
+
progress: Progress | null;
|
|
119
|
+
durationMs: number;
|
|
120
|
+
checks: JsonCheckEntry[];
|
|
121
|
+
}
|
|
122
|
+
export interface JsonChecklistEntry {
|
|
123
|
+
name: string;
|
|
124
|
+
passed: number;
|
|
125
|
+
failed: number;
|
|
126
|
+
skipped: number;
|
|
127
|
+
allPassed: boolean;
|
|
128
|
+
durationMs: number;
|
|
129
|
+
checks: JsonCheckEntry[];
|
|
130
|
+
}
|
|
131
|
+
export interface JsonReport {
|
|
132
|
+
allPassed: boolean;
|
|
133
|
+
passed: number;
|
|
134
|
+
failed: number;
|
|
135
|
+
skipped: number;
|
|
136
|
+
durationMs: number;
|
|
137
|
+
checklists: JsonChecklistEntry[];
|
|
138
|
+
}
|
|
139
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
function validateCollection(collection) {
|
|
2
|
+
const { suites } = collection;
|
|
3
|
+
if (suites === void 0) return;
|
|
4
|
+
const checklistNames = new Set(collection.checklists.map((c) => c.name));
|
|
5
|
+
const collisions = Object.keys(suites).filter((name) => checklistNames.has(name));
|
|
6
|
+
if (collisions.length > 0) {
|
|
7
|
+
throw new Error(
|
|
8
|
+
`Suite name(s) collide with checklist name(s): ${collisions.join(", ")}. Suite names and checklist names must be unique across both pools.`
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
const missingBySource = [];
|
|
12
|
+
for (const [suiteName, entries] of Object.entries(suites)) {
|
|
13
|
+
for (const entry of entries) {
|
|
14
|
+
if (!checklistNames.has(entry)) {
|
|
15
|
+
missingBySource.push(`suite "${suiteName}" references unknown checklist "${entry}"`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
if (missingBySource.length > 0) {
|
|
20
|
+
throw new Error(
|
|
21
|
+
`Invalid suite references: ${missingBySource.join("; ")}. Available checklists: ${[...checklistNames].join(", ")}`
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export {
|
|
26
|
+
validateCollection
|
|
27
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
function validateKit(kit) {
|
|
2
|
+
const { suites } = kit;
|
|
3
|
+
if (suites === void 0) return;
|
|
4
|
+
const checklistNames = new Set(kit.checklists.map((c) => c.name));
|
|
5
|
+
const collisions = Object.keys(suites).filter((name) => checklistNames.has(name));
|
|
6
|
+
if (collisions.length > 0) {
|
|
7
|
+
throw new Error(
|
|
8
|
+
`Suite name(s) collide with checklist name(s): ${collisions.join(", ")}. Suite names and checklist names must be unique across both pools.`
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
const missingBySource = [];
|
|
12
|
+
for (const [suiteName, entries] of Object.entries(suites)) {
|
|
13
|
+
for (const entry of entries) {
|
|
14
|
+
if (!checklistNames.has(entry)) {
|
|
15
|
+
missingBySource.push(`suite "${suiteName}" references unknown checklist "${entry}"`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
if (missingBySource.length > 0) {
|
|
20
|
+
throw new Error(
|
|
21
|
+
`Invalid suite references: ${missingBySource.join("; ")}. Available checklists: ${[...checklistNames].join(", ")}`
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export {
|
|
26
|
+
validateKit
|
|
27
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const VERSION = "0.13.0";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type WriteOutcome = 'created' | 'overwritten' | 'up-to-date' | 'skipped' | 'failed';
|
|
2
|
+
export interface WriteResult {
|
|
3
|
+
filePath: string;
|
|
4
|
+
outcome: WriteOutcome;
|
|
5
|
+
error?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function writeFileWithCheck(filePath: string, content: string, options: {
|
|
8
|
+
dryRun: boolean;
|
|
9
|
+
overwrite: boolean;
|
|
10
|
+
}): WriteResult;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname } from "node:path";
|
|
3
|
+
function normalizeTrailingWhitespace(content) {
|
|
4
|
+
return content.split("\n").map((line) => line.trimEnd()).join("\n").trimEnd();
|
|
5
|
+
}
|
|
6
|
+
function writeFileWithCheck(filePath, content, options) {
|
|
7
|
+
const { dryRun, overwrite } = options;
|
|
8
|
+
const fileExists = existsSync(filePath);
|
|
9
|
+
if (fileExists && !overwrite) {
|
|
10
|
+
try {
|
|
11
|
+
const existing = readFileSync(filePath, "utf8");
|
|
12
|
+
if (normalizeTrailingWhitespace(existing) === normalizeTrailingWhitespace(content)) {
|
|
13
|
+
return { filePath, outcome: "up-to-date" };
|
|
14
|
+
}
|
|
15
|
+
} catch (error) {
|
|
16
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
17
|
+
return { filePath, outcome: "skipped", error: message };
|
|
18
|
+
}
|
|
19
|
+
return { filePath, outcome: "skipped" };
|
|
20
|
+
}
|
|
21
|
+
const outcome = fileExists ? "overwritten" : "created";
|
|
22
|
+
if (dryRun) {
|
|
23
|
+
return { filePath, outcome };
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
27
|
+
} catch (error) {
|
|
28
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
29
|
+
return { filePath, outcome: "failed", error: message };
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
writeFileSync(filePath, content, "utf8");
|
|
33
|
+
} catch (error) {
|
|
34
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
35
|
+
return { filePath, outcome: "failed", error: message };
|
|
36
|
+
}
|
|
37
|
+
return { filePath, outcome };
|
|
38
|
+
}
|
|
39
|
+
export {
|
|
40
|
+
writeFileWithCheck
|
|
41
|
+
};
|
package/package.json
CHANGED
|
@@ -1,12 +1,58 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "readyup",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
3
|
+
"version": "0.13.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "Run pre-deployment checks to verify environment and configuration",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"checks",
|
|
8
|
+
"deploy",
|
|
9
|
+
"readyup",
|
|
10
|
+
"verification"
|
|
11
|
+
],
|
|
12
|
+
"homepage": "https://github.com/williamthorsen/workshop/tree/main/packages/readyup#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/williamthorsen/workshop/issues"
|
|
15
|
+
},
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/williamthorsen/workshop.git",
|
|
19
|
+
"directory": "packages/readyup"
|
|
20
|
+
},
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"author": "William Thorsen <william@thorsen.dev> (https://github.com/williamthorsen)",
|
|
23
|
+
"type": "module",
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"import": "./dist/esm/index.js",
|
|
27
|
+
"types": "./dist/esm/index.d.ts"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"bin": {
|
|
31
|
+
"rdy": "bin/rdy.js",
|
|
32
|
+
"readyup": "bin/rdy.js"
|
|
33
|
+
},
|
|
34
|
+
"files": [
|
|
35
|
+
"bin",
|
|
36
|
+
"dist"
|
|
37
|
+
],
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"jiti": "2.6.1",
|
|
40
|
+
"picomatch": "4.0.4",
|
|
41
|
+
"zod": "4.3.6"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/picomatch": "4.0.3"
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"esbuild": ">=0.17.0"
|
|
48
|
+
},
|
|
49
|
+
"peerDependenciesMeta": {
|
|
50
|
+
"esbuild": {
|
|
51
|
+
"optional": true
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"engines": {
|
|
55
|
+
"node": ">=18.17.0"
|
|
56
|
+
},
|
|
57
|
+
"scripts": {}
|
|
58
|
+
}
|