slskit-cli 1.0.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 +61 -0
- package/COMMAND.md +636 -0
- package/LICENSE +21 -0
- package/NOTICE.md +22 -0
- package/README.md +168 -0
- package/bin/slskit.js +3 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +25 -0
- package/dist/commands/base-command.d.ts +5 -0
- package/dist/commands/base-command.js +29 -0
- package/dist/commands/configure/action.d.ts +2 -0
- package/dist/commands/configure/action.js +120 -0
- package/dist/commands/configure/aws-cli.d.ts +16 -0
- package/dist/commands/configure/aws-cli.js +135 -0
- package/dist/commands/configure/index.d.ts +2 -0
- package/dist/commands/configure/index.js +20 -0
- package/dist/commands/configure/prompts.d.ts +8 -0
- package/dist/commands/configure/prompts.js +117 -0
- package/dist/commands/configure/types.d.ts +24 -0
- package/dist/commands/configure/types.js +6 -0
- package/dist/commands/deploy/action.d.ts +2 -0
- package/dist/commands/deploy/action.js +115 -0
- package/dist/commands/deploy/index.d.ts +2 -0
- package/dist/commands/deploy/index.js +23 -0
- package/dist/commands/deploy/sam-deploy.d.ts +10 -0
- package/dist/commands/deploy/sam-deploy.js +127 -0
- package/dist/commands/deploy/scope.d.ts +9 -0
- package/dist/commands/deploy/scope.js +34 -0
- package/dist/commands/deploy/types.d.ts +20 -0
- package/dist/commands/deploy/types.js +2 -0
- package/dist/commands/env/action.d.ts +11 -0
- package/dist/commands/env/action.js +274 -0
- package/dist/commands/env/dotenv.d.ts +6 -0
- package/dist/commands/env/dotenv.js +99 -0
- package/dist/commands/env/index.d.ts +2 -0
- package/dist/commands/env/index.js +76 -0
- package/dist/commands/env/keys.d.ts +8 -0
- package/dist/commands/env/keys.js +41 -0
- package/dist/commands/env/parameters.d.ts +7 -0
- package/dist/commands/env/parameters.js +63 -0
- package/dist/commands/env/templates.d.ts +3 -0
- package/dist/commands/env/templates.js +65 -0
- package/dist/commands/env/types.d.ts +21 -0
- package/dist/commands/env/types.js +2 -0
- package/dist/commands/function/action.d.ts +2 -0
- package/dist/commands/function/action.js +71 -0
- package/dist/commands/function/generator.d.ts +8 -0
- package/dist/commands/function/generator.js +58 -0
- package/dist/commands/function/index.d.ts +2 -0
- package/dist/commands/function/index.js +26 -0
- package/dist/commands/function/manifest.d.ts +5 -0
- package/dist/commands/function/manifest.js +57 -0
- package/dist/commands/function/prompts.d.ts +18 -0
- package/dist/commands/function/prompts.js +196 -0
- package/dist/commands/function/tooling.d.ts +2 -0
- package/dist/commands/function/tooling.js +43 -0
- package/dist/commands/function/types.d.ts +52 -0
- package/dist/commands/function/types.js +2 -0
- package/dist/commands/index.d.ts +2 -0
- package/dist/commands/index.js +19 -0
- package/dist/commands/init/action.d.ts +2 -0
- package/dist/commands/init/action.js +36 -0
- package/dist/commands/init/content.d.ts +2 -0
- package/dist/commands/init/content.js +97 -0
- package/dist/commands/init/index.d.ts +2 -0
- package/dist/commands/init/index.js +30 -0
- package/dist/commands/init/manifest.d.ts +6 -0
- package/dist/commands/init/manifest.js +147 -0
- package/dist/commands/init/prompts.d.ts +6 -0
- package/dist/commands/init/prompts.js +155 -0
- package/dist/commands/init/scaffold.d.ts +7 -0
- package/dist/commands/init/scaffold.js +85 -0
- package/dist/commands/init/templates/helpers.d.ts +9 -0
- package/dist/commands/init/templates/helpers.js +42 -0
- package/dist/commands/init/templates/node.d.ts +4 -0
- package/dist/commands/init/templates/node.js +99 -0
- package/dist/commands/init/templates/project.d.ts +8 -0
- package/dist/commands/init/templates/project.js +239 -0
- package/dist/commands/init/templates/python.d.ts +4 -0
- package/dist/commands/init/templates/python.js +65 -0
- package/dist/commands/init/templates/sam.d.ts +4 -0
- package/dist/commands/init/templates/sam.js +369 -0
- package/dist/commands/init/templates/shared-code.d.ts +6 -0
- package/dist/commands/init/templates/shared-code.js +159 -0
- package/dist/commands/init/types.d.ts +47 -0
- package/dist/commands/init/types.js +75 -0
- package/dist/commands/rm/action.d.ts +2 -0
- package/dist/commands/rm/action.js +89 -0
- package/dist/commands/rm/index.d.ts +2 -0
- package/dist/commands/rm/index.js +25 -0
- package/dist/commands/rm/plan.d.ts +19 -0
- package/dist/commands/rm/plan.js +78 -0
- package/dist/commands/rm/prompts.d.ts +4 -0
- package/dist/commands/rm/prompts.js +107 -0
- package/dist/commands/rm/types.d.ts +7 -0
- package/dist/commands/rm/types.js +2 -0
- package/dist/commands/run/action.d.ts +2 -0
- package/dist/commands/run/action.js +171 -0
- package/dist/commands/run/index.d.ts +2 -0
- package/dist/commands/run/index.js +21 -0
- package/dist/commands/run/local-template.d.ts +7 -0
- package/dist/commands/run/local-template.js +51 -0
- package/dist/commands/run/manifest.d.ts +2 -0
- package/dist/commands/run/manifest.js +20 -0
- package/dist/commands/run/resources.d.ts +20 -0
- package/dist/commands/run/resources.js +93 -0
- package/dist/commands/run/sam-cli.d.ts +10 -0
- package/dist/commands/run/sam-cli.js +183 -0
- package/dist/commands/run/types.d.ts +18 -0
- package/dist/commands/run/types.js +2 -0
- package/dist/commands/run/watch.d.ts +11 -0
- package/dist/commands/run/watch.js +131 -0
- package/dist/core/context.d.ts +15 -0
- package/dist/core/context.js +41 -0
- package/dist/core/credentials.d.ts +10 -0
- package/dist/core/credentials.js +22 -0
- package/dist/core/environments.d.ts +46 -0
- package/dist/core/environments.js +161 -0
- package/dist/core/errors.d.ts +4 -0
- package/dist/core/errors.js +11 -0
- package/dist/core/flags-docs.d.ts +2 -0
- package/dist/core/flags-docs.js +63 -0
- package/dist/core/is-ci.d.ts +4 -0
- package/dist/core/is-ci.js +16 -0
- package/dist/core/logger.d.ts +4 -0
- package/dist/core/logger.js +19 -0
- package/dist/core/run.d.ts +1 -0
- package/dist/core/run.js +27 -0
- package/dist/core/scope.d.ts +33 -0
- package/dist/core/scope.js +108 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +9 -0
- package/dist/program.d.ts +2 -0
- package/dist/program.js +26 -0
- package/package.json +110 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.FUNCTION_NAME_MAX = exports.APP_ENVIRONMENT_PARAM = exports.APP_ENVIRONMENT_KEY = exports.DEFAULT_ENVIRONMENT = exports.LEGACY_MANIFEST_FILE = exports.MANIFEST_FILE = void 0;
|
|
7
|
+
exports.manifestPathFor = manifestPathFor;
|
|
8
|
+
exports.readManifest = readManifest;
|
|
9
|
+
exports.writeManifest = writeManifest;
|
|
10
|
+
exports.parseEnvironmentName = parseEnvironmentName;
|
|
11
|
+
exports.environmentNames = environmentNames;
|
|
12
|
+
exports.defaultEnvironment = defaultEnvironment;
|
|
13
|
+
exports.resolveEnvironmentName = resolveEnvironmentName;
|
|
14
|
+
exports.requireEnvironment = requireEnvironment;
|
|
15
|
+
exports.stackNameFor = stackNameFor;
|
|
16
|
+
exports.functionNameFor = functionNameFor;
|
|
17
|
+
exports.assertFunctionNameFits = assertFunctionNameFits;
|
|
18
|
+
exports.envVarSource = envVarSource;
|
|
19
|
+
exports.allEnvKeys = allEnvKeys;
|
|
20
|
+
exports.writeEnvironment = writeEnvironment;
|
|
21
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
22
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
23
|
+
const errors_js_1 = require("./errors.js");
|
|
24
|
+
exports.MANIFEST_FILE = "slskit.json";
|
|
25
|
+
// The manifest was called sless.json before the CLI was renamed. Projects generated
|
|
26
|
+
// then are still read, and migrated to the new name the next time one is written.
|
|
27
|
+
exports.LEGACY_MANIFEST_FILE = "sless.json";
|
|
28
|
+
// The manifest this project actually has on disk, new name preferred.
|
|
29
|
+
function manifestPathFor(cwd) {
|
|
30
|
+
for (const name of [exports.MANIFEST_FILE, exports.LEGACY_MANIFEST_FILE]) {
|
|
31
|
+
const candidate = node_path_1.default.join(cwd, name);
|
|
32
|
+
if (node_fs_1.default.existsSync(candidate)) {
|
|
33
|
+
return candidate;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
// Every project has this environment from "slskit init" onward, and every
|
|
39
|
+
// stage-aware command falls back to it when no --env is given.
|
|
40
|
+
exports.DEFAULT_ENVIRONMENT = "dev";
|
|
41
|
+
// The variable slskit always generates. Its value is the environment name, and
|
|
42
|
+
// every stage-scoped resource name is built from it.
|
|
43
|
+
exports.APP_ENVIRONMENT_KEY = "APP_ENVIRONMENT";
|
|
44
|
+
// The matching CloudFormation parameter. Templates are shared by every
|
|
45
|
+
// environment, so the name has to arrive as an override at deploy time.
|
|
46
|
+
exports.APP_ENVIRONMENT_PARAM = "AppEnvironment";
|
|
47
|
+
// Lambda caps a function name at 64 characters, and slskit builds it as
|
|
48
|
+
// <project>-<environment>-<function>.
|
|
49
|
+
exports.FUNCTION_NAME_MAX = 64;
|
|
50
|
+
const ENVIRONMENT_PATTERN = /^[a-z][a-z0-9-]*$/;
|
|
51
|
+
function readManifest(cwd, command = "slskit") {
|
|
52
|
+
const manifestPath = manifestPathFor(cwd);
|
|
53
|
+
if (!manifestPath) {
|
|
54
|
+
throw new errors_js_1.CliError(`No ${exports.MANIFEST_FILE} found in ${cwd}. Run "slskit init" first, or run "${command}" from your project root.`);
|
|
55
|
+
}
|
|
56
|
+
let manifest;
|
|
57
|
+
try {
|
|
58
|
+
manifest = JSON.parse(node_fs_1.default.readFileSync(manifestPath, "utf8"));
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
62
|
+
throw new errors_js_1.CliError(`${exports.MANIFEST_FILE} is not valid JSON: ${message}`);
|
|
63
|
+
}
|
|
64
|
+
if (!manifest?.name) {
|
|
65
|
+
throw new errors_js_1.CliError(`${exports.MANIFEST_FILE} is missing a project "name".`);
|
|
66
|
+
}
|
|
67
|
+
return manifest;
|
|
68
|
+
}
|
|
69
|
+
function writeManifest(cwd, manifest) {
|
|
70
|
+
node_fs_1.default.writeFileSync(node_path_1.default.join(cwd, exports.MANIFEST_FILE), `${JSON.stringify(manifest, null, 2)}\n`);
|
|
71
|
+
// Writing completes the rename: leaving both files behind would make it ambiguous
|
|
72
|
+
// which one a command had actually read.
|
|
73
|
+
const legacy = node_path_1.default.join(cwd, exports.LEGACY_MANIFEST_FILE);
|
|
74
|
+
if (node_fs_1.default.existsSync(legacy)) {
|
|
75
|
+
node_fs_1.default.rmSync(legacy);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function parseEnvironmentName(value, label = "Environment name") {
|
|
79
|
+
if (value === undefined || value.trim() === "") {
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
const name = value.trim().toLowerCase();
|
|
83
|
+
if (!ENVIRONMENT_PATTERN.test(name)) {
|
|
84
|
+
throw new errors_js_1.CliError(`Invalid ${label.toLowerCase()} "${value}". Use lowercase letters, digits and hyphens, starting with a letter (for example: dev, staging, stage-1, production).`);
|
|
85
|
+
}
|
|
86
|
+
return name;
|
|
87
|
+
}
|
|
88
|
+
function environmentNames(manifest) {
|
|
89
|
+
return Object.keys(manifest.environments?.list ?? {}).sort();
|
|
90
|
+
}
|
|
91
|
+
function defaultEnvironment(manifest) {
|
|
92
|
+
return manifest.environments?.default ?? exports.DEFAULT_ENVIRONMENT;
|
|
93
|
+
}
|
|
94
|
+
function resolveEnvironmentName(manifest, requested) {
|
|
95
|
+
return parseEnvironmentName(requested) ?? defaultEnvironment(manifest);
|
|
96
|
+
}
|
|
97
|
+
function requireEnvironment(manifest, name) {
|
|
98
|
+
const config = manifest.environments?.list?.[name];
|
|
99
|
+
if (!config) {
|
|
100
|
+
const known = environmentNames(manifest).join(", ") || "(none)";
|
|
101
|
+
throw new errors_js_1.CliError(`Environment "${name}" was not found. Existing environments: ${known}. Add one with "slskit env add ${name}".`);
|
|
102
|
+
}
|
|
103
|
+
return config;
|
|
104
|
+
}
|
|
105
|
+
// Resource names are derived, never stored, so renaming an environment can never
|
|
106
|
+
// leave a stale name behind in the manifest.
|
|
107
|
+
function stackNameFor(projectName, environment) {
|
|
108
|
+
return sanitizeName(`${projectName}-${environment}`);
|
|
109
|
+
}
|
|
110
|
+
function functionNameFor(projectName, environment, functionName) {
|
|
111
|
+
return sanitizeName(`${projectName}-${environment}-${functionName}`);
|
|
112
|
+
}
|
|
113
|
+
function sanitizeName(value) {
|
|
114
|
+
const cleaned = value
|
|
115
|
+
.replace(/[^A-Za-z0-9-]/g, "-")
|
|
116
|
+
.replace(/-{2,}/g, "-")
|
|
117
|
+
.replace(/^-+/, "")
|
|
118
|
+
.replace(/-+$/, "");
|
|
119
|
+
return /^[A-Za-z]/.test(cleaned) ? cleaned : `app-${cleaned}`;
|
|
120
|
+
}
|
|
121
|
+
// Checked at generate time so a too-long name fails while it is still a local
|
|
122
|
+
// file, rather than midway through a CloudFormation deploy.
|
|
123
|
+
function assertFunctionNameFits(projectName, environment, functionName) {
|
|
124
|
+
const full = functionNameFor(projectName, environment, functionName);
|
|
125
|
+
if (full.length > exports.FUNCTION_NAME_MAX) {
|
|
126
|
+
throw new errors_js_1.CliError(`Lambda function name "${full}" is ${full.length} characters, over the ${exports.FUNCTION_NAME_MAX} character limit.\nShorten the project name, the environment name "${environment}", or the function name "${functionName}".`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function envVarSource(def) {
|
|
130
|
+
if (def.ssm) {
|
|
131
|
+
return "ssm";
|
|
132
|
+
}
|
|
133
|
+
if (def.secret) {
|
|
134
|
+
return "secret";
|
|
135
|
+
}
|
|
136
|
+
return "value";
|
|
137
|
+
}
|
|
138
|
+
// Templates are shared by every environment, so they declare a parameter for the
|
|
139
|
+
// union of variable names. APP_ENVIRONMENT is excluded: it has its own dedicated
|
|
140
|
+
// parameter and is never stored as a normal variable.
|
|
141
|
+
function allEnvKeys(manifest) {
|
|
142
|
+
const keys = new Set();
|
|
143
|
+
for (const environment of Object.values(manifest.environments?.list ?? {})) {
|
|
144
|
+
for (const key of Object.keys(environment.variables ?? {})) {
|
|
145
|
+
if (key !== exports.APP_ENVIRONMENT_KEY) {
|
|
146
|
+
keys.add(key);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return [...keys].sort();
|
|
151
|
+
}
|
|
152
|
+
function writeEnvironment(cwd, manifest, name, config) {
|
|
153
|
+
const environments = manifest.environments;
|
|
154
|
+
writeManifest(cwd, {
|
|
155
|
+
...manifest,
|
|
156
|
+
environments: {
|
|
157
|
+
default: environments?.default ?? name,
|
|
158
|
+
list: { ...environments?.list, [name]: config },
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CliError = void 0;
|
|
4
|
+
class CliError extends Error {
|
|
5
|
+
constructor(message, exitCode = 1) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = "CliError";
|
|
8
|
+
this.exitCode = exitCode;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
exports.CliError = CliError;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateFlagsMarkdown = generateFlagsMarkdown;
|
|
4
|
+
const GLOBAL_LONG = new Set(["--cwd", "--debug", "--silent", "--json", "--version"]);
|
|
5
|
+
const HEADER = `# slskit — generated flag reference
|
|
6
|
+
|
|
7
|
+
This file is generated from the Commander program. Do not edit it by hand.
|
|
8
|
+
|
|
9
|
+
\`\`\`bash
|
|
10
|
+
npm run docs
|
|
11
|
+
\`\`\`
|
|
12
|
+
|
|
13
|
+
CI fails if this file is stale. Narrative docs live in [COMMAND.md](../COMMAND.md).
|
|
14
|
+
|
|
15
|
+
`;
|
|
16
|
+
function optionLine(option) {
|
|
17
|
+
const def = option.defaultValue === undefined || option.defaultValue === false
|
|
18
|
+
? ""
|
|
19
|
+
: ` (default: \`${String(option.defaultValue)}\`)`;
|
|
20
|
+
return `- \`${option.flags}\` — ${option.description ?? ""}${def}`;
|
|
21
|
+
}
|
|
22
|
+
function walk(command, trail) {
|
|
23
|
+
const name = [...trail, command.name()].filter(Boolean).join(" ");
|
|
24
|
+
const sections = [];
|
|
25
|
+
if (trail.length > 0 || command.name() !== "slskit") {
|
|
26
|
+
const args = command.registeredArguments ?? [];
|
|
27
|
+
const argText = args
|
|
28
|
+
.map((argument) => (argument.required ? `<${argument.name()}>` : `[${argument.name()}]`))
|
|
29
|
+
.join(" ");
|
|
30
|
+
const heading = argText ? `${name} ${argText}` : name;
|
|
31
|
+
sections.push(`## \`${heading}\``, "");
|
|
32
|
+
if (command.description()) {
|
|
33
|
+
sections.push(command.description(), "");
|
|
34
|
+
}
|
|
35
|
+
const options = command.options.filter((option) => !option.hidden && !GLOBAL_LONG.has(option.long ?? ""));
|
|
36
|
+
if (options.length > 0) {
|
|
37
|
+
sections.push("Flags:", "");
|
|
38
|
+
for (const option of options) {
|
|
39
|
+
sections.push(optionLine(option));
|
|
40
|
+
}
|
|
41
|
+
sections.push("");
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
for (const child of command.commands) {
|
|
45
|
+
const nextTrail = [...trail, command.name() === "slskit" ? "" : command.name()].filter(Boolean);
|
|
46
|
+
sections.push(...walk(child, nextTrail));
|
|
47
|
+
}
|
|
48
|
+
return sections;
|
|
49
|
+
}
|
|
50
|
+
function generateFlagsMarkdown(program) {
|
|
51
|
+
const globals = program.options.filter((option) => !option.hidden);
|
|
52
|
+
const parts = [
|
|
53
|
+
HEADER,
|
|
54
|
+
"## Global flags",
|
|
55
|
+
"",
|
|
56
|
+
"Available on every command.",
|
|
57
|
+
"",
|
|
58
|
+
...globals.map(optionLine),
|
|
59
|
+
"",
|
|
60
|
+
...walk(program, []),
|
|
61
|
+
];
|
|
62
|
+
return `${parts.join("\n").replace(/\n{3,}/g, "\n\n").trim()}\n`;
|
|
63
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isCI = isCI;
|
|
4
|
+
exports.isInteractive = isInteractive;
|
|
5
|
+
// Detects hosted CI without a dependency. `CI` is the de-facto signal; GitHub
|
|
6
|
+
// Actions is listed explicitly because some self-hosted runners omit `CI`.
|
|
7
|
+
function isCI(env = process.env) {
|
|
8
|
+
const ci = env.CI;
|
|
9
|
+
if (ci === "true" || ci === "1") {
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
return env.GITHUB_ACTIONS === "true";
|
|
13
|
+
}
|
|
14
|
+
function isInteractive(stdin = process.stdin, env = process.env) {
|
|
15
|
+
return Boolean(stdin.isTTY) && !isCI(env);
|
|
16
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.logger = void 0;
|
|
4
|
+
const context_js_1 = require("./context.js");
|
|
5
|
+
function shouldWriteInfo() {
|
|
6
|
+
const { silent, json } = (0, context_js_1.getContext)();
|
|
7
|
+
return !silent && !json;
|
|
8
|
+
}
|
|
9
|
+
exports.logger = {
|
|
10
|
+
info(message) {
|
|
11
|
+
if (!shouldWriteInfo()) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
process.stdout.write(`${message}\n`);
|
|
15
|
+
},
|
|
16
|
+
error(message) {
|
|
17
|
+
process.stderr.write(`${message}\n`);
|
|
18
|
+
},
|
|
19
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runCommand(action: () => Promise<void> | void): Promise<void>;
|
package/dist/core/run.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runCommand = runCommand;
|
|
4
|
+
const context_js_1 = require("./context.js");
|
|
5
|
+
const errors_js_1 = require("./errors.js");
|
|
6
|
+
const logger_js_1 = require("./logger.js");
|
|
7
|
+
async function runCommand(action) {
|
|
8
|
+
try {
|
|
9
|
+
await action();
|
|
10
|
+
}
|
|
11
|
+
catch (error) {
|
|
12
|
+
if (error instanceof errors_js_1.CliError) {
|
|
13
|
+
logger_js_1.logger.error(error.message);
|
|
14
|
+
if ((0, context_js_1.getContext)().debug && error.stack) {
|
|
15
|
+
logger_js_1.logger.error(error.stack);
|
|
16
|
+
}
|
|
17
|
+
process.exitCode = error.exitCode;
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const message = error instanceof Error ? error.message : "Unexpected CLI error";
|
|
21
|
+
logger_js_1.logger.error(message);
|
|
22
|
+
if ((0, context_js_1.getContext)().debug && error instanceof Error && error.stack) {
|
|
23
|
+
logger_js_1.logger.error(error.stack);
|
|
24
|
+
}
|
|
25
|
+
process.exitCode = 1;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ProjectManifest } from "./environments.js";
|
|
2
|
+
export interface ApplicationView {
|
|
3
|
+
name: string;
|
|
4
|
+
functions?: {
|
|
5
|
+
name: string;
|
|
6
|
+
}[];
|
|
7
|
+
}
|
|
8
|
+
export type ScopeKind = "all" | "service" | "function";
|
|
9
|
+
export type Scope = {
|
|
10
|
+
kind: "all";
|
|
11
|
+
label: string;
|
|
12
|
+
} | {
|
|
13
|
+
kind: "service";
|
|
14
|
+
label: string;
|
|
15
|
+
service: string;
|
|
16
|
+
} | {
|
|
17
|
+
kind: "function";
|
|
18
|
+
label: string;
|
|
19
|
+
service: string;
|
|
20
|
+
functionName: string;
|
|
21
|
+
};
|
|
22
|
+
export declare const allScope: Scope;
|
|
23
|
+
export declare function applicationsOf(manifest: ProjectManifest): ApplicationView[];
|
|
24
|
+
export declare function requireService(manifest: ProjectManifest, name: string): ApplicationView;
|
|
25
|
+
export declare function serviceScope(manifest: ProjectManifest, name: string): Scope;
|
|
26
|
+
export declare function functionScope(manifest: ProjectManifest, name: string): Scope;
|
|
27
|
+
export interface ScopeOptions {
|
|
28
|
+
service?: string;
|
|
29
|
+
function?: string;
|
|
30
|
+
all?: boolean;
|
|
31
|
+
}
|
|
32
|
+
export declare function scopeFromFlags(manifest: ProjectManifest, options: ScopeOptions): Scope | undefined;
|
|
33
|
+
export declare function promptForScope(manifest: ProjectManifest, verb: string, everything: string): Promise<Scope>;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.allScope = void 0;
|
|
4
|
+
exports.applicationsOf = applicationsOf;
|
|
5
|
+
exports.requireService = requireService;
|
|
6
|
+
exports.serviceScope = serviceScope;
|
|
7
|
+
exports.functionScope = functionScope;
|
|
8
|
+
exports.scopeFromFlags = scopeFromFlags;
|
|
9
|
+
exports.promptForScope = promptForScope;
|
|
10
|
+
const errors_js_1 = require("./errors.js");
|
|
11
|
+
exports.allScope = { kind: "all", label: "the whole project" };
|
|
12
|
+
function applicationsOf(manifest) {
|
|
13
|
+
return manifest.applications ?? [];
|
|
14
|
+
}
|
|
15
|
+
function requireService(manifest, name) {
|
|
16
|
+
const apps = applicationsOf(manifest);
|
|
17
|
+
const found = apps.find((app) => app.name === name);
|
|
18
|
+
if (!found) {
|
|
19
|
+
const known = apps.map((app) => app.name).join(", ") || "(none)";
|
|
20
|
+
throw new errors_js_1.CliError(`Service "${name}" was not found. This project has: ${known}.`);
|
|
21
|
+
}
|
|
22
|
+
return found;
|
|
23
|
+
}
|
|
24
|
+
function serviceScope(manifest, name) {
|
|
25
|
+
const app = requireService(manifest, name);
|
|
26
|
+
const count = (app.functions ?? []).length;
|
|
27
|
+
if (count === 0) {
|
|
28
|
+
throw new errors_js_1.CliError(`Service "${name}" has no functions.`);
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
kind: "service",
|
|
32
|
+
label: `service "${name}" (${count} function${count === 1 ? "" : "s"})`,
|
|
33
|
+
service: name,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
// Function names are unique across a project, so the service is derived rather than
|
|
37
|
+
// asked for a second time.
|
|
38
|
+
function functionScope(manifest, name) {
|
|
39
|
+
for (const app of applicationsOf(manifest)) {
|
|
40
|
+
for (const fn of app.functions ?? []) {
|
|
41
|
+
if (fn.name === name) {
|
|
42
|
+
return {
|
|
43
|
+
kind: "function",
|
|
44
|
+
label: `function "${app.name}/${fn.name}"`,
|
|
45
|
+
service: app.name,
|
|
46
|
+
functionName: fn.name,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const known = applicationsOf(manifest)
|
|
52
|
+
.flatMap((app) => (app.functions ?? []).map((fn) => fn.name))
|
|
53
|
+
.join(", ");
|
|
54
|
+
throw new errors_js_1.CliError(`Function "${name}" was not found. This project has: ${known || "(none)"}.`);
|
|
55
|
+
}
|
|
56
|
+
function scopeFromFlags(manifest, options) {
|
|
57
|
+
if (options.service && options.function) {
|
|
58
|
+
throw new errors_js_1.CliError('Pass either "--service" or "--function", not both.');
|
|
59
|
+
}
|
|
60
|
+
if (options.service) {
|
|
61
|
+
return serviceScope(manifest, options.service);
|
|
62
|
+
}
|
|
63
|
+
if (options.function) {
|
|
64
|
+
return functionScope(manifest, options.function);
|
|
65
|
+
}
|
|
66
|
+
return options.all ? exports.allScope : undefined;
|
|
67
|
+
}
|
|
68
|
+
// Asks what to act on, then which one. Only reached with a TTY and no scope flag.
|
|
69
|
+
async function promptForScope(manifest, verb, everything) {
|
|
70
|
+
const apps = applicationsOf(manifest).filter((app) => (app.functions ?? []).length > 0);
|
|
71
|
+
if (apps.length === 0) {
|
|
72
|
+
return exports.allScope;
|
|
73
|
+
}
|
|
74
|
+
const { select } = await import("@inquirer/prompts");
|
|
75
|
+
const kind = await select({
|
|
76
|
+
message: `What do you want to ${verb}?`,
|
|
77
|
+
choices: [
|
|
78
|
+
{ name: everything, value: "all" },
|
|
79
|
+
{ name: "One service — all of its functions", value: "service" },
|
|
80
|
+
{ name: "One function", value: "function" },
|
|
81
|
+
],
|
|
82
|
+
});
|
|
83
|
+
if (kind === "all") {
|
|
84
|
+
return exports.allScope;
|
|
85
|
+
}
|
|
86
|
+
if (kind === "service") {
|
|
87
|
+
const name = await select({
|
|
88
|
+
message: "Service:",
|
|
89
|
+
choices: apps.map((app) => ({
|
|
90
|
+
name: `${app.name} (${(app.functions ?? []).length} functions)`,
|
|
91
|
+
value: app.name,
|
|
92
|
+
})),
|
|
93
|
+
});
|
|
94
|
+
return serviceScope(manifest, name);
|
|
95
|
+
}
|
|
96
|
+
const service = await select({
|
|
97
|
+
message: "Service:",
|
|
98
|
+
choices: apps.map((app) => ({ name: app.name, value: app.name })),
|
|
99
|
+
});
|
|
100
|
+
const functionName = await select({
|
|
101
|
+
message: "Function:",
|
|
102
|
+
choices: (requireService(manifest, service).functions ?? []).map((fn) => ({
|
|
103
|
+
name: fn.name,
|
|
104
|
+
value: fn.name,
|
|
105
|
+
})),
|
|
106
|
+
});
|
|
107
|
+
return functionScope(manifest, functionName);
|
|
108
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.logger = exports.CliError = exports.createProgram = void 0;
|
|
4
|
+
var program_js_1 = require("./program.js");
|
|
5
|
+
Object.defineProperty(exports, "createProgram", { enumerable: true, get: function () { return program_js_1.createProgram; } });
|
|
6
|
+
var errors_js_1 = require("./core/errors.js");
|
|
7
|
+
Object.defineProperty(exports, "CliError", { enumerable: true, get: function () { return errors_js_1.CliError; } });
|
|
8
|
+
var logger_js_1 = require("./core/logger.js");
|
|
9
|
+
Object.defineProperty(exports, "logger", { enumerable: true, get: function () { return logger_js_1.logger; } });
|
package/dist/program.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createProgram = createProgram;
|
|
4
|
+
const base_command_js_1 = require("./commands/base-command.js");
|
|
5
|
+
const index_js_1 = require("./commands/index.js");
|
|
6
|
+
// Read at runtime rather than hardcoded, so "slskit --version" can never drift from
|
|
7
|
+
// what was actually published. Resolves to the package root from both dist/ and src/,
|
|
8
|
+
// which is why running from source via tsx reports the same number.
|
|
9
|
+
function packageVersion() {
|
|
10
|
+
try {
|
|
11
|
+
return require("../package.json").version;
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return "0.0.0";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function createProgram() {
|
|
18
|
+
const program = new base_command_js_1.BaseCommand();
|
|
19
|
+
program
|
|
20
|
+
.name("slskit")
|
|
21
|
+
.description("Scaffold and incrementally grow multi-service AWS Lambda projects")
|
|
22
|
+
.version(packageVersion());
|
|
23
|
+
(0, base_command_js_1.addGlobalOptions)(program);
|
|
24
|
+
(0, index_js_1.registerCommands)(program);
|
|
25
|
+
return program;
|
|
26
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "slskit-cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Scaffold and grow multi-service AWS Lambda projects on AWS SAM — local runs with hot reload, isolated environments, and single-function deploys",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"aws",
|
|
7
|
+
"aws-lambda",
|
|
8
|
+
"lambda",
|
|
9
|
+
"serverless",
|
|
10
|
+
"aws-sam",
|
|
11
|
+
"sam",
|
|
12
|
+
"sam-cli",
|
|
13
|
+
"cli",
|
|
14
|
+
"scaffold",
|
|
15
|
+
"generator",
|
|
16
|
+
"project-generator",
|
|
17
|
+
"boilerplate",
|
|
18
|
+
"starter",
|
|
19
|
+
"typescript",
|
|
20
|
+
"javascript",
|
|
21
|
+
"python",
|
|
22
|
+
"api-gateway",
|
|
23
|
+
"http-api",
|
|
24
|
+
"cloudformation",
|
|
25
|
+
"iac",
|
|
26
|
+
"infrastructure-as-code",
|
|
27
|
+
"lambda-layer",
|
|
28
|
+
"dynamodb",
|
|
29
|
+
"hot-reload",
|
|
30
|
+
"multi-service",
|
|
31
|
+
"deployment",
|
|
32
|
+
"developer-tools"
|
|
33
|
+
],
|
|
34
|
+
"homepage": "https://github.com/savindaJ/SLSKIT-CLI#readme",
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://github.com/savindaJ/SLSKIT-CLI/issues"
|
|
37
|
+
},
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "git+https://github.com/savindaJ/SLSKIT-CLI.git"
|
|
41
|
+
},
|
|
42
|
+
"license": "MIT",
|
|
43
|
+
"author": {
|
|
44
|
+
"name": "Savinda Jayasekara",
|
|
45
|
+
"url": "https://github.com/savindaJ"
|
|
46
|
+
},
|
|
47
|
+
"type": "commonjs",
|
|
48
|
+
"main": "dist/index.js",
|
|
49
|
+
"types": "dist/index.d.ts",
|
|
50
|
+
"exports": {
|
|
51
|
+
".": {
|
|
52
|
+
"types": "./dist/index.d.ts",
|
|
53
|
+
"require": "./dist/index.js",
|
|
54
|
+
"default": "./dist/index.js"
|
|
55
|
+
},
|
|
56
|
+
"./package.json": "./package.json"
|
|
57
|
+
},
|
|
58
|
+
"bin": {
|
|
59
|
+
"slskit": "bin/slskit.js"
|
|
60
|
+
},
|
|
61
|
+
"files": [
|
|
62
|
+
"bin",
|
|
63
|
+
"dist",
|
|
64
|
+
"COMMAND.md",
|
|
65
|
+
"CHANGELOG.md",
|
|
66
|
+
"NOTICE.md",
|
|
67
|
+
"LICENSE"
|
|
68
|
+
],
|
|
69
|
+
"engines": {
|
|
70
|
+
"node": ">=18"
|
|
71
|
+
},
|
|
72
|
+
"publishConfig": {
|
|
73
|
+
"access": "public"
|
|
74
|
+
},
|
|
75
|
+
"scripts": {
|
|
76
|
+
"build": "tsc",
|
|
77
|
+
"build:release": "npm run clean && tsc -p tsconfig.build.json",
|
|
78
|
+
"changeset": "changeset",
|
|
79
|
+
"changeset:publish": "changeset publish",
|
|
80
|
+
"changeset:status": "changeset status --verbose",
|
|
81
|
+
"changeset:version": "changeset version",
|
|
82
|
+
"clean": "rm -rf dist",
|
|
83
|
+
"dev": "tsx src/cli.ts",
|
|
84
|
+
"docs": "tsx scripts/generate-docs.ts",
|
|
85
|
+
"docs:check": "tsx scripts/generate-docs.ts --check",
|
|
86
|
+
"licenses": "node scripts/check-licenses.js",
|
|
87
|
+
"lint": "tsc --noEmit",
|
|
88
|
+
"prepublishOnly": "npm run clean && npm run typecheck && npm run licenses && npm test && npm run build:release",
|
|
89
|
+
"start": "node bin/slskit.js",
|
|
90
|
+
"test": "jest",
|
|
91
|
+
"test:cli": "jest test/cli",
|
|
92
|
+
"test:unit": "jest test/unit",
|
|
93
|
+
"test:watch": "jest --watch",
|
|
94
|
+
"typecheck": "tsc --noEmit"
|
|
95
|
+
},
|
|
96
|
+
"dependencies": {
|
|
97
|
+
"@inquirer/prompts": "^8.5.2",
|
|
98
|
+
"commander": "^12.1.0"
|
|
99
|
+
},
|
|
100
|
+
"devDependencies": {
|
|
101
|
+
"@changesets/cli": "^2.31.1",
|
|
102
|
+
"@types/jest": "^30.0.0",
|
|
103
|
+
"@types/node": "^22.10.2",
|
|
104
|
+
"jest": "^30.4.2",
|
|
105
|
+
"pkg-pr-new": "^0.0.88",
|
|
106
|
+
"ts-jest": "^29.4.12",
|
|
107
|
+
"tsx": "^4.19.2",
|
|
108
|
+
"typescript": "^5.7.2"
|
|
109
|
+
}
|
|
110
|
+
}
|