@smoothbricks/cli 0.4.2 → 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/packed-package.d.ts.map +1 -1
- package/dist/monorepo/packed-package.js +132 -24
- package/package.json +2 -2
- package/src/lib/run.ts +1 -5
- package/src/monorepo/packed-package.ts +145 -24
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":"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)) {
|
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,7 +44,7 @@
|
|
|
44
44
|
"!**/*.tsbuildinfo"
|
|
45
45
|
],
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@arethetypeswrong/
|
|
47
|
+
"@arethetypeswrong/core": "^0.18.2",
|
|
48
48
|
"@smoothbricks/nx-plugin": "0.2.5",
|
|
49
49
|
"@smoothbricks/validation": "0.1.1",
|
|
50
50
|
"commander": "^14.0.3",
|
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
|
}
|
|
@@ -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[] {
|