@williamthorsen/nmr 0.16.0 → 0.17.1
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/AGENTS.md +1 -1
- package/README.md +41 -44
- package/dist/esm/cli-build.js +5 -5
- package/dist/esm/cli-ensure-prepublish-hooks.js +33 -34
- package/dist/esm/cli-report-overrides.js +7 -6
- package/dist/esm/cli-sync-agent-files.js +20 -22
- package/dist/esm/cli-sync-pnpm-version.js +7 -6
- package/dist/esm/cli.js +13 -13
- package/dist/esm/commands/build.d.ts +3 -9
- package/dist/esm/commands/build.js +288 -120
- package/dist/esm/commands/ensure-prepublish-hooks.js +66 -69
- package/dist/esm/commands/report-overrides.js +10 -13
- package/dist/esm/commands/sync-agent-files.js +46 -52
- package/dist/esm/commands/sync-pnpm-version.js +35 -42
- package/dist/esm/config.js +59 -57
- package/dist/esm/context.d.ts +1 -1
- package/dist/esm/context.js +70 -72
- package/dist/esm/default-scripts.js +63 -68
- package/dist/esm/help.d.ts +1 -1
- package/dist/esm/help.js +65 -67
- package/dist/esm/helpers/code-quality-pnpm-action.js +20 -24
- package/dist/esm/helpers/hook-name.js +2 -5
- package/dist/esm/helpers/package-json.js +46 -41
- package/dist/esm/helpers/type-guards.js +2 -5
- package/dist/esm/index.d.ts +3 -3
- package/dist/esm/index.js +1 -4
- package/dist/esm/resolve-scripts.d.ts +2 -2
- package/dist/esm/resolve-scripts.js +7 -11
- package/dist/esm/resolver.d.ts +2 -2
- package/dist/esm/resolver.js +84 -86
- package/dist/esm/runCli.js +136 -144
- package/dist/esm/runner.js +35 -34
- package/dist/esm/scripts.d.ts +2 -2
- package/dist/esm/scripts.js +1 -5
- package/dist/esm/tests/consistency.d.ts +1 -1
- package/dist/esm/tests/consistency.js +45 -54
- package/dist/esm/tests/helpers/get-runtime-version-from-asdf.js +11 -14
- package/dist/esm/tests/helpers/get-string-from-yaml-file.js +10 -13
- package/dist/esm/tests/helpers/get-value-at-path.js +30 -30
- package/package.json +5 -3
- package/dist/esm/.cache +0 -1
|
@@ -1,64 +1,58 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from
|
|
2
|
-
import path from
|
|
3
|
-
import { fileURLToPath } from
|
|
4
|
-
import { readPackageVersion } from
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { readPackageVersion } from '@williamthorsen/nmr-core';
|
|
5
5
|
const VERSION = readPackageVersion(import.meta.url);
|
|
6
|
-
const PACKAGE_NAME =
|
|
7
|
-
const DESTINATION_RELATIVE_PATH =
|
|
8
|
-
const SOURCE_FILENAME =
|
|
6
|
+
const PACKAGE_NAME = '@williamthorsen/nmr';
|
|
7
|
+
const DESTINATION_RELATIVE_PATH = '.agents/nmr/AGENTS.md';
|
|
8
|
+
const SOURCE_FILENAME = 'AGENTS.md';
|
|
9
9
|
const FRONTMATTER_REGEX = /^---\n((?:.*\n)*?)---\n/;
|
|
10
|
-
function check(destinationDir) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
10
|
+
export function check(destinationDir) {
|
|
11
|
+
const destinationPath = getDestinationPath(destinationDir);
|
|
12
|
+
if (!existsSync(destinationPath)) {
|
|
13
|
+
return {
|
|
14
|
+
ok: false,
|
|
15
|
+
reason: `${DESTINATION_RELATIVE_PATH} is missing. Run \`nmr sync-agent-files\`.`,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
const expectedBody = stripFrontmatter(readFileSync(getSourcePath(), 'utf8'));
|
|
19
|
+
const foundBody = stripFrontmatter(readFileSync(destinationPath, 'utf8'));
|
|
20
|
+
if (foundBody !== expectedBody) {
|
|
21
|
+
return {
|
|
22
|
+
ok: false,
|
|
23
|
+
reason: `${DESTINATION_RELATIVE_PATH} content is out of date. Run \`nmr sync-agent-files\`.`,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
return { ok: true };
|
|
27
27
|
}
|
|
28
|
-
function sync(destinationDir) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
mkdirSync(path.dirname(destinationPath), { recursive: true });
|
|
40
|
-
writeFileSync(destinationPath, output, "utf8");
|
|
41
|
-
return { path: destinationPath, packageSpecifier, changed: true };
|
|
28
|
+
export function sync(destinationDir) {
|
|
29
|
+
const body = stripFrontmatter(readFileSync(getSourcePath(), 'utf8'));
|
|
30
|
+
const packageSpecifier = buildPackageSpecifier();
|
|
31
|
+
const destinationPath = getDestinationPath(destinationDir);
|
|
32
|
+
if (existsSync(destinationPath) && stripFrontmatter(readFileSync(destinationPath, 'utf8')) === body) {
|
|
33
|
+
return { path: destinationPath, packageSpecifier, changed: false };
|
|
34
|
+
}
|
|
35
|
+
const output = `---\nsource: '${packageSpecifier}'\n---\n${body}`;
|
|
36
|
+
mkdirSync(path.dirname(destinationPath), { recursive: true });
|
|
37
|
+
writeFileSync(destinationPath, output, 'utf8');
|
|
38
|
+
return { path: destinationPath, packageSpecifier, changed: true };
|
|
42
39
|
}
|
|
43
40
|
function buildPackageSpecifier() {
|
|
44
|
-
|
|
41
|
+
return `${PACKAGE_NAME}@${VERSION}`;
|
|
45
42
|
}
|
|
46
43
|
function getDestinationPath(destinationDir) {
|
|
47
|
-
|
|
44
|
+
return path.join(destinationDir, DESTINATION_RELATIVE_PATH);
|
|
48
45
|
}
|
|
49
46
|
function getSourcePath() {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
47
|
+
let dir = path.dirname(fileURLToPath(import.meta.url));
|
|
48
|
+
while (dir !== path.dirname(dir)) {
|
|
49
|
+
const candidate = path.join(dir, SOURCE_FILENAME);
|
|
50
|
+
if (existsSync(candidate))
|
|
51
|
+
return candidate;
|
|
52
|
+
dir = path.dirname(dir);
|
|
53
|
+
}
|
|
54
|
+
throw new Error(`Could not locate ${SOURCE_FILENAME} in any parent of ${fileURLToPath(import.meta.url)}`);
|
|
57
55
|
}
|
|
58
56
|
function stripFrontmatter(content) {
|
|
59
|
-
|
|
57
|
+
return content.replace(FRONTMATTER_REGEX, '');
|
|
60
58
|
}
|
|
61
|
-
export {
|
|
62
|
-
check,
|
|
63
|
-
sync
|
|
64
|
-
};
|
|
@@ -1,47 +1,40 @@
|
|
|
1
|
-
import { readFileSync, writeFileSync } from
|
|
2
|
-
import path from
|
|
3
|
-
import { parseDocument } from
|
|
1
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { parseDocument } from 'yaml';
|
|
4
4
|
import { CodeQualityPnpmWorkflowSchema, getPnpmVersionNodes } from "../helpers/code-quality-pnpm-action.js";
|
|
5
5
|
import { readPackageJson } from "../helpers/package-json.js";
|
|
6
|
-
const WORKFLOW_RELATIVE_PATH =
|
|
6
|
+
const WORKFLOW_RELATIVE_PATH = '.github/workflows/code-quality.yaml';
|
|
7
7
|
function extractPnpmVersion(packageManager) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
if (!packageManager) {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
const match = /^pnpm@(.+)$/.exec(packageManager);
|
|
12
|
+
return match?.[1] ?? null;
|
|
13
13
|
}
|
|
14
|
-
function syncPnpmVersion(monorepoRoot) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
);
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
node.value = pnpmVersion;
|
|
40
|
-
}
|
|
41
|
-
writeFileSync(workflowPath, doc.toString(), "utf8");
|
|
42
|
-
console.info(`\u2713 Updated ${outdatedNodes.length} pnpm-version occurrence(s) \u2192 ${pnpmVersion}`);
|
|
14
|
+
export function syncPnpmVersion(monorepoRoot) {
|
|
15
|
+
console.info('Synchronizing pnpm version in GitHub workflow...');
|
|
16
|
+
const pkg = readPackageJson(monorepoRoot);
|
|
17
|
+
const pnpmVersion = extractPnpmVersion(pkg.packageManager);
|
|
18
|
+
if (!pnpmVersion) {
|
|
19
|
+
throw new Error(`Could not extract pnpm version from package.json packageManager field\npackageManager field: ${pkg.packageManager ?? '(not set)'}`);
|
|
20
|
+
}
|
|
21
|
+
console.info(`Package.json pnpm version: ${pnpmVersion}`);
|
|
22
|
+
const workflowPath = path.join(monorepoRoot, WORKFLOW_RELATIVE_PATH);
|
|
23
|
+
const doc = parseDocument(readFileSync(workflowPath, 'utf8'));
|
|
24
|
+
const [parseError] = doc.errors;
|
|
25
|
+
if (parseError) {
|
|
26
|
+
throw new Error(`Failed to parse workflow file: ${workflowPath}\n${parseError.message}`);
|
|
27
|
+
}
|
|
28
|
+
CodeQualityPnpmWorkflowSchema.parse(doc.toJS());
|
|
29
|
+
const outdatedNodes = getPnpmVersionNodes(doc).filter((node) => String(node.value) !== pnpmVersion);
|
|
30
|
+
if (outdatedNodes.length === 0) {
|
|
31
|
+
console.info('Workflow pnpm version is already up to date');
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
for (const node of outdatedNodes) {
|
|
35
|
+
node.value = pnpmVersion;
|
|
36
|
+
}
|
|
37
|
+
writeFileSync(workflowPath, doc.toString(), 'utf8');
|
|
38
|
+
console.info(`✓ Updated ${outdatedNodes.length} pnpm-version occurrence(s) → ${pnpmVersion}`);
|
|
43
39
|
}
|
|
44
|
-
export {
|
|
45
|
-
extractPnpmVersion,
|
|
46
|
-
syncPnpmVersion
|
|
47
|
-
};
|
|
40
|
+
export { extractPnpmVersion };
|
package/dist/esm/config.js
CHANGED
|
@@ -1,70 +1,72 @@
|
|
|
1
|
-
import { existsSync } from
|
|
2
|
-
import path from
|
|
3
|
-
import { createJiti } from
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { createJiti } from 'jiti';
|
|
4
4
|
import { isObject } from "./helpers/type-guards.js";
|
|
5
|
-
const CONFIG_FILENAME =
|
|
6
|
-
const CONFIG_DIR =
|
|
7
|
-
function defineConfig(config) {
|
|
8
|
-
|
|
5
|
+
const CONFIG_FILENAME = 'nmr.config.ts';
|
|
6
|
+
const CONFIG_DIR = '.config';
|
|
7
|
+
export function defineConfig(config) {
|
|
8
|
+
return config;
|
|
9
9
|
}
|
|
10
10
|
function isScriptRecord(value) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
if (!isObject(value))
|
|
12
|
+
return false;
|
|
13
|
+
for (const v of Object.values(value)) {
|
|
14
|
+
if (typeof v !== 'string' && !Array.isArray(v))
|
|
15
|
+
return false;
|
|
16
|
+
if (Array.isArray(v) && v.some((item) => typeof item !== 'string'))
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
return true;
|
|
17
20
|
}
|
|
18
21
|
function validateScriptField(value, fieldName, configPath) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
return value[fieldName];
|
|
22
|
+
if (!(fieldName in value) || value[fieldName] === undefined) {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
if (!isScriptRecord(value[fieldName])) {
|
|
26
|
+
throw new Error(`Invalid nmr config at ${configPath}: \`${fieldName}\` must be a Record<string, string | string[]>`);
|
|
27
|
+
}
|
|
28
|
+
return value[fieldName];
|
|
28
29
|
}
|
|
29
30
|
function isStringRecord(value) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
if (!isObject(value))
|
|
32
|
+
return false;
|
|
33
|
+
for (const v of Object.values(value)) {
|
|
34
|
+
if (typeof v !== 'string')
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
return true;
|
|
35
38
|
}
|
|
36
39
|
function validateStringRecordField(value, fieldName, configPath) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
if (!(fieldName in value) || value[fieldName] === undefined) {
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
if (!isStringRecord(value[fieldName])) {
|
|
44
|
+
throw new Error(`Invalid nmr config at ${configPath}: \`${fieldName}\` must be a Record<string, string>`);
|
|
45
|
+
}
|
|
46
|
+
return value[fieldName];
|
|
44
47
|
}
|
|
45
48
|
function validateConfig(value, configPath) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
49
|
+
if (!isObject(value)) {
|
|
50
|
+
throw new Error(`Invalid nmr config at ${configPath}: expected an object, got ${typeof value}`);
|
|
51
|
+
}
|
|
52
|
+
const config = {};
|
|
53
|
+
const devBin = validateStringRecordField(value, 'devBin', configPath);
|
|
54
|
+
if (devBin)
|
|
55
|
+
config.devBin = devBin;
|
|
56
|
+
const workspaceScripts = validateScriptField(value, 'workspaceScripts', configPath);
|
|
57
|
+
if (workspaceScripts)
|
|
58
|
+
config.workspaceScripts = workspaceScripts;
|
|
59
|
+
const rootScripts = validateScriptField(value, 'rootScripts', configPath);
|
|
60
|
+
if (rootScripts)
|
|
61
|
+
config.rootScripts = rootScripts;
|
|
62
|
+
return config;
|
|
57
63
|
}
|
|
58
|
-
async function loadConfig(monorepoRoot) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
export async function loadConfig(monorepoRoot) {
|
|
65
|
+
const configPath = path.join(monorepoRoot, CONFIG_DIR, CONFIG_FILENAME);
|
|
66
|
+
if (!existsSync(configPath)) {
|
|
67
|
+
return {};
|
|
68
|
+
}
|
|
69
|
+
const jiti = createJiti(path.join(monorepoRoot, 'package.json'));
|
|
70
|
+
const loaded = await jiti.import(configPath, { default: true });
|
|
71
|
+
return validateConfig(loaded, configPath);
|
|
66
72
|
}
|
|
67
|
-
export {
|
|
68
|
-
defineConfig,
|
|
69
|
-
loadConfig
|
|
70
|
-
};
|
package/dist/esm/context.d.ts
CHANGED
package/dist/esm/context.js
CHANGED
|
@@ -1,84 +1,82 @@
|
|
|
1
|
-
import { existsSync, readdirSync, readFileSync, statSync } from
|
|
2
|
-
import path from
|
|
3
|
-
import { parse } from
|
|
1
|
+
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { parse } from 'yaml';
|
|
4
4
|
import { loadConfig } from "./config.js";
|
|
5
5
|
import { isObject } from "./helpers/type-guards.js";
|
|
6
|
-
function findMonorepoRoot(startDir) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
6
|
+
export function findMonorepoRoot(startDir) {
|
|
7
|
+
let dir = path.resolve(startDir ?? process.cwd());
|
|
8
|
+
for (;;) {
|
|
9
|
+
if (existsSync(path.join(dir, 'pnpm-workspace.yaml'))) {
|
|
10
|
+
return dir;
|
|
11
|
+
}
|
|
12
|
+
const parent = path.dirname(dir);
|
|
13
|
+
if (parent === dir) {
|
|
14
|
+
throw new Error('Could not find monorepo root: no pnpm-workspace.yaml found in any parent directory');
|
|
15
|
+
}
|
|
16
|
+
dir = parent;
|
|
15
17
|
}
|
|
16
|
-
dir = parent;
|
|
17
|
-
}
|
|
18
18
|
}
|
|
19
|
-
function getWorkspacePackageDirs(monorepoRoot) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
19
|
+
export function getWorkspacePackageDirs(monorepoRoot) {
|
|
20
|
+
const workspaceFile = path.join(monorepoRoot, 'pnpm-workspace.yaml');
|
|
21
|
+
const content = readFileSync(workspaceFile, 'utf8');
|
|
22
|
+
const parsed = parse(content);
|
|
23
|
+
const packages = getPackagesFromParsedYaml(parsed);
|
|
24
|
+
if (!packages) {
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
const dirs = [];
|
|
28
|
+
for (const pattern of packages) {
|
|
29
|
+
if (pattern.endsWith('/*')) {
|
|
30
|
+
const prefix = pattern.slice(0, -2);
|
|
31
|
+
const prefixDir = path.resolve(monorepoRoot, prefix);
|
|
32
|
+
if (existsSync(prefixDir)) {
|
|
33
|
+
for (const entry of readdirSync(prefixDir)) {
|
|
34
|
+
const fullPath = path.join(prefixDir, entry);
|
|
35
|
+
if (statSync(fullPath).isDirectory() && existsSync(path.join(fullPath, 'package.json'))) {
|
|
36
|
+
dirs.push(fullPath);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
else if (!pattern.includes('*')) {
|
|
42
|
+
const fullPath = path.resolve(monorepoRoot, pattern);
|
|
43
|
+
if (existsSync(fullPath) && existsSync(path.join(fullPath, 'package.json'))) {
|
|
44
|
+
dirs.push(fullPath);
|
|
45
|
+
}
|
|
38
46
|
}
|
|
39
|
-
}
|
|
40
|
-
} else if (!pattern.includes("*")) {
|
|
41
|
-
const fullPath = path.resolve(monorepoRoot, pattern);
|
|
42
|
-
if (existsSync(fullPath) && existsSync(path.join(fullPath, "package.json"))) {
|
|
43
|
-
dirs.push(fullPath);
|
|
44
|
-
}
|
|
45
47
|
}
|
|
46
|
-
|
|
47
|
-
return dirs;
|
|
48
|
+
return dirs;
|
|
48
49
|
}
|
|
49
|
-
function findContainingPackageDir(dir, workspacePackageDirs) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
export function findContainingPackageDir(dir, workspacePackageDirs) {
|
|
51
|
+
const resolved = path.resolve(dir);
|
|
52
|
+
for (const pkgDir of workspacePackageDirs) {
|
|
53
|
+
const resolvedPkgDir = path.resolve(pkgDir);
|
|
54
|
+
if (resolved === resolvedPkgDir || resolved.startsWith(resolvedPkgDir + path.sep)) {
|
|
55
|
+
return resolvedPkgDir;
|
|
56
|
+
}
|
|
55
57
|
}
|
|
56
|
-
|
|
57
|
-
return void 0;
|
|
58
|
+
return undefined;
|
|
58
59
|
}
|
|
59
60
|
function getPackagesFromParsedYaml(parsed) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
61
|
+
if (!isObject(parsed))
|
|
62
|
+
return undefined;
|
|
63
|
+
const packages = parsed.packages;
|
|
64
|
+
if (!Array.isArray(packages))
|
|
65
|
+
return undefined;
|
|
66
|
+
if (!packages.every((p) => typeof p === 'string'))
|
|
67
|
+
return undefined;
|
|
68
|
+
return packages;
|
|
65
69
|
}
|
|
66
|
-
async function resolveContext(cwd) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
70
|
+
export async function resolveContext(cwd) {
|
|
71
|
+
const resolvedCwd = path.resolve(cwd ?? process.cwd());
|
|
72
|
+
const monorepoRoot = findMonorepoRoot(resolvedCwd);
|
|
73
|
+
const config = await loadConfig(monorepoRoot);
|
|
74
|
+
const workspaceDirs = getWorkspacePackageDirs(monorepoRoot);
|
|
75
|
+
const packageDir = findContainingPackageDir(resolvedCwd, workspaceDirs);
|
|
76
|
+
return {
|
|
77
|
+
monorepoRoot,
|
|
78
|
+
isRoot: packageDir === undefined,
|
|
79
|
+
...(packageDir === undefined ? {} : { packageDir }),
|
|
80
|
+
config,
|
|
81
|
+
};
|
|
78
82
|
}
|
|
79
|
-
export {
|
|
80
|
-
findContainingPackageDir,
|
|
81
|
-
findMonorepoRoot,
|
|
82
|
-
getWorkspacePackageDirs,
|
|
83
|
-
resolveContext
|
|
84
|
-
};
|
|
@@ -1,72 +1,67 @@
|
|
|
1
|
-
const commonWorkspaceScripts = {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
export const commonWorkspaceScripts = {
|
|
2
|
+
attw: 'attw --pack --profile esm-only',
|
|
3
|
+
build: ['compile'],
|
|
4
|
+
check: ['typecheck', 'fmt:check', 'lint:check', 'test'],
|
|
5
|
+
'check:strict': ['typecheck', 'fmt:check', 'lint:strict', 'test:coverage', 'attw'],
|
|
6
|
+
clean: 'pnpm exec rimraf dist/*',
|
|
7
|
+
compile: 'nmr-compile',
|
|
8
|
+
fix: ['lint', 'fmt'],
|
|
9
|
+
'fix:check': ['fmt:check', 'lint:check'],
|
|
10
|
+
fmt: 'prettier --list-different --write .',
|
|
11
|
+
'fmt:check': 'prettier --check .',
|
|
12
|
+
lint: 'eslint --fix .',
|
|
13
|
+
'lint:check': 'eslint .',
|
|
14
|
+
'lint:strict': 'strict-lint',
|
|
15
|
+
typecheck: 'tsgo --noEmit',
|
|
16
|
+
'view-coverage': 'open coverage/index.html',
|
|
17
17
|
};
|
|
18
|
-
const integrationTestScripts = {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
export const integrationTestScripts = {
|
|
19
|
+
test: 'pnpm exec vitest --config=vitest.standalone.config.ts',
|
|
20
|
+
'test:all': 'pnpm exec vitest',
|
|
21
|
+
'test:coverage': 'pnpm exec vitest --config=vitest.standalone.config.ts --coverage',
|
|
22
|
+
'test:integration': 'pnpm exec vitest --config=vitest.integration.config.ts',
|
|
23
|
+
'test:watch': 'pnpm exec vitest --config=vitest.standalone.config.ts --watch',
|
|
24
24
|
};
|
|
25
|
-
const standardTestScripts = {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
export const standardTestScripts = {
|
|
26
|
+
test: 'pnpm exec vitest',
|
|
27
|
+
'test:coverage': 'pnpm exec vitest --coverage',
|
|
28
|
+
'test:watch': 'pnpm exec vitest --watch',
|
|
29
29
|
};
|
|
30
|
-
const rootScripts = {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
export {
|
|
68
|
-
commonWorkspaceScripts,
|
|
69
|
-
integrationTestScripts,
|
|
70
|
-
rootScripts,
|
|
71
|
-
standardTestScripts
|
|
30
|
+
export const rootScripts = {
|
|
31
|
+
attw: 'pnpm --recursive exec nmr attw',
|
|
32
|
+
audit: ['audit:prod', 'audit:dev'],
|
|
33
|
+
'audit:dev': 'pnpm exec v11y --dev',
|
|
34
|
+
'audit:prod': 'pnpm exec v11y --prod',
|
|
35
|
+
build: 'pnpm --recursive exec nmr build',
|
|
36
|
+
check: ['typecheck', 'fmt:check', 'lint:check', 'test'],
|
|
37
|
+
'check:agent-files': 'nmr-sync-agent-files --check',
|
|
38
|
+
'check:strict': ['typecheck', 'fmt:check', 'lint:strict', 'test:coverage', 'attw', 'check:agent-files'],
|
|
39
|
+
ci: ['build', 'check:strict', 'audit'],
|
|
40
|
+
clean: 'pnpm --recursive exec nmr clean',
|
|
41
|
+
fix: ['lint', 'fmt'],
|
|
42
|
+
'fix:check': ['fmt:check', 'lint:check'],
|
|
43
|
+
fmt: 'sh -c \'prettier --list-different --write "${@:-.}"\' --',
|
|
44
|
+
'fmt:all': ['fmt', 'fmt:sh'],
|
|
45
|
+
'fmt:check': 'sh -c \'prettier --check "${@:-.}"\' --',
|
|
46
|
+
'fmt:sh': 'shfmt --write **/*.sh',
|
|
47
|
+
lint: 'nmr root:lint && pnpm --recursive exec nmr lint',
|
|
48
|
+
'lint:check': 'nmr root:lint:check && pnpm --recursive exec nmr lint:check',
|
|
49
|
+
'lint:strict': 'nmr root:lint:strict && pnpm --recursive exec nmr lint:strict',
|
|
50
|
+
outdated: 'pnpm outdated --compatible --recursive',
|
|
51
|
+
'outdated:latest': 'pnpm outdated --recursive',
|
|
52
|
+
'report-overrides': 'nmr-report-overrides',
|
|
53
|
+
'root:check': ['root:typecheck', 'fmt:check', 'root:lint:check', 'root:test'],
|
|
54
|
+
'root:lint': "eslint --fix --ignore-pattern 'packages/**' .",
|
|
55
|
+
'root:lint:check': "eslint --ignore-pattern 'packages/**' .",
|
|
56
|
+
'root:lint:strict': "strict-lint --ignore-pattern 'packages/**' .",
|
|
57
|
+
'root:test': 'vitest --config ./vitest.root.config.ts',
|
|
58
|
+
'root:typecheck': 'tsgo --noEmit',
|
|
59
|
+
'sync-agent-files': 'nmr-sync-agent-files',
|
|
60
|
+
'sync-pnpm-version': 'nmr-sync-pnpm-version',
|
|
61
|
+
test: 'nmr root:test && pnpm --recursive exec nmr test',
|
|
62
|
+
'test:coverage': 'nmr root:test && pnpm --recursive exec nmr test:coverage',
|
|
63
|
+
'test:watch': 'vitest --watch',
|
|
64
|
+
typecheck: 'nmr root:typecheck && pnpm --recursive exec nmr typecheck',
|
|
65
|
+
update: 'pnpm update --recursive',
|
|
66
|
+
'update:latest': 'pnpm update --latest --recursive',
|
|
72
67
|
};
|