@smoothbricks/cli 0.4.1 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/run.d.ts.map +1 -1
- package/dist/lib/run.js +1 -5
- package/dist/monorepo/managed-files.d.ts.map +1 -1
- package/dist/monorepo/managed-files.js +11 -0
- package/dist/monorepo/packed-package.d.ts.map +1 -1
- package/dist/monorepo/packed-package.js +132 -24
- package/dist/monorepo/packs/index.js +2 -0
- package/dist/nx/index.d.ts +4 -0
- package/dist/nx/index.d.ts.map +1 -1
- package/dist/nx/index.js +32 -0
- package/managed/raw/envrc +18 -0
- package/managed/raw/tooling/direnv/setup-environment.ts +131 -0
- package/package.json +3 -3
- package/src/lib/run.ts +1 -5
- package/src/monorepo/managed-files.ts +11 -0
- package/src/monorepo/packed-package.ts +145 -24
- package/src/monorepo/packs/index.ts +2 -0
- package/src/nx/index.ts +36 -0
package/dist/lib/run.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/lib/run.ts"],"names":[],"mappings":"AAMA,wBAAsB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAKnH;AAED,wBAAsB,SAAS,CAC7B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,EACX,KAAK,UAAQ,EACb,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC3B,OAAO,CAAC,MAAM,CAAC,CAQjB;AAED,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,EACX,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC3B,OAAO,CAAC,MAAM,CAAC,CAiBjB;AAED,wBAAsB,SAAS,CAC7B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,EACX,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC3B,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAY/D;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAOvE;
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/lib/run.ts"],"names":[],"mappings":"AAMA,wBAAsB,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAKnH;AAED,wBAAsB,SAAS,CAC7B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,EACX,KAAK,UAAQ,EACb,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC3B,OAAO,CAAC,MAAM,CAAC,CAQjB;AAED,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,EACX,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC3B,OAAO,CAAC,MAAM,CAAC,CAiBjB;AAED,wBAAsB,SAAS,CAC7B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,EACX,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC3B,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAY/D;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAOvE;AAmCD,wBAAsB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,CAMpD;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAEhD"}
|
package/dist/lib/run.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
2
|
import { existsSync } from 'node:fs';
|
|
3
|
-
import {
|
|
3
|
+
import { join } from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
5
|
import { $ } from 'bun';
|
|
6
6
|
export async function run(command, args, cwd, env) {
|
|
@@ -82,10 +82,6 @@ function resolveBundledCommand(command) {
|
|
|
82
82
|
if (command === 'sherif') {
|
|
83
83
|
return fileURLToPath(import.meta.resolve('sherif'));
|
|
84
84
|
}
|
|
85
|
-
if (command === 'attw') {
|
|
86
|
-
const packageJson = fileURLToPath(import.meta.resolve('@arethetypeswrong/cli/package.json'));
|
|
87
|
-
return join(dirname(packageJson), 'dist', 'index.js');
|
|
88
|
-
}
|
|
89
85
|
}
|
|
90
86
|
catch {
|
|
91
87
|
return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"managed-files.d.ts","sourceRoot":"","sources":["../../src/monorepo/managed-files.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,iBAAiB,GAAG,SAAS,GAAG,YAAY,CAAC;CACxG;
|
|
1
|
+
{"version":3,"file":"managed-files.d.ts","sourceRoot":"","sources":["../../src/monorepo/managed-files.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,iBAAiB,GAAG,SAAS,GAAG,YAAY,CAAC;CACxG;AAmGD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,UAAU,EAAE,CAG/F;AA4KD,wBAAgB,YAAY,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,IAAI,CAIxD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQzD"}
|
|
@@ -6,6 +6,11 @@ import { listReleasePackages, readPackageJson } from '../lib/workspace.js';
|
|
|
6
6
|
import { renderCiWorkflowYaml } from './ci-workflow.js';
|
|
7
7
|
import { renderPublishWorkflowYaml } from './publish-workflow.js';
|
|
8
8
|
const managedFiles = [
|
|
9
|
+
{
|
|
10
|
+
kind: 'raw',
|
|
11
|
+
source: 'envrc',
|
|
12
|
+
target: '.envrc',
|
|
13
|
+
},
|
|
9
14
|
{
|
|
10
15
|
kind: 'raw',
|
|
11
16
|
source: 'tooling/direnv/repo-path',
|
|
@@ -18,6 +23,12 @@ const managedFiles = [
|
|
|
18
23
|
target: 'tooling/direnv/github-actions-bootstrap.sh',
|
|
19
24
|
executable: true,
|
|
20
25
|
},
|
|
26
|
+
{
|
|
27
|
+
kind: 'raw',
|
|
28
|
+
source: 'tooling/direnv/setup-environment.ts',
|
|
29
|
+
target: 'tooling/direnv/setup-environment.ts',
|
|
30
|
+
executable: true,
|
|
31
|
+
},
|
|
21
32
|
{
|
|
22
33
|
kind: 'raw',
|
|
23
34
|
source: 'tooling/git-hooks/pre-commit.sh',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packed-package.d.ts","sourceRoot":"","sources":["../../src/monorepo/packed-package.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"packed-package.d.ts","sourceRoot":"","sources":["../../src/monorepo/packed-package.ts"],"names":[],"mappings":"AAYA,wBAAsB,4BAA4B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAMhF;AAED,wBAAsB,kCAAkC,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAMtF;AAED,wBAAsB,mCAAmC,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAMvF;AAED,wBAAsB,gCAAgC,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAMpF"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { readFileSync, rmSync, unlinkSync } from 'node:fs';
|
|
2
|
-
import {
|
|
1
|
+
import { mkdtempSync, readdirSync, readFileSync, rmSync, statSync, unlinkSync } from 'node:fs';
|
|
2
|
+
import { tmpdir } from 'node:os';
|
|
3
|
+
import { dirname, join, relative } from 'node:path';
|
|
4
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
3
5
|
import { publint } from 'publint';
|
|
4
6
|
import { formatMessage } from 'publint/utils';
|
|
5
7
|
import { isRecord } from '../lib/json.js';
|
|
@@ -65,37 +67,143 @@ async function validatePackedManifest(root, pkg, packed) {
|
|
|
65
67
|
return failures;
|
|
66
68
|
}
|
|
67
69
|
async function validateAttw(root, pkg, packed) {
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
'--profile',
|
|
74
|
-
'node16',
|
|
75
|
-
'--ignore-rules',
|
|
76
|
-
'cjs-resolves-to-esm',
|
|
77
|
-
...attwExcludedEntrypointArgs(pkg),
|
|
78
|
-
];
|
|
79
|
-
const attw = await runResult('attw', attwArgs, root);
|
|
80
|
-
if (attw.exitCode === 0) {
|
|
70
|
+
const attw = await loadAttwCore();
|
|
71
|
+
const analysis = await attw.checkPackage(await createAttwPackageFromTarball(attw, root, packed.path), {
|
|
72
|
+
excludeEntrypoints: wasmExportEntrypoints(pkg.json.exports),
|
|
73
|
+
});
|
|
74
|
+
if (!isRecord(analysis) || analysis.types === false) {
|
|
81
75
|
return 0;
|
|
82
76
|
}
|
|
83
|
-
|
|
84
|
-
|
|
77
|
+
const rawProblems = Array.isArray(analysis.problems) ? analysis.problems : [];
|
|
78
|
+
const problems = rawProblems.filter(isReportedAttwProblem);
|
|
79
|
+
if (problems.length === 0) {
|
|
80
|
+
return 0;
|
|
81
|
+
}
|
|
82
|
+
for (const problem of problems) {
|
|
83
|
+
console.error(`${pkg.path}: are-the-types-wrong ${problem.kind}${formatProblemLocation(problem)}`);
|
|
84
|
+
}
|
|
85
85
|
console.error(`${pkg.path}: are-the-types-wrong validation failed`);
|
|
86
86
|
return 1;
|
|
87
87
|
}
|
|
88
|
-
function
|
|
89
|
-
|
|
90
|
-
|
|
88
|
+
async function loadAttwCore() {
|
|
89
|
+
const packageJson = fileURLToPath(import.meta.resolve('@arethetypeswrong/core/package.json'));
|
|
90
|
+
const core = await import(pathToFileURL(join(dirname(packageJson), 'dist', 'index.js')).href);
|
|
91
|
+
if (!isRecord(core)) {
|
|
92
|
+
throw new Error('@arethetypeswrong/core does not expose the expected API');
|
|
93
|
+
}
|
|
94
|
+
const PackageConstructor = core.Package;
|
|
95
|
+
const checkPackage = core.checkPackage;
|
|
96
|
+
if (typeof PackageConstructor !== 'function' || typeof checkPackage !== 'function') {
|
|
97
|
+
throw new Error('@arethetypeswrong/core does not expose the expected API');
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
createPackage: (files, packageName, packageVersion) => Reflect.construct(PackageConstructor, [files, packageName, packageVersion]),
|
|
101
|
+
checkPackage: (pkg, options) => Promise.resolve(checkPackage(pkg, options)),
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
async function createAttwPackageFromTarball(attw, root, tarballPath) {
|
|
105
|
+
const temp = mkdtempSync(join(tmpdir(), 'smoo-attw-'));
|
|
106
|
+
try {
|
|
107
|
+
const extract = await runResult('tar', ['-xzf', tarballPath, '-C', temp], root);
|
|
108
|
+
if (extract.exitCode !== 0) {
|
|
109
|
+
printCommandOutput(extract.stdout, extract.stderr);
|
|
110
|
+
throw new Error('unable to extract packed package for are-the-types-wrong');
|
|
111
|
+
}
|
|
112
|
+
return createAttwPackageFromDirectory(attw, join(temp, 'package'));
|
|
113
|
+
}
|
|
114
|
+
finally {
|
|
115
|
+
rmSync(temp, { recursive: true, force: true });
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
function createAttwPackageFromDirectory(attw, packageDir) {
|
|
119
|
+
const packageJson = readJsonFile(join(packageDir, 'package.json'));
|
|
120
|
+
const packageName = typeof packageJson.name === 'string' ? packageJson.name : null;
|
|
121
|
+
const packageVersion = typeof packageJson.version === 'string' ? packageJson.version : null;
|
|
122
|
+
if (!packageName || !packageVersion) {
|
|
123
|
+
throw new Error('packed package.json must contain name and version');
|
|
124
|
+
}
|
|
125
|
+
const files = {};
|
|
126
|
+
collectAttwFiles(packageDir, packageDir, packageName, files);
|
|
127
|
+
return attw.createPackage(files, packageName, packageVersion);
|
|
128
|
+
}
|
|
129
|
+
function collectAttwFiles(root, current, packageName, files) {
|
|
130
|
+
for (const entry of readdirSync(current)) {
|
|
131
|
+
const path = join(current, entry);
|
|
132
|
+
const stat = statSync(path);
|
|
133
|
+
if (stat.isDirectory()) {
|
|
134
|
+
collectAttwFiles(root, path, packageName, files);
|
|
91
135
|
continue;
|
|
92
136
|
}
|
|
93
|
-
|
|
137
|
+
if (!stat.isFile()) {
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
const packageRelativePath = relative(root, path).split('\\').join('/');
|
|
141
|
+
files[`/node_modules/${packageName}/${packageRelativePath}`] = new Uint8Array(readFileSync(path));
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
function readJsonFile(path) {
|
|
145
|
+
const parsed = JSON.parse(readFileSync(path, 'utf8'));
|
|
146
|
+
if (!isRecord(parsed)) {
|
|
147
|
+
throw new Error(`${path} is not a JSON object`);
|
|
148
|
+
}
|
|
149
|
+
return parsed;
|
|
150
|
+
}
|
|
151
|
+
function isReportedAttwProblem(problem) {
|
|
152
|
+
if (!isRecord(problem) || typeof problem.kind !== 'string') {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
const flag = attwProblemFlag(problem.kind);
|
|
156
|
+
if (flag === 'cjs-resolves-to-esm') {
|
|
157
|
+
return false;
|
|
94
158
|
}
|
|
159
|
+
return problem.resolutionKind !== 'node10';
|
|
95
160
|
}
|
|
96
|
-
function
|
|
97
|
-
|
|
98
|
-
|
|
161
|
+
function attwProblemFlag(kind) {
|
|
162
|
+
switch (kind) {
|
|
163
|
+
case 'NoResolution':
|
|
164
|
+
return 'no-resolution';
|
|
165
|
+
case 'UntypedResolution':
|
|
166
|
+
return 'untyped-resolution';
|
|
167
|
+
case 'FalseCJS':
|
|
168
|
+
return 'false-cjs';
|
|
169
|
+
case 'FalseESM':
|
|
170
|
+
return 'false-esm';
|
|
171
|
+
case 'CJSResolvesToESM':
|
|
172
|
+
return 'cjs-resolves-to-esm';
|
|
173
|
+
case 'FallbackCondition':
|
|
174
|
+
return 'fallback-condition';
|
|
175
|
+
case 'CJSOnlyExportsDefault':
|
|
176
|
+
return 'cjs-only-exports-default';
|
|
177
|
+
case 'NamedExports':
|
|
178
|
+
return 'named-exports';
|
|
179
|
+
case 'FalseExportDefault':
|
|
180
|
+
return 'false-export-default';
|
|
181
|
+
case 'MissingExportEquals':
|
|
182
|
+
return 'missing-export-equals';
|
|
183
|
+
case 'UnexpectedModuleSyntax':
|
|
184
|
+
return 'unexpected-module-syntax';
|
|
185
|
+
case 'InternalResolutionError':
|
|
186
|
+
return 'internal-resolution-error';
|
|
187
|
+
default:
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
function formatProblemLocation(problem) {
|
|
192
|
+
if (!isRecord(problem)) {
|
|
193
|
+
return '';
|
|
194
|
+
}
|
|
195
|
+
const entrypoint = typeof problem.entrypoint === 'string' ? ` ${problem.entrypoint}` : '';
|
|
196
|
+
const resolution = typeof problem.resolutionKind === 'string' ? ` ${formatResolutionKind(problem.resolutionKind)}` : '';
|
|
197
|
+
return `${entrypoint}${resolution}`;
|
|
198
|
+
}
|
|
199
|
+
function formatResolutionKind(kind) {
|
|
200
|
+
if (kind === 'node16-cjs') {
|
|
201
|
+
return 'node16 (from CJS)';
|
|
202
|
+
}
|
|
203
|
+
if (kind === 'node16-esm') {
|
|
204
|
+
return 'node16 (from ESM)';
|
|
205
|
+
}
|
|
206
|
+
return kind;
|
|
99
207
|
}
|
|
100
208
|
function wasmExportEntrypoints(exports) {
|
|
101
209
|
if (!isRecord(exports)) {
|
|
@@ -296,6 +296,8 @@ async function readResolvedTargetsByProject(ctx) {
|
|
|
296
296
|
{
|
|
297
297
|
targets: new Set(project.targets),
|
|
298
298
|
...(project.buildDependsOn ? { buildDependsOn: project.buildDependsOn } : {}),
|
|
299
|
+
...(project.targetExecutors ? { targetExecutors: project.targetExecutors } : {}),
|
|
300
|
+
...(project.targetScripts ? { targetScripts: project.targetScripts } : {}),
|
|
299
301
|
},
|
|
300
302
|
]));
|
|
301
303
|
}
|
package/dist/nx/index.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ export interface ProjectTargets {
|
|
|
2
2
|
project: string;
|
|
3
3
|
targets: string[];
|
|
4
4
|
buildDependsOn?: string[];
|
|
5
|
+
targetExecutors?: Map<string, string>;
|
|
6
|
+
targetScripts?: Map<string, string>;
|
|
5
7
|
}
|
|
6
8
|
export interface CommandInvocation {
|
|
7
9
|
command: string;
|
|
@@ -12,6 +14,8 @@ export declare function nxShowProjectCommand(project: string): CommandInvocation
|
|
|
12
14
|
export declare function nxCacheDirectories(root: string): string[];
|
|
13
15
|
export declare function targetNamesFromNxProjectJson(value: unknown): string[];
|
|
14
16
|
export declare function buildDependsOnFromNxProjectJson(value: unknown): string[] | undefined;
|
|
17
|
+
export declare function targetExecutorsFromNxProjectJson(value: unknown): Map<string, string>;
|
|
18
|
+
export declare function targetScriptsFromNxProjectJson(value: unknown): Map<string, string>;
|
|
15
19
|
export declare function formatProjectTargetLines(projects: ProjectTargets[]): string;
|
|
16
20
|
export declare function projectNamesWithTarget(projects: ProjectTargets[], target: string): string[];
|
|
17
21
|
export declare function projectNamesFromNxShowProjectsOutput(output: string): string[];
|
package/dist/nx/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/nx/index.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/nx/index.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,wBAAgB,cAAc,IAAI,iBAAiB,CAElD;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,CAEvE;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAEzD;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAGrE;AAED,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,GAAG,SAAS,CAOpF;AAED,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,OAAO,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAYpF;AAED,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,OAAO,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAgBlF;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,MAAM,CAK3E;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,cAAc,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAK3F;AAED,wBAAgB,oCAAoC,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAsB7E;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAK7D;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAQhG;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAG5D;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAa5D;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAGhF"}
|
package/dist/nx/index.js
CHANGED
|
@@ -25,6 +25,36 @@ export function buildDependsOnFromNxProjectJson(value) {
|
|
|
25
25
|
}
|
|
26
26
|
return build.dependsOn;
|
|
27
27
|
}
|
|
28
|
+
export function targetExecutorsFromNxProjectJson(value) {
|
|
29
|
+
const targets = isRecord(value) ? recordProperty(value, 'targets') : null;
|
|
30
|
+
const executors = new Map();
|
|
31
|
+
if (!targets) {
|
|
32
|
+
return executors;
|
|
33
|
+
}
|
|
34
|
+
for (const [targetName, target] of Object.entries(targets)) {
|
|
35
|
+
if (isRecord(target) && typeof target.executor === 'string') {
|
|
36
|
+
executors.set(targetName, target.executor);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return executors;
|
|
40
|
+
}
|
|
41
|
+
export function targetScriptsFromNxProjectJson(value) {
|
|
42
|
+
const targets = isRecord(value) ? recordProperty(value, 'targets') : null;
|
|
43
|
+
const scripts = new Map();
|
|
44
|
+
if (!targets) {
|
|
45
|
+
return scripts;
|
|
46
|
+
}
|
|
47
|
+
for (const [targetName, target] of Object.entries(targets)) {
|
|
48
|
+
if (!isRecord(target)) {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const options = recordProperty(target, 'options');
|
|
52
|
+
if (typeof options?.script === 'string') {
|
|
53
|
+
scripts.set(targetName, options.script);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return scripts;
|
|
57
|
+
}
|
|
28
58
|
export function formatProjectTargetLines(projects) {
|
|
29
59
|
return projects
|
|
30
60
|
.flatMap((project) => project.targets.map((target) => `${project.project}:${target}`))
|
|
@@ -108,5 +138,7 @@ async function readProjectTarget(root, project) {
|
|
|
108
138
|
project,
|
|
109
139
|
targets: targetNamesFromNxProjectJson(parsed),
|
|
110
140
|
buildDependsOn: buildDependsOnFromNxProjectJson(parsed),
|
|
141
|
+
targetExecutors: targetExecutorsFromNxProjectJson(parsed),
|
|
142
|
+
targetScripts: targetScriptsFromNxProjectJson(parsed),
|
|
111
143
|
};
|
|
112
144
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Worktrees inherit the real project .envrc once, then stop. The same file is
|
|
2
|
+
# checked out inside .jcode-worktrees, so continuing after source_up_if_exists
|
|
3
|
+
# would run the devenv setup twice while sandbox blocks access to tooling/.
|
|
4
|
+
case "$PWD" in
|
|
5
|
+
*/.jcode-worktrees/*)
|
|
6
|
+
;;
|
|
7
|
+
*)
|
|
8
|
+
source_up_if_exists
|
|
9
|
+
;;
|
|
10
|
+
esac
|
|
11
|
+
|
|
12
|
+
watch_file tooling/direnv/envrc.sh
|
|
13
|
+
|
|
14
|
+
cd tooling/direnv
|
|
15
|
+
. envrc.sh
|
|
16
|
+
|
|
17
|
+
# Load local extensions and overrides
|
|
18
|
+
source_env_if_exists .envrc-local
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { mkdir, rmdir } from 'node:fs/promises';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { $ } from 'bun';
|
|
6
|
+
|
|
7
|
+
const devenvRoot = process.env.DEVENV_ROOT;
|
|
8
|
+
const projectRoot = path.resolve(`${devenvRoot}/../..`);
|
|
9
|
+
const startedWithoutNodeModules = !existsSync(path.join(projectRoot, 'node_modules'));
|
|
10
|
+
|
|
11
|
+
class CapturedCommandError extends Error {
|
|
12
|
+
constructor(
|
|
13
|
+
public readonly command: string,
|
|
14
|
+
public readonly exitCode: number,
|
|
15
|
+
public readonly stdout: Uint8Array,
|
|
16
|
+
public readonly stderr: Uint8Array,
|
|
17
|
+
) {
|
|
18
|
+
super(`${command} failed with exit code ${exitCode}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Go to project root
|
|
23
|
+
process.chdir(projectRoot);
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
// Install dependencies first so node_modules/.bin tools are available
|
|
27
|
+
if (process.env.CI) {
|
|
28
|
+
try {
|
|
29
|
+
await runSetupCommand('bun install --frozen-lockfile', $`bun install --frozen-lockfile`, { quiet: false });
|
|
30
|
+
} catch (error) {
|
|
31
|
+
console.error('! Failed to install dependencies with frozen lockfile');
|
|
32
|
+
replayCapturedOutput(error);
|
|
33
|
+
await runSetupCommand('bun install', $`bun install`, { quiet: false });
|
|
34
|
+
console.error('git diff after install:');
|
|
35
|
+
await runSetupCommand('git diff', $`git diff`, { quiet: false, allowNonzero: true });
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
await installLocalDependencies();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Bun selects its resolver mode at process startup. If this process started
|
|
43
|
+
// before node_modules existed, imports below can stay in auto-install mode
|
|
44
|
+
// even after bun install succeeds, so restart once into the real workspace.
|
|
45
|
+
if (startedWithoutNodeModules) {
|
|
46
|
+
await runSetupCommand('restart setup-environment.ts', $`bun --no-install ${import.meta.path}`, { quiet: false });
|
|
47
|
+
process.exit(0);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (!process.env.CI) {
|
|
51
|
+
const { syncRootRuntimeVersions } = await import('@smoothbricks/cli/monorepo/runtime');
|
|
52
|
+
await syncRootRuntimeVersions(projectRoot);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const { applyWorkspaceGitConfig } = await import('@smoothbricks/cli/monorepo/git-config');
|
|
56
|
+
await applyWorkspaceGitConfig(projectRoot);
|
|
57
|
+
} catch (error) {
|
|
58
|
+
if (error instanceof CapturedCommandError) {
|
|
59
|
+
console.error(`--- ERROR: setup-environment.ts failed while running: ${error.command}`);
|
|
60
|
+
console.error(`exit code: ${error.exitCode}`);
|
|
61
|
+
} else {
|
|
62
|
+
console.error(`--- ERROR: setup-environment.ts failed: ${error}`);
|
|
63
|
+
}
|
|
64
|
+
replayCapturedOutput(error);
|
|
65
|
+
console.error('\n---');
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async function installLocalDependencies(): Promise<void> {
|
|
70
|
+
// bun install runs the root prepare script, which patches TypeScript with
|
|
71
|
+
// ts-patch. Multiple concurrent direnv activations can otherwise race while
|
|
72
|
+
// mutating the same files under node_modules.
|
|
73
|
+
await withSetupLock(async () => {
|
|
74
|
+
await runSetupCommand('bun install --no-summary', $`bun install --no-summary`);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async function runSetupCommand(
|
|
79
|
+
command: string,
|
|
80
|
+
shell: ReturnType<typeof $>,
|
|
81
|
+
options: { quiet?: boolean; allowNonzero?: boolean } = {},
|
|
82
|
+
): Promise<void> {
|
|
83
|
+
const result = await shell
|
|
84
|
+
.quiet(options.quiet ?? true)
|
|
85
|
+
.nothrow()
|
|
86
|
+
.cwd(projectRoot);
|
|
87
|
+
if (result.exitCode !== 0 && options.allowNonzero !== true) {
|
|
88
|
+
throw new CapturedCommandError(command, result.exitCode, result.stdout, result.stderr);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async function withSetupLock<T>(fn: () => Promise<T>): Promise<T> {
|
|
93
|
+
const lockDir = path.join(projectRoot, 'tooling/direnv/.devenv/setup-environment.lock');
|
|
94
|
+
await acquireLock(lockDir);
|
|
95
|
+
try {
|
|
96
|
+
return await fn();
|
|
97
|
+
} finally {
|
|
98
|
+
await rmdir(lockDir).catch(() => undefined);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async function acquireLock(lockDir: string): Promise<void> {
|
|
103
|
+
const deadline = Date.now() + 120_000;
|
|
104
|
+
while (true) {
|
|
105
|
+
try {
|
|
106
|
+
await mkdir(lockDir, { recursive: false });
|
|
107
|
+
return;
|
|
108
|
+
} catch (error) {
|
|
109
|
+
if (!isFileExistsError(error) || Date.now() > deadline) {
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
await Bun.sleep(100);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function isFileExistsError(error: unknown): boolean {
|
|
118
|
+
return error instanceof Error && 'code' in error && error.code === 'EEXIST';
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function replayCapturedOutput(error: unknown): void {
|
|
122
|
+
if (!(error instanceof CapturedCommandError)) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (error.stdout.length > 0) {
|
|
126
|
+
process.stdout.write(error.stdout);
|
|
127
|
+
}
|
|
128
|
+
if (error.stderr.length > 0) {
|
|
129
|
+
process.stderr.write(error.stderr);
|
|
130
|
+
}
|
|
131
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smoothbricks/cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "SmoothBricks monorepo automation CLI",
|
|
6
6
|
"bin": {
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
"!**/*.tsbuildinfo"
|
|
45
45
|
],
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@arethetypeswrong/
|
|
48
|
-
"@smoothbricks/nx-plugin": "0.2.
|
|
47
|
+
"@arethetypeswrong/core": "^0.18.2",
|
|
48
|
+
"@smoothbricks/nx-plugin": "0.2.5",
|
|
49
49
|
"@smoothbricks/validation": "0.1.1",
|
|
50
50
|
"commander": "^14.0.3",
|
|
51
51
|
"publint": "^0.3.18",
|
package/src/lib/run.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
2
|
import { existsSync } from 'node:fs';
|
|
3
|
-
import {
|
|
3
|
+
import { join } from 'node:path';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
5
|
import { $ } from 'bun';
|
|
6
6
|
|
|
@@ -106,10 +106,6 @@ function resolveBundledCommand(command: string): string | null {
|
|
|
106
106
|
if (command === 'sherif') {
|
|
107
107
|
return fileURLToPath(import.meta.resolve('sherif'));
|
|
108
108
|
}
|
|
109
|
-
if (command === 'attw') {
|
|
110
|
-
const packageJson = fileURLToPath(import.meta.resolve('@arethetypeswrong/cli/package.json'));
|
|
111
|
-
return join(dirname(packageJson), 'dist', 'index.js');
|
|
112
|
-
}
|
|
113
109
|
} catch {
|
|
114
110
|
return null;
|
|
115
111
|
}
|
|
@@ -38,6 +38,11 @@ interface DeployTargetInfo {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
const managedFiles: ManagedFile[] = [
|
|
41
|
+
{
|
|
42
|
+
kind: 'raw',
|
|
43
|
+
source: 'envrc',
|
|
44
|
+
target: '.envrc',
|
|
45
|
+
},
|
|
41
46
|
{
|
|
42
47
|
kind: 'raw',
|
|
43
48
|
source: 'tooling/direnv/repo-path',
|
|
@@ -50,6 +55,12 @@ const managedFiles: ManagedFile[] = [
|
|
|
50
55
|
target: 'tooling/direnv/github-actions-bootstrap.sh',
|
|
51
56
|
executable: true,
|
|
52
57
|
},
|
|
58
|
+
{
|
|
59
|
+
kind: 'raw',
|
|
60
|
+
source: 'tooling/direnv/setup-environment.ts',
|
|
61
|
+
target: 'tooling/direnv/setup-environment.ts',
|
|
62
|
+
executable: true,
|
|
63
|
+
},
|
|
53
64
|
{
|
|
54
65
|
kind: 'raw',
|
|
55
66
|
source: 'tooling/git-hooks/pre-commit.sh',
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { readFileSync, rmSync, unlinkSync } from 'node:fs';
|
|
2
|
-
import {
|
|
1
|
+
import { mkdtempSync, readdirSync, readFileSync, rmSync, statSync, unlinkSync } from 'node:fs';
|
|
2
|
+
import { tmpdir } from 'node:os';
|
|
3
|
+
import { dirname, join, relative } from 'node:path';
|
|
4
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
3
5
|
import { publint } from 'publint';
|
|
4
6
|
import { formatMessage } from 'publint/utils';
|
|
5
7
|
import { isRecord } from '../lib/json.js';
|
|
@@ -86,39 +88,158 @@ async function validatePackedManifest(
|
|
|
86
88
|
}
|
|
87
89
|
|
|
88
90
|
async function validateAttw(root: string, pkg: PackageInfo, packed: { path: string }): Promise<number> {
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
'--profile',
|
|
95
|
-
'node16',
|
|
96
|
-
'--ignore-rules',
|
|
97
|
-
'cjs-resolves-to-esm',
|
|
98
|
-
...attwExcludedEntrypointArgs(pkg),
|
|
99
|
-
];
|
|
100
|
-
const attw = await runResult('attw', attwArgs, root);
|
|
101
|
-
if (attw.exitCode === 0) {
|
|
91
|
+
const attw = await loadAttwCore();
|
|
92
|
+
const analysis = await attw.checkPackage(await createAttwPackageFromTarball(attw, root, packed.path), {
|
|
93
|
+
excludeEntrypoints: wasmExportEntrypoints(pkg.json.exports),
|
|
94
|
+
});
|
|
95
|
+
if (!isRecord(analysis) || analysis.types === false) {
|
|
102
96
|
return 0;
|
|
103
97
|
}
|
|
104
|
-
|
|
105
|
-
|
|
98
|
+
const rawProblems = Array.isArray(analysis.problems) ? analysis.problems : [];
|
|
99
|
+
const problems = rawProblems.filter(isReportedAttwProblem);
|
|
100
|
+
if (problems.length === 0) {
|
|
101
|
+
return 0;
|
|
102
|
+
}
|
|
103
|
+
for (const problem of problems) {
|
|
104
|
+
console.error(`${pkg.path}: are-the-types-wrong ${problem.kind}${formatProblemLocation(problem)}`);
|
|
105
|
+
}
|
|
106
106
|
console.error(`${pkg.path}: are-the-types-wrong validation failed`);
|
|
107
107
|
return 1;
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
110
|
+
interface AttwCore {
|
|
111
|
+
createPackage: (files: Record<string, Uint8Array>, packageName: string, packageVersion: string) => unknown;
|
|
112
|
+
checkPackage: (pkg: unknown, options: { excludeEntrypoints: string[] }) => Promise<unknown>;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async function loadAttwCore(): Promise<AttwCore> {
|
|
116
|
+
const packageJson = fileURLToPath(import.meta.resolve('@arethetypeswrong/core/package.json'));
|
|
117
|
+
const core = await import(pathToFileURL(join(dirname(packageJson), 'dist', 'index.js')).href);
|
|
118
|
+
if (!isRecord(core)) {
|
|
119
|
+
throw new Error('@arethetypeswrong/core does not expose the expected API');
|
|
120
|
+
}
|
|
121
|
+
const PackageConstructor = core.Package;
|
|
122
|
+
const checkPackage = core.checkPackage;
|
|
123
|
+
if (typeof PackageConstructor !== 'function' || typeof checkPackage !== 'function') {
|
|
124
|
+
throw new Error('@arethetypeswrong/core does not expose the expected API');
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
createPackage: (files, packageName, packageVersion) =>
|
|
128
|
+
Reflect.construct(PackageConstructor, [files, packageName, packageVersion]),
|
|
129
|
+
checkPackage: (pkg, options) => Promise.resolve(checkPackage(pkg, options)),
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
async function createAttwPackageFromTarball(attw: AttwCore, root: string, tarballPath: string): Promise<unknown> {
|
|
134
|
+
const temp = mkdtempSync(join(tmpdir(), 'smoo-attw-'));
|
|
135
|
+
try {
|
|
136
|
+
const extract = await runResult('tar', ['-xzf', tarballPath, '-C', temp], root);
|
|
137
|
+
if (extract.exitCode !== 0) {
|
|
138
|
+
printCommandOutput(extract.stdout, extract.stderr);
|
|
139
|
+
throw new Error('unable to extract packed package for are-the-types-wrong');
|
|
140
|
+
}
|
|
141
|
+
return createAttwPackageFromDirectory(attw, join(temp, 'package'));
|
|
142
|
+
} finally {
|
|
143
|
+
rmSync(temp, { recursive: true, force: true });
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function createAttwPackageFromDirectory(attw: AttwCore, packageDir: string): unknown {
|
|
148
|
+
const packageJson = readJsonFile(join(packageDir, 'package.json'));
|
|
149
|
+
const packageName = typeof packageJson.name === 'string' ? packageJson.name : null;
|
|
150
|
+
const packageVersion = typeof packageJson.version === 'string' ? packageJson.version : null;
|
|
151
|
+
if (!packageName || !packageVersion) {
|
|
152
|
+
throw new Error('packed package.json must contain name and version');
|
|
153
|
+
}
|
|
154
|
+
const files: Record<string, Uint8Array> = {};
|
|
155
|
+
collectAttwFiles(packageDir, packageDir, packageName, files);
|
|
156
|
+
return attw.createPackage(files, packageName, packageVersion);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function collectAttwFiles(root: string, current: string, packageName: string, files: Record<string, Uint8Array>): void {
|
|
160
|
+
for (const entry of readdirSync(current)) {
|
|
161
|
+
const path = join(current, entry);
|
|
162
|
+
const stat = statSync(path);
|
|
163
|
+
if (stat.isDirectory()) {
|
|
164
|
+
collectAttwFiles(root, path, packageName, files);
|
|
113
165
|
continue;
|
|
114
166
|
}
|
|
115
|
-
|
|
167
|
+
if (!stat.isFile()) {
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
const packageRelativePath = relative(root, path).split('\\').join('/');
|
|
171
|
+
files[`/node_modules/${packageName}/${packageRelativePath}`] = new Uint8Array(readFileSync(path));
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function readJsonFile(path: string): Record<string, unknown> {
|
|
176
|
+
const parsed: unknown = JSON.parse(readFileSync(path, 'utf8'));
|
|
177
|
+
if (!isRecord(parsed)) {
|
|
178
|
+
throw new Error(`${path} is not a JSON object`);
|
|
179
|
+
}
|
|
180
|
+
return parsed;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function isReportedAttwProblem(problem: unknown): boolean {
|
|
184
|
+
if (!isRecord(problem) || typeof problem.kind !== 'string') {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
const flag = attwProblemFlag(problem.kind);
|
|
188
|
+
if (flag === 'cjs-resolves-to-esm') {
|
|
189
|
+
return false;
|
|
116
190
|
}
|
|
191
|
+
return problem.resolutionKind !== 'node10';
|
|
117
192
|
}
|
|
118
193
|
|
|
119
|
-
function
|
|
120
|
-
|
|
121
|
-
|
|
194
|
+
function attwProblemFlag(kind: string): string | null {
|
|
195
|
+
switch (kind) {
|
|
196
|
+
case 'NoResolution':
|
|
197
|
+
return 'no-resolution';
|
|
198
|
+
case 'UntypedResolution':
|
|
199
|
+
return 'untyped-resolution';
|
|
200
|
+
case 'FalseCJS':
|
|
201
|
+
return 'false-cjs';
|
|
202
|
+
case 'FalseESM':
|
|
203
|
+
return 'false-esm';
|
|
204
|
+
case 'CJSResolvesToESM':
|
|
205
|
+
return 'cjs-resolves-to-esm';
|
|
206
|
+
case 'FallbackCondition':
|
|
207
|
+
return 'fallback-condition';
|
|
208
|
+
case 'CJSOnlyExportsDefault':
|
|
209
|
+
return 'cjs-only-exports-default';
|
|
210
|
+
case 'NamedExports':
|
|
211
|
+
return 'named-exports';
|
|
212
|
+
case 'FalseExportDefault':
|
|
213
|
+
return 'false-export-default';
|
|
214
|
+
case 'MissingExportEquals':
|
|
215
|
+
return 'missing-export-equals';
|
|
216
|
+
case 'UnexpectedModuleSyntax':
|
|
217
|
+
return 'unexpected-module-syntax';
|
|
218
|
+
case 'InternalResolutionError':
|
|
219
|
+
return 'internal-resolution-error';
|
|
220
|
+
default:
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function formatProblemLocation(problem: unknown): string {
|
|
226
|
+
if (!isRecord(problem)) {
|
|
227
|
+
return '';
|
|
228
|
+
}
|
|
229
|
+
const entrypoint = typeof problem.entrypoint === 'string' ? ` ${problem.entrypoint}` : '';
|
|
230
|
+
const resolution =
|
|
231
|
+
typeof problem.resolutionKind === 'string' ? ` ${formatResolutionKind(problem.resolutionKind)}` : '';
|
|
232
|
+
return `${entrypoint}${resolution}`;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function formatResolutionKind(kind: string): string {
|
|
236
|
+
if (kind === 'node16-cjs') {
|
|
237
|
+
return 'node16 (from CJS)';
|
|
238
|
+
}
|
|
239
|
+
if (kind === 'node16-esm') {
|
|
240
|
+
return 'node16 (from ESM)';
|
|
241
|
+
}
|
|
242
|
+
return kind;
|
|
122
243
|
}
|
|
123
244
|
|
|
124
245
|
function wasmExportEntrypoints(exports: unknown): string[] {
|
|
@@ -395,6 +395,8 @@ async function readResolvedTargetsByProject(ctx: MonorepoContext): Promise<Map<s
|
|
|
395
395
|
{
|
|
396
396
|
targets: new Set(project.targets),
|
|
397
397
|
...(project.buildDependsOn ? { buildDependsOn: project.buildDependsOn } : {}),
|
|
398
|
+
...(project.targetExecutors ? { targetExecutors: project.targetExecutors } : {}),
|
|
399
|
+
...(project.targetScripts ? { targetScripts: project.targetScripts } : {}),
|
|
398
400
|
},
|
|
399
401
|
]),
|
|
400
402
|
);
|
package/src/nx/index.ts
CHANGED
|
@@ -9,6 +9,8 @@ export interface ProjectTargets {
|
|
|
9
9
|
project: string;
|
|
10
10
|
targets: string[];
|
|
11
11
|
buildDependsOn?: string[];
|
|
12
|
+
targetExecutors?: Map<string, string>;
|
|
13
|
+
targetScripts?: Map<string, string>;
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
export interface CommandInvocation {
|
|
@@ -42,6 +44,38 @@ export function buildDependsOnFromNxProjectJson(value: unknown): string[] | unde
|
|
|
42
44
|
return build.dependsOn;
|
|
43
45
|
}
|
|
44
46
|
|
|
47
|
+
export function targetExecutorsFromNxProjectJson(value: unknown): Map<string, string> {
|
|
48
|
+
const targets = isRecord(value) ? recordProperty(value, 'targets') : null;
|
|
49
|
+
const executors = new Map<string, string>();
|
|
50
|
+
if (!targets) {
|
|
51
|
+
return executors;
|
|
52
|
+
}
|
|
53
|
+
for (const [targetName, target] of Object.entries(targets)) {
|
|
54
|
+
if (isRecord(target) && typeof target.executor === 'string') {
|
|
55
|
+
executors.set(targetName, target.executor);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return executors;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function targetScriptsFromNxProjectJson(value: unknown): Map<string, string> {
|
|
62
|
+
const targets = isRecord(value) ? recordProperty(value, 'targets') : null;
|
|
63
|
+
const scripts = new Map<string, string>();
|
|
64
|
+
if (!targets) {
|
|
65
|
+
return scripts;
|
|
66
|
+
}
|
|
67
|
+
for (const [targetName, target] of Object.entries(targets)) {
|
|
68
|
+
if (!isRecord(target)) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
const options = recordProperty(target, 'options');
|
|
72
|
+
if (typeof options?.script === 'string') {
|
|
73
|
+
scripts.set(targetName, options.script);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return scripts;
|
|
77
|
+
}
|
|
78
|
+
|
|
45
79
|
export function formatProjectTargetLines(projects: ProjectTargets[]): string {
|
|
46
80
|
return projects
|
|
47
81
|
.flatMap((project) => project.targets.map((target) => `${project.project}:${target}`))
|
|
@@ -135,5 +169,7 @@ async function readProjectTarget(root: string, project: string): Promise<Project
|
|
|
135
169
|
project,
|
|
136
170
|
targets: targetNamesFromNxProjectJson(parsed),
|
|
137
171
|
buildDependsOn: buildDependsOnFromNxProjectJson(parsed),
|
|
172
|
+
targetExecutors: targetExecutorsFromNxProjectJson(parsed),
|
|
173
|
+
targetScripts: targetScriptsFromNxProjectJson(parsed),
|
|
138
174
|
};
|
|
139
175
|
}
|