skuba 13.0.3 → 13.1.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/lib/cli/adapter/eslint.js +3 -3
- package/lib/cli/adapter/eslint.js.map +3 -3
- package/lib/cli/build/assets.d.ts +3 -2
- package/lib/cli/build/assets.js +2 -2
- package/lib/cli/build/assets.js.map +3 -3
- package/lib/cli/build/esbuild.js +3 -12
- package/lib/cli/build/esbuild.js.map +3 -3
- package/lib/cli/build/index.js +3 -13
- package/lib/cli/build/index.js.map +3 -3
- package/lib/cli/build/tsc.js +1 -2
- package/lib/cli/build/tsc.js.map +2 -2
- package/lib/cli/configure/analysis/diff.js +3 -13
- package/lib/cli/configure/analysis/diff.js.map +3 -3
- package/lib/cli/configure/ensureTemplateCompletion.js +5 -2
- package/lib/cli/configure/ensureTemplateCompletion.js.map +3 -3
- package/lib/cli/configure/getEntryPoint.d.ts +1 -1
- package/lib/cli/configure/getEntryPoint.js +8 -10
- package/lib/cli/configure/getEntryPoint.js.map +3 -3
- package/lib/cli/configure/getProjectType.js +4 -6
- package/lib/cli/configure/getProjectType.js.map +2 -2
- package/lib/cli/configure/index.js +12 -11
- package/lib/cli/configure/index.js.map +2 -2
- package/lib/cli/format/index.js +4 -14
- package/lib/cli/format/index.js.map +3 -3
- package/lib/cli/init/getConfig.d.ts +1 -1
- package/lib/cli/init/getConfig.js +35 -42
- package/lib/cli/init/getConfig.js.map +3 -3
- package/lib/cli/init/git.js +2 -2
- package/lib/cli/init/git.js.map +3 -3
- package/lib/cli/init/prompts.d.ts +13 -10
- package/lib/cli/init/prompts.js +26 -36
- package/lib/cli/init/prompts.js.map +3 -3
- package/lib/cli/init/types.d.ts +1 -1
- package/lib/cli/lint/autofix.js +2 -2
- package/lib/cli/lint/autofix.js.map +3 -3
- package/lib/cli/lint/eslint.js +2 -2
- package/lib/cli/lint/eslint.js.map +3 -3
- package/lib/cli/lint/index.js +1 -3
- package/lib/cli/lint/index.js.map +2 -2
- package/lib/cli/lint/internal.js +6 -14
- package/lib/cli/lint/internal.js.map +3 -3
- package/lib/cli/lint/internalLints/noSkubaTemplateJs.js +3 -5
- package/lib/cli/lint/internalLints/noSkubaTemplateJs.js.map +3 -3
- package/lib/cli/lint/internalLints/refreshConfigFiles.js +1 -3
- package/lib/cli/lint/internalLints/refreshConfigFiles.js.map +2 -2
- package/lib/cli/lint/internalLints/upgrade/index.js +1 -3
- package/lib/cli/lint/internalLints/upgrade/index.js.map +2 -2
- package/lib/cli/lint/internalLints/upgrade/patches/10.1.0/migrateNpmrcToPnpmWorkspace.js +17 -21
- package/lib/cli/lint/internalLints/upgrade/patches/10.1.0/migrateNpmrcToPnpmWorkspace.js.map +2 -2
- package/lib/cli/lint/internalLints/upgrade/patches/8.2.1/index.js +0 -5
- package/lib/cli/lint/internalLints/upgrade/patches/8.2.1/index.js.map +2 -2
- package/lib/cli/lint/prettier.js +2 -2
- package/lib/cli/lint/prettier.js.map +3 -3
- package/lib/utils/dir.js +3 -2
- package/lib/utils/dir.js.map +2 -2
- package/lib/utils/exec.d.ts +3 -2
- package/lib/utils/exec.js +1 -1
- package/lib/utils/exec.js.map +2 -2
- package/lib/utils/fs.d.ts +1 -0
- package/lib/utils/fs.js +51 -0
- package/lib/utils/fs.js.map +7 -0
- package/lib/utils/logging.d.ts +9 -10
- package/lib/utils/logging.js +9 -19
- package/lib/utils/logging.js.map +3 -3
- package/lib/utils/logo.js +11 -18
- package/lib/utils/logo.js.map +3 -3
- package/lib/utils/sleep.d.ts +5 -0
- package/lib/utils/sleep.js +35 -0
- package/lib/utils/sleep.js.map +7 -0
- package/lib/utils/wait.d.ts +0 -4
- package/lib/utils/wait.js +2 -10
- package/lib/utils/wait.js.map +2 -2
- package/lib/utils/worker.d.ts +3 -3
- package/lib/wrapper/http.d.ts +0 -6
- package/lib/wrapper/http.js +4 -12
- package/lib/wrapper/http.js.map +2 -2
- package/lib/wrapper/requestListener.js +3 -2
- package/lib/wrapper/requestListener.js.map +2 -2
- package/lib/wrapper/server.d.ts +7 -0
- package/lib/wrapper/server.js +35 -0
- package/lib/wrapper/server.js.map +7 -0
- package/package.json +16 -18
- package/template/base/_pnpm-workspace.yaml +1 -0
- package/template/express-rest-api/.buildkite/pipeline.yml +1 -1
- package/template/express-rest-api/.gantry/dev.yml +2 -2
- package/template/express-rest-api/.gantry/prod.yml +2 -2
- package/template/express-rest-api/package.json +5 -5
- package/template/greeter/.buildkite/pipeline.yml +1 -1
- package/template/greeter/package.json +2 -2
- package/template/koa-rest-api/.buildkite/pipeline.yml +1 -1
- package/template/koa-rest-api/.gantry/dev.yml +2 -2
- package/template/koa-rest-api/.gantry/prod.yml +2 -2
- package/template/koa-rest-api/package.json +5 -5
- package/template/lambda-sqs-worker-cdk/.buildkite/pipeline.yml +2 -2
- package/template/lambda-sqs-worker-cdk/infra/__snapshots__/appStack.test.ts.snap +2 -4
- package/template/lambda-sqs-worker-cdk/infra/appStack.ts +1 -1
- package/template/lambda-sqs-worker-cdk/infra/config.ts +2 -4
- package/template/lambda-sqs-worker-cdk/package.json +3 -2
- package/template/lambda-sqs-worker-cdk/skuba.template.js +12 -0
- package/template/oss-npm-package/.github/workflows/release.yml +2 -2
- package/template/oss-npm-package/.github/workflows/validate.yml +2 -2
- package/template/private-npm-package/skuba.template.js +1 -1
- package/lib/cli/lint/internalLints/upgrade/patches/8.2.1/upgradeESLint.d.ts +0 -2
- package/lib/cli/lint/internalLints/upgrade/patches/8.2.1/upgradeESLint.js +0 -144
- package/lib/cli/lint/internalLints/upgrade/patches/8.2.1/upgradeESLint.js.map +0 -7
- package/lib/enquirer.d.js +0 -2
- package/lib/enquirer.d.js.map +0 -7
- package/lib/eslint.d.js +0 -2
- package/lib/eslint.d.js.map +0 -7
package/lib/utils/wait.js
CHANGED
|
@@ -18,20 +18,13 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var wait_exports = {};
|
|
20
20
|
__export(wait_exports, {
|
|
21
|
-
sleep: () => sleep,
|
|
22
21
|
throwOnTimeout: () => throwOnTimeout,
|
|
23
22
|
withTimeout: () => withTimeout
|
|
24
23
|
});
|
|
25
24
|
module.exports = __toCommonJS(wait_exports);
|
|
26
25
|
var import_error = require("./error.js");
|
|
27
26
|
var import_logging = require("./logging.js");
|
|
28
|
-
|
|
29
|
-
let timeout;
|
|
30
|
-
return Object.assign(
|
|
31
|
-
new Promise((resolve) => timeout = setTimeout(resolve, ms)),
|
|
32
|
-
{ clear: () => clearTimeout(timeout) }
|
|
33
|
-
);
|
|
34
|
-
};
|
|
27
|
+
var import_sleep = require("./sleep.js");
|
|
35
28
|
const throwOnTimeout = async (promise, { s }) => {
|
|
36
29
|
const result = await withTimeout(promise, { s });
|
|
37
30
|
if (!result.ok) {
|
|
@@ -40,7 +33,7 @@ const throwOnTimeout = async (promise, { s }) => {
|
|
|
40
33
|
return result.value;
|
|
41
34
|
};
|
|
42
35
|
const withTimeout = async (promise, { s }) => {
|
|
43
|
-
const timeout = sleep(s * 1e3);
|
|
36
|
+
const timeout = (0, import_sleep.sleep)(s * 1e3);
|
|
44
37
|
try {
|
|
45
38
|
return await Promise.race([
|
|
46
39
|
Promise.resolve(promise).then((value) => ({ ok: true, value })),
|
|
@@ -52,7 +45,6 @@ const withTimeout = async (promise, { s }) => {
|
|
|
52
45
|
};
|
|
53
46
|
// Annotate the CommonJS export names for ESM import in node:
|
|
54
47
|
0 && (module.exports = {
|
|
55
|
-
sleep,
|
|
56
48
|
throwOnTimeout,
|
|
57
49
|
withTimeout
|
|
58
50
|
});
|
package/lib/utils/wait.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/utils/wait.ts"],
|
|
4
|
-
"sourcesContent": ["import { createTerseError } from './error.js';\nimport { pluralise } from './logging.js';\
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA
|
|
4
|
+
"sourcesContent": ["import { createTerseError } from './error.js';\nimport { pluralise } from './logging.js';\nimport { sleep } from './sleep.js';\n\nexport const throwOnTimeout = async <T>(\n promise: PromiseLike<T>,\n { s }: { s: number },\n): Promise<T> => {\n const result = await withTimeout(promise, { s });\n\n if (!result.ok) {\n throw createTerseError(`Timed out after ${pluralise(s, 'second')}`);\n }\n\n return result.value;\n};\n\ntype TimeoutResult<T> = { ok: true; value: T } | { ok: false };\n\nexport const withTimeout = async <T>(\n promise: T | PromiseLike<T>,\n { s }: { s: number },\n): Promise<TimeoutResult<T>> => {\n const timeout = sleep(s * 1_000);\n\n try {\n return await Promise.race<TimeoutResult<T>>([\n Promise.resolve(promise).then((value) => ({ ok: true, value })),\n timeout.then(() => ({ ok: false })),\n ]);\n } finally {\n timeout.clear?.();\n }\n};\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAiC;AACjC,qBAA0B;AAC1B,mBAAsB;AAEf,MAAM,iBAAiB,OAC5B,SACA,EAAE,EAAE,MACW;AACf,QAAM,SAAS,MAAM,YAAY,SAAS,EAAE,EAAE,CAAC;AAE/C,MAAI,CAAC,OAAO,IAAI;AACd,cAAM,+BAAiB,uBAAmB,0BAAU,GAAG,QAAQ,CAAC,EAAE;AAAA,EACpE;AAEA,SAAO,OAAO;AAChB;AAIO,MAAM,cAAc,OACzB,SACA,EAAE,EAAE,MAC0B;AAC9B,QAAM,cAAU,oBAAM,IAAI,GAAK;AAE/B,MAAI;AACF,WAAO,MAAM,QAAQ,KAAuB;AAAA,MAC1C,QAAQ,QAAQ,OAAO,EAAE,KAAK,CAAC,WAAW,EAAE,IAAI,MAAM,MAAM,EAAE;AAAA,MAC9D,QAAQ,KAAK,OAAO,EAAE,IAAI,MAAM,EAAE;AAAA,IACpC,CAAC;AAAA,EACH,UAAE;AACA,YAAQ,QAAQ;AAAA,EAClB;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/lib/utils/worker.d.ts
CHANGED
|
@@ -12,9 +12,9 @@ export declare const postWorkerOutput: <Input, Output>(fn: (input: Input) => Pro
|
|
|
12
12
|
prefixes: unknown[];
|
|
13
13
|
suffixes: unknown[];
|
|
14
14
|
};
|
|
15
|
-
bold:
|
|
16
|
-
dim:
|
|
17
|
-
formatSubtle:
|
|
15
|
+
bold: (text: string) => string;
|
|
16
|
+
dim: (text: string) => string;
|
|
17
|
+
formatSubtle: (text: string) => string;
|
|
18
18
|
timing: (start: bigint, end: bigint) => string;
|
|
19
19
|
debug: (...message: unknown[]) => void;
|
|
20
20
|
subtle: (...message: unknown[]) => void;
|
package/lib/wrapper/http.d.ts
CHANGED
|
@@ -12,9 +12,3 @@ export declare const createRequestListenerFromFunction: (fn: (...args: unknown[]
|
|
|
12
12
|
* This function resolves when the server is closed.
|
|
13
13
|
*/
|
|
14
14
|
export declare const serveRequestListener: (requestListener: http.RequestListener, port?: number) => Promise<void>;
|
|
15
|
-
/**
|
|
16
|
-
* Returns a HTTP server wrapped in a promise
|
|
17
|
-
*
|
|
18
|
-
* This function resolves when the server is closed.
|
|
19
|
-
*/
|
|
20
|
-
export declare const startServer: (server: http.Server, port?: number) => Promise<void>;
|
package/lib/wrapper/http.js
CHANGED
|
@@ -29,13 +29,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
29
29
|
var http_exports = {};
|
|
30
30
|
__export(http_exports, {
|
|
31
31
|
createRequestListenerFromFunction: () => createRequestListenerFromFunction,
|
|
32
|
-
serveRequestListener: () => serveRequestListener
|
|
33
|
-
startServer: () => startServer
|
|
32
|
+
serveRequestListener: () => serveRequestListener
|
|
34
33
|
});
|
|
35
34
|
module.exports = __toCommonJS(http_exports);
|
|
36
35
|
var import_http = __toESM(require("http"));
|
|
37
36
|
var import_util = __toESM(require("util"));
|
|
38
|
-
var
|
|
37
|
+
var import_server = require("./server.js");
|
|
39
38
|
const createRequestListenerFromFunction = (fn) => async (req, res) => {
|
|
40
39
|
const writeResponse = (response) => new Promise(
|
|
41
40
|
(resolve, reject) => response === void 0 ? res.end(resolve) : res.write(
|
|
@@ -61,18 +60,11 @@ const createRequestListenerFromFunction = (fn) => async (req, res) => {
|
|
|
61
60
|
};
|
|
62
61
|
const serveRequestListener = (requestListener, port) => {
|
|
63
62
|
const server = import_http.default.createServer(requestListener);
|
|
64
|
-
return startServer(server, port);
|
|
63
|
+
return (0, import_server.startServer)(server, port);
|
|
65
64
|
};
|
|
66
|
-
const startServer = (server, port) => new Promise(
|
|
67
|
-
(resolve, reject) => server.listen(port).on("close", resolve).on("error", reject).on("listening", () => {
|
|
68
|
-
const address = server.address();
|
|
69
|
-
import_logging.log.ok("listening on port", import_logging.log.bold(address.port));
|
|
70
|
-
})
|
|
71
|
-
);
|
|
72
65
|
// Annotate the CommonJS export names for ESM import in node:
|
|
73
66
|
0 && (module.exports = {
|
|
74
67
|
createRequestListenerFromFunction,
|
|
75
|
-
serveRequestListener
|
|
76
|
-
startServer
|
|
68
|
+
serveRequestListener
|
|
77
69
|
});
|
|
78
70
|
//# sourceMappingURL=http.js.map
|
package/lib/wrapper/http.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/wrapper/http.ts"],
|
|
4
|
-
"sourcesContent": ["import http from 'http';\nimport
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA
|
|
4
|
+
"sourcesContent": ["import http from 'http';\nimport util from 'util';\n\nimport { startServer } from './server.js';\n\n/**\n * Create an HTTP request listener based on the supplied function.\n *\n * - The request body is JSON parsed and passed into the function as parameters.\n * - The function's return value is JSON stringified into the response body.\n */\nexport const createRequestListenerFromFunction =\n (fn: (...args: unknown[]) => Promise<unknown>): http.RequestListener =>\n async (req, res) => {\n const writeResponse = (response: unknown) =>\n new Promise<void>((resolve, reject) =>\n response === undefined\n ? res.end(resolve)\n : res.write(response, 'utf8', (err) =>\n err ? reject(err) : res.end(resolve),\n ),\n );\n\n try {\n const requestBody = await new Promise<string>((resolve, reject) => {\n const data: Buffer[] = [];\n\n req\n .on('data', (chunk: Buffer) => data.push(chunk))\n .on('end', () => resolve(Buffer.concat(data).toString()))\n .on('error', (err) => reject(err));\n });\n\n // Treat an empty body as no arguments\n const jsonRequest: unknown = requestBody ? JSON.parse(requestBody) : [];\n\n // Pass a non-array request body as the first parameter\n const args: unknown[] = Array.isArray(jsonRequest)\n ? jsonRequest\n : [jsonRequest];\n\n const response: unknown = await fn(...args);\n\n res.writeHead(200, { 'Content-Type': 'application/json' });\n\n await writeResponse(JSON.stringify(response, null, 2));\n } catch (err) {\n res.writeHead(500);\n\n await writeResponse(util.inspect(err));\n }\n };\n\n/**\n * Create a HTTP server based on the supplied `http.RequestListener`.\n *\n * This function resolves when the server is closed.\n */\nexport const serveRequestListener = (\n requestListener: http.RequestListener,\n port?: number,\n) => {\n const server = http.createServer(requestListener);\n return startServer(server, port);\n};\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAiB;AACjB,kBAAiB;AAEjB,oBAA4B;AAQrB,MAAM,oCACX,CAAC,OACD,OAAO,KAAK,QAAQ;AAClB,QAAM,gBAAgB,CAAC,aACrB,IAAI;AAAA,IAAc,CAAC,SAAS,WAC1B,aAAa,SACT,IAAI,IAAI,OAAO,IACf,IAAI;AAAA,MAAM;AAAA,MAAU;AAAA,MAAQ,CAAC,QAC3B,MAAM,OAAO,GAAG,IAAI,IAAI,IAAI,OAAO;AAAA,IACrC;AAAA,EACN;AAEF,MAAI;AACF,UAAM,cAAc,MAAM,IAAI,QAAgB,CAAC,SAAS,WAAW;AACjE,YAAM,OAAiB,CAAC;AAExB,UACG,GAAG,QAAQ,CAAC,UAAkB,KAAK,KAAK,KAAK,CAAC,EAC9C,GAAG,OAAO,MAAM,QAAQ,OAAO,OAAO,IAAI,EAAE,SAAS,CAAC,CAAC,EACvD,GAAG,SAAS,CAAC,QAAQ,OAAO,GAAG,CAAC;AAAA,IACrC,CAAC;AAGD,UAAM,cAAuB,cAAc,KAAK,MAAM,WAAW,IAAI,CAAC;AAGtE,UAAM,OAAkB,MAAM,QAAQ,WAAW,IAC7C,cACA,CAAC,WAAW;AAEhB,UAAM,WAAoB,MAAM,GAAG,GAAG,IAAI;AAE1C,QAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AAEzD,UAAM,cAAc,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAAA,EACvD,SAAS,KAAK;AACZ,QAAI,UAAU,GAAG;AAEjB,UAAM,cAAc,YAAAA,QAAK,QAAQ,GAAG,CAAC;AAAA,EACvC;AACF;AAOK,MAAM,uBAAuB,CAClC,iBACA,SACG;AACH,QAAM,SAAS,YAAAC,QAAK,aAAa,eAAe;AAChD,aAAO,2BAAY,QAAQ,IAAI;AACjC;",
|
|
6
6
|
"names": ["util", "http"]
|
|
7
7
|
}
|
|
@@ -34,6 +34,7 @@ module.exports = __toCommonJS(requestListener_exports);
|
|
|
34
34
|
var import_http = __toESM(require("http"));
|
|
35
35
|
var import_validation = require("../utils/validation.js");
|
|
36
36
|
var import_http2 = require("./http.js");
|
|
37
|
+
var import_server = require("./server.js");
|
|
37
38
|
const isConfig = (data) => (0, import_validation.isFunction)(data) || (0, import_validation.isObject)(data);
|
|
38
39
|
const runRequestListener = async ({
|
|
39
40
|
availablePort,
|
|
@@ -51,10 +52,10 @@ const runRequestListener = async ({
|
|
|
51
52
|
}
|
|
52
53
|
const port = (0, import_validation.isIpPort)(config.port) ? config.port : availablePort;
|
|
53
54
|
if (typeof config !== "function" && config instanceof import_http.default.Server) {
|
|
54
|
-
return (0,
|
|
55
|
+
return (0, import_server.startServer)(config, port);
|
|
55
56
|
}
|
|
56
57
|
if (typeof config !== "function" && config.server && config.server instanceof import_http.default.Server) {
|
|
57
|
-
return (0,
|
|
58
|
+
return (0, import_server.startServer)(config.server, port);
|
|
58
59
|
}
|
|
59
60
|
const requestListener = typeof config === "function" ? config : config.requestListener ?? config.callback?.();
|
|
60
61
|
if (typeof requestListener !== "function") {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/wrapper/requestListener.ts"],
|
|
4
|
-
"sourcesContent": ["import http from 'http';\n\nimport { isFunction, isIpPort, isObject } from '../utils/validation.js';\n\nimport { serveRequestListener
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAiB;AAEjB,wBAA+C;AAE/C,IAAAA,
|
|
4
|
+
"sourcesContent": ["import http from 'http';\n\nimport { isFunction, isIpPort, isObject } from '../utils/validation.js';\n\nimport { serveRequestListener } from './http.js';\nimport { startServer } from './server.js';\n\n// Express compatibility\ninterface FunctionConfig extends http.RequestListener {\n port?: number;\n}\n\ninterface ObjectConfig {\n // Koa compatibility\n callback?: () => http.RequestListener;\n\n requestListener?: http.RequestListener;\n\n // Fastify compatibility\n server?: http.Server;\n\n default?: Promise<unknown>;\n port?: unknown;\n}\n\nconst isConfig = (\n data: unknown,\n): data is Promise<FunctionConfig> | Promise<ObjectConfig> =>\n isFunction(data) || isObject(data);\n\ninterface Args {\n availablePort?: number;\n entryPoint: unknown;\n}\n\n/**\n * Create an HTTP server that calls into an exported `http.RequestListener`.\n *\n * This supports Express and Koa applications out of the box.\n */\nexport const runRequestListener = async ({\n availablePort,\n entryPoint,\n}: Args): Promise<void> => {\n if (!isConfig(entryPoint)) {\n // Assume an executable script with weird exports\n return;\n }\n\n let config: FunctionConfig | ObjectConfig = await entryPoint;\n\n if (typeof config === 'object' && isConfig(config.default)) {\n // Prefer `export default` over `export =`\n config = await config.default;\n }\n\n if (Object.keys(config).length === 0) {\n // Assume an executable script with no exports\n return;\n }\n\n const port = isIpPort(config.port) ? config.port : availablePort;\n\n // http.Server support\n if (typeof config !== 'function' && config instanceof http.Server) {\n return startServer(config, port);\n }\n\n // Fastify workaround\n if (\n typeof config !== 'function' &&\n config.server &&\n config.server instanceof http.Server\n ) {\n return startServer(config.server, port);\n }\n\n const requestListener =\n typeof config === 'function'\n ? config\n : (config.requestListener ?? config.callback?.());\n\n if (typeof requestListener !== 'function') {\n // Assume an executable script with non-request listener exports\n return;\n }\n\n return serveRequestListener(requestListener, port);\n};\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAiB;AAEjB,wBAA+C;AAE/C,IAAAA,eAAqC;AACrC,oBAA4B;AAoB5B,MAAM,WAAW,CACf,aAEA,8BAAW,IAAI,SAAK,4BAAS,IAAI;AAY5B,MAAM,qBAAqB,OAAO;AAAA,EACvC;AAAA,EACA;AACF,MAA2B;AACzB,MAAI,CAAC,SAAS,UAAU,GAAG;AAEzB;AAAA,EACF;AAEA,MAAI,SAAwC,MAAM;AAElD,MAAI,OAAO,WAAW,YAAY,SAAS,OAAO,OAAO,GAAG;AAE1D,aAAS,MAAM,OAAO;AAAA,EACxB;AAEA,MAAI,OAAO,KAAK,MAAM,EAAE,WAAW,GAAG;AAEpC;AAAA,EACF;AAEA,QAAM,WAAO,4BAAS,OAAO,IAAI,IAAI,OAAO,OAAO;AAGnD,MAAI,OAAO,WAAW,cAAc,kBAAkB,YAAAC,QAAK,QAAQ;AACjE,eAAO,2BAAY,QAAQ,IAAI;AAAA,EACjC;AAGA,MACE,OAAO,WAAW,cAClB,OAAO,UACP,OAAO,kBAAkB,YAAAA,QAAK,QAC9B;AACA,eAAO,2BAAY,OAAO,QAAQ,IAAI;AAAA,EACxC;AAEA,QAAM,kBACJ,OAAO,WAAW,aACd,SACC,OAAO,mBAAmB,OAAO,WAAW;AAEnD,MAAI,OAAO,oBAAoB,YAAY;AAEzC;AAAA,EACF;AAEA,aAAO,mCAAqB,iBAAiB,IAAI;AACnD;",
|
|
6
6
|
"names": ["import_http", "http"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var server_exports = {};
|
|
20
|
+
__export(server_exports, {
|
|
21
|
+
startServer: () => startServer
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(server_exports);
|
|
24
|
+
var import_logging = require("../utils/logging.js");
|
|
25
|
+
const startServer = (server, port) => new Promise(
|
|
26
|
+
(resolve, reject) => server.listen(port).on("close", resolve).on("error", reject).on("listening", () => {
|
|
27
|
+
const address = server.address();
|
|
28
|
+
import_logging.log.ok("listening on port", import_logging.log.bold(String(address.port)));
|
|
29
|
+
})
|
|
30
|
+
);
|
|
31
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
32
|
+
0 && (module.exports = {
|
|
33
|
+
startServer
|
|
34
|
+
});
|
|
35
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/wrapper/server.ts"],
|
|
4
|
+
"sourcesContent": ["import type http from 'http';\nimport type { AddressInfo } from 'net';\n\nimport { log } from '../utils/logging.js';\n\n/**\n * Returns a HTTP server wrapped in a promise\n *\n * This function resolves when the server is closed.\n */\nexport const startServer = (server: http.Server, port?: number) =>\n new Promise<void>((resolve, reject) =>\n server\n .listen(port)\n .on('close', resolve)\n .on('error', reject)\n .on('listening', () => {\n const address = server.address() as AddressInfo;\n\n log.ok('listening on port', log.bold(String(address.port)));\n }),\n );\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,qBAAoB;AAOb,MAAM,cAAc,CAAC,QAAqB,SAC/C,IAAI;AAAA,EAAc,CAAC,SAAS,WAC1B,OACG,OAAO,IAAI,EACX,GAAG,SAAS,OAAO,EACnB,GAAG,SAAS,MAAM,EAClB,GAAG,aAAa,MAAM;AACrB,UAAM,UAAU,OAAO,QAAQ;AAE/B,uBAAI,GAAG,qBAAqB,mBAAI,KAAK,OAAO,QAAQ,IAAI,CAAC,CAAC;AAAA,EAC5D,CAAC;AACL;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skuba",
|
|
3
|
-
"version": "13.0
|
|
3
|
+
"version": "13.1.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "SEEK development toolkit for backend applications and packages",
|
|
6
6
|
"homepage": "https://github.com/seek-oss/skuba#readme",
|
|
@@ -56,20 +56,18 @@
|
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
58
|
"@esbuild-plugins/tsconfig-paths": "^0.1.0",
|
|
59
|
-
"@
|
|
59
|
+
"@inquirer/prompts": "^7.9.0",
|
|
60
60
|
"@jest/types": "^30.0.0",
|
|
61
61
|
"@octokit/graphql": "^9.0.0",
|
|
62
62
|
"@octokit/graphql-schema": "^15.3.0",
|
|
63
63
|
"@octokit/rest": "^22.0.0",
|
|
64
|
-
"@octokit/types": "^
|
|
64
|
+
"@octokit/types": "^16.0.0",
|
|
65
65
|
"@types/jest": "^30.0.0",
|
|
66
66
|
"@types/node": "^22.0.0",
|
|
67
|
-
"chalk": "^4.1.0",
|
|
68
67
|
"concurrently": "^9.0.0",
|
|
69
68
|
"ejs": "^3.1.6",
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"eslint": "^9.11.1",
|
|
69
|
+
"esbuild": "~0.27.0",
|
|
70
|
+
"eslint": "^9.39.1",
|
|
73
71
|
"execa": "^5.0.0",
|
|
74
72
|
"fast-glob": "^3.3.2",
|
|
75
73
|
"find-up": "^5.0.0",
|
|
@@ -89,7 +87,7 @@
|
|
|
89
87
|
"npm-run-path": "^4.0.1",
|
|
90
88
|
"npm-which": "^3.0.1",
|
|
91
89
|
"picomatch": "^4.0.0",
|
|
92
|
-
"prettier": "~3.
|
|
90
|
+
"prettier": "~3.7.0",
|
|
93
91
|
"prettier-plugin-packagejson": "^2.4.10",
|
|
94
92
|
"read-pkg-up": "^7.0.1",
|
|
95
93
|
"semantic-release": "^24.2.3",
|
|
@@ -103,40 +101,40 @@
|
|
|
103
101
|
"typescript": "~5.9.0",
|
|
104
102
|
"zod": "^4.0.0",
|
|
105
103
|
"@skuba-lib/api": "^1.0.1",
|
|
106
|
-
"eslint-config-skuba": "7.2.
|
|
104
|
+
"eslint-config-skuba": "7.2.1"
|
|
107
105
|
},
|
|
108
106
|
"devDependencies": {
|
|
109
|
-
"@changesets/cli": "2.29.
|
|
110
|
-
"@changesets/get-github-info": "0.
|
|
107
|
+
"@changesets/cli": "2.29.8",
|
|
108
|
+
"@changesets/get-github-info": "0.7.0",
|
|
111
109
|
"@jest/reporters": "30.2.0",
|
|
112
110
|
"@jest/test-result": "30.2.0",
|
|
113
111
|
"@types/ejs": "3.1.5",
|
|
114
112
|
"@types/express": "5.0.3",
|
|
115
113
|
"@types/fs-extra": "11.0.4",
|
|
116
|
-
"@types/koa": "3.0.
|
|
114
|
+
"@types/koa": "3.0.1",
|
|
117
115
|
"@types/lodash.mergewith": "4.6.9",
|
|
118
116
|
"@types/minimist": "1.2.5",
|
|
119
117
|
"@types/module-alias": "2.0.4",
|
|
120
|
-
"@types/npm-registry-fetch": "8.0.
|
|
118
|
+
"@types/npm-registry-fetch": "8.0.9",
|
|
121
119
|
"@types/npm-which": "3.0.4",
|
|
122
120
|
"@types/picomatch": "4.0.2",
|
|
123
121
|
"@types/semver": "7.7.1",
|
|
124
122
|
"@types/supertest": "6.0.3",
|
|
125
123
|
"enhanced-resolve": "5.18.3",
|
|
126
124
|
"express": "5.1.0",
|
|
127
|
-
"fastify": "5.6.
|
|
125
|
+
"fastify": "5.6.2",
|
|
128
126
|
"jest-diff": "30.2.0",
|
|
129
127
|
"jsonfile": "6.2.0",
|
|
130
|
-
"koa": "3.
|
|
131
|
-
"memfs": "4.
|
|
128
|
+
"koa": "3.1.1",
|
|
129
|
+
"memfs": "4.51.0",
|
|
132
130
|
"remark-cli": "12.0.1",
|
|
133
131
|
"remark-preset-lint-recommended": "7.0.1",
|
|
134
|
-
"semver": "7.7.
|
|
132
|
+
"semver": "7.7.3",
|
|
135
133
|
"supertest": "7.1.4",
|
|
136
134
|
"type-fest": "2.19.0"
|
|
137
135
|
},
|
|
138
136
|
"peerDependencies": {
|
|
139
|
-
"skuba-dive": "1 || 2"
|
|
137
|
+
"skuba-dive": "1 || 2 || 3"
|
|
140
138
|
},
|
|
141
139
|
"peerDependenciesMeta": {
|
|
142
140
|
"skuba-dive": {
|
|
@@ -21,11 +21,11 @@
|
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@opentelemetry/api": "^1.9.0",
|
|
23
23
|
"@opentelemetry/core": "^2.0.0",
|
|
24
|
-
"@opentelemetry/exporter-trace-otlp-grpc": "^0.
|
|
25
|
-
"@opentelemetry/instrumentation-aws-sdk": "^0.
|
|
26
|
-
"@opentelemetry/instrumentation-http": "^0.
|
|
24
|
+
"@opentelemetry/exporter-trace-otlp-grpc": "^0.208.0",
|
|
25
|
+
"@opentelemetry/instrumentation-aws-sdk": "^0.64.0",
|
|
26
|
+
"@opentelemetry/instrumentation-http": "^0.208.0",
|
|
27
27
|
"@opentelemetry/propagator-b3": "^2.0.0",
|
|
28
|
-
"@opentelemetry/sdk-node": "^0.
|
|
28
|
+
"@opentelemetry/sdk-node": "^0.208.0",
|
|
29
29
|
"@seek/logger": "^11.1.0",
|
|
30
30
|
"express": "^5.0.0",
|
|
31
31
|
"hot-shots": "^11.0.0",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"skuba": "*",
|
|
41
41
|
"supertest": "^7.0.0"
|
|
42
42
|
},
|
|
43
|
-
"packageManager": "pnpm@10.
|
|
43
|
+
"packageManager": "pnpm@10.24.0",
|
|
44
44
|
"engines": {
|
|
45
45
|
"node": ">=22"
|
|
46
46
|
}
|
|
@@ -19,13 +19,13 @@
|
|
|
19
19
|
"test:watch": "skuba test --watch"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"skuba-dive": "^
|
|
22
|
+
"skuba-dive": "^3.0.0"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@types/node": "^22.13.10",
|
|
26
26
|
"skuba": "*"
|
|
27
27
|
},
|
|
28
|
-
"packageManager": "pnpm@10.
|
|
28
|
+
"packageManager": "pnpm@10.24.0",
|
|
29
29
|
"engines": {
|
|
30
30
|
"node": ">=22"
|
|
31
31
|
}
|
|
@@ -23,11 +23,11 @@
|
|
|
23
23
|
"@koa/router": "^14.0.0",
|
|
24
24
|
"@opentelemetry/api": "^1.9.0",
|
|
25
25
|
"@opentelemetry/core": "^2.0.0",
|
|
26
|
-
"@opentelemetry/exporter-trace-otlp-grpc": "^0.
|
|
27
|
-
"@opentelemetry/instrumentation-aws-sdk": "^0.
|
|
28
|
-
"@opentelemetry/instrumentation-http": "^0.
|
|
26
|
+
"@opentelemetry/exporter-trace-otlp-grpc": "^0.208.0",
|
|
27
|
+
"@opentelemetry/instrumentation-aws-sdk": "^0.64.0",
|
|
28
|
+
"@opentelemetry/instrumentation-http": "^0.208.0",
|
|
29
29
|
"@opentelemetry/propagator-b3": "^2.0.0",
|
|
30
|
-
"@opentelemetry/sdk-node": "^0.
|
|
30
|
+
"@opentelemetry/sdk-node": "^0.208.0",
|
|
31
31
|
"@seek/logger": "^11.1.0",
|
|
32
32
|
"hot-shots": "^11.0.0",
|
|
33
33
|
"koa": "^3.0.1",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"skuba": "*",
|
|
50
50
|
"supertest": "^7.0.0"
|
|
51
51
|
},
|
|
52
|
-
"packageManager": "pnpm@10.
|
|
52
|
+
"packageManager": "pnpm@10.24.0",
|
|
53
53
|
"engines": {
|
|
54
54
|
"node": ">=22"
|
|
55
55
|
}
|
|
@@ -23,7 +23,7 @@ configs:
|
|
|
23
23
|
concurrency: 1
|
|
24
24
|
plugins:
|
|
25
25
|
- *docker-ecr-cache
|
|
26
|
-
- docker-compose#v5.
|
|
26
|
+
- docker-compose#v5.12.1:
|
|
27
27
|
dependencies: false
|
|
28
28
|
environment:
|
|
29
29
|
- GITHUB_API_TOKEN
|
|
@@ -53,7 +53,7 @@ steps:
|
|
|
53
53
|
GET_NPM_TOKEN: please
|
|
54
54
|
plugins:
|
|
55
55
|
- *docker-ecr-cache
|
|
56
|
-
- docker-compose#v5.
|
|
56
|
+
- docker-compose#v5.12.1:
|
|
57
57
|
run: app
|
|
58
58
|
environment:
|
|
59
59
|
- GITHUB_API_TOKEN
|
|
@@ -184,7 +184,6 @@ exports[`returns expected CloudFormation stack for dev 1`] = `
|
|
|
184
184
|
"DD_LAMBDA_HANDLER": "index.handler",
|
|
185
185
|
"DD_LOGS_INJECTION": "false",
|
|
186
186
|
"DD_MERGE_XRAY_TRACES": "false",
|
|
187
|
-
"DD_SERVERLESS_APPSEC_ENABLED": "false",
|
|
188
187
|
"DD_SERVERLESS_LOGS_ENABLED": "false",
|
|
189
188
|
"DD_SERVICE": "serviceName",
|
|
190
189
|
"DD_SITE": "datadoghq.com",
|
|
@@ -920,14 +919,13 @@ exports[`returns expected CloudFormation stack for prod 1`] = `
|
|
|
920
919
|
},
|
|
921
920
|
"Environment": {
|
|
922
921
|
"Variables": {
|
|
923
|
-
"DD_API_KEY_SECRET_ARN": "arn:aws:secretsmanager:<Region>:<AccountId>:secret:
|
|
922
|
+
"DD_API_KEY_SECRET_ARN": "arn:aws:secretsmanager:<Region>:<AccountId>:secret:datadog-api-key",
|
|
924
923
|
"DD_CAPTURE_LAMBDA_PAYLOAD": "false",
|
|
925
924
|
"DD_ENV": "production",
|
|
926
925
|
"DD_FLUSH_TO_LOG": "false",
|
|
927
926
|
"DD_LAMBDA_HANDLER": "index.handler",
|
|
928
927
|
"DD_LOGS_INJECTION": "false",
|
|
929
928
|
"DD_MERGE_XRAY_TRACES": "false",
|
|
930
|
-
"DD_SERVERLESS_APPSEC_ENABLED": "false",
|
|
931
929
|
"DD_SERVERLESS_LOGS_ENABLED": "false",
|
|
932
930
|
"DD_SERVICE": "serviceName",
|
|
933
931
|
"DD_SITE": "datadoghq.com",
|
|
@@ -1384,7 +1382,7 @@ exports[`returns expected CloudFormation stack for prod 1`] = `
|
|
|
1384
1382
|
"secretsmanager:DescribeSecret",
|
|
1385
1383
|
],
|
|
1386
1384
|
"Effect": "Allow",
|
|
1387
|
-
"Resource": "arn:aws:secretsmanager:<Region>:<AccountId>:secret:
|
|
1385
|
+
"Resource": "arn:aws:secretsmanager:<Region>:<AccountId>:secret:datadog-api-key-??????",
|
|
1388
1386
|
},
|
|
1389
1387
|
{
|
|
1390
1388
|
"Action": [
|
|
@@ -19,7 +19,7 @@ import { DatadogLambda } from 'datadog-cdk-constructs-v2';
|
|
|
19
19
|
import { config } from './config.js';
|
|
20
20
|
|
|
21
21
|
// Updated by https://github.com/seek-oss/rynovate
|
|
22
|
-
const DATADOG_EXTENSION_LAYER_VERSION =
|
|
22
|
+
const DATADOG_EXTENSION_LAYER_VERSION = 90;
|
|
23
23
|
|
|
24
24
|
// Updated by https://github.com/seek-oss/rynovate
|
|
25
25
|
const DATADOG_NODE_LAYER_VERSION = 126;
|
|
@@ -40,8 +40,7 @@ const configs: Record<Deployment, Config> = {
|
|
|
40
40
|
},
|
|
41
41
|
},
|
|
42
42
|
|
|
43
|
-
datadogApiKeySecretArn:
|
|
44
|
-
'arn:aws:secretsmanager:<Region>:<AccountId>:secret:TODO_SECRET_NAME',
|
|
43
|
+
datadogApiKeySecretArn: '<%- devDataDogApiKeySecretArn %>',
|
|
45
44
|
sourceSnsTopicArn: 'TODO: sourceSnsTopicArn',
|
|
46
45
|
},
|
|
47
46
|
prod: {
|
|
@@ -57,8 +56,7 @@ const configs: Record<Deployment, Config> = {
|
|
|
57
56
|
},
|
|
58
57
|
},
|
|
59
58
|
|
|
60
|
-
datadogApiKeySecretArn:
|
|
61
|
-
'arn:aws:secretsmanager:<Region>:<AccountId>:secret:TODO_SECRET_NAME',
|
|
59
|
+
datadogApiKeySecretArn: '<%- prodDataDogApiKeySecretArn %>',
|
|
62
60
|
sourceSnsTopicArn: 'TODO: sourceSnsTopicArn',
|
|
63
61
|
},
|
|
64
62
|
};
|
|
@@ -20,10 +20,11 @@
|
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"@aws-sdk/client-codedeploy": "^3.363.0",
|
|
22
22
|
"@aws-sdk/client-lambda": "^3.363.0",
|
|
23
|
+
"@aws-sdk/client-secrets-manager": "^3.363.0",
|
|
23
24
|
"@aws-sdk/client-sns": "^3.363.0",
|
|
24
25
|
"@seek/aws-codedeploy-hooks": "^2.0.0",
|
|
25
26
|
"@seek/logger": "^11.1.0",
|
|
26
|
-
"skuba-dive": "^
|
|
27
|
+
"skuba-dive": "^3.0.0",
|
|
27
28
|
"zod": "^4.0.0"
|
|
28
29
|
},
|
|
29
30
|
"devDependencies": {
|
|
@@ -43,7 +44,7 @@
|
|
|
43
44
|
"pino-pretty": "^13.0.0",
|
|
44
45
|
"skuba": "*"
|
|
45
46
|
},
|
|
46
|
-
"packageManager": "pnpm@10.
|
|
47
|
+
"packageManager": "pnpm@10.24.0",
|
|
47
48
|
"engines": {
|
|
48
49
|
"node": ">=22"
|
|
49
50
|
}
|
|
@@ -22,6 +22,18 @@ module.exports = {
|
|
|
22
22
|
initial: 'my-team-aws-account-prod:cicd',
|
|
23
23
|
validate: (value) => /^.+:.+$/.test(value),
|
|
24
24
|
},
|
|
25
|
+
{
|
|
26
|
+
name: 'devDataDogApiKeySecretArn',
|
|
27
|
+
message: 'Dev DataDog API Key Secret ARN',
|
|
28
|
+
initial:
|
|
29
|
+
'arn:aws:secretsmanager:<Region>:<AccountId>:secret:datadog-api-key',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: 'prodDataDogApiKeySecretArn',
|
|
33
|
+
message: 'Prod DataDog API Key Secret ARN',
|
|
34
|
+
initial:
|
|
35
|
+
'arn:aws:secretsmanager:<Region>:<AccountId>:secret:datadog-api-key',
|
|
36
|
+
},
|
|
25
37
|
],
|
|
26
38
|
packageManager: 'pnpm',
|
|
27
39
|
type: 'application',
|
|
@@ -18,7 +18,7 @@ jobs:
|
|
|
18
18
|
timeout-minutes: 20
|
|
19
19
|
steps:
|
|
20
20
|
- name: Check out repo
|
|
21
|
-
uses: actions/checkout@
|
|
21
|
+
uses: actions/checkout@v6
|
|
22
22
|
with:
|
|
23
23
|
fetch-depth: 0
|
|
24
24
|
|
|
@@ -26,7 +26,7 @@ jobs:
|
|
|
26
26
|
uses: pnpm/action-setup@v4
|
|
27
27
|
|
|
28
28
|
- name: Set up Node.js
|
|
29
|
-
uses: actions/setup-node@
|
|
29
|
+
uses: actions/setup-node@v6
|
|
30
30
|
with:
|
|
31
31
|
node-version-file: .nvmrc
|
|
32
32
|
|