@jointhedots/gear 1.1.13 → 1.1.15
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.
|
@@ -66,7 +66,8 @@ export class BuildTarget {
|
|
|
66
66
|
const start = Date.now();
|
|
67
67
|
await task.execute();
|
|
68
68
|
const elapsed = (Date.now() - start) / 1000;
|
|
69
|
-
|
|
69
|
+
if (elapsed > 1.0)
|
|
70
|
+
this.log.info(`⏱ ${name} completed in ${elapsed.toFixed(2)}s`);
|
|
70
71
|
}
|
|
71
72
|
async build() {
|
|
72
73
|
const buildStartTime = Date.now();
|
|
@@ -9,7 +9,7 @@ import { PackageRootDir, resolve_normalized_suffixed_path } from "../../utils/fi
|
|
|
9
9
|
import { Library } from "../../model/workspace.js";
|
|
10
10
|
import { computeNameHashID } from "../../utils/normalized-name.js";
|
|
11
11
|
import { BuildTask } from "./task.js";
|
|
12
|
-
const VirtualOutDir =
|
|
12
|
+
const VirtualOutDir = process.platform === 'win32' ? 'X:\\' : '/_/';
|
|
13
13
|
function getEsbuildLogLevel(mode) {
|
|
14
14
|
switch (mode) {
|
|
15
15
|
case "verbose":
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import Fs from 'fs';
|
|
2
2
|
import Os from 'os';
|
|
3
3
|
import Path from 'path';
|
|
4
4
|
import Ts from 'typescript';
|
|
5
|
+
import { execFile } from 'child_process';
|
|
6
|
+
import { promisify } from 'util';
|
|
5
7
|
import { BuildTask } from "./task.js";
|
|
6
8
|
import { BuildTarget } from "../build-target.js";
|
|
7
9
|
import { Library } from "../../model/workspace.js";
|
|
@@ -33,15 +35,6 @@ function getError(diagnostics) {
|
|
|
33
35
|
error.name = 'EmitterError';
|
|
34
36
|
return error;
|
|
35
37
|
}
|
|
36
|
-
function getFilenames(baseDir, files) {
|
|
37
|
-
return files.map(function (filename) {
|
|
38
|
-
const resolvedFilename = Path.resolve(filename);
|
|
39
|
-
if (resolvedFilename.indexOf(baseDir) === 0) {
|
|
40
|
-
return resolvedFilename;
|
|
41
|
-
}
|
|
42
|
-
return Path.resolve(baseDir, filename);
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
38
|
function processTree(sourceFile, replacer) {
|
|
46
39
|
let code = '';
|
|
47
40
|
let cursorPosition = 0;
|
|
@@ -67,19 +60,6 @@ function processTree(sourceFile, replacer) {
|
|
|
67
60
|
code += sourceFile.text.slice(cursorPosition);
|
|
68
61
|
return code;
|
|
69
62
|
}
|
|
70
|
-
function getTSConfig(baseDir, tsconfig) {
|
|
71
|
-
const { config, error } = Ts.parseConfigFileTextToJson("tsconfig.json", tsconfig);
|
|
72
|
-
if (error)
|
|
73
|
-
throw getError([error]);
|
|
74
|
-
const configParsed = Ts.parseJsonConfigFileContent(config, Ts.sys, baseDir);
|
|
75
|
-
if (configParsed.errors && configParsed.errors.length) {
|
|
76
|
-
throw getError(configParsed.errors);
|
|
77
|
-
}
|
|
78
|
-
return [
|
|
79
|
-
configParsed.fileNames,
|
|
80
|
-
configParsed.options
|
|
81
|
-
];
|
|
82
|
-
}
|
|
83
63
|
function isNodeKindImportType(value) {
|
|
84
64
|
return value && value.kind === Ts.SyntaxKind.ImportType;
|
|
85
65
|
}
|
|
@@ -97,212 +77,144 @@ function isNodeKindExportDeclaration(value) {
|
|
|
97
77
|
}
|
|
98
78
|
class TypescriptProject {
|
|
99
79
|
baseDir;
|
|
100
|
-
files;
|
|
101
80
|
compilerOptions;
|
|
102
|
-
|
|
103
|
-
program;
|
|
104
|
-
filenames;
|
|
81
|
+
dtsDir;
|
|
105
82
|
constructor(baseDir, tsconfig, outDir) {
|
|
106
83
|
this.baseDir = Path.resolve(baseDir);
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
84
|
+
const { config, error } = Ts.parseConfigFileTextToJson("tsconfig.json", tsconfig);
|
|
85
|
+
if (error)
|
|
86
|
+
throw getError([error]);
|
|
87
|
+
const configParsed = Ts.parseJsonConfigFileContent(config, Ts.sys, baseDir);
|
|
88
|
+
if (configParsed.errors?.length)
|
|
89
|
+
throw getError(configParsed.errors);
|
|
90
|
+
const compilerOptions = configParsed.options;
|
|
113
91
|
compilerOptions.outDir = compilerOptions.outDir || outDir;
|
|
114
|
-
this.files = files;
|
|
115
92
|
this.compilerOptions = compilerOptions;
|
|
116
|
-
|
|
117
|
-
this.
|
|
118
|
-
this.program = Ts.createProgram(this.filenames, compilerOptions, this.host);
|
|
93
|
+
// Create a temp directory for tsgo to emit .d.ts into
|
|
94
|
+
this.dtsDir = Fs.mkdtempSync(Path.join(Os.tmpdir(), 'gear-dts-'));
|
|
119
95
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
96
|
+
/** Run tsgo to emit .d.ts files into dtsDir. Returns stderr output. */
|
|
97
|
+
async emitWithTsgo() {
|
|
98
|
+
const tsgoPath = Path.resolve('node_modules/.bin/tsgo');
|
|
99
|
+
const args = [
|
|
100
|
+
'-p', Path.join(this.baseDir, 'tsconfig.json'),
|
|
101
|
+
'--declaration',
|
|
102
|
+
'--emitDeclarationOnly',
|
|
103
|
+
'--skipLibCheck',
|
|
104
|
+
'--outDir', this.dtsDir,
|
|
105
|
+
];
|
|
106
|
+
try {
|
|
107
|
+
await promisify(execFile)(tsgoPath, args, {
|
|
108
|
+
cwd: this.baseDir,
|
|
109
|
+
timeout: 120_000,
|
|
110
|
+
shell: true,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
catch (e) {
|
|
114
|
+
// tsgo may exit non-zero on type errors but still emit .d.ts files
|
|
115
|
+
}
|
|
128
116
|
}
|
|
129
|
-
|
|
130
|
-
|
|
117
|
+
/** Recursively collect all .d.ts files emitted by tsgo */
|
|
118
|
+
getEmittedDtsFiles() {
|
|
119
|
+
const results = [];
|
|
120
|
+
function walk(dir) {
|
|
121
|
+
for (const entry of Fs.readdirSync(dir, { withFileTypes: true })) {
|
|
122
|
+
const full = Path.join(dir, entry.name);
|
|
123
|
+
if (entry.isDirectory())
|
|
124
|
+
walk(full);
|
|
125
|
+
else if (isDtsFilename(entry.name))
|
|
126
|
+
results.push(full);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (Fs.existsSync(this.dtsDir))
|
|
130
|
+
walk(this.dtsDir);
|
|
131
|
+
return results;
|
|
131
132
|
}
|
|
132
|
-
|
|
133
|
-
|
|
133
|
+
/** Clean up temp directory */
|
|
134
|
+
cleanup() {
|
|
135
|
+
try {
|
|
136
|
+
Fs.rmSync(this.dtsDir, { recursive: true, force: true });
|
|
137
|
+
}
|
|
138
|
+
catch { }
|
|
134
139
|
}
|
|
135
140
|
}
|
|
136
141
|
export function createTypescriptProject(baseDir, tsconfig, outDir) {
|
|
137
142
|
return new TypescriptProject(baseDir, tsconfig, outDir);
|
|
138
143
|
}
|
|
139
144
|
export function generateTypescriptDefinition(options) {
|
|
140
|
-
const project = options
|
|
141
|
-
const diagnostics = [];
|
|
145
|
+
const { project, prefix } = options;
|
|
142
146
|
const baseDir = project.baseDir;
|
|
143
|
-
const outDir = project.compilerOptions.outDir;
|
|
144
|
-
const excludesMap = {};
|
|
145
|
-
options.exclude = options.exclude || ['node_modules/**/*'];
|
|
146
|
-
options.exclude.forEach(function (filename) {
|
|
147
|
-
Glob.sync(filename, { cwd: baseDir }).forEach(function (globFileName) {
|
|
148
|
-
excludesMap[normalizeFileName(Path.resolve(baseDir, globFileName))] = true;
|
|
149
|
-
});
|
|
150
|
-
});
|
|
151
|
-
// Compute baseUrl prefix to strip from module paths
|
|
152
147
|
const normalizedBaseDir = normalizeFileName(Path.resolve(baseDir)) + "/";
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
const normalizedBaseUrl = normalizeFileName(absoluteBaseUrl);
|
|
157
|
-
baseUrlPrefix = normalizedBaseUrl.slice(normalizedBaseDir.length);
|
|
158
|
-
if (baseUrlPrefix && !baseUrlPrefix.endsWith('/')) {
|
|
159
|
-
baseUrlPrefix += '/';
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
function stripBaseUrlPrefix(modulePath) {
|
|
163
|
-
if (baseUrlPrefix && modulePath.startsWith(baseUrlPrefix)) {
|
|
164
|
-
return modulePath.slice(baseUrlPrefix.length);
|
|
165
|
-
}
|
|
166
|
-
return modulePath;
|
|
167
|
-
}
|
|
168
|
-
let outputContent = '';
|
|
148
|
+
const normalizedDtsDir = normalizeFileName(Path.resolve(project.dtsDir)) + "/";
|
|
149
|
+
const resolveCache = new Map();
|
|
150
|
+
const outputParts = [];
|
|
169
151
|
if (options.externs) {
|
|
170
152
|
options.externs.forEach(function (path) {
|
|
171
|
-
|
|
153
|
+
outputParts.push(`/// <reference path="${path}" />` + eol);
|
|
172
154
|
});
|
|
173
155
|
}
|
|
174
156
|
if (options.types) {
|
|
175
157
|
options.types.forEach(function (type) {
|
|
176
|
-
|
|
158
|
+
outputParts.push(`/// <reference types="${type}" />` + eol);
|
|
177
159
|
});
|
|
178
160
|
}
|
|
179
|
-
//
|
|
180
|
-
const
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
const moduleId = `${options.prefix}/${strippedShortNameNoExt}`;
|
|
193
|
-
internalsMap[shortName] = moduleId;
|
|
194
|
-
internalsMap[shortNameNoExt] = moduleId;
|
|
195
|
-
internalsMap[strippedShortName] = moduleId;
|
|
196
|
-
internalsMap[strippedShortNameNoExt] = moduleId;
|
|
197
|
-
sourcesMap[fileName] = true;
|
|
198
|
-
});
|
|
199
|
-
// Build reverse map from internal paths to export names
|
|
200
|
-
// e.g., "src/Inputs" -> "./Inputs" means internal path "src/Inputs" exports as "prefix/Inputs"
|
|
201
|
-
// Store as [internalPrefix, exportName] pairs for prefix matching
|
|
161
|
+
// Process each emitted .d.ts file as internal: module
|
|
162
|
+
const dtsFiles = project.getEmittedDtsFiles();
|
|
163
|
+
for (const dtsPath of dtsFiles) {
|
|
164
|
+
const normalizedDts = normalizeFileName(Path.resolve(dtsPath));
|
|
165
|
+
if (!normalizedDts.startsWith(normalizedDtsDir))
|
|
166
|
+
continue;
|
|
167
|
+
const relativeDts = normalizedDts.slice(normalizedDtsDir.length);
|
|
168
|
+
const relativeSource = relativeDts.replace(/\.d\.ts$/, '');
|
|
169
|
+
const data = Fs.readFileSync(dtsPath, 'utf-8');
|
|
170
|
+
const declFile = Ts.createSourceFile(dtsPath, data, Ts.ScriptTarget.Latest, true);
|
|
171
|
+
writeDeclaration(declFile, relativeSource);
|
|
172
|
+
}
|
|
173
|
+
// Emit public re-export modules
|
|
202
174
|
if (options.exports) {
|
|
203
175
|
for (const entry of Object.values(options.exports)) {
|
|
204
|
-
const
|
|
205
|
-
if (
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
const shortNameNoExt = shortName.slice(0, -Path.extname(fileName).length);
|
|
211
|
-
const strippedShortName = stripBaseUrlPrefix(shortName);
|
|
212
|
-
const strippedShortNameNoExt = stripBaseUrlPrefix(shortNameNoExt);
|
|
213
|
-
const moduleId = entry.id;
|
|
214
|
-
internalsMap[shortName] = moduleId;
|
|
215
|
-
internalsMap[shortNameNoExt] = moduleId;
|
|
216
|
-
internalsMap[strippedShortName] = moduleId;
|
|
217
|
-
internalsMap[strippedShortNameNoExt] = moduleId;
|
|
218
|
-
sourcesMap[fileName] = true;
|
|
176
|
+
const internalId = resolveInternalModuleImport(entry.source);
|
|
177
|
+
if (internalId) {
|
|
178
|
+
outputParts.push(`declare module '${entry.id}' {${eol}`);
|
|
179
|
+
outputParts.push(`${indent}export * from '${internalId}';${eol}`);
|
|
180
|
+
outputParts.push(`}${eol}${eol}`);
|
|
181
|
+
}
|
|
219
182
|
}
|
|
220
183
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
moduleId = moduleId.replace(/\.(d\.ts|ts|tsx|js|jsx)$/, '');
|
|
225
|
-
// Strip baseUrl prefix
|
|
226
|
-
moduleId = stripBaseUrlPrefix(moduleId);
|
|
227
|
-
// Apply resolved prefix
|
|
228
|
-
const remapped = internalsMap[moduleId] ||
|
|
229
|
-
internalsMap[moduleId + "/index"] ||
|
|
230
|
-
internalsMap[moduleId + "/index.ts"];
|
|
231
|
-
return remapped || moduleId;
|
|
232
|
-
}
|
|
233
|
-
// Generate source files
|
|
234
|
-
project.getSourceFiles().some(function (sourceFile) {
|
|
235
|
-
if (!sourcesMap[sourceFile.fileName])
|
|
236
|
-
return;
|
|
237
|
-
// Source file is already a declaration file so should does not need to be pre-processed by the emitter
|
|
238
|
-
if (isDtsFilename(sourceFile.fileName)) {
|
|
239
|
-
writeDeclaration(sourceFile, sourceFile.fileName);
|
|
240
|
-
return;
|
|
241
|
-
}
|
|
242
|
-
const emitOutput = project.emit(sourceFile, (filename, data) => writeFile(filename, data, sourceFile.fileName));
|
|
243
|
-
if (emitOutput.emitSkipped || emitOutput.diagnostics.length > 0) {
|
|
244
|
-
diagnostics.push(...emitOutput.diagnostics);
|
|
245
|
-
diagnostics.push(...project.getSemanticDiagnostics(sourceFile));
|
|
246
|
-
diagnostics.push(...project.getSyntacticDiagnostics(sourceFile));
|
|
247
|
-
diagnostics.push(...project.getDeclarationDiagnostics(sourceFile));
|
|
184
|
+
function resolveInternalModuleImport(moduleId, importDir = "") {
|
|
185
|
+
if (moduleId.charAt(0) === '.') {
|
|
186
|
+
return prefix + normalizeFileName(Path.join(importDir, moduleId));
|
|
248
187
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
188
|
+
if (resolveCache.has(moduleId))
|
|
189
|
+
return resolveCache.get(moduleId);
|
|
190
|
+
const containingFile = Path.resolve(baseDir, importDir, '__resolve.ts');
|
|
191
|
+
const result = Ts.resolveModuleName(moduleId, containingFile, project.compilerOptions, Ts.sys);
|
|
192
|
+
if (result.resolvedModule && !result.resolvedModule.isExternalLibraryImport) {
|
|
193
|
+
const resolved = normalizeFileName(result.resolvedModule.resolvedFileName);
|
|
194
|
+
if (resolved.startsWith(normalizedBaseDir)) {
|
|
195
|
+
const value = prefix + resolved.slice(normalizedBaseDir.length).replace(/\.(d\.ts|tsx?|jsx?)$/, '');
|
|
196
|
+
resolveCache.set(moduleId, value);
|
|
197
|
+
return value;
|
|
198
|
+
}
|
|
253
199
|
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
200
|
+
// Check if moduleId is already an internal path relative to baseDir
|
|
201
|
+
const absolute = normalizeFileName(Path.resolve(baseDir, importDir, moduleId));
|
|
202
|
+
if (absolute.startsWith(normalizedBaseDir)) {
|
|
203
|
+
const value = prefix + absolute.slice(normalizedBaseDir.length);
|
|
204
|
+
resolveCache.set(moduleId, value);
|
|
205
|
+
return value;
|
|
260
206
|
}
|
|
207
|
+
resolveCache.set(moduleId, null);
|
|
208
|
+
return null;
|
|
261
209
|
}
|
|
262
|
-
function writeDeclaration(declarationFile,
|
|
263
|
-
|
|
264
|
-
const
|
|
265
|
-
|
|
266
|
-
const rawSourceModuleId = normalizeFileName(resolvedSourcePath.slice(baseDir.length + 1, -sourceExt.length));
|
|
267
|
-
// Normalize and remap the module ID
|
|
268
|
-
const moduleDeclId = normalizeModuleId(rawSourceModuleId);
|
|
269
|
-
outputContent += `declare module '${moduleDeclId}' {${eol}${indent}`;
|
|
270
|
-
function resolveModuleImport(moduleId) {
|
|
271
|
-
// Resolve module id
|
|
272
|
-
let resolved;
|
|
273
|
-
if (moduleId.charAt(0) === '.') {
|
|
274
|
-
resolved = normalizeFileName(Path.join(Path.dirname(rawSourceModuleId), moduleId));
|
|
275
|
-
}
|
|
276
|
-
else {
|
|
277
|
-
// Try to resolve using TypeScript's module resolution (handles tsconfig paths)
|
|
278
|
-
const resolveResult = Ts.resolveModuleName(moduleId, declarationFile.fileName, project.compilerOptions, project.host);
|
|
279
|
-
if (resolveResult.resolvedModule) {
|
|
280
|
-
const resolvedFileName = normalizeFileName(resolveResult.resolvedModule.resolvedFileName);
|
|
281
|
-
if (excludesMap[resolvedFileName])
|
|
282
|
-
return moduleId;
|
|
283
|
-
// Check if resolved file is within our project (internal module)
|
|
284
|
-
if (resolvedFileName.startsWith(normalizedBaseDir)) {
|
|
285
|
-
// Convert absolute path to relative module id
|
|
286
|
-
resolved = resolvedFileName.slice(normalizedBaseDir.length);
|
|
287
|
-
}
|
|
288
|
-
else {
|
|
289
|
-
// External module - return as-is
|
|
290
|
-
return moduleId;
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
else {
|
|
294
|
-
resolved = moduleId;
|
|
295
|
-
if (isExternalModule(resolved))
|
|
296
|
-
return resolved;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
// Normalize: strip extensions, baseUrl prefix, and remap to exports
|
|
300
|
-
return normalizeModuleId(resolved);
|
|
301
|
-
}
|
|
210
|
+
function writeDeclaration(declarationFile, rawSourceModuleId) {
|
|
211
|
+
const moduleDeclId = resolveInternalModuleImport(rawSourceModuleId);
|
|
212
|
+
const moduleDir = Path.dirname(rawSourceModuleId);
|
|
213
|
+
outputParts.push(`declare module '${moduleDeclId}' {${eol}${indent}`);
|
|
302
214
|
const content = processTree(declarationFile, function (node) {
|
|
303
215
|
if (isNodeKindExternalModuleReference(node)) {
|
|
304
216
|
const expression = node.expression;
|
|
305
|
-
const resolved =
|
|
217
|
+
const resolved = resolveInternalModuleImport(expression.text, moduleDir) ?? expression.text;
|
|
306
218
|
return ` require('${resolved}')`;
|
|
307
219
|
}
|
|
308
220
|
else if (isNodeKindImportDeclaration(node) && !node.importClause) {
|
|
@@ -313,8 +225,8 @@ export function generateTypescriptDefinition(options) {
|
|
|
313
225
|
}
|
|
314
226
|
else if (isNodeKindStringLiteral(node) && node.parent &&
|
|
315
227
|
(isNodeKindExportDeclaration(node.parent) || isNodeKindImportDeclaration(node.parent) || isNodeKindImportType(node.parent?.parent))) {
|
|
316
|
-
const resolved =
|
|
317
|
-
if (resolved) {
|
|
228
|
+
const resolved = resolveInternalModuleImport(node.text, moduleDir);
|
|
229
|
+
if (resolved != null) {
|
|
318
230
|
return ` '${resolved}'`;
|
|
319
231
|
}
|
|
320
232
|
}
|
|
@@ -322,38 +234,13 @@ export function generateTypescriptDefinition(options) {
|
|
|
322
234
|
const chunks = content.replaceAll("\r", "").split("\n").map(c => c.trimEnd());
|
|
323
235
|
while (chunks.length > 0 && chunks[chunks.length - 1] === "")
|
|
324
236
|
chunks.pop();
|
|
325
|
-
|
|
326
|
-
|
|
237
|
+
outputParts.push(chunks.join(eol + indent) + eol);
|
|
238
|
+
outputParts.push('}' + eol + eol);
|
|
327
239
|
}
|
|
328
240
|
return {
|
|
329
|
-
dts:
|
|
330
|
-
diagnostics,
|
|
241
|
+
dts: outputParts.join(''),
|
|
331
242
|
};
|
|
332
243
|
}
|
|
333
|
-
export function logDiagnostics(log, diagnostics) {
|
|
334
|
-
if (diagnostics && diagnostics.length > 0) {
|
|
335
|
-
for (const diagnostic of diagnostics) {
|
|
336
|
-
const text = typeof diagnostic.messageText === 'string'
|
|
337
|
-
? diagnostic.messageText
|
|
338
|
-
: diagnostic.messageText.messageText;
|
|
339
|
-
const message = {
|
|
340
|
-
id: `TS${diagnostic.code}`,
|
|
341
|
-
text,
|
|
342
|
-
detail: diagnostic,
|
|
343
|
-
};
|
|
344
|
-
if (diagnostic.file && diagnostic.start !== undefined) {
|
|
345
|
-
const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
|
|
346
|
-
message.location = {
|
|
347
|
-
file: diagnostic.file.fileName,
|
|
348
|
-
line: line + 1,
|
|
349
|
-
column: character,
|
|
350
|
-
length: diagnostic.length ?? 0,
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
|
-
log.put('error', message);
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
244
|
export class TypescriptDefinitionTask extends BuildTask {
|
|
358
245
|
library;
|
|
359
246
|
constructor(target, library) {
|
|
@@ -367,14 +254,15 @@ export class TypescriptDefinitionTask extends BuildTask {
|
|
|
367
254
|
const configText = file.read.text(Path.join(lib.path, "./tsconfig.json"))
|
|
368
255
|
|| file.read.text("./tsconfig.json");
|
|
369
256
|
const project = createTypescriptProject(lib.path, configText, storage.getBaseDirFS());
|
|
370
|
-
|
|
257
|
+
await project.emitWithTsgo();
|
|
258
|
+
const { dts } = generateTypescriptDefinition({
|
|
371
259
|
project,
|
|
372
|
-
prefix: lib.name,
|
|
260
|
+
prefix: lib.name + ":",
|
|
373
261
|
exclude: ["node_modules/**/*"],
|
|
374
262
|
exports: create_export_map(lib, lib.bundle),
|
|
375
263
|
});
|
|
376
264
|
file.write.text(storage.getBaseDirFS() + "/types.d.ts", dts);
|
|
377
|
-
|
|
265
|
+
project.cleanup();
|
|
378
266
|
}
|
|
379
267
|
catch (e) {
|
|
380
268
|
this.log.error("no 'type.d.ts' will be generated for the package:" + e.message);
|
|
@@ -7,6 +7,7 @@ import { create_bundle_manifest } from "./create-manifests.js";
|
|
|
7
7
|
import { Bundle, Library, Workspace } from "../workspace.js";
|
|
8
8
|
import { file, make_canonical_path, make_normalized_dirname, make_normalized_path, make_relative_path } from "../../utils/file.js";
|
|
9
9
|
import { findConfigFile, is_config_filename, readConfigFile, readSingletonConfigFile } from "./config-loader.js";
|
|
10
|
+
import { read_lockfile } from "./lockfile.js";
|
|
10
11
|
const exclude_dirs = ["node_modules", ".git"];
|
|
11
12
|
function is_ignored_dir(ws, path) {
|
|
12
13
|
const normalized_path = make_normalized_path(path);
|
|
@@ -252,7 +253,7 @@ function show_constants(ws) {
|
|
|
252
253
|
}
|
|
253
254
|
}
|
|
254
255
|
export async function discover_workspace(ws) {
|
|
255
|
-
let
|
|
256
|
+
let lockfile = null;
|
|
256
257
|
for (let path = ws.path;;) {
|
|
257
258
|
const package_json = await readJsonFile(path + "/package.json");
|
|
258
259
|
if (package_json) {
|
|
@@ -267,30 +268,20 @@ export async function discover_workspace(ws) {
|
|
|
267
268
|
};
|
|
268
269
|
}
|
|
269
270
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
package_lock = await readJsonFile(package_lock_path);
|
|
271
|
+
if (!lockfile) {
|
|
272
|
+
lockfile = await read_lockfile(path);
|
|
273
273
|
}
|
|
274
274
|
const next_path = make_normalized_dirname(path);
|
|
275
275
|
if (next_path === path)
|
|
276
276
|
break;
|
|
277
277
|
path = next_path;
|
|
278
278
|
}
|
|
279
|
-
if (!
|
|
280
|
-
throw new Error(`
|
|
281
|
-
}
|
|
282
|
-
for (const location in package_lock.packages) {
|
|
283
|
-
let pkg = package_lock.packages[location];
|
|
284
|
-
if (location.startsWith("node_modules/")) {
|
|
285
|
-
if (pkg.link) {
|
|
286
|
-
pkg = package_lock.packages[pkg.resolved];
|
|
287
|
-
}
|
|
288
|
-
const name = location.replace(/^.*node_modules\//, "");
|
|
289
|
-
ws.resolved_versions[name] = pkg.version;
|
|
290
|
-
}
|
|
279
|
+
if (!lockfile) {
|
|
280
|
+
throw new Error(`Lock file not found for '${ws.name}'`);
|
|
291
281
|
}
|
|
282
|
+
ws.resolved_versions = lockfile.resolved_versions;
|
|
292
283
|
await discover_workspace_libraries(ws);
|
|
293
|
-
for (const location
|
|
284
|
+
for (const location of lockfile.installed_locations) {
|
|
294
285
|
await discover_library(ws, location, true);
|
|
295
286
|
}
|
|
296
287
|
for (const bun of ws.bundles) {
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import Fs from "node:fs";
|
|
2
|
+
import Fsp from "node:fs/promises";
|
|
3
|
+
import YAML from "yaml";
|
|
4
|
+
import { readJsonFile } from "../storage.js";
|
|
5
|
+
export async function read_lockfile(dir) {
|
|
6
|
+
const npm_path = dir + "/package-lock.json";
|
|
7
|
+
if (Fs.existsSync(npm_path)) {
|
|
8
|
+
return parse_npm_lockfile(await readJsonFile(npm_path));
|
|
9
|
+
}
|
|
10
|
+
const pnpm_path = dir + "/pnpm-lock.yaml";
|
|
11
|
+
if (Fs.existsSync(pnpm_path)) {
|
|
12
|
+
return parse_pnpm_lockfile(YAML.parse(await Fsp.readFile(pnpm_path, "utf-8")));
|
|
13
|
+
}
|
|
14
|
+
const yarn_path = dir + "/yarn.lock";
|
|
15
|
+
if (Fs.existsSync(yarn_path)) {
|
|
16
|
+
return parse_yarn_lockfile(await Fsp.readFile(yarn_path, "utf-8"));
|
|
17
|
+
}
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
function parse_npm_lockfile(lock) {
|
|
21
|
+
const resolved_versions = {};
|
|
22
|
+
const installed_locations = [];
|
|
23
|
+
for (const location in lock.packages) {
|
|
24
|
+
if (!location)
|
|
25
|
+
continue;
|
|
26
|
+
installed_locations.push(location);
|
|
27
|
+
if (location.startsWith("node_modules/")) {
|
|
28
|
+
let pkg = lock.packages[location];
|
|
29
|
+
if (pkg.link) {
|
|
30
|
+
pkg = lock.packages[pkg.resolved];
|
|
31
|
+
}
|
|
32
|
+
const name = location.replace(/^.*node_modules\//, "");
|
|
33
|
+
if (pkg?.version) {
|
|
34
|
+
resolved_versions[name] = pkg.version;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return { resolved_versions, installed_locations };
|
|
39
|
+
}
|
|
40
|
+
function parse_pnpm_lockfile(lock) {
|
|
41
|
+
const resolved_versions = {};
|
|
42
|
+
const locations = new Set();
|
|
43
|
+
if (lock.packages) {
|
|
44
|
+
for (const key in lock.packages) {
|
|
45
|
+
const clean = key.startsWith("/") ? key.slice(1) : key;
|
|
46
|
+
const atIdx = clean.lastIndexOf("@");
|
|
47
|
+
if (atIdx > 0) {
|
|
48
|
+
const name = clean.slice(0, atIdx);
|
|
49
|
+
const version = clean.slice(atIdx + 1).split("(")[0];
|
|
50
|
+
if (name && version) {
|
|
51
|
+
resolved_versions[name] = version;
|
|
52
|
+
locations.add("node_modules/" + name);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (lock.importers) {
|
|
58
|
+
for (const key in lock.importers) {
|
|
59
|
+
if (key !== ".")
|
|
60
|
+
locations.add(key);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return { resolved_versions, installed_locations: [...locations] };
|
|
64
|
+
}
|
|
65
|
+
function parse_yarn_lockfile(text) {
|
|
66
|
+
const resolved_versions = {};
|
|
67
|
+
const locations = new Set();
|
|
68
|
+
if (text.includes("__metadata:")) {
|
|
69
|
+
const lock = YAML.parse(text);
|
|
70
|
+
for (const key in lock) {
|
|
71
|
+
if (key === "__metadata")
|
|
72
|
+
continue;
|
|
73
|
+
if (lock[key]?.version) {
|
|
74
|
+
const name = extract_package_name(key.split(",")[0].trim());
|
|
75
|
+
if (name) {
|
|
76
|
+
resolved_versions[name] = lock[key].version;
|
|
77
|
+
locations.add("node_modules/" + name);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
parse_yarn_classic(text, resolved_versions, locations);
|
|
84
|
+
}
|
|
85
|
+
return { resolved_versions, installed_locations: [...locations] };
|
|
86
|
+
}
|
|
87
|
+
function extract_package_name(entry) {
|
|
88
|
+
entry = entry.replace(/^"|"$/g, "");
|
|
89
|
+
// @scope/name@version or name@version
|
|
90
|
+
const at = entry.startsWith("@") ? entry.indexOf("@", 1) : entry.indexOf("@");
|
|
91
|
+
return at > 0 ? entry.slice(0, at) : null;
|
|
92
|
+
}
|
|
93
|
+
function parse_yarn_classic(text, resolved_versions, locations) {
|
|
94
|
+
let current_name = null;
|
|
95
|
+
for (const line of text.split("\n")) {
|
|
96
|
+
const trimmed = line.trim();
|
|
97
|
+
if (!line.startsWith(" ") && !line.startsWith("#") && trimmed.endsWith(":")) {
|
|
98
|
+
current_name = extract_package_name(trimmed.slice(0, -1).split(",")[0].trim());
|
|
99
|
+
}
|
|
100
|
+
else if (current_name && trimmed.startsWith("version ")) {
|
|
101
|
+
const version = trimmed.slice(8).replace(/^"|"$/g, "");
|
|
102
|
+
resolved_versions[current_name] = version;
|
|
103
|
+
locations.add("node_modules/" + current_name);
|
|
104
|
+
current_name = null;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=lockfile.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jointhedots/gear",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.15",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"jointhedots-gear": "esm/cli.js"
|
|
@@ -33,19 +33,17 @@
|
|
|
33
33
|
"@aws-sdk/client-s3": "^3.968.0",
|
|
34
34
|
"@jspm/core": "^2.1.0",
|
|
35
35
|
"@tailwindcss/postcss": "~4.1.3",
|
|
36
|
-
"@
|
|
36
|
+
"@typescript/native-preview": "^7.0.0-dev.20260310.1",
|
|
37
37
|
"dotenv": "~17.2.3",
|
|
38
38
|
"esbuild": "~0.27.2",
|
|
39
39
|
"esbuild-sass-plugin": "~3.6.0",
|
|
40
40
|
"express": "~5.2.1",
|
|
41
|
-
"glob": "~13.0.0",
|
|
42
41
|
"mime": "~4.1.0",
|
|
43
42
|
"node-watch": "~0.7.4",
|
|
44
43
|
"postcss": "~8.5.6",
|
|
45
44
|
"sass": "~1.97.2",
|
|
46
45
|
"semver": "~7.7.3",
|
|
47
46
|
"sharp": "~0.34.5",
|
|
48
|
-
"source-map-support": "~0.5.21",
|
|
49
47
|
"toml": "^3.0.0",
|
|
50
48
|
"typescript": "~5.9.3",
|
|
51
49
|
"yaml": "^2.8.2",
|
|
@@ -55,6 +53,7 @@
|
|
|
55
53
|
"@polycuber/script.cli": "~1.0.5",
|
|
56
54
|
"@types/chrome": "~0.1.33",
|
|
57
55
|
"@types/node": "~22.7.4",
|
|
56
|
+
"@types/semver": "~7.7.1",
|
|
58
57
|
"@types/web-app-manifest": "~1.0.9",
|
|
59
58
|
"@types/yargs": "~17.0.35"
|
|
60
59
|
},
|