skuba 10.2.0-config-20250421023131 → 11.0.0-feat-npmrc-to-workspace-20250511013825
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/README.md +0 -3
- package/lib/api/github/issueComment.d.ts +4 -2
- package/lib/api/github/issueComment.js +13 -0
- package/lib/api/github/issueComment.js.map +2 -2
- package/lib/cli/build/assets.js +3 -9
- package/lib/cli/build/assets.js.map +2 -2
- package/lib/cli/configure/processing/configFile.d.ts +2 -2
- package/lib/cli/configure/processing/configFile.js +18 -21
- package/lib/cli/configure/processing/configFile.js.map +2 -2
- package/lib/cli/lint/internalLints/detectBadCodeowners.js +1 -2
- package/lib/cli/lint/internalLints/detectBadCodeowners.js.map +2 -2
- package/lib/cli/lint/internalLints/refreshConfigFiles.d.ts +6 -2
- package/lib/cli/lint/internalLints/refreshConfigFiles.js +26 -22
- package/lib/cli/lint/internalLints/refreshConfigFiles.js.map +3 -3
- package/lib/cli/lint/internalLints/upgrade/patches/10.1.0/index.js +5 -0
- package/lib/cli/lint/internalLints/upgrade/patches/10.1.0/index.js.map +2 -2
- package/lib/cli/lint/internalLints/upgrade/patches/10.1.0/migrateNpmrcToPnpmWorkspace.d.ts +2 -0
- package/lib/cli/lint/internalLints/upgrade/patches/10.1.0/migrateNpmrcToPnpmWorkspace.js +167 -0
- package/lib/cli/lint/internalLints/upgrade/patches/10.1.0/migrateNpmrcToPnpmWorkspace.js.map +7 -0
- package/lib/cli/lint/internalLints/upgrade/patches/7.3.1/index.js +0 -9
- package/lib/cli/lint/internalLints/upgrade/patches/7.3.1/index.js.map +2 -2
- package/lib/cli/test/index.js +1 -0
- package/lib/cli/test/index.js.map +2 -2
- package/lib/index.d.ts +0 -1
- package/lib/index.js +2 -5
- package/lib/index.js.map +2 -2
- package/lib/utils/copy.js +1 -1
- package/lib/utils/copy.js.map +2 -2
- package/lib/utils/dir.d.ts +10 -0
- package/lib/utils/dir.js +74 -2
- package/lib/utils/dir.js.map +3 -3
- package/lib/utils/npmrc.d.ts +0 -1
- package/lib/utils/npmrc.js +0 -3
- package/lib/utils/npmrc.js.map +2 -2
- package/package.json +12 -12
- package/template/base/_.gitignore +2 -0
- package/template/base/_pnpm-workspace.yaml +10 -0
- package/template/express-rest-api/.buildkite/pipeline.yml +9 -18
- package/template/express-rest-api/Dockerfile.dev-deps +4 -3
- package/template/express-rest-api/package.json +1 -1
- package/template/greeter/.buildkite/pipeline.yml +5 -14
- package/template/greeter/Dockerfile +4 -3
- package/template/greeter/package.json +2 -2
- package/template/koa-rest-api/.buildkite/pipeline.yml +9 -18
- package/template/koa-rest-api/Dockerfile.dev-deps +4 -3
- package/template/koa-rest-api/package.json +1 -1
- package/template/lambda-sqs-worker-cdk/.buildkite/pipeline.yml +9 -18
- package/template/lambda-sqs-worker-cdk/Dockerfile +4 -3
- package/template/lambda-sqs-worker-cdk/infra/appStack.ts +7 -0
- package/template/lambda-sqs-worker-cdk/package.json +3 -2
- package/template/lambda-sqs-worker-cdk/src/app.ts +10 -3
- package/template/lambda-sqs-worker-cdk/src/framework/handler.ts +5 -8
- package/template/oss-npm-package/_package.json +2 -2
- package/template/private-npm-package/_package.json +1 -1
- package/lib/cli/lint/internalLints/upgrade/patches/7.3.1/moveNpmrcOutOfIgnoreManagedSection.d.ts +0 -2
- package/lib/cli/lint/internalLints/upgrade/patches/7.3.1/moveNpmrcOutOfIgnoreManagedSection.js +0 -95
- package/lib/cli/lint/internalLints/upgrade/patches/7.3.1/moveNpmrcOutOfIgnoreManagedSection.js.map +0 -7
- package/lib/config/load.d.ts +0 -2
- package/lib/config/load.js +0 -75
- package/lib/config/load.js.map +0 -7
- package/lib/config/types.d.ts +0 -51
- package/lib/config/types.js +0 -74
- package/lib/config/types.js.map +0 -7
- package/template/base/_.npmrc +0 -9
package/README.md
CHANGED
|
@@ -2,9 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
[](https://github.com/seek-oss/skuba/actions?query=workflow%3ARelease)
|
|
6
|
-
[](https://github.com/seek-oss/skuba/actions?query=workflow%3AValidate)
|
|
7
|
-
[](https://nodejs.org/en/)
|
|
8
5
|
[](https://www.npmjs.com/package/skuba)
|
|
9
6
|
|
|
10
7
|
---
|
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
interface PutIssueCommentParameters {
|
|
5
5
|
/**
|
|
6
6
|
* The body of the issue comment.
|
|
7
|
+
*
|
|
8
|
+
* An explicit `null` value will remove the comment, if `internalId` is provided.
|
|
7
9
|
*/
|
|
8
|
-
body: string;
|
|
10
|
+
body: string | null;
|
|
9
11
|
/**
|
|
10
12
|
* An internal identifier for the issue comment.
|
|
11
13
|
*
|
|
@@ -55,5 +57,5 @@ interface IssueComment {
|
|
|
55
57
|
* A `GITHUB_API_TOKEN` or `GITHUB_TOKEN` with write permissions must be present
|
|
56
58
|
* on the environment.
|
|
57
59
|
*/
|
|
58
|
-
export declare const putIssueComment: (params: PutIssueCommentParameters) => Promise<IssueComment>;
|
|
60
|
+
export declare const putIssueComment: (params: PutIssueCommentParameters) => Promise<IssueComment | null>;
|
|
59
61
|
export {};
|
|
@@ -40,6 +40,9 @@ const getUserId = async (client) => {
|
|
|
40
40
|
return data.id;
|
|
41
41
|
};
|
|
42
42
|
const putIssueComment = async (params) => {
|
|
43
|
+
if (params.body === null && !params.internalId) {
|
|
44
|
+
throw new Error("Cannot remove comment without an internalId");
|
|
45
|
+
}
|
|
43
46
|
const env = params.env ?? process.env;
|
|
44
47
|
const dir = process.cwd();
|
|
45
48
|
const { owner, repo } = await Git.getOwnerAndRepo({ dir });
|
|
@@ -62,6 +65,16 @@ const putIssueComment = async (params) => {
|
|
|
62
65
|
|
|
63
66
|
<!-- ${params.internalId} -->`) : true)
|
|
64
67
|
)?.id;
|
|
68
|
+
if (params.body === null) {
|
|
69
|
+
if (commentId) {
|
|
70
|
+
await client.issues.deleteComment({
|
|
71
|
+
comment_id: commentId,
|
|
72
|
+
owner,
|
|
73
|
+
repo
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
65
78
|
const body = params.internalId ? [params.body.trim(), `<!-- ${params.internalId} -->`].join("\n\n") : params.body.trim();
|
|
66
79
|
const response = await (commentId ? client.issues.updateComment({
|
|
67
80
|
body,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/api/github/issueComment.ts"],
|
|
4
|
-
"sourcesContent": ["import type { Octokit } from '@octokit/rest';\n\nimport * as Git from '../git';\n\nimport { apiTokenFromEnvironment } from './environment';\nimport { createRestClient } from './octokit';\nimport { getPullRequestNumber } from './pullRequest';\n\nconst getUserId = async (client: Octokit): Promise<number> => {\n const { data } = await client.users.getAuthenticated();\n\n return data.id;\n};\n\n/**\n * https://docs.github.com/en/rest/reference/issues#create-an-issue-comment\n */\ninterface PutIssueCommentParameters {\n /**\n * The body of the issue comment.\n */\n body: string;\n\n /**\n * An internal identifier for the issue comment.\n *\n * This can be used to scope a given `put` to a particular comment, preventing\n * it from clobbering other comments from the same bot or user.\n *\n * The identifier is embedded as hidden content in the comment body.\n */\n internalId?: string;\n\n env?: Record<string, string | undefined>;\n\n /**\n * The number that identifies the GitHub issue.\n *\n * If this is not provided, the number will be inferred from the GitHub Repos\n * API by finding the latest pull request associated with the head commit.\n *\n * https://docs.github.com/en/rest/reference/repos#list-pull-requests-associated-with-a-commit\n */\n issueNumber?: number;\n\n /**\n * The ID of authenticated bot or user that is putting the issue comment.\n *\n * This drives our `put` behaviour, which tries to locate and edit an existing\n * comment before creating a new one. If this is not provided, the ID will be\n * inferred from the GitHub Users API.\n *\n * https://docs.github.com/en/rest/reference/users#get-the-authenticated-user\n *\n * If you're at SEEK and using BuildAgency's GitHub API integration, you may\n * use `'seek-build-agency'` as an optimisation to skip the user lookup.\n *\n * https://api.github.com/users/buildagencygitapitoken[bot]\n */\n userId?: number | 'seek-build-agency';\n}\n\ninterface IssueComment {\n id: number;\n}\n\n/**\n * Asynchronously creates or updates a GitHub issue comment.\n *\n * This emulates `put` behaviour by overwriting the first existing comment by\n * the same author on the issue, enabling use cases like a persistent bot\n * comment at the top of the pull request that reflects the current status of a\n * CI check.\n *\n * A `GITHUB_API_TOKEN` or `GITHUB_TOKEN` with write permissions must be present\n * on the environment.\n */\nexport const putIssueComment = async (\n params: PutIssueCommentParameters,\n): Promise<IssueComment> => {\n const env = params.env ?? process.env;\n\n const dir = process.cwd();\n\n const { owner, repo } = await Git.getOwnerAndRepo({ dir });\n\n const client = await createRestClient({ auth: apiTokenFromEnvironment() });\n\n const issueNumber =\n params.issueNumber ?? (await getPullRequestNumber({ client, env }));\n\n if (!issueNumber) {\n throw new Error('Failed to infer an issue number');\n }\n\n const comments = await client.issues.listComments({\n issue_number: issueNumber,\n owner,\n repo,\n });\n\n const userId: number =\n params.userId === 'seek-build-agency'\n ? // https://api.github.com/users/buildagencygitapitoken[bot]\n 87109344\n : (params.userId ?? (await getUserId(client)));\n\n const commentId = comments.data.find(\n (comment) =>\n comment.user?.id === userId &&\n (params.internalId\n ? comment.body?.endsWith(`\\n\\n<!-- ${params.internalId} -->`)\n : true),\n )?.id;\n\n const body = params.internalId\n ? [params.body.trim(), `<!-- ${params.internalId} -->`].join('\\n\\n')\n : params.body.trim();\n\n const response = await (commentId\n ? client.issues.updateComment({\n body,\n comment_id: commentId,\n issue_number: issueNumber,\n owner,\n repo,\n })\n : client.issues.createComment({\n body,\n issue_number: issueNumber,\n owner,\n repo,\n }));\n\n return {\n id: response.data.id,\n };\n};\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,UAAqB;AAErB,yBAAwC;AACxC,qBAAiC;AACjC,yBAAqC;AAErC,MAAM,YAAY,OAAO,WAAqC;AAC5D,QAAM,EAAE,KAAK,IAAI,MAAM,OAAO,MAAM,iBAAiB;AAErD,SAAO,KAAK;AACd;
|
|
4
|
+
"sourcesContent": ["import type { Octokit } from '@octokit/rest';\n\nimport * as Git from '../git';\n\nimport { apiTokenFromEnvironment } from './environment';\nimport { createRestClient } from './octokit';\nimport { getPullRequestNumber } from './pullRequest';\n\nconst getUserId = async (client: Octokit): Promise<number> => {\n const { data } = await client.users.getAuthenticated();\n\n return data.id;\n};\n\n/**\n * https://docs.github.com/en/rest/reference/issues#create-an-issue-comment\n */\ninterface PutIssueCommentParameters {\n /**\n * The body of the issue comment.\n *\n * An explicit `null` value will remove the comment, if `internalId` is provided.\n */\n body: string | null;\n\n /**\n * An internal identifier for the issue comment.\n *\n * This can be used to scope a given `put` to a particular comment, preventing\n * it from clobbering other comments from the same bot or user.\n *\n * The identifier is embedded as hidden content in the comment body.\n */\n internalId?: string;\n\n env?: Record<string, string | undefined>;\n\n /**\n * The number that identifies the GitHub issue.\n *\n * If this is not provided, the number will be inferred from the GitHub Repos\n * API by finding the latest pull request associated with the head commit.\n *\n * https://docs.github.com/en/rest/reference/repos#list-pull-requests-associated-with-a-commit\n */\n issueNumber?: number;\n\n /**\n * The ID of authenticated bot or user that is putting the issue comment.\n *\n * This drives our `put` behaviour, which tries to locate and edit an existing\n * comment before creating a new one. If this is not provided, the ID will be\n * inferred from the GitHub Users API.\n *\n * https://docs.github.com/en/rest/reference/users#get-the-authenticated-user\n *\n * If you're at SEEK and using BuildAgency's GitHub API integration, you may\n * use `'seek-build-agency'` as an optimisation to skip the user lookup.\n *\n * https://api.github.com/users/buildagencygitapitoken[bot]\n */\n userId?: number | 'seek-build-agency';\n}\n\ninterface IssueComment {\n id: number;\n}\n\n/**\n * Asynchronously creates or updates a GitHub issue comment.\n *\n * This emulates `put` behaviour by overwriting the first existing comment by\n * the same author on the issue, enabling use cases like a persistent bot\n * comment at the top of the pull request that reflects the current status of a\n * CI check.\n *\n * A `GITHUB_API_TOKEN` or `GITHUB_TOKEN` with write permissions must be present\n * on the environment.\n */\nexport const putIssueComment = async (\n params: PutIssueCommentParameters,\n): Promise<IssueComment | null> => {\n if (params.body === null && !params.internalId) {\n // It's dangerous to just delete the first comment, as it may not be\n // from the current flow.\n throw new Error('Cannot remove comment without an internalId');\n }\n\n const env = params.env ?? process.env;\n\n const dir = process.cwd();\n\n const { owner, repo } = await Git.getOwnerAndRepo({ dir });\n\n const client = await createRestClient({ auth: apiTokenFromEnvironment() });\n\n const issueNumber =\n params.issueNumber ?? (await getPullRequestNumber({ client, env }));\n\n if (!issueNumber) {\n throw new Error('Failed to infer an issue number');\n }\n\n const comments = await client.issues.listComments({\n issue_number: issueNumber,\n owner,\n repo,\n });\n\n const userId: number =\n params.userId === 'seek-build-agency'\n ? // https://api.github.com/users/buildagencygitapitoken[bot]\n 87109344\n : (params.userId ?? (await getUserId(client)));\n\n const commentId = comments.data.find(\n (comment) =>\n comment.user?.id === userId &&\n (params.internalId\n ? comment.body?.endsWith(`\\n\\n<!-- ${params.internalId} -->`)\n : true),\n )?.id;\n\n if (params.body === null) {\n if (commentId) {\n await client.issues.deleteComment({\n comment_id: commentId,\n owner,\n repo,\n });\n }\n\n return null;\n }\n\n const body = params.internalId\n ? [params.body.trim(), `<!-- ${params.internalId} -->`].join('\\n\\n')\n : params.body.trim();\n\n const response = await (commentId\n ? client.issues.updateComment({\n body,\n comment_id: commentId,\n issue_number: issueNumber,\n owner,\n repo,\n })\n : client.issues.createComment({\n body,\n issue_number: issueNumber,\n owner,\n repo,\n }));\n\n return {\n id: response.data.id,\n };\n};\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,UAAqB;AAErB,yBAAwC;AACxC,qBAAiC;AACjC,yBAAqC;AAErC,MAAM,YAAY,OAAO,WAAqC;AAC5D,QAAM,EAAE,KAAK,IAAI,MAAM,OAAO,MAAM,iBAAiB;AAErD,SAAO,KAAK;AACd;AAmEO,MAAM,kBAAkB,OAC7B,WACiC;AACjC,MAAI,OAAO,SAAS,QAAQ,CAAC,OAAO,YAAY;AAG9C,UAAM,IAAI,MAAM,6CAA6C;AAAA,EAC/D;AAEA,QAAM,MAAM,OAAO,OAAO,QAAQ;AAElC,QAAM,MAAM,QAAQ,IAAI;AAExB,QAAM,EAAE,OAAO,KAAK,IAAI,MAAM,IAAI,gBAAgB,EAAE,IAAI,CAAC;AAEzD,QAAM,SAAS,UAAM,iCAAiB,EAAE,UAAM,4CAAwB,EAAE,CAAC;AAEzE,QAAM,cACJ,OAAO,eAAgB,UAAM,yCAAqB,EAAE,QAAQ,IAAI,CAAC;AAEnE,MAAI,CAAC,aAAa;AAChB,UAAM,IAAI,MAAM,iCAAiC;AAAA,EACnD;AAEA,QAAM,WAAW,MAAM,OAAO,OAAO,aAAa;AAAA,IAChD,cAAc;AAAA,IACd;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,SACJ,OAAO,WAAW;AAAA;AAAA,IAEd;AAAA,MACC,OAAO,UAAW,MAAM,UAAU,MAAM;AAE/C,QAAM,YAAY,SAAS,KAAK;AAAA,IAC9B,CAAC,YACC,QAAQ,MAAM,OAAO,WACpB,OAAO,aACJ,QAAQ,MAAM,SAAS;AAAA;AAAA,OAAY,OAAO,UAAU,MAAM,IAC1D;AAAA,EACR,GAAG;AAEH,MAAI,OAAO,SAAS,MAAM;AACxB,QAAI,WAAW;AACb,YAAM,OAAO,OAAO,cAAc;AAAA,QAChC,YAAY;AAAA,QACZ;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,OAAO,aAChB,CAAC,OAAO,KAAK,KAAK,GAAG,QAAQ,OAAO,UAAU,MAAM,EAAE,KAAK,MAAM,IACjE,OAAO,KAAK,KAAK;AAErB,QAAM,WAAW,OAAO,YACpB,OAAO,OAAO,cAAc;AAAA,IAC1B;AAAA,IACA,YAAY;AAAA,IACZ,cAAc;AAAA,IACd;AAAA,IACA;AAAA,EACF,CAAC,IACD,OAAO,OAAO,cAAc;AAAA,IAC1B;AAAA,IACA,cAAc;AAAA,IACd;AAAA,IACA;AAAA,EACF,CAAC;AAEL,SAAO;AAAA,IACL,IAAI,SAAS,KAAK;AAAA,EACpB;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/lib/cli/build/assets.js
CHANGED
|
@@ -35,8 +35,6 @@ module.exports = __toCommonJS(assets_exports);
|
|
|
35
35
|
var import_path = __toESM(require("path"));
|
|
36
36
|
var import_chalk = __toESM(require("chalk"));
|
|
37
37
|
var import_fs_extra = __toESM(require("fs-extra"));
|
|
38
|
-
var import_load = require("../../config/load");
|
|
39
|
-
var import_types = require("../../config/types");
|
|
40
38
|
var import_copy = require("../../utils/copy");
|
|
41
39
|
var import_dir = require("../../utils/dir");
|
|
42
40
|
var import_logging = require("../../utils/logging");
|
|
@@ -44,17 +42,13 @@ var import_manifest = require("../../utils/manifest");
|
|
|
44
42
|
const copyAssets = async (destinationDir, logger = import_logging.log) => {
|
|
45
43
|
const manifest = await (0, import_manifest.getConsumerManifest)();
|
|
46
44
|
if (!manifest) {
|
|
47
|
-
logger.err(
|
|
48
|
-
"Could not find a package.json file in/above the current directory."
|
|
49
|
-
);
|
|
50
45
|
return;
|
|
51
46
|
}
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
if (!assets.length) {
|
|
47
|
+
const assets = await (0, import_manifest.getPropFromConsumerManifest)("assets");
|
|
48
|
+
if (!assets) {
|
|
55
49
|
return;
|
|
56
50
|
}
|
|
57
|
-
const entryPoint =
|
|
51
|
+
const entryPoint = await (0, import_manifest.getEntryPointFromManifest)();
|
|
58
52
|
if (!entryPoint) {
|
|
59
53
|
return;
|
|
60
54
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/cli/build/assets.ts"],
|
|
4
|
-
"sourcesContent": ["import path from 'path';\n\nimport chalk, { type Color } from 'chalk';\nimport fs from 'fs-extra';\n\nimport {
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAiB;AAEjB,mBAAkC;AAClC,sBAAe;AAEf,
|
|
4
|
+
"sourcesContent": ["import path from 'path';\n\nimport chalk, { type Color } from 'chalk';\nimport fs from 'fs-extra';\n\nimport { copyFile } from '../../utils/copy';\nimport { buildPatternToFilepathMap, crawlDirectory } from '../../utils/dir';\nimport { type Logger, createLogger, log } from '../../utils/logging';\nimport {\n getConsumerManifest,\n getEntryPointFromManifest,\n getPropFromConsumerManifest,\n} from '../../utils/manifest';\n\nexport const copyAssets = async (\n destinationDir: string,\n logger: Logger = log,\n) => {\n const manifest = await getConsumerManifest();\n if (!manifest) {\n return;\n }\n\n const assets = await getPropFromConsumerManifest<string, string[]>('assets');\n if (!assets) {\n return;\n }\n\n const entryPoint = await getEntryPointFromManifest();\n if (!entryPoint) {\n return;\n }\n\n const pathSegments = entryPoint.split(path.sep);\n const srcDir = (pathSegments.length > 1 && pathSegments[0]) || '';\n const resolvedSrcDir = path.resolve(path.dirname(manifest.path), srcDir);\n const resolvedDestinationDir = path.resolve(\n path.dirname(manifest.path),\n destinationDir,\n );\n\n const allFiles = await crawlDirectory(resolvedSrcDir);\n const filesByPattern = buildPatternToFilepathMap(assets, allFiles, {\n cwd: resolvedSrcDir,\n dot: true,\n });\n const matchedFiles = Array.from(\n new Set(Object.values(filesByPattern).flat()),\n );\n\n await Promise.all(\n matchedFiles.map(async (filename) => {\n logger.subtle(`Copying ${filename}`);\n\n await fs.promises.mkdir(\n path.dirname(path.join(resolvedDestinationDir, filename)),\n { recursive: true },\n );\n await copyFile(\n path.join(resolvedSrcDir, filename),\n path.join(resolvedDestinationDir, filename),\n { processors: [] },\n );\n }),\n );\n};\n\ninterface CopyAssetsConfig {\n outDir: string;\n name: string;\n prefixColor: typeof Color;\n}\n\nexport const copyAssetsConcurrently = async (configs: CopyAssetsConfig[]) => {\n const maxNameLength = configs.reduce(\n (length, command) => Math.max(length, command.name.length),\n 0,\n );\n\n await Promise.all(\n configs.map(({ outDir, name, prefixColor }) =>\n copyAssets(\n outDir,\n createLogger({\n debug: false,\n prefixes: [chalk[prefixColor](`${name.padEnd(maxNameLength)} \u2502`)],\n }),\n ),\n ),\n );\n};\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAiB;AAEjB,mBAAkC;AAClC,sBAAe;AAEf,kBAAyB;AACzB,iBAA0D;AAC1D,qBAA+C;AAC/C,sBAIO;AAEA,MAAM,aAAa,OACxB,gBACA,SAAiB,uBACd;AACH,QAAM,WAAW,UAAM,qCAAoB;AAC3C,MAAI,CAAC,UAAU;AACb;AAAA,EACF;AAEA,QAAM,SAAS,UAAM,6CAA8C,QAAQ;AAC3E,MAAI,CAAC,QAAQ;AACX;AAAA,EACF;AAEA,QAAM,aAAa,UAAM,2CAA0B;AACnD,MAAI,CAAC,YAAY;AACf;AAAA,EACF;AAEA,QAAM,eAAe,WAAW,MAAM,YAAAA,QAAK,GAAG;AAC9C,QAAM,SAAU,aAAa,SAAS,KAAK,aAAa,CAAC,KAAM;AAC/D,QAAM,iBAAiB,YAAAA,QAAK,QAAQ,YAAAA,QAAK,QAAQ,SAAS,IAAI,GAAG,MAAM;AACvE,QAAM,yBAAyB,YAAAA,QAAK;AAAA,IAClC,YAAAA,QAAK,QAAQ,SAAS,IAAI;AAAA,IAC1B;AAAA,EACF;AAEA,QAAM,WAAW,UAAM,2BAAe,cAAc;AACpD,QAAM,qBAAiB,sCAA0B,QAAQ,UAAU;AAAA,IACjE,KAAK;AAAA,IACL,KAAK;AAAA,EACP,CAAC;AACD,QAAM,eAAe,MAAM;AAAA,IACzB,IAAI,IAAI,OAAO,OAAO,cAAc,EAAE,KAAK,CAAC;AAAA,EAC9C;AAEA,QAAM,QAAQ;AAAA,IACZ,aAAa,IAAI,OAAO,aAAa;AACnC,aAAO,OAAO,WAAW,QAAQ,EAAE;AAEnC,YAAM,gBAAAC,QAAG,SAAS;AAAA,QAChB,YAAAD,QAAK,QAAQ,YAAAA,QAAK,KAAK,wBAAwB,QAAQ,CAAC;AAAA,QACxD,EAAE,WAAW,KAAK;AAAA,MACpB;AACA,gBAAM;AAAA,QACJ,YAAAA,QAAK,KAAK,gBAAgB,QAAQ;AAAA,QAClC,YAAAA,QAAK,KAAK,wBAAwB,QAAQ;AAAA,QAC1C,EAAE,YAAY,CAAC,EAAE;AAAA,MACnB;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAQO,MAAM,yBAAyB,OAAO,YAAgC;AAC3E,QAAM,gBAAgB,QAAQ;AAAA,IAC5B,CAAC,QAAQ,YAAY,KAAK,IAAI,QAAQ,QAAQ,KAAK,MAAM;AAAA,IACzD;AAAA,EACF;AAEA,QAAM,QAAQ;AAAA,IACZ,QAAQ;AAAA,MAAI,CAAC,EAAE,QAAQ,MAAM,YAAY,MACvC;AAAA,QACE;AAAA,YACA,6BAAa;AAAA,UACX,OAAO;AAAA,UACP,UAAU,CAAC,aAAAE,QAAM,WAAW,EAAE,GAAG,KAAK,OAAO,aAAa,CAAC,SAAI,CAAC;AAAA,QAClE,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;",
|
|
6
6
|
"names": ["path", "fs", "chalk"]
|
|
7
7
|
}
|
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* than `lib/`) but they generally represent the same _intent_.
|
|
6
6
|
*/
|
|
7
7
|
export declare const generateIgnoreFileSimpleVariants: (patterns: string[]) => Set<string>;
|
|
8
|
-
export declare const
|
|
9
|
-
export declare const mergeWithConfigFile: (rawTemplateFile: string, fileType?: "ignore" | "
|
|
8
|
+
export declare const replaceManagedSection: (input: string, template: string) => string;
|
|
9
|
+
export declare const mergeWithConfigFile: (rawTemplateFile: string, fileType?: "ignore" | "pnpm-workspace") => (rawInputFile?: string) => string;
|
|
@@ -19,8 +19,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
19
19
|
var configFile_exports = {};
|
|
20
20
|
__export(configFile_exports, {
|
|
21
21
|
generateIgnoreFileSimpleVariants: () => generateIgnoreFileSimpleVariants,
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
mergeWithConfigFile: () => mergeWithConfigFile,
|
|
23
|
+
replaceManagedSection: () => replaceManagedSection
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(configFile_exports);
|
|
26
26
|
const OUTDATED_PATTERNS = ["node_modules_bak/", "tmp-*/"];
|
|
@@ -46,24 +46,18 @@ const generateIgnoreFileSimpleVariants = (patterns) => {
|
|
|
46
46
|
set.delete("");
|
|
47
47
|
return set;
|
|
48
48
|
};
|
|
49
|
-
const
|
|
50
|
-
const set = /* @__PURE__ */ new Set();
|
|
51
|
-
for (const pattern of patterns) {
|
|
52
|
-
set.add(pattern);
|
|
53
|
-
const match = /^(?<key>[^"=]+)="?(?<value>[^"=]+)"?$/.exec(pattern);
|
|
54
|
-
if (!match?.groups) {
|
|
55
|
-
continue;
|
|
56
|
-
}
|
|
57
|
-
const { key, value } = match.groups;
|
|
58
|
-
set.add(`${key}=${value}`);
|
|
59
|
-
set.add(`${key}="${value}"`);
|
|
60
|
-
}
|
|
61
|
-
set.delete("");
|
|
62
|
-
return set;
|
|
63
|
-
};
|
|
49
|
+
const replaceManagedSection = (input, template) => input.replace(/# managed by skuba[\s\S]*# end managed by skuba/, template);
|
|
64
50
|
const mergeWithConfigFile = (rawTemplateFile, fileType = "ignore") => {
|
|
65
51
|
const templateFile = rawTemplateFile.trim();
|
|
66
|
-
|
|
52
|
+
let generator;
|
|
53
|
+
switch (fileType) {
|
|
54
|
+
case "ignore":
|
|
55
|
+
generator = generateIgnoreFileSimpleVariants;
|
|
56
|
+
break;
|
|
57
|
+
case "pnpm-workspace":
|
|
58
|
+
generator = () => /* @__PURE__ */ new Set();
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
67
61
|
const templatePatterns = generator([
|
|
68
62
|
...OUTDATED_PATTERNS,
|
|
69
63
|
...templateFile.split("\n").map((line) => line.trim())
|
|
@@ -73,7 +67,10 @@ const mergeWithConfigFile = (rawTemplateFile, fileType = "ignore") => {
|
|
|
73
67
|
return `${templateFile}
|
|
74
68
|
`;
|
|
75
69
|
}
|
|
76
|
-
const replacedFile =
|
|
70
|
+
const replacedFile = replaceManagedSection(
|
|
71
|
+
rawInputFile.replace(/\r?\n/g, "\n"),
|
|
72
|
+
templateFile
|
|
73
|
+
);
|
|
77
74
|
if (replacedFile.includes(templateFile)) {
|
|
78
75
|
return replacedFile;
|
|
79
76
|
}
|
|
@@ -86,7 +83,7 @@ const mergeWithConfigFile = (rawTemplateFile, fileType = "ignore") => {
|
|
|
86
83
|
// Annotate the CommonJS export names for ESM import in node:
|
|
87
84
|
0 && (module.exports = {
|
|
88
85
|
generateIgnoreFileSimpleVariants,
|
|
89
|
-
|
|
90
|
-
|
|
86
|
+
mergeWithConfigFile,
|
|
87
|
+
replaceManagedSection
|
|
91
88
|
});
|
|
92
89
|
//# sourceMappingURL=configFile.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/cli/configure/processing/configFile.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Patterns that are superseded by skuba's bundled ignore file patterns and are\n * non-trivial to derive using e.g. `generateSimpleVariants`.\n */\nconst OUTDATED_PATTERNS = ['node_modules_bak/', 'tmp-*/'];\n\nconst ASTERISKS = /\\*/g;\nconst LEADING_SLASH = /^\\//;\nconst TRAILING_SLASH = /\\/$/;\n\n/**\n * Generate simple variants of an ignore pattern for exact matching purposes.\n *\n * Note that these patterns are not actually equivalent (e.g. `lib` matches more\n * than `lib/`) but they generally represent the same _intent_.\n */\nexport const generateIgnoreFileSimpleVariants = (patterns: string[]) => {\n const set = new Set<string>();\n\n for (const pattern of patterns) {\n const deAsterisked = pattern.replace(ASTERISKS, '');\n const stripped = deAsterisked\n .replace(LEADING_SLASH, '')\n .replace(TRAILING_SLASH, '');\n\n set.add(pattern);\n set.add(deAsterisked);\n set.add(deAsterisked.replace(LEADING_SLASH, ''));\n set.add(deAsterisked.replace(TRAILING_SLASH, ''));\n set.add(stripped);\n\n if (stripped !== '') {\n set.add(`/${stripped}`);\n set.add(`${stripped}/`);\n set.add(`/${stripped}/`);\n }\n }\n\n set.delete('');\n\n return set;\n};\n\nexport const
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAIA,MAAM,oBAAoB,CAAC,qBAAqB,QAAQ;AAExD,MAAM,YAAY;AAClB,MAAM,gBAAgB;AACtB,MAAM,iBAAiB;AAQhB,MAAM,mCAAmC,CAAC,aAAuB;AACtE,QAAM,MAAM,oBAAI,IAAY;AAE5B,aAAW,WAAW,UAAU;AAC9B,UAAM,eAAe,QAAQ,QAAQ,WAAW,EAAE;AAClD,UAAM,WAAW,aACd,QAAQ,eAAe,EAAE,EACzB,QAAQ,gBAAgB,EAAE;AAE7B,QAAI,IAAI,OAAO;AACf,QAAI,IAAI,YAAY;AACpB,QAAI,IAAI,aAAa,QAAQ,eAAe,EAAE,CAAC;AAC/C,QAAI,IAAI,aAAa,QAAQ,gBAAgB,EAAE,CAAC;AAChD,QAAI,IAAI,QAAQ;AAEhB,QAAI,aAAa,IAAI;AACnB,UAAI,IAAI,IAAI,QAAQ,EAAE;AACtB,UAAI,IAAI,GAAG,QAAQ,GAAG;AACtB,UAAI,IAAI,IAAI,QAAQ,GAAG;AAAA,IACzB;AAAA,EACF;AAEA,MAAI,OAAO,EAAE;AAEb,SAAO;AACT;AAEO,MAAM,
|
|
4
|
+
"sourcesContent": ["/**\n * Patterns that are superseded by skuba's bundled ignore file patterns and are\n * non-trivial to derive using e.g. `generateSimpleVariants`.\n */\nconst OUTDATED_PATTERNS = ['node_modules_bak/', 'tmp-*/'];\n\nconst ASTERISKS = /\\*/g;\nconst LEADING_SLASH = /^\\//;\nconst TRAILING_SLASH = /\\/$/;\n\n/**\n * Generate simple variants of an ignore pattern for exact matching purposes.\n *\n * Note that these patterns are not actually equivalent (e.g. `lib` matches more\n * than `lib/`) but they generally represent the same _intent_.\n */\nexport const generateIgnoreFileSimpleVariants = (patterns: string[]) => {\n const set = new Set<string>();\n\n for (const pattern of patterns) {\n const deAsterisked = pattern.replace(ASTERISKS, '');\n const stripped = deAsterisked\n .replace(LEADING_SLASH, '')\n .replace(TRAILING_SLASH, '');\n\n set.add(pattern);\n set.add(deAsterisked);\n set.add(deAsterisked.replace(LEADING_SLASH, ''));\n set.add(deAsterisked.replace(TRAILING_SLASH, ''));\n set.add(stripped);\n\n if (stripped !== '') {\n set.add(`/${stripped}`);\n set.add(`${stripped}/`);\n set.add(`/${stripped}/`);\n }\n }\n\n set.delete('');\n\n return set;\n};\n\nexport const replaceManagedSection = (input: string, template: string) =>\n input.replace(/# managed by skuba[\\s\\S]*# end managed by skuba/, template);\n\nexport const mergeWithConfigFile = (\n rawTemplateFile: string,\n fileType: 'ignore' | 'pnpm-workspace' = 'ignore',\n) => {\n const templateFile = rawTemplateFile.trim();\n\n let generator: (s: string[]) => Set<string>;\n\n switch (fileType) {\n case 'ignore':\n generator = generateIgnoreFileSimpleVariants;\n break;\n case 'pnpm-workspace':\n generator = () => new Set<string>();\n break;\n }\n\n const templatePatterns = generator([\n ...OUTDATED_PATTERNS,\n ...templateFile.split('\\n').map((line) => line.trim()),\n ]);\n\n return (rawInputFile?: string) => {\n if (rawInputFile === undefined) {\n return `${templateFile}\\n`;\n }\n\n const replacedFile = replaceManagedSection(\n rawInputFile.replace(/\\r?\\n/g, '\\n'),\n templateFile,\n );\n\n if (replacedFile.includes(templateFile)) {\n return replacedFile;\n }\n\n // Crunch the existing lines of a non-skuba config.\n const migratedFile = replacedFile\n .split('\\n')\n .filter((line) => !templatePatterns.has(line))\n .join('\\n')\n .replace(/\\n{3,}/g, '\\n\\n')\n .trim();\n\n const outputFile = [templateFile, migratedFile].join('\\n\\n').trim();\n\n return `${outputFile}\\n`;\n };\n};\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAIA,MAAM,oBAAoB,CAAC,qBAAqB,QAAQ;AAExD,MAAM,YAAY;AAClB,MAAM,gBAAgB;AACtB,MAAM,iBAAiB;AAQhB,MAAM,mCAAmC,CAAC,aAAuB;AACtE,QAAM,MAAM,oBAAI,IAAY;AAE5B,aAAW,WAAW,UAAU;AAC9B,UAAM,eAAe,QAAQ,QAAQ,WAAW,EAAE;AAClD,UAAM,WAAW,aACd,QAAQ,eAAe,EAAE,EACzB,QAAQ,gBAAgB,EAAE;AAE7B,QAAI,IAAI,OAAO;AACf,QAAI,IAAI,YAAY;AACpB,QAAI,IAAI,aAAa,QAAQ,eAAe,EAAE,CAAC;AAC/C,QAAI,IAAI,aAAa,QAAQ,gBAAgB,EAAE,CAAC;AAChD,QAAI,IAAI,QAAQ;AAEhB,QAAI,aAAa,IAAI;AACnB,UAAI,IAAI,IAAI,QAAQ,EAAE;AACtB,UAAI,IAAI,GAAG,QAAQ,GAAG;AACtB,UAAI,IAAI,IAAI,QAAQ,GAAG;AAAA,IACzB;AAAA,EACF;AAEA,MAAI,OAAO,EAAE;AAEb,SAAO;AACT;AAEO,MAAM,wBAAwB,CAAC,OAAe,aACnD,MAAM,QAAQ,mDAAmD,QAAQ;AAEpE,MAAM,sBAAsB,CACjC,iBACA,WAAwC,aACrC;AACH,QAAM,eAAe,gBAAgB,KAAK;AAE1C,MAAI;AAEJ,UAAQ,UAAU;AAAA,IAChB,KAAK;AACH,kBAAY;AACZ;AAAA,IACF,KAAK;AACH,kBAAY,MAAM,oBAAI,IAAY;AAClC;AAAA,EACJ;AAEA,QAAM,mBAAmB,UAAU;AAAA,IACjC,GAAG;AAAA,IACH,GAAG,aAAa,MAAM,IAAI,EAAE,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC;AAAA,EACvD,CAAC;AAED,SAAO,CAAC,iBAA0B;AAChC,QAAI,iBAAiB,QAAW;AAC9B,aAAO,GAAG,YAAY;AAAA;AAAA,IACxB;AAEA,UAAM,eAAe;AAAA,MACnB,aAAa,QAAQ,UAAU,IAAI;AAAA,MACnC;AAAA,IACF;AAEA,QAAI,aAAa,SAAS,YAAY,GAAG;AACvC,aAAO;AAAA,IACT;AAGA,UAAM,eAAe,aAClB,MAAM,IAAI,EACV,OAAO,CAAC,SAAS,CAAC,iBAAiB,IAAI,IAAI,CAAC,EAC5C,KAAK,IAAI,EACT,QAAQ,WAAW,MAAM,EACzB,KAAK;AAER,UAAM,aAAa,CAAC,cAAc,YAAY,EAAE,KAAK,MAAM,EAAE,KAAK;AAElE,WAAO,GAAG,UAAU;AAAA;AAAA,EACtB;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -43,8 +43,7 @@ const detectBadCodeowners = async (logger) => {
|
|
|
43
43
|
return [];
|
|
44
44
|
}
|
|
45
45
|
)
|
|
46
|
-
)).flat();
|
|
47
|
-
annotations.sort((a, b) => a.path.localeCompare(b.path));
|
|
46
|
+
)).flat().toSorted((a, b) => a.path.localeCompare(b.path));
|
|
48
47
|
annotations.forEach(({ path, message }) => {
|
|
49
48
|
logger.warn(`${path}: ${message}`);
|
|
50
49
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/cli/lint/internalLints/detectBadCodeowners.ts"],
|
|
4
|
-
"sourcesContent": ["import { inspect } from 'util';\n\nimport { Git } from '../../..';\nimport type { Logger } from '../../../utils/logging';\nimport { createDestinationFileReader } from '../../configure/analysis/project';\nimport type { InternalLintResult } from '../internal';\n\nexport const detectBadCodeowners = async (\n logger: Logger,\n): Promise<InternalLintResult> => {\n const gitRoot = await Git.findRoot({ dir: process.cwd() });\n const reader = createDestinationFileReader(gitRoot ?? process.cwd());\n\n const annotations = (\n await Promise.all(\n ['.github/CODEOWNERS', 'CODEOWNERS', 'docs/CODEOWNERS'].map(\n async (filename) => {\n const lines = (await reader(filename))?.split('\\n');\n\n if (lines?.some((line) => line.startsWith('- '))) {\n return [\n {\n message:\n 'CODEOWNERS file has a line starting with `- `. This is probably an autoformatting mistake, where your editor thinks this file is a markdown file and is trying to format a list item. Did you mean to use `*` instead?',\n path: filename,\n },\n ];\n }\n\n return [];\n },\n ),\n )\n ).flat()
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAwB;AAExB,eAAoB;AAEpB,qBAA4C;AAGrC,MAAM,sBAAsB,OACjC,WACgC;AAChC,QAAM,UAAU,MAAM,aAAI,SAAS,EAAE,KAAK,QAAQ,IAAI,EAAE,CAAC;AACzD,QAAM,aAAS,4CAA4B,WAAW,QAAQ,IAAI,CAAC;AAEnE,QAAM,eACJ,MAAM,QAAQ;AAAA,IACZ,CAAC,sBAAsB,cAAc,iBAAiB,EAAE;AAAA,MACtD,OAAO,aAAa;AAClB,cAAM,SAAS,MAAM,OAAO,QAAQ,IAAI,MAAM,IAAI;AAElD,YAAI,OAAO,KAAK,CAAC,SAAS,KAAK,WAAW,IAAI,CAAC,GAAG;AAChD,iBAAO;AAAA,YACL;AAAA,cACE,SACE;AAAA,cACF,MAAM;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAEA,eAAO,CAAC;AAAA,MACV;AAAA,IACF;AAAA,EACF,
|
|
4
|
+
"sourcesContent": ["import { inspect } from 'util';\n\nimport { Git } from '../../..';\nimport type { Logger } from '../../../utils/logging';\nimport { createDestinationFileReader } from '../../configure/analysis/project';\nimport type { InternalLintResult } from '../internal';\n\nexport const detectBadCodeowners = async (\n logger: Logger,\n): Promise<InternalLintResult> => {\n const gitRoot = await Git.findRoot({ dir: process.cwd() });\n const reader = createDestinationFileReader(gitRoot ?? process.cwd());\n\n const annotations = (\n await Promise.all(\n ['.github/CODEOWNERS', 'CODEOWNERS', 'docs/CODEOWNERS'].map(\n async (filename) => {\n const lines = (await reader(filename))?.split('\\n');\n\n if (lines?.some((line) => line.startsWith('- '))) {\n return [\n {\n message:\n 'CODEOWNERS file has a line starting with `- `. This is probably an autoformatting mistake, where your editor thinks this file is a markdown file and is trying to format a list item. Did you mean to use `*` instead?',\n path: filename,\n },\n ];\n }\n\n return [];\n },\n ),\n )\n )\n .flat()\n .toSorted((a, b) => a.path.localeCompare(b.path));\n\n annotations.forEach(({ path, message }) => {\n logger.warn(`${path}: ${message}`);\n });\n\n return {\n ok: annotations.length === 0,\n fixable: false,\n annotations,\n };\n};\n\nexport const tryDetectBadCodeowners = async (\n _mode: 'format' | 'lint',\n logger: Logger,\n): Promise<InternalLintResult> => {\n try {\n return await detectBadCodeowners(logger);\n } catch (err) {\n logger.warn('Failed to detect bad CODEOWNERS.');\n logger.subtle(inspect(err));\n\n return {\n ok: false,\n fixable: false,\n annotations: [],\n };\n }\n};\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAwB;AAExB,eAAoB;AAEpB,qBAA4C;AAGrC,MAAM,sBAAsB,OACjC,WACgC;AAChC,QAAM,UAAU,MAAM,aAAI,SAAS,EAAE,KAAK,QAAQ,IAAI,EAAE,CAAC;AACzD,QAAM,aAAS,4CAA4B,WAAW,QAAQ,IAAI,CAAC;AAEnE,QAAM,eACJ,MAAM,QAAQ;AAAA,IACZ,CAAC,sBAAsB,cAAc,iBAAiB,EAAE;AAAA,MACtD,OAAO,aAAa;AAClB,cAAM,SAAS,MAAM,OAAO,QAAQ,IAAI,MAAM,IAAI;AAElD,YAAI,OAAO,KAAK,CAAC,SAAS,KAAK,WAAW,IAAI,CAAC,GAAG;AAChD,iBAAO;AAAA,YACL;AAAA,cACE,SACE;AAAA,cACF,MAAM;AAAA,YACR;AAAA,UACF;AAAA,QACF;AAEA,eAAO,CAAC;AAAA,MACV;AAAA,IACF;AAAA,EACF,GAEC,KAAK,EACL,SAAS,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAElD,cAAY,QAAQ,CAAC,EAAE,MAAM,QAAQ,MAAM;AACzC,WAAO,KAAK,GAAG,IAAI,KAAK,OAAO,EAAE;AAAA,EACnC,CAAC;AAED,SAAO;AAAA,IACL,IAAI,YAAY,WAAW;AAAA,IAC3B,SAAS;AAAA,IACT;AAAA,EACF;AACF;AAEO,MAAM,yBAAyB,OACpC,OACA,WACgC;AAChC,MAAI;AACF,WAAO,MAAM,oBAAoB,MAAM;AAAA,EACzC,SAAS,KAAK;AACZ,WAAO,KAAK,kCAAkC;AAC9C,WAAO,WAAO,qBAAQ,GAAG,CAAC;AAE1B,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,SAAS;AAAA,MACT,aAAa,CAAC;AAAA,IAChB;AAAA,EACF;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import type { Logger } from '../../../utils/logging';
|
|
2
2
|
import { type PackageManagerConfig } from '../../../utils/packageManager';
|
|
3
3
|
import type { InternalLintResult } from '../internal';
|
|
4
|
+
type ConditionOptions = {
|
|
5
|
+
packageManager: PackageManagerConfig;
|
|
6
|
+
isInWorkspaceRoot: boolean;
|
|
7
|
+
};
|
|
4
8
|
type RefreshableConfigFile = {
|
|
5
9
|
name: string;
|
|
6
|
-
type: 'ignore' | '
|
|
10
|
+
type: 'ignore' | 'pnpm-workspace';
|
|
7
11
|
additionalMapping?: (s: string, packageManager: PackageManagerConfig) => string;
|
|
8
|
-
if?: (
|
|
12
|
+
if?: (options: ConditionOptions) => boolean;
|
|
9
13
|
};
|
|
10
14
|
export declare const REFRESHABLE_CONFIG_FILES: RefreshableConfigFile[];
|
|
11
15
|
export declare const refreshConfigFiles: (mode: "format" | "lint", logger: Logger) => Promise<{
|
|
@@ -37,43 +37,44 @@ var import_path = __toESM(require("path"));
|
|
|
37
37
|
var import_util = require("util");
|
|
38
38
|
var import_fs_extra = require("fs-extra");
|
|
39
39
|
var import__ = require("../../..");
|
|
40
|
-
var
|
|
40
|
+
var import_dir = require("../../../utils/dir");
|
|
41
41
|
var import_packageManager = require("../../../utils/packageManager");
|
|
42
42
|
var import_template = require("../../../utils/template");
|
|
43
43
|
var import_package = require("../../configure/analysis/package");
|
|
44
44
|
var import_project = require("../../configure/analysis/project");
|
|
45
45
|
var import_configFile = require("../../configure/processing/configFile");
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
46
|
+
const OLD_IGNORE_WARNING = `# Ignore .npmrc. This is no longer managed by skuba as pnpm projects use a managed .npmrc.
|
|
47
|
+
# IMPORTANT: if migrating to pnpm, remove this line and add an .npmrc IN THE SAME COMMIT.
|
|
48
|
+
# You can use \`skuba format\` to generate the file or otherwise commit an empty file.
|
|
49
|
+
# Doing so will conflict with a local .npmrc and make it more difficult to unintentionally commit auth secrets.
|
|
50
|
+
.npmrc
|
|
51
|
+
`;
|
|
52
|
+
const removeOldWarning = (contents) => contents.includes(OLD_IGNORE_WARNING) ? `${contents.replace(OLD_IGNORE_WARNING, "").trim()}
|
|
53
|
+
` : contents;
|
|
54
54
|
const REFRESHABLE_CONFIG_FILES = [
|
|
55
55
|
{
|
|
56
56
|
name: ".gitignore",
|
|
57
57
|
type: "ignore",
|
|
58
|
-
additionalMapping:
|
|
58
|
+
additionalMapping: removeOldWarning
|
|
59
59
|
},
|
|
60
60
|
{ name: ".prettierignore", type: "ignore" },
|
|
61
61
|
{
|
|
62
|
-
name: ".
|
|
63
|
-
type: "
|
|
64
|
-
|
|
65
|
-
if: (packageManager) => packageManager.command === "pnpm"
|
|
62
|
+
name: "pnpm-workspace.yaml",
|
|
63
|
+
type: "pnpm-workspace",
|
|
64
|
+
if: ({ packageManager, isInWorkspaceRoot }) => isInWorkspaceRoot && packageManager.command === "pnpm"
|
|
66
65
|
},
|
|
67
66
|
{
|
|
68
67
|
name: ".dockerignore",
|
|
69
68
|
type: "ignore",
|
|
70
|
-
additionalMapping:
|
|
69
|
+
additionalMapping: removeOldWarning
|
|
71
70
|
}
|
|
72
71
|
];
|
|
73
72
|
const refreshConfigFiles = async (mode, logger) => {
|
|
74
|
-
const [manifest, gitRoot] = await Promise.all([
|
|
73
|
+
const [manifest, gitRoot, workspaceRoot, currentWorkspaceProjectRoot] = await Promise.all([
|
|
75
74
|
(0, import_package.getDestinationManifest)(),
|
|
76
|
-
import__.Git.findRoot({ dir: process.cwd() })
|
|
75
|
+
import__.Git.findRoot({ dir: process.cwd() }),
|
|
76
|
+
(0, import_dir.findWorkspaceRoot)(),
|
|
77
|
+
(0, import_dir.findCurrentWorkspaceProjectRoot)()
|
|
77
78
|
]);
|
|
78
79
|
const destinationRoot = import_path.default.dirname(manifest.path);
|
|
79
80
|
const readDestinationFile = (0, import_project.createDestinationFileReader)(destinationRoot);
|
|
@@ -82,8 +83,8 @@ const refreshConfigFiles = async (mode, logger) => {
|
|
|
82
83
|
type: fileType,
|
|
83
84
|
additionalMapping = (s) => s,
|
|
84
85
|
if: condition = () => true
|
|
85
|
-
},
|
|
86
|
-
if (!condition(
|
|
86
|
+
}, conditionOptions) => {
|
|
87
|
+
if (!condition(conditionOptions)) {
|
|
87
88
|
return { needsChange: false };
|
|
88
89
|
}
|
|
89
90
|
const [inputFile, templateFile, isGitIgnored] = await Promise.all([
|
|
@@ -99,7 +100,7 @@ const refreshConfigFiles = async (mode, logger) => {
|
|
|
99
100
|
}
|
|
100
101
|
const data = additionalMapping(
|
|
101
102
|
inputFile ? (0, import_configFile.mergeWithConfigFile)(templateFile, fileType)(inputFile) : templateFile,
|
|
102
|
-
|
|
103
|
+
packageManager
|
|
103
104
|
);
|
|
104
105
|
const filepath = import_path.default.join(destinationRoot, filename);
|
|
105
106
|
if (mode === "format") {
|
|
@@ -119,7 +120,7 @@ const refreshConfigFiles = async (mode, logger) => {
|
|
|
119
120
|
msg: `The ${logger.bold(
|
|
120
121
|
filename
|
|
121
122
|
)} file is out of date. Run \`${logger.bold(
|
|
122
|
-
|
|
123
|
+
packageManager.print.exec,
|
|
123
124
|
"skuba",
|
|
124
125
|
"format"
|
|
125
126
|
)}\` to update it.`,
|
|
@@ -131,7 +132,10 @@ const refreshConfigFiles = async (mode, logger) => {
|
|
|
131
132
|
const packageManager = await (0, import_packageManager.detectPackageManager)(destinationRoot);
|
|
132
133
|
const results = await Promise.all(
|
|
133
134
|
REFRESHABLE_CONFIG_FILES.map(
|
|
134
|
-
(conf) => refreshConfigFile(conf,
|
|
135
|
+
(conf) => refreshConfigFile(conf, {
|
|
136
|
+
packageManager,
|
|
137
|
+
isInWorkspaceRoot: workspaceRoot === currentWorkspaceProjectRoot
|
|
138
|
+
})
|
|
135
139
|
)
|
|
136
140
|
);
|
|
137
141
|
results.forEach((result) => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/cli/lint/internalLints/refreshConfigFiles.ts"],
|
|
4
|
-
"sourcesContent": ["import path from 'path';\nimport { inspect, stripVTControlCharacters as stripAnsi } from 'util';\n\nimport { writeFile } from 'fs-extra';\n\nimport { Git } from '../../..';\nimport
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAiB;AACjB,kBAA+D;AAE/D,sBAA0B;AAE1B,eAAoB;
|
|
6
|
-
"names": ["path", "
|
|
4
|
+
"sourcesContent": ["import path from 'path';\nimport { inspect, stripVTControlCharacters as stripAnsi } from 'util';\n\nimport { writeFile } from 'fs-extra';\n\nimport { Git } from '../../..';\nimport {\n findCurrentWorkspaceProjectRoot,\n findWorkspaceRoot,\n} from '../../../utils/dir';\nimport type { Logger } from '../../../utils/logging';\nimport {\n type PackageManagerConfig,\n detectPackageManager,\n} from '../../../utils/packageManager';\nimport { readBaseTemplateFile } from '../../../utils/template';\nimport { getDestinationManifest } from '../../configure/analysis/package';\nimport { createDestinationFileReader } from '../../configure/analysis/project';\nimport { mergeWithConfigFile } from '../../configure/processing/configFile';\nimport type { InternalLintResult } from '../internal';\n\ntype ConditionOptions = {\n packageManager: PackageManagerConfig;\n isInWorkspaceRoot: boolean;\n};\n\ntype RefreshableConfigFile = {\n name: string;\n type: 'ignore' | 'pnpm-workspace';\n additionalMapping?: (\n s: string,\n packageManager: PackageManagerConfig,\n ) => string;\n if?: (options: ConditionOptions) => boolean;\n};\n\nconst OLD_IGNORE_WARNING = `# Ignore .npmrc. This is no longer managed by skuba as pnpm projects use a managed .npmrc.\n# IMPORTANT: if migrating to pnpm, remove this line and add an .npmrc IN THE SAME COMMIT.\n# You can use \\`skuba format\\` to generate the file or otherwise commit an empty file.\n# Doing so will conflict with a local .npmrc and make it more difficult to unintentionally commit auth secrets.\n.npmrc\n`;\n\nconst removeOldWarning = (contents: string) =>\n contents.includes(OLD_IGNORE_WARNING)\n ? `${contents.replace(OLD_IGNORE_WARNING, '').trim()}\\n`\n : contents;\n\nexport const REFRESHABLE_CONFIG_FILES: RefreshableConfigFile[] = [\n {\n name: '.gitignore',\n type: 'ignore',\n additionalMapping: removeOldWarning,\n },\n { name: '.prettierignore', type: 'ignore' },\n {\n name: 'pnpm-workspace.yaml',\n type: 'pnpm-workspace',\n if: ({ packageManager, isInWorkspaceRoot }) =>\n isInWorkspaceRoot && packageManager.command === 'pnpm',\n },\n {\n name: '.dockerignore',\n type: 'ignore',\n additionalMapping: removeOldWarning,\n },\n];\n\nexport const refreshConfigFiles = async (\n mode: 'format' | 'lint',\n logger: Logger,\n) => {\n const [manifest, gitRoot, workspaceRoot, currentWorkspaceProjectRoot] =\n await Promise.all([\n getDestinationManifest(),\n Git.findRoot({ dir: process.cwd() }),\n findWorkspaceRoot(),\n findCurrentWorkspaceProjectRoot(),\n ]);\n\n const destinationRoot = path.dirname(manifest.path);\n\n const readDestinationFile = createDestinationFileReader(destinationRoot);\n\n const refreshConfigFile = async (\n {\n name: filename,\n type: fileType,\n additionalMapping = (s) => s,\n if: condition = () => true,\n }: RefreshableConfigFile,\n conditionOptions: ConditionOptions,\n ) => {\n if (!condition(conditionOptions)) {\n return { needsChange: false };\n }\n\n const [inputFile, templateFile, isGitIgnored] = await Promise.all([\n readDestinationFile(filename),\n readBaseTemplateFile(`_${filename}`),\n gitRoot\n ? Git.isFileGitIgnored({\n gitRoot,\n absolutePath: path.join(destinationRoot, filename),\n })\n : false,\n ]);\n\n // If the file is gitignored and doesn't exist, don't make it\n if (inputFile === undefined && isGitIgnored) {\n return { needsChange: false };\n }\n\n const data = additionalMapping(\n inputFile\n ? mergeWithConfigFile(templateFile, fileType)(inputFile)\n : templateFile,\n packageManager,\n );\n\n const filepath = path.join(destinationRoot, filename);\n\n if (mode === 'format') {\n if (data === inputFile) {\n return { needsChange: false };\n }\n\n await writeFile(filepath, data);\n return {\n needsChange: false,\n msg: `Refreshed ${logger.bold(filename)}.`,\n filename,\n };\n }\n\n if (data !== inputFile) {\n return {\n needsChange: true,\n msg: `The ${logger.bold(\n filename,\n )} file is out of date. Run \\`${logger.bold(\n packageManager.print.exec,\n 'skuba',\n 'format',\n )}\\` to update it.`,\n filename,\n };\n }\n\n return { needsChange: false };\n };\n\n const packageManager = await detectPackageManager(destinationRoot);\n\n const results = await Promise.all(\n REFRESHABLE_CONFIG_FILES.map((conf) =>\n refreshConfigFile(conf, {\n packageManager,\n isInWorkspaceRoot: workspaceRoot === currentWorkspaceProjectRoot,\n }),\n ),\n );\n\n // Log after for reproducible test output ordering\n results.forEach((result) => {\n if (result.msg) {\n logger.warn(result.msg);\n }\n });\n\n const anyNeedChanging = results.some(({ needsChange }) => needsChange);\n\n return {\n ok: !anyNeedChanging,\n fixable: anyNeedChanging,\n annotations: results.flatMap(({ needsChange, filename, msg }) =>\n needsChange && msg\n ? [\n {\n path: filename,\n message: stripAnsi(msg),\n },\n ]\n : [],\n ),\n };\n};\n\nexport const tryRefreshConfigFiles = async (\n mode: 'format' | 'lint',\n logger: Logger,\n): Promise<InternalLintResult> => {\n try {\n return await refreshConfigFiles(mode, logger);\n } catch (err) {\n logger.warn('Failed to refresh config files.');\n logger.subtle(inspect(err));\n\n return {\n ok: false,\n fixable: false,\n annotations: [],\n };\n }\n};\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAiB;AACjB,kBAA+D;AAE/D,sBAA0B;AAE1B,eAAoB;AACpB,iBAGO;AAEP,4BAGO;AACP,sBAAqC;AACrC,qBAAuC;AACvC,qBAA4C;AAC5C,wBAAoC;AAkBpC,MAAM,qBAAqB;AAAA;AAAA;AAAA;AAAA;AAAA;AAO3B,MAAM,mBAAmB,CAAC,aACxB,SAAS,SAAS,kBAAkB,IAChC,GAAG,SAAS,QAAQ,oBAAoB,EAAE,EAAE,KAAK,CAAC;AAAA,IAClD;AAEC,MAAM,2BAAoD;AAAA,EAC/D;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,mBAAmB;AAAA,EACrB;AAAA,EACA,EAAE,MAAM,mBAAmB,MAAM,SAAS;AAAA,EAC1C;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,IAAI,CAAC,EAAE,gBAAgB,kBAAkB,MACvC,qBAAqB,eAAe,YAAY;AAAA,EACpD;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,mBAAmB;AAAA,EACrB;AACF;AAEO,MAAM,qBAAqB,OAChC,MACA,WACG;AACH,QAAM,CAAC,UAAU,SAAS,eAAe,2BAA2B,IAClE,MAAM,QAAQ,IAAI;AAAA,QAChB,uCAAuB;AAAA,IACvB,aAAI,SAAS,EAAE,KAAK,QAAQ,IAAI,EAAE,CAAC;AAAA,QACnC,8BAAkB;AAAA,QAClB,4CAAgC;AAAA,EAClC,CAAC;AAEH,QAAM,kBAAkB,YAAAA,QAAK,QAAQ,SAAS,IAAI;AAElD,QAAM,0BAAsB,4CAA4B,eAAe;AAEvE,QAAM,oBAAoB,OACxB;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,oBAAoB,CAAC,MAAM;AAAA,IAC3B,IAAI,YAAY,MAAM;AAAA,EACxB,GACA,qBACG;AACH,QAAI,CAAC,UAAU,gBAAgB,GAAG;AAChC,aAAO,EAAE,aAAa,MAAM;AAAA,IAC9B;AAEA,UAAM,CAAC,WAAW,cAAc,YAAY,IAAI,MAAM,QAAQ,IAAI;AAAA,MAChE,oBAAoB,QAAQ;AAAA,UAC5B,sCAAqB,IAAI,QAAQ,EAAE;AAAA,MACnC,UACI,aAAI,iBAAiB;AAAA,QACnB;AAAA,QACA,cAAc,YAAAA,QAAK,KAAK,iBAAiB,QAAQ;AAAA,MACnD,CAAC,IACD;AAAA,IACN,CAAC;AAGD,QAAI,cAAc,UAAa,cAAc;AAC3C,aAAO,EAAE,aAAa,MAAM;AAAA,IAC9B;AAEA,UAAM,OAAO;AAAA,MACX,gBACI,uCAAoB,cAAc,QAAQ,EAAE,SAAS,IACrD;AAAA,MACJ;AAAA,IACF;AAEA,UAAM,WAAW,YAAAA,QAAK,KAAK,iBAAiB,QAAQ;AAEpD,QAAI,SAAS,UAAU;AACrB,UAAI,SAAS,WAAW;AACtB,eAAO,EAAE,aAAa,MAAM;AAAA,MAC9B;AAEA,gBAAM,2BAAU,UAAU,IAAI;AAC9B,aAAO;AAAA,QACL,aAAa;AAAA,QACb,KAAK,aAAa,OAAO,KAAK,QAAQ,CAAC;AAAA,QACvC;AAAA,MACF;AAAA,IACF;AAEA,QAAI,SAAS,WAAW;AACtB,aAAO;AAAA,QACL,aAAa;AAAA,QACb,KAAK,OAAO,OAAO;AAAA,UACjB;AAAA,QACF,CAAC,+BAA+B,OAAO;AAAA,UACrC,eAAe,MAAM;AAAA,UACrB;AAAA,UACA;AAAA,QACF,CAAC;AAAA,QACD;AAAA,MACF;AAAA,IACF;AAEA,WAAO,EAAE,aAAa,MAAM;AAAA,EAC9B;AAEA,QAAM,iBAAiB,UAAM,4CAAqB,eAAe;AAEjE,QAAM,UAAU,MAAM,QAAQ;AAAA,IAC5B,yBAAyB;AAAA,MAAI,CAAC,SAC5B,kBAAkB,MAAM;AAAA,QACtB;AAAA,QACA,mBAAmB,kBAAkB;AAAA,MACvC,CAAC;AAAA,IACH;AAAA,EACF;AAGA,UAAQ,QAAQ,CAAC,WAAW;AAC1B,QAAI,OAAO,KAAK;AACd,aAAO,KAAK,OAAO,GAAG;AAAA,IACxB;AAAA,EACF,CAAC;AAED,QAAM,kBAAkB,QAAQ,KAAK,CAAC,EAAE,YAAY,MAAM,WAAW;AAErE,SAAO;AAAA,IACL,IAAI,CAAC;AAAA,IACL,SAAS;AAAA,IACT,aAAa,QAAQ;AAAA,MAAQ,CAAC,EAAE,aAAa,UAAU,IAAI,MACzD,eAAe,MACX;AAAA,QACE;AAAA,UACE,MAAM;AAAA,UACN,aAAS,YAAAC,0BAAU,GAAG;AAAA,QACxB;AAAA,MACF,IACA,CAAC;AAAA,IACP;AAAA,EACF;AACF;AAEO,MAAM,wBAAwB,OACnC,MACA,WACgC;AAChC,MAAI;AACF,WAAO,MAAM,mBAAmB,MAAM,MAAM;AAAA,EAC9C,SAAS,KAAK;AACZ,WAAO,KAAK,iCAAiC;AAC7C,WAAO,WAAO,qBAAQ,GAAG,CAAC;AAE1B,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,SAAS;AAAA,MACT,aAAa,CAAC;AAAA,IAChB;AAAA,EACF;AACF;",
|
|
6
|
+
"names": ["path", "stripAnsi"]
|
|
7
7
|
}
|
|
@@ -21,11 +21,16 @@ __export(__exports, {
|
|
|
21
21
|
patches: () => patches
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(__exports);
|
|
24
|
+
var import_migrateNpmrcToPnpmWorkspace = require("./migrateNpmrcToPnpmWorkspace");
|
|
24
25
|
var import_stopBundlingInCDKTests = require("./stopBundlingInCDKTests");
|
|
25
26
|
const patches = [
|
|
26
27
|
{
|
|
27
28
|
apply: import_stopBundlingInCDKTests.tryStopBundlingInCDKTests,
|
|
28
29
|
description: "Stop bundling inside CDK unit tests"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
apply: import_migrateNpmrcToPnpmWorkspace.tryMigrateNpmrcToPnpmWorkspace,
|
|
33
|
+
description: "Move .npmrc config to pnpm-workspace.yaml"
|
|
29
34
|
}
|
|
30
35
|
];
|
|
31
36
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../../src/cli/lint/internalLints/upgrade/patches/10.1.0/index.ts"],
|
|
4
|
-
"sourcesContent": ["import type { Patches } from '../..';\n\nimport { tryStopBundlingInCDKTests } from './stopBundlingInCDKTests';\n\nexport const patches: Patches = [\n {\n apply: tryStopBundlingInCDKTests,\n description: 'Stop bundling inside CDK unit tests',\n },\n];\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,oCAA0C;AAEnC,MAAM,UAAmB;AAAA,EAC9B;AAAA,IACE,OAAO;AAAA,IACP,aAAa;AAAA,EACf;AACF;",
|
|
4
|
+
"sourcesContent": ["import type { Patches } from '../..';\n\nimport { tryMigrateNpmrcToPnpmWorkspace } from './migrateNpmrcToPnpmWorkspace';\nimport { tryStopBundlingInCDKTests } from './stopBundlingInCDKTests';\n\nexport const patches: Patches = [\n {\n apply: tryStopBundlingInCDKTests,\n description: 'Stop bundling inside CDK unit tests',\n },\n {\n apply: tryMigrateNpmrcToPnpmWorkspace,\n description: 'Move .npmrc config to pnpm-workspace.yaml',\n },\n];\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,yCAA+C;AAC/C,oCAA0C;AAEnC,MAAM,UAAmB;AAAA,EAC9B;AAAA,IACE,OAAO;AAAA,IACP,aAAa;AAAA,EACf;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,aAAa;AAAA,EACf;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|