@saws/core 2.0.0-beta.0 → 2.0.0-beta.11
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/.tsbuildinfo +1 -1
- package/dist/Host.d.ts +62 -0
- package/dist/Host.js +202 -0
- package/dist/ServiceDefinition.d.ts +66 -0
- package/dist/ServiceDefinition.js +182 -0
- package/dist/find-service-definition.d.ts +1 -8
- package/dist/find-service-definition.js +0 -6
- package/dist/get-saws-config.d.ts +14 -3
- package/dist/get-saws-config.js +16 -54
- package/dist/global-hosts.d.ts +8 -0
- package/dist/global-hosts.js +119 -0
- package/dist/host-readiness.d.ts +12 -0
- package/dist/host-readiness.js +230 -0
- package/dist/index.d.ts +5 -5
- package/dist/index.js +5 -4
- package/dist/secrets-manager.d.ts +66 -0
- package/dist/secrets-manager.js +325 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/utils/constants.d.ts +4 -0
- package/dist/utils/constants.js +5 -0
- package/dist/utils/create-directories.d.ts +2 -0
- package/dist/utils/create-directories.js +20 -0
- package/dist/utils/create-file-if-not-exists.d.ts +1 -0
- package/dist/utils/create-file-if-not-exists.js +12 -0
- package/dist/utils/create-file-if-note-exists.d.ts +1 -0
- package/dist/utils/create-file-if-note-exists.js +11 -0
- package/dist/utils/dependency-management.d.ts +16 -0
- package/dist/utils/dependency-management.js +132 -0
- package/dist/utils/file-exists.d.ts +1 -0
- package/dist/utils/file-exists.js +12 -0
- package/dist/utils/generate-token.d.ts +1 -0
- package/dist/utils/generate-token.js +13 -0
- package/dist/utils/get-project-name.d.ts +1 -0
- package/dist/utils/get-project-name.js +5 -0
- package/dist/utils/get-service-path.js +1 -0
- package/dist/utils/list-files.d.ts +1 -0
- package/dist/utils/list-files.js +17 -0
- package/dist/utils/on-exit.d.ts +1 -0
- package/dist/utils/on-exit.js +14 -0
- package/dist/utils/parameterized-env-var-name.d.ts +1 -0
- package/dist/utils/parameterized-env-var-name.js +1 -0
- package/dist/utils/recursively-read-dir.d.ts +1 -0
- package/dist/utils/recursively-read-dir.js +15 -0
- package/dist/utils/retry-until.d.ts +1 -0
- package/dist/utils/retry-until.js +9 -0
- package/dist/utils/run-local.d.ts +9 -0
- package/dist/utils/run-local.js +87 -0
- package/dist/utils/shell-quote.d.ts +1 -0
- package/dist/utils/shell-quote.js +3 -0
- package/dist/utils/stage-outputs.d.ts +3 -0
- package/dist/utils/stage-outputs.js +24 -0
- package/dist/utils/uppercase.d.ts +1 -0
- package/dist/utils/uppercase.js +4 -0
- package/package.json +34 -21
- package/dist/context.d.ts +0 -41
- package/dist/context.d.ts.map +0 -1
- package/dist/context.js +0 -38
- package/dist/context.test.d.ts +0 -2
- package/dist/context.test.d.ts.map +0 -1
- package/dist/context.test.js +0 -13
- package/dist/find-service-definition.d.ts.map +0 -1
- package/dist/find-service-definition.test.d.ts +0 -2
- package/dist/find-service-definition.test.d.ts.map +0 -1
- package/dist/find-service-definition.test.js +0 -44
- package/dist/get-saws-config.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/service-commands.d.ts +0 -10
- package/dist/service-commands.d.ts.map +0 -1
- package/dist/service-commands.js +0 -25
- package/dist/service-commands.test.d.ts +0 -2
- package/dist/service-commands.test.d.ts.map +0 -1
- package/dist/service-commands.test.js +0 -26
- package/dist/service-definition.d.ts +0 -36
- package/dist/service-definition.d.ts.map +0 -1
- package/dist/service-definition.js +0 -104
- package/dist/service-types.d.ts +0 -9
- package/dist/service-types.d.ts.map +0 -1
- /package/dist/{service-types.js → utils/get-service-path.d.ts} +0 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileExists } from "./file-exists.js";
|
|
5
|
+
export async function installDependencies(dependencies, options = {}) {
|
|
6
|
+
if (dependencies.length === 0)
|
|
7
|
+
return;
|
|
8
|
+
const rootDirectory = path.resolve(options.cwd ?? process.cwd());
|
|
9
|
+
const packageManager = await detectPackageManager(rootDirectory);
|
|
10
|
+
const args = installArguments(packageManager, dependencies, options.development ?? false, options.workspace);
|
|
11
|
+
await new Promise((resolve, reject) => {
|
|
12
|
+
const captureOutput = options.logSink != null;
|
|
13
|
+
const serviceName = options.serviceName ?? "system";
|
|
14
|
+
const child = spawn(packageManager, args, {
|
|
15
|
+
// Workspace-aware package managers must be run from the workspace root.
|
|
16
|
+
// Running npm from within a workspace can install into the root package
|
|
17
|
+
// instead of updating the generated service's package.json.
|
|
18
|
+
cwd: rootDirectory,
|
|
19
|
+
env: process.env,
|
|
20
|
+
stdio: captureOutput ? ["ignore", "pipe", "pipe"] : "inherit",
|
|
21
|
+
});
|
|
22
|
+
child.stdout?.on("data", (chunk) => {
|
|
23
|
+
options.logSink?.({
|
|
24
|
+
serviceName,
|
|
25
|
+
stream: "stdout",
|
|
26
|
+
chunk: chunk.toString("utf8"),
|
|
27
|
+
timestamp: new Date(),
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
child.stderr?.on("data", (chunk) => {
|
|
31
|
+
options.logSink?.({
|
|
32
|
+
serviceName,
|
|
33
|
+
stream: "stderr",
|
|
34
|
+
chunk: chunk.toString("utf8"),
|
|
35
|
+
timestamp: new Date(),
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
child.once("error", (error) => {
|
|
39
|
+
reject(new Error(`Unable to run ${packageManager}: ${error.message}`, { cause: error }));
|
|
40
|
+
});
|
|
41
|
+
child.once("close", (code, signal) => {
|
|
42
|
+
if (code === 0) {
|
|
43
|
+
resolve();
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const reason = signal == null ? `exit code ${code ?? "unknown"}` : `signal ${signal}`;
|
|
47
|
+
reject(new Error(`${packageManager} failed to install dependencies with ${reason}`));
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
export async function hasDependency(dependency, cwd = process.cwd()) {
|
|
52
|
+
try {
|
|
53
|
+
const contents = await readFile(path.resolve(cwd, "package.json"), "utf8");
|
|
54
|
+
const packageJson = JSON.parse(contents);
|
|
55
|
+
return (packageJson.dependencies?.[dependency] != null ||
|
|
56
|
+
packageJson.devDependencies?.[dependency] != null);
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
if (error.code === "ENOENT")
|
|
60
|
+
return false;
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async function detectPackageManager(cwd) {
|
|
65
|
+
for (let directory = cwd;; directory = path.dirname(directory)) {
|
|
66
|
+
const packageManager = await readPackageManagerField(directory);
|
|
67
|
+
if (packageManager != null)
|
|
68
|
+
return packageManager;
|
|
69
|
+
for (const [lockfile, manager] of LOCKFILES) {
|
|
70
|
+
if (await fileExists(path.join(directory, lockfile)))
|
|
71
|
+
return manager;
|
|
72
|
+
}
|
|
73
|
+
const parent = path.dirname(directory);
|
|
74
|
+
if (parent === directory)
|
|
75
|
+
return "npm";
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
async function readPackageManagerField(directory) {
|
|
79
|
+
try {
|
|
80
|
+
const contents = await readFile(path.join(directory, "package.json"), "utf8");
|
|
81
|
+
const packageJson = JSON.parse(contents);
|
|
82
|
+
if (typeof packageJson.packageManager !== "string")
|
|
83
|
+
return undefined;
|
|
84
|
+
const name = packageJson.packageManager.split("@", 1)[0];
|
|
85
|
+
return isPackageManager(name) ? name : undefined;
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
if (error.code === "ENOENT")
|
|
89
|
+
return undefined;
|
|
90
|
+
throw error;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
function installArguments(packageManager, dependencies, development, workspace) {
|
|
94
|
+
switch (packageManager) {
|
|
95
|
+
case "npm":
|
|
96
|
+
return [
|
|
97
|
+
"install",
|
|
98
|
+
...(workspace == null ? [] : ["--workspace", workspace]),
|
|
99
|
+
development ? "--save-dev" : "--save-prod",
|
|
100
|
+
...dependencies,
|
|
101
|
+
];
|
|
102
|
+
case "pnpm":
|
|
103
|
+
return [
|
|
104
|
+
...(workspace == null ? [] : ["--filter", workspace]),
|
|
105
|
+
"add",
|
|
106
|
+
...(development ? ["--dev"] : []),
|
|
107
|
+
...dependencies,
|
|
108
|
+
];
|
|
109
|
+
case "yarn":
|
|
110
|
+
return workspace == null
|
|
111
|
+
? ["add", ...(development ? ["--dev"] : []), ...dependencies]
|
|
112
|
+
: ["workspace", workspace, "add", ...(development ? ["--dev"] : []), ...dependencies];
|
|
113
|
+
case "bun":
|
|
114
|
+
return [
|
|
115
|
+
"add",
|
|
116
|
+
...(workspace == null ? [] : ["--filter", workspace]),
|
|
117
|
+
...(development ? ["--dev"] : []),
|
|
118
|
+
...dependencies,
|
|
119
|
+
];
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function isPackageManager(value) {
|
|
123
|
+
return value === "npm" || value === "pnpm" || value === "yarn" || value === "bun";
|
|
124
|
+
}
|
|
125
|
+
const LOCKFILES = [
|
|
126
|
+
["pnpm-lock.yaml", "pnpm"],
|
|
127
|
+
["yarn.lock", "yarn"],
|
|
128
|
+
["bun.lock", "bun"],
|
|
129
|
+
["bun.lockb", "bun"],
|
|
130
|
+
["package-lock.json", "npm"],
|
|
131
|
+
["npm-shrinkwrap.json", "npm"],
|
|
132
|
+
];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function fileExists(filePath: string): Promise<boolean>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const generateToken: () => Promise<string>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as crypto from "crypto";
|
|
2
|
+
export const generateToken = async () => {
|
|
3
|
+
return new Promise((resolve, reject) => {
|
|
4
|
+
crypto.randomBytes(20, (err, buffer) => {
|
|
5
|
+
if (err) {
|
|
6
|
+
reject(err);
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
resolve(buffer.toString("hex"));
|
|
10
|
+
return;
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const getProjectName: () => string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function listFiles(directory: string): Promise<string[]>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { readdir } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
export async function listFiles(directory) {
|
|
4
|
+
const entries = await readdir(directory, { withFileTypes: true });
|
|
5
|
+
const files = [];
|
|
6
|
+
for (const entry of entries) {
|
|
7
|
+
const fullPath = path.join(directory, entry.name);
|
|
8
|
+
if (entry.isDirectory()) {
|
|
9
|
+
files.push(...(await listFiles(fullPath)));
|
|
10
|
+
continue;
|
|
11
|
+
}
|
|
12
|
+
if (entry.isFile()) {
|
|
13
|
+
files.push(fullPath);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return files;
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const onProcessExit: (callback: () => void) => void;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
let registeredFunctions = [];
|
|
2
|
+
export const onProcessExit = (callback) => {
|
|
3
|
+
registeredFunctions.push(callback);
|
|
4
|
+
};
|
|
5
|
+
process.on("exit", () => {
|
|
6
|
+
registeredFunctions.forEach((f) => f());
|
|
7
|
+
registeredFunctions = [];
|
|
8
|
+
process.exit();
|
|
9
|
+
});
|
|
10
|
+
process.on("SIGINT", () => {
|
|
11
|
+
registeredFunctions.forEach((f) => f());
|
|
12
|
+
registeredFunctions = [];
|
|
13
|
+
process.exit();
|
|
14
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const parameterizedEnvVarName: (name: string, variable: string) => string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const parameterizedEnvVarName = (name, variable) => `${name.replace(/[^a-zA-Z\d]/g, "_").toUpperCase()}_${variable}`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const recursivelyReadDir: (dir: string) => Promise<string[]>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { promises as fs } from "fs";
|
|
2
|
+
import { resolve } from "path";
|
|
3
|
+
export const recursivelyReadDir = async (dir) => {
|
|
4
|
+
const files = [];
|
|
5
|
+
const dirContents = await fs.readdir(dir, { withFileTypes: true });
|
|
6
|
+
for (const item of dirContents) {
|
|
7
|
+
if (item.isDirectory()) {
|
|
8
|
+
const nestedFiles = await recursivelyReadDir(resolve(dir, item.name));
|
|
9
|
+
files.push(...nestedFiles);
|
|
10
|
+
continue;
|
|
11
|
+
}
|
|
12
|
+
files.push(resolve(dir, item.name));
|
|
13
|
+
}
|
|
14
|
+
return files;
|
|
15
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const retryUntil: (callback: () => Promise<boolean>, timeout: number) => Promise<void>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { RuntimeLogSink } from "../ServiceDefinition.js";
|
|
2
|
+
export declare function runLocal(command: string, options?: {
|
|
3
|
+
dryRun?: boolean;
|
|
4
|
+
input?: string;
|
|
5
|
+
cwd?: string;
|
|
6
|
+
logSink?: RuntimeLogSink;
|
|
7
|
+
serviceName?: string;
|
|
8
|
+
signal?: AbortSignal;
|
|
9
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
export async function runLocal(command, options = {}) {
|
|
3
|
+
if (options.dryRun) {
|
|
4
|
+
if (options.logSink == null) {
|
|
5
|
+
console.log(`[dry-run:local] ${command}`);
|
|
6
|
+
}
|
|
7
|
+
else {
|
|
8
|
+
options.logSink({
|
|
9
|
+
serviceName: options.serviceName ?? "system",
|
|
10
|
+
stream: "stdout",
|
|
11
|
+
chunk: `[dry-run:local] ${command}\n`,
|
|
12
|
+
timestamp: new Date(),
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
await new Promise((resolve, reject) => {
|
|
18
|
+
if (options.signal?.aborted) {
|
|
19
|
+
reject(new Error(`local command aborted: ${command}`));
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const captureOutput = options.logSink != null;
|
|
23
|
+
const serviceName = options.serviceName ?? "system";
|
|
24
|
+
const child = spawn(command, {
|
|
25
|
+
cwd: options.cwd,
|
|
26
|
+
shell: true,
|
|
27
|
+
detached: true,
|
|
28
|
+
stdio: [
|
|
29
|
+
options.input == null ? "ignore" : "pipe",
|
|
30
|
+
captureOutput ? "pipe" : "inherit",
|
|
31
|
+
captureOutput ? "pipe" : "inherit",
|
|
32
|
+
],
|
|
33
|
+
});
|
|
34
|
+
let aborted = false;
|
|
35
|
+
const abort = () => {
|
|
36
|
+
aborted = true;
|
|
37
|
+
if (child.pid == null)
|
|
38
|
+
return;
|
|
39
|
+
try {
|
|
40
|
+
process.kill(-child.pid, "SIGTERM");
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
if (error.code !== "ESRCH") {
|
|
44
|
+
options.logSink?.({
|
|
45
|
+
serviceName: options.serviceName ?? "system",
|
|
46
|
+
stream: "stderr",
|
|
47
|
+
chunk: `Failed to stop local command: ${error.message}\n`,
|
|
48
|
+
timestamp: new Date(),
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
options.signal?.addEventListener("abort", abort, { once: true });
|
|
54
|
+
if (options.input != null) {
|
|
55
|
+
child.stdin?.end(options.input);
|
|
56
|
+
}
|
|
57
|
+
child.stdout?.on("data", (chunk) => {
|
|
58
|
+
options.logSink?.({
|
|
59
|
+
serviceName,
|
|
60
|
+
stream: "stdout",
|
|
61
|
+
chunk: chunk.toString("utf8"),
|
|
62
|
+
timestamp: new Date(),
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
child.stderr?.on("data", (chunk) => {
|
|
66
|
+
options.logSink?.({
|
|
67
|
+
serviceName,
|
|
68
|
+
stream: "stderr",
|
|
69
|
+
chunk: chunk.toString("utf8"),
|
|
70
|
+
timestamp: new Date(),
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
child.on("error", reject);
|
|
74
|
+
child.on("exit", (code) => {
|
|
75
|
+
options.signal?.removeEventListener("abort", abort);
|
|
76
|
+
if (aborted) {
|
|
77
|
+
reject(new Error(`local command aborted: ${command}`));
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (code === 0) {
|
|
81
|
+
resolve();
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
reject(new Error(`local command exited with code ${code}: ${command}`));
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function shellQuote(value: string): string;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export type Outputs = Record<string, string | number | boolean | null | undefined>;
|
|
2
|
+
export declare const getStageOutputs: (stage: string) => Promise<Record<string, Outputs>>;
|
|
3
|
+
export declare const writeStageOutputs: (newOutputs: Record<string, Outputs>, stage: string) => Promise<Record<string, Outputs>>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { SAWS_DIR } from "./constants.js";
|
|
4
|
+
export const getStageOutputs = async (stage) => {
|
|
5
|
+
const outputPath = path.resolve(SAWS_DIR, `saws-${stage}-output.json`);
|
|
6
|
+
try {
|
|
7
|
+
await fs.stat(outputPath);
|
|
8
|
+
const outputsText = await fs.readFile(outputPath, { encoding: "utf-8" });
|
|
9
|
+
return JSON.parse(outputsText);
|
|
10
|
+
}
|
|
11
|
+
catch (err) {
|
|
12
|
+
return {};
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
export const writeStageOutputs = async (newOutputs, stage) => {
|
|
16
|
+
const currentOutputs = await getStageOutputs(stage);
|
|
17
|
+
// write outputs
|
|
18
|
+
const outputs = {
|
|
19
|
+
...currentOutputs,
|
|
20
|
+
...newOutputs,
|
|
21
|
+
};
|
|
22
|
+
await fs.writeFile(path.resolve(SAWS_DIR, `saws-${stage}-output.json`), JSON.stringify(outputs, null, 2));
|
|
23
|
+
return outputs;
|
|
24
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const uppercase: (text: string) => string;
|
package/package.json
CHANGED
|
@@ -1,34 +1,47 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saws/core",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.11",
|
|
4
|
+
"description": "",
|
|
5
|
+
"keywords": [],
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "",
|
|
4
8
|
"repository": {
|
|
5
9
|
"type": "git",
|
|
6
|
-
"url": "git+https://github.com/shichongrui/saws.git"
|
|
7
|
-
"directory": "packages/core"
|
|
8
|
-
},
|
|
9
|
-
"type": "module",
|
|
10
|
-
"main": "./dist/index.js",
|
|
11
|
-
"types": "./dist/index.d.ts",
|
|
12
|
-
"exports": {
|
|
13
|
-
".": {
|
|
14
|
-
"types": "./dist/index.d.ts",
|
|
15
|
-
"import": "./dist/index.js"
|
|
16
|
-
}
|
|
10
|
+
"url": "git+https://github.com/shichongrui/saws.git"
|
|
17
11
|
},
|
|
18
12
|
"files": [
|
|
19
|
-
"dist"
|
|
13
|
+
"./dist"
|
|
20
14
|
],
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
15
|
+
"type": "module",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": "./dist/index.js",
|
|
18
|
+
"./ServiceDefinition": "./dist/ServiceDefinition.js",
|
|
19
|
+
"./get-saws-config": "./dist/get-saws-config.js",
|
|
20
|
+
"./Host": "./dist/Host.js",
|
|
21
|
+
"./global-hosts": "./dist/global-hosts.js",
|
|
22
|
+
"./host-readiness": "./dist/host-readiness.js",
|
|
23
|
+
"./secrets-manager": "./dist/secrets-manager.js",
|
|
24
|
+
"./utils/constants": "./dist/utils/constants.js",
|
|
25
|
+
"./utils/create-directories": "./dist/utils/create-directories.js",
|
|
26
|
+
"./utils/file-exists": "./dist/utils/file-exists.js",
|
|
27
|
+
"./utils/generate-token": "./dist/utils/generate-token.js",
|
|
28
|
+
"./utils/get-project-name": "./dist/utils/get-project-name.js",
|
|
29
|
+
"./utils/list-files": "./dist/utils/list-files.js",
|
|
30
|
+
"./utils/on-exit": "./dist/utils/on-exit.js",
|
|
31
|
+
"./utils/parameterized-env-var-name": "./dist/utils/parameterized-env-var-name.js",
|
|
32
|
+
"./utils/recursively-read-dir": "./dist/utils/recursively-read-dir.js",
|
|
33
|
+
"./utils/retry-until": "./dist/utils/retry-until.js",
|
|
34
|
+
"./utils/shell-quote": "./dist/utils/shell-quote.js",
|
|
35
|
+
"./utils/stage-outputs": "./dist/utils/stage-outputs.js",
|
|
36
|
+
"./utils/uppercase": "./dist/utils/uppercase.js",
|
|
37
|
+
"./utils/create-file-if-not-exists": "./dist/utils/create-file-if-not-exists.js",
|
|
38
|
+
"./utils/dependency-management": "./dist/utils/dependency-management.js",
|
|
39
|
+
"./utils/run-local": "./dist/utils/run-local.js"
|
|
26
40
|
},
|
|
27
41
|
"dependencies": {
|
|
28
|
-
"
|
|
29
|
-
"typescript": "^5.3.3"
|
|
42
|
+
"find-package-json": "^1.2.0"
|
|
30
43
|
},
|
|
31
44
|
"devDependencies": {
|
|
32
|
-
"@types/
|
|
45
|
+
"@types/find-package-json": "^1.2.7"
|
|
33
46
|
}
|
|
34
47
|
}
|
package/dist/context.d.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import type { ServiceDefinition } from "./service-definition.js";
|
|
2
|
-
export type StageName = "local" | string;
|
|
3
|
-
export interface RuntimeContextConfig {
|
|
4
|
-
stage: StageName;
|
|
5
|
-
rootDir?: string;
|
|
6
|
-
env?: Record<string, string>;
|
|
7
|
-
dryRun?: boolean;
|
|
8
|
-
logSink?: RuntimeLogSink;
|
|
9
|
-
currentServiceName?: string;
|
|
10
|
-
}
|
|
11
|
-
export interface RuntimeLogEntry {
|
|
12
|
-
serviceName: string;
|
|
13
|
-
stream: "stdout" | "stderr";
|
|
14
|
-
chunk: string;
|
|
15
|
-
timestamp: Date;
|
|
16
|
-
}
|
|
17
|
-
export type RuntimeLogSink = (entry: RuntimeLogEntry) => void;
|
|
18
|
-
export declare class RuntimeContext {
|
|
19
|
-
readonly stage: StageName;
|
|
20
|
-
readonly rootDir: string;
|
|
21
|
-
readonly env: Record<string, string>;
|
|
22
|
-
readonly dryRun: boolean;
|
|
23
|
-
readonly logSink?: RuntimeLogSink;
|
|
24
|
-
readonly currentServiceName?: string;
|
|
25
|
-
constructor(config: RuntimeContextConfig);
|
|
26
|
-
writeLog(chunk: string, stream?: "stdout" | "stderr"): void;
|
|
27
|
-
}
|
|
28
|
-
export declare class InitContext extends RuntimeContext {
|
|
29
|
-
}
|
|
30
|
-
export declare class DevContext extends RuntimeContext {
|
|
31
|
-
}
|
|
32
|
-
export declare class DeployContext extends RuntimeContext {
|
|
33
|
-
}
|
|
34
|
-
export declare class ExitContext extends RuntimeContext {
|
|
35
|
-
}
|
|
36
|
-
export declare function assertValidStageName(stage: string): void;
|
|
37
|
-
export interface DependencyEnvironment {
|
|
38
|
-
service: ServiceDefinition;
|
|
39
|
-
variables: Record<string, string>;
|
|
40
|
-
}
|
|
41
|
-
//# sourceMappingURL=context.d.ts.map
|
package/dist/context.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,CAAC;AAEzC,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,SAAS,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,MAAM,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;AAE9D,qBAAa,cAAc;IACzB,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,cAAc,CAAC;IAClC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;gBAEzB,MAAM,EAAE,oBAAoB;IAUxC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,GAAE,QAAQ,GAAG,QAAmB;CAQ/D;AAED,qBAAa,WAAY,SAAQ,cAAc;CAAG;AAClD,qBAAa,UAAW,SAAQ,cAAc;CAAG;AACjD,qBAAa,aAAc,SAAQ,cAAc;CAAG;AACpD,qBAAa,WAAY,SAAQ,cAAc;CAAG;AAElD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,QAMjD;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC"}
|
package/dist/context.js
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
export class RuntimeContext {
|
|
2
|
-
stage;
|
|
3
|
-
rootDir;
|
|
4
|
-
env;
|
|
5
|
-
dryRun;
|
|
6
|
-
logSink;
|
|
7
|
-
currentServiceName;
|
|
8
|
-
constructor(config) {
|
|
9
|
-
assertValidStageName(config.stage);
|
|
10
|
-
this.stage = config.stage;
|
|
11
|
-
this.rootDir = config.rootDir ?? process.cwd();
|
|
12
|
-
this.env = config.env ?? process.env;
|
|
13
|
-
this.dryRun = config.dryRun ?? false;
|
|
14
|
-
this.logSink = config.logSink;
|
|
15
|
-
this.currentServiceName = config.currentServiceName;
|
|
16
|
-
}
|
|
17
|
-
writeLog(chunk, stream = "stdout") {
|
|
18
|
-
this.logSink?.({
|
|
19
|
-
serviceName: this.currentServiceName ?? "system",
|
|
20
|
-
stream,
|
|
21
|
-
chunk,
|
|
22
|
-
timestamp: new Date(),
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
export class InitContext extends RuntimeContext {
|
|
27
|
-
}
|
|
28
|
-
export class DevContext extends RuntimeContext {
|
|
29
|
-
}
|
|
30
|
-
export class DeployContext extends RuntimeContext {
|
|
31
|
-
}
|
|
32
|
-
export class ExitContext extends RuntimeContext {
|
|
33
|
-
}
|
|
34
|
-
export function assertValidStageName(stage) {
|
|
35
|
-
if (!/^[a-z0-9][a-z0-9._-]*$/.test(stage)) {
|
|
36
|
-
throw new Error(`Invalid stage "${stage}": stages must start with a lower-case letter or number and contain only lower-case letters, numbers, ".", "_", or "-"`);
|
|
37
|
-
}
|
|
38
|
-
}
|
package/dist/context.test.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"context.test.d.ts","sourceRoot":"","sources":["../src/context.test.ts"],"names":[],"mappings":""}
|
package/dist/context.test.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import test from "node:test";
|
|
3
|
-
import { RuntimeContext } from "./context.js";
|
|
4
|
-
test("accepts stage names that are safe for Docker resources and paths", () => {
|
|
5
|
-
for (const stage of ["local", "production", "review-42", "release_1.2"]) {
|
|
6
|
-
assert.equal(new RuntimeContext({ stage }).stage, stage);
|
|
7
|
-
}
|
|
8
|
-
});
|
|
9
|
-
test("rejects unsafe or ambiguous stage names", () => {
|
|
10
|
-
for (const stage of ["", "../production", "Production", "review 42", "."]) {
|
|
11
|
-
assert.throws(() => new RuntimeContext({ stage }), /Invalid stage/);
|
|
12
|
-
}
|
|
13
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"find-service-definition.d.ts","sourceRoot":"","sources":["../src/find-service-definition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,iBAAiB,EACvB,IAAI,EAAE,MAAM,GACX,iBAAiB,CA+BnB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"find-service-definition.test.d.ts","sourceRoot":"","sources":["../src/find-service-definition.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import assert from "node:assert/strict";
|
|
2
|
-
import test from "node:test";
|
|
3
|
-
import { findServiceDefinition } from "./find-service-definition.js";
|
|
4
|
-
import { ServiceDefinition } from "./service-definition.js";
|
|
5
|
-
test("finds a nested service by its configured name", () => {
|
|
6
|
-
const database = new ServiceDefinition({ name: "db" });
|
|
7
|
-
const api = new ServiceDefinition({
|
|
8
|
-
name: "api",
|
|
9
|
-
dependencies: [database],
|
|
10
|
-
});
|
|
11
|
-
const root = new ServiceDefinition({
|
|
12
|
-
name: "app",
|
|
13
|
-
dependencies: [api],
|
|
14
|
-
});
|
|
15
|
-
assert.equal(findServiceDefinition(root, "db"), database);
|
|
16
|
-
});
|
|
17
|
-
test("allows one shared service instance to appear in multiple branches", () => {
|
|
18
|
-
const database = new ServiceDefinition({ name: "db" });
|
|
19
|
-
const root = new ServiceDefinition({
|
|
20
|
-
name: "app",
|
|
21
|
-
dependencies: [
|
|
22
|
-
new ServiceDefinition({ name: "api", dependencies: [database] }),
|
|
23
|
-
new ServiceDefinition({ name: "worker", dependencies: [database] }),
|
|
24
|
-
],
|
|
25
|
-
});
|
|
26
|
-
assert.equal(findServiceDefinition(root, "db"), database);
|
|
27
|
-
});
|
|
28
|
-
test("reports available services when the requested service is missing", () => {
|
|
29
|
-
const root = new ServiceDefinition({
|
|
30
|
-
name: "app",
|
|
31
|
-
dependencies: [new ServiceDefinition({ name: "db" })],
|
|
32
|
-
});
|
|
33
|
-
assert.throws(() => findServiceDefinition(root, "missing"), /Available services: app, db/);
|
|
34
|
-
});
|
|
35
|
-
test("rejects duplicate names assigned to different service instances", () => {
|
|
36
|
-
const root = new ServiceDefinition({
|
|
37
|
-
name: "app",
|
|
38
|
-
dependencies: [
|
|
39
|
-
new ServiceDefinition({ name: "worker" }),
|
|
40
|
-
new ServiceDefinition({ name: "worker" }),
|
|
41
|
-
],
|
|
42
|
-
});
|
|
43
|
-
assert.throws(() => findServiceDefinition(root, "worker"), /Service name "worker" is ambiguous/);
|
|
44
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"get-saws-config.d.ts","sourceRoot":"","sources":["../src/get-saws-config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,wBAAsB,aAAa,CACjC,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,iBAAiB,CAAC,CAuB5B"}
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,8BAA8B,CAAC;AAC7C,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC"}
|