@_linked/cli 1.13.0 → 1.15.0
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/CHANGELOG.md +71 -0
- package/README.md +78 -38
- package/defaults/app-react-native/README.md +62 -22
- package/defaults/app-react-native/apps/mobile/App.tsx +6 -3
- package/defaults/app-react-native/apps/mobile/__tests__/composePort.test.ts +33 -0
- package/defaults/app-react-native/apps/mobile/__tests__/env.test.ts +39 -0
- package/defaults/app-react-native/apps/mobile/__tests__/integration/apiEnv.ts +75 -0
- package/defaults/app-react-native/apps/mobile/__tests__/integration/globalSetup.ts +160 -0
- package/defaults/app-react-native/apps/mobile/__tests__/integration/globalTeardown.ts +20 -0
- package/defaults/app-react-native/apps/mobile/__tests__/integration/nodeFetchEnvironment.js +13 -0
- package/defaults/app-react-native/apps/mobile/__tests__/integration/personOverview.test.tsx +51 -0
- package/defaults/app-react-native/apps/mobile/__tests__/integration/restoreNodeFetch.ts +8 -0
- package/defaults/app-react-native/apps/mobile/__tests__/{linkedDefaults.test.tsx → nativeDefaults.test.tsx} +5 -7
- package/defaults/app-react-native/apps/mobile/__tests__/storage.test.ts +24 -0
- package/defaults/app-react-native/apps/mobile/__tests__/stripJsonImportAttributes.test.ts +45 -0
- package/defaults/app-react-native/apps/mobile/app.config.ts +21 -0
- package/defaults/app-react-native/apps/mobile/babel/stripJsonImportAttributes.js +41 -0
- package/defaults/app-react-native/apps/mobile/babel.config.js +13 -0
- package/defaults/app-react-native/apps/mobile/jest.integration.config.js +16 -0
- package/defaults/app-react-native/apps/mobile/package.json +11 -3
- package/defaults/app-react-native/apps/mobile/src/components/PersonOverview.tsx +123 -0
- package/defaults/app-react-native/apps/mobile/src/components/PersonOverviewContext.tsx +12 -0
- package/defaults/app-react-native/apps/mobile/src/components/PersonPreview.tsx +135 -0
- package/defaults/app-react-native/apps/mobile/src/shell/apiPort.json +1 -0
- package/defaults/app-react-native/apps/mobile/src/shell/env.ts +30 -0
- package/defaults/app-react-native/apps/mobile/src/shell/storage.ts +9 -0
- package/defaults/app-react-native/docker-compose.yml +22 -0
- package/defaults/app-react-native/eslint.config.js +47 -0
- package/defaults/app-react-native/gitignore.template +5 -0
- package/defaults/app-react-native/package.json +14 -4
- package/defaults/app-react-native/packages/app-shapes/package.json +17 -3
- package/defaults/app-react-native/packages/app-shapes/tsconfig-esm.json +12 -0
- package/defaults/app-react-native/scripts/check-react.mjs +55 -0
- package/defaults/app-react-native/services/api/README.md +50 -2
- package/defaults/app-react-native/services/api/env.example.template +11 -0
- package/defaults/app-react-native/services/api/linked.backend.datasets.json +15 -0
- package/defaults/app-react-native/services/api/linked.backend.storage.ts +35 -0
- package/defaults/app-react-native/services/api/package.json +27 -1
- package/defaults/app-react-native/services/api/scripts/wait-for-fuseki.mjs +26 -0
- package/defaults/app-react-native/services/api/src/backend.ts +9 -0
- package/defaults/app-react-native/services/api/src/fileStoreEnv.ts +14 -0
- package/defaults/app-react-native/services/api/test/hasS3Env.test.mjs +28 -0
- package/defaults/app-react-native/services/api/test/waitForFuseki.test.mjs +27 -0
- package/defaults/app-react-native/services/api/tsconfig.json +15 -0
- package/lib/esm/cli-methods.d.ts +7 -2
- package/lib/esm/cli-methods.d.ts.map +1 -1
- package/lib/esm/cli-methods.js +147 -104
- package/lib/esm/cli-methods.js.map +1 -1
- package/lib/esm/cli.js +24 -11
- package/lib/esm/cli.js.map +1 -1
- package/lib/esm/commands/start.d.ts.map +1 -1
- package/lib/esm/commands/start.js +12 -8
- package/lib/esm/commands/start.js.map +1 -1
- package/lib/esm/utils/esmSpecifiers.d.ts +12 -2
- package/lib/esm/utils/esmSpecifiers.d.ts.map +1 -1
- package/lib/esm/utils/esmSpecifiers.js +57 -14
- package/lib/esm/utils/esmSpecifiers.js.map +1 -1
- package/lib/esm/utils/shippedDotfiles.d.ts.map +1 -1
- package/lib/esm/utils/shippedDotfiles.js +3 -1
- package/lib/esm/utils/shippedDotfiles.js.map +1 -1
- package/lib/esm/utils.d.ts +16 -7
- package/lib/esm/utils.d.ts.map +1 -1
- package/lib/esm/utils.js +92 -40
- package/lib/esm/utils.js.map +1 -1
- package/lib/esm/vite-config.js +6 -6
- package/lib/esm/vite-config.js.map +1 -1
- package/package.json +1 -1
- package/defaults/app-react-native/apps/mobile/src/shell/linkedDefaults.tsx +0 -10
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"experimentalDecorators": true,
|
|
8
|
+
"resolveJsonModule": true,
|
|
9
|
+
"allowImportingTsExtensions": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"noEmit": true,
|
|
12
|
+
"types": ["node"]
|
|
13
|
+
},
|
|
14
|
+
"include": ["src", "linked.backend.storage.ts"]
|
|
15
|
+
}
|
package/lib/esm/cli-methods.d.ts
CHANGED
|
@@ -24,7 +24,7 @@ export declare const createApp: (name: any, basePath?: string, options?: {
|
|
|
24
24
|
}) => Promise<void>;
|
|
25
25
|
/**
|
|
26
26
|
* iOS bundle identifier from the app domain and prefix:
|
|
27
|
-
* ('
|
|
27
|
+
* ('example.com', 'demo') -> 'com.example.demo'.
|
|
28
28
|
*/
|
|
29
29
|
export declare function reactNativeBundleId(appDomain: string, appPrefix: string): string;
|
|
30
30
|
/**
|
|
@@ -34,6 +34,11 @@ export declare function reactNativeBundleId(appDomain: string, appPrefix: string
|
|
|
34
34
|
export declare const RN_PREFIX_PATTERN: RegExp;
|
|
35
35
|
/** Placeholder name of the shapes package in defaults/app-react-native. */
|
|
36
36
|
export declare const RN_SHAPES_TOKEN = "app-shapes";
|
|
37
|
+
/**
|
|
38
|
+
* Literal tokens in defaults/app-react-native that are replaced by names
|
|
39
|
+
* derived from the app prefix: the shapes package and the Fuseki datasets.
|
|
40
|
+
*/
|
|
41
|
+
export declare function reactNativeTokens(appPrefix: string): Record<string, string>;
|
|
37
42
|
/**
|
|
38
43
|
* Scaffold the React Native monorepo from defaults/app-react-native.
|
|
39
44
|
* Identity is stamped into named fields only; the global ${...} substitution
|
|
@@ -88,7 +93,7 @@ export declare const buildBackend: () => Promise<boolean>;
|
|
|
88
93
|
export declare const upgradePackages: () => Promise<void>;
|
|
89
94
|
export declare const createPackage: (name: any, uriBase?: any, basePath?: string) => Promise<void>;
|
|
90
95
|
export declare const register: (registryURL: any) => Promise<void>;
|
|
91
|
-
export declare const buildPackage: (target: any, target2: any, packagePath?: string, logResults?: boolean) => Promise<
|
|
96
|
+
export declare const buildPackage: (target: any, target2: any, packagePath?: string, logResults?: boolean) => Promise<boolean>;
|
|
92
97
|
type BuildStep = {
|
|
93
98
|
name: string;
|
|
94
99
|
apply: () => Promise<unknown>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-methods.d.ts","sourceRoot":"","sources":["../../src/cli-methods.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli-methods.d.ts","sourceRoot":"","sources":["../../src/cli-methods.ts"],"names":[],"mappings":"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"}
|
package/lib/esm/cli-methods.js
CHANGED
|
@@ -14,7 +14,7 @@ import { getEnvFile } from 'env-cmd/dist/get-env-vars.js';
|
|
|
14
14
|
import fs from 'fs-extra';
|
|
15
15
|
import path, { dirname } from 'path';
|
|
16
16
|
import { createInterface } from 'readline';
|
|
17
|
-
import { debugInfo, execp, execPromise, getFileImports, getFiles, getLastCommitTime, getPackageJSON, isImportOutsideOfPackage,
|
|
17
|
+
import { debugInfo, execp, execPromise, getFileImports, getFiles, getLastCommitTime, getPackageJSON, isImportOutsideOfPackage, isInternalLinkedImport, needsRebuilding, } from './utils.js';
|
|
18
18
|
import { renameShippedDotfiles } from './utils/shippedDotfiles.js';
|
|
19
19
|
import { planPackageSetup } from './utils/packageSetup.js';
|
|
20
20
|
import { rewriteExtensionlessImports } from './utils/esmSpecifiers.js';
|
|
@@ -40,7 +40,7 @@ let dirname__ = typeof __dirname !== 'undefined'
|
|
|
40
40
|
* `scripts/storage-config.js` (pre-rename). The fallback chain lets older
|
|
41
41
|
* app clones keep booting through the rename.
|
|
42
42
|
*/
|
|
43
|
-
//
|
|
43
|
+
// Extracted to ./lifecycle.ts so the Vite SSR loader doesn't
|
|
44
44
|
// have to graph-walk the rest of cli-methods.ts (which contains many
|
|
45
45
|
// dynamic imports Vite can't analyze). We import for internal callers
|
|
46
46
|
// AND re-export so external consumers can keep importing from here.
|
|
@@ -212,7 +212,7 @@ export const createApp = (name_1, ...args_1) => __awaiter(void 0, [name_1, ...ar
|
|
|
212
212
|
});
|
|
213
213
|
/**
|
|
214
214
|
* iOS bundle identifier from the app domain and prefix:
|
|
215
|
-
* ('
|
|
215
|
+
* ('example.com', 'demo') -> 'com.example.demo'.
|
|
216
216
|
*/
|
|
217
217
|
export function reactNativeBundleId(appDomain, appPrefix) {
|
|
218
218
|
const host = appDomain
|
|
@@ -248,6 +248,17 @@ function assertReactNativeScaffoldable(targetFolder, appPrefix) {
|
|
|
248
248
|
}
|
|
249
249
|
/** Placeholder name of the shapes package in defaults/app-react-native. */
|
|
250
250
|
export const RN_SHAPES_TOKEN = 'app-shapes';
|
|
251
|
+
/**
|
|
252
|
+
* Literal tokens in defaults/app-react-native that are replaced by names
|
|
253
|
+
* derived from the app prefix: the shapes package and the Fuseki datasets.
|
|
254
|
+
*/
|
|
255
|
+
export function reactNativeTokens(appPrefix) {
|
|
256
|
+
return {
|
|
257
|
+
[RN_SHAPES_TOKEN]: `${appPrefix}-shapes`,
|
|
258
|
+
'app-dev': `${appPrefix}-dev`,
|
|
259
|
+
'app-test': `${appPrefix}-test`,
|
|
260
|
+
};
|
|
261
|
+
}
|
|
251
262
|
/**
|
|
252
263
|
* Replace every occurrence of `token` in the text files under `folder`
|
|
253
264
|
* (node_modules and files containing a NUL byte are skipped). A literal token
|
|
@@ -310,8 +321,11 @@ export function scaffoldReactNativeApp(targetFolder_1, id_1) {
|
|
|
310
321
|
}
|
|
311
322
|
// 4a. Rename the shapes package token everywhere: workspaces, .gitignore
|
|
312
323
|
// negation, package names, dependency keys, Jest patterns, import specifiers,
|
|
313
|
-
// test expectations and docs.
|
|
314
|
-
|
|
324
|
+
// test expectations and docs. The Fuseki dataset tokens (`app-dev`,
|
|
325
|
+
// `app-test`) are replaced the same way. Only these literal tokens change.
|
|
326
|
+
for (const [token, value] of Object.entries(reactNativeTokens(appPrefix))) {
|
|
327
|
+
replaceTokenInTextFiles(targetFolder, token, value);
|
|
328
|
+
}
|
|
315
329
|
// 4b. Stamp the identity fields that are not the shapes token.
|
|
316
330
|
const rootPkgPath = path.join(targetFolder, 'package.json');
|
|
317
331
|
if (fs.existsSync(rootPkgPath)) {
|
|
@@ -354,7 +368,7 @@ export function scaffoldReactNativeApp(targetFolder_1, id_1) {
|
|
|
354
368
|
}
|
|
355
369
|
}
|
|
356
370
|
// 6. Next steps.
|
|
357
|
-
log(`Your Linked React Native app is ready at ${chalk.blueBright(targetFolder)}`, `\nNext steps:`, ` ${chalk.blueBright(`cd ${path.basename(targetFolder)}`)}`, ` ${chalk.blueBright('npm test
|
|
371
|
+
log(`Your Linked React Native app is ready at ${chalk.blueBright(targetFolder)}`, `\nNext steps:`, ` ${chalk.blueBright(`cd ${path.basename(targetFolder)}`)}`, ` ${chalk.blueBright('npm test')} app and API unit tests`, ` ${chalk.blueBright('cp services/api/.env.example services/api/.env')} once`, ` ${chalk.blueBright('npm run fuseki:up')} Fuseki on :3030 (Docker)`, ` ${chalk.blueBright('npm run api')} API-only backend on :4000`, ` ${chalk.blueBright('npm run test:integration')} round trip against Fuseki`, ` ${chalk.blueBright('cd apps/mobile && npx expo run:ios')}`, `See README.md (and services/api/README.md if port 3030 is taken).`);
|
|
358
372
|
});
|
|
359
373
|
}
|
|
360
374
|
// Indirection so tests can replace the scaffold step when exercising createApp.
|
|
@@ -1162,7 +1176,7 @@ export const addShapeToBarrel = function (shapeHyphenName, root = process.cwd())
|
|
|
1162
1176
|
ensureBackendImportsShapes(root);
|
|
1163
1177
|
return barrelPath;
|
|
1164
1178
|
};
|
|
1165
|
-
// Exported for Shape-Builder reuse
|
|
1179
|
+
// Exported for Shape-Builder reuse: CodeShapeSyncService adds
|
|
1166
1180
|
// the `import './shapes/<Shape>.js';` line to a generated app package's index.
|
|
1167
1181
|
export const addLineToIndex = function (line, insertMatchString, root = process.cwd(), insertAtStart = false) {
|
|
1168
1182
|
//import ontology in index
|
|
@@ -1348,7 +1362,7 @@ export const createShape = (name_1, ...args_1) => __awaiter(void 0, [name_1, ...
|
|
|
1348
1362
|
log(`Created a new shape class template in ${chalk.magenta(targetFile.replace(basePath, ''))}`);
|
|
1349
1363
|
// Register the shape in the shapes barrel (src/shapes/index.ts) — NOT the main index —
|
|
1350
1364
|
// and make sure the barrel is loaded on both boot paths. This is what makes the app
|
|
1351
|
-
// materialize its own shapes on boot
|
|
1365
|
+
// materialize its own shapes on boot.
|
|
1352
1366
|
const barrelPath = addShapeToBarrel(hyphenName);
|
|
1353
1367
|
log(`Registered the shape in ${chalk.magenta(barrelPath.replace(basePath, ''))}`);
|
|
1354
1368
|
});
|
|
@@ -1386,9 +1400,10 @@ export const createComponent = (name_1, ...args_1) => __awaiter(void 0, [name_1,
|
|
|
1386
1400
|
log(`Added an import of this file from ${chalk.magenta(indexPath)}`);
|
|
1387
1401
|
}
|
|
1388
1402
|
});
|
|
1389
|
-
//
|
|
1390
|
-
//
|
|
1391
|
-
//
|
|
1403
|
+
// Reads the source of all ts/tsx files in the src folder and fails on imports
|
|
1404
|
+
// that reach outside the package source root ('outside_package'), or that point
|
|
1405
|
+
// into another Linked package's /src/ or /lib/ ('internal_linked'). Extensionless relative
|
|
1406
|
+
// imports are fine: `linked build` rewrites the emitted ESM specifiers.
|
|
1392
1407
|
export const checkImports = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (sourceFolder = getSourceFolder(), depth = 0, // Used to check if the import is outside the src folder
|
|
1393
1408
|
invalidImports = new Map()) {
|
|
1394
1409
|
if (!fs.existsSync(sourceFolder)) {
|
|
@@ -1399,12 +1414,8 @@ invalidImports = new Map()) {
|
|
|
1399
1414
|
// Start checking each file in the source folder
|
|
1400
1415
|
for (const file of dir) {
|
|
1401
1416
|
const filename = path.join(sourceFolder, file);
|
|
1402
|
-
//
|
|
1403
|
-
//
|
|
1404
|
-
// isn't load-bearing for them; enforcing it only blocks `linked build`
|
|
1405
|
-
// (the real ESM-output gate stays in force for shipped source). This is
|
|
1406
|
-
// what makes `linked build` green for packages whose tests use
|
|
1407
|
-
// extensionless imports (e.g. @_linked/core).
|
|
1417
|
+
// Skip test sources. Test files (and their helpers/probes) are not part
|
|
1418
|
+
// of the shipped package, so the import rules do not apply to them.
|
|
1408
1419
|
if (/(?:^|[\\/])(?:tests?|__tests__|test-helpers)(?:[\\/]|$)/.test(filename) ||
|
|
1409
1420
|
/\.(?:test|spec)\.tsx?$/.test(file) ||
|
|
1410
1421
|
/^type-probe.*\.tsx?$/.test(file)) {
|
|
@@ -1418,16 +1429,13 @@ invalidImports = new Map()) {
|
|
|
1418
1429
|
if (statSync(filename).isDirectory()) {
|
|
1419
1430
|
yield checkImports(filename, depth + 1, invalidImports);
|
|
1420
1431
|
}
|
|
1421
|
-
else {
|
|
1422
|
-
// Ignore all files that aren't one of the following:
|
|
1423
|
-
// - .ts
|
|
1424
|
-
// - .tsx
|
|
1425
|
-
continue;
|
|
1426
|
-
}
|
|
1427
1432
|
}
|
|
1428
1433
|
catch (e) {
|
|
1429
1434
|
console.log(e);
|
|
1430
1435
|
}
|
|
1436
|
+
// A directory has now been recursed into, and any other file is not a
|
|
1437
|
+
// source file: either way there is nothing here to read imports from.
|
|
1438
|
+
continue;
|
|
1431
1439
|
}
|
|
1432
1440
|
const allImports = yield getFileImports(filename);
|
|
1433
1441
|
if (!invalidImports.has(filename)) {
|
|
@@ -1440,15 +1448,9 @@ invalidImports = new Map()) {
|
|
|
1440
1448
|
importPath: i,
|
|
1441
1449
|
});
|
|
1442
1450
|
}
|
|
1443
|
-
if (
|
|
1444
|
-
invalidImports.get(filename).push({
|
|
1445
|
-
type: 'lincd',
|
|
1446
|
-
importPath: i,
|
|
1447
|
-
});
|
|
1448
|
-
}
|
|
1449
|
-
if (isImportWithMissingExtension(i)) {
|
|
1451
|
+
if (isInternalLinkedImport(i)) {
|
|
1450
1452
|
invalidImports.get(filename).push({
|
|
1451
|
-
type: '
|
|
1453
|
+
type: 'internal_linked',
|
|
1452
1454
|
importPath: i,
|
|
1453
1455
|
});
|
|
1454
1456
|
}
|
|
@@ -1467,26 +1469,22 @@ invalidImports = new Map()) {
|
|
|
1467
1469
|
if (type === 'outside_package') {
|
|
1468
1470
|
message += ' which is outside the package source root';
|
|
1469
1471
|
}
|
|
1470
|
-
if (type === '
|
|
1471
|
-
message +=
|
|
1472
|
-
' which should not contain /src/ or /lib/ in the import path';
|
|
1473
|
-
}
|
|
1474
|
-
if (type === 'missing_extension') {
|
|
1472
|
+
if (type === 'internal_linked') {
|
|
1475
1473
|
message +=
|
|
1476
|
-
|
|
1474
|
+
" which reaches into another Linked package's /src/ or /lib/." +
|
|
1475
|
+
' That breaks when its build layout changes and bypasses its' +
|
|
1476
|
+
' exports map. Import its public subpath instead.';
|
|
1477
1477
|
}
|
|
1478
1478
|
res += chalk.red(message + '\n');
|
|
1479
1479
|
});
|
|
1480
1480
|
});
|
|
1481
|
-
// Throw so buildStep aborts the compile pipeline
|
|
1482
|
-
//
|
|
1481
|
+
// Throw so buildStep aborts the compile pipeline: importing from outside
|
|
1482
|
+
// the package, or into another Linked package's /src/ or /lib/, breaks the
|
|
1483
|
+
// published package.
|
|
1483
1484
|
throw res;
|
|
1484
1485
|
}
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
// process.exit(0);
|
|
1488
|
-
return true;
|
|
1489
|
-
}
|
|
1486
|
+
// Nothing invalid: all imports OK.
|
|
1487
|
+
return true;
|
|
1490
1488
|
});
|
|
1491
1489
|
export const depCheckStaged = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
1492
1490
|
console.log('Checking dependencies of staged files');
|
|
@@ -1632,6 +1630,13 @@ export const runMethod = (packageName, method, options) => __awaiter(void 0, voi
|
|
|
1632
1630
|
.then(() => {
|
|
1633
1631
|
console.log('Done');
|
|
1634
1632
|
process.exit();
|
|
1633
|
+
})
|
|
1634
|
+
// An unmatched method (ServerCallError 501) or a provider error rejects; report it instead of an
|
|
1635
|
+
// unhandled rejection.
|
|
1636
|
+
.catch((err) => {
|
|
1637
|
+
var _a;
|
|
1638
|
+
console.error((_a = err === null || err === void 0 ? void 0 : err.message) !== null && _a !== void 0 ? _a : err);
|
|
1639
|
+
process.exit(1);
|
|
1635
1640
|
});
|
|
1636
1641
|
});
|
|
1637
1642
|
}
|
|
@@ -2181,7 +2186,6 @@ export const register = function (registryURL) {
|
|
|
2181
2186
|
}
|
|
2182
2187
|
};
|
|
2183
2188
|
export const buildPackage = (target_1, target2_1, ...args_1) => __awaiter(void 0, [target_1, target2_1, ...args_1], void 0, function* (target, target2, packagePath = process.cwd(), logResults = true) {
|
|
2184
|
-
var _a;
|
|
2185
2189
|
// Ensure packagePath is absolute and points to a directory containing package.json; if not, go up until we find one
|
|
2186
2190
|
// First, resolve to absolute path
|
|
2187
2191
|
let currentPath = path.isAbsolute(packagePath)
|
|
@@ -2224,6 +2228,7 @@ export const buildPackage = (target_1, target2_1, ...args_1) => __awaiter(void 0
|
|
|
2224
2228
|
}).start();
|
|
2225
2229
|
}
|
|
2226
2230
|
let buildProcess = Promise.resolve(true);
|
|
2231
|
+
let warned = false;
|
|
2227
2232
|
let buildStep = (step) => {
|
|
2228
2233
|
buildProcess = buildProcess.then((previousResult) => {
|
|
2229
2234
|
if (!previousResult) {
|
|
@@ -2237,11 +2242,14 @@ export const buildPackage = (target_1, target2_1, ...args_1) => __awaiter(void 0
|
|
|
2237
2242
|
//if a build step returns a string,
|
|
2238
2243
|
//a warning is shown but the build is still successful with warnings
|
|
2239
2244
|
if (typeof stepResult === 'string') {
|
|
2240
|
-
|
|
2245
|
+
warned = true;
|
|
2241
2246
|
if (logResults) {
|
|
2242
2247
|
spinner.warn(step.name + ' - ' + stepResult);
|
|
2243
2248
|
spinner.stop();
|
|
2244
2249
|
}
|
|
2250
|
+
else {
|
|
2251
|
+
console.warn(chalk.yellow(step.name + ' - ' + stepResult));
|
|
2252
|
+
}
|
|
2245
2253
|
//can still continue
|
|
2246
2254
|
return true;
|
|
2247
2255
|
}
|
|
@@ -2251,21 +2259,45 @@ export const buildPackage = (target_1, target2_1, ...args_1) => __awaiter(void 0
|
|
|
2251
2259
|
}
|
|
2252
2260
|
return previousResult && true;
|
|
2253
2261
|
}
|
|
2254
|
-
else if (
|
|
2262
|
+
else if (
|
|
2263
|
+
//a step may report a detail alongside success, e.g. how many files
|
|
2264
|
+
//it changed. Not a warning: the build stays clean.
|
|
2265
|
+
stepResult &&
|
|
2266
|
+
typeof stepResult === 'object' &&
|
|
2267
|
+
stepResult.info) {
|
|
2268
|
+
if (logResults) {
|
|
2269
|
+
spinner.succeed(step.name + ' - ' + stepResult.info);
|
|
2270
|
+
}
|
|
2271
|
+
return previousResult && true;
|
|
2272
|
+
}
|
|
2273
|
+
else if (stepResult &&
|
|
2274
|
+
typeof stepResult === 'object' &&
|
|
2275
|
+
stepResult.error) {
|
|
2255
2276
|
if (logResults) {
|
|
2256
2277
|
spinner.fail(step.name + ' - ' + stepResult.error);
|
|
2257
2278
|
spinner.stop();
|
|
2258
2279
|
}
|
|
2280
|
+
else {
|
|
2281
|
+
console.error(chalk.red(step.name + ' - ' + stepResult.error));
|
|
2282
|
+
}
|
|
2259
2283
|
//failed and should stop
|
|
2260
2284
|
return false;
|
|
2261
2285
|
}
|
|
2286
|
+
//anything else — notably a literal false, which several steps return
|
|
2287
|
+
//on failure — is a failure. Name the step, so the build does not end
|
|
2288
|
+
//on a bare 'Build failed'.
|
|
2289
|
+
const failure = step.name + ' failed';
|
|
2290
|
+
if (logResults) {
|
|
2291
|
+
spinner.fail(failure);
|
|
2292
|
+
spinner.stop();
|
|
2293
|
+
}
|
|
2294
|
+
else {
|
|
2295
|
+
console.error(chalk.red(failure));
|
|
2296
|
+
}
|
|
2297
|
+
return false;
|
|
2262
2298
|
});
|
|
2263
2299
|
});
|
|
2264
2300
|
};
|
|
2265
|
-
if (((_a = pkgJson.linked) === null || _a === void 0 ? void 0 : _a.extensionlessImports) === true) {
|
|
2266
|
-
const skipped = "Skipping the import check: package.json sets 'linked.extensionlessImports'";
|
|
2267
|
-
logResults ? spinner.info(skipped) : console.log(skipped);
|
|
2268
|
-
}
|
|
2269
2301
|
planBuildSteps(pkgJson, packagePath).forEach(buildStep);
|
|
2270
2302
|
let success = yield buildProcess.catch((err) => {
|
|
2271
2303
|
let msg = typeof err === 'string' || err instanceof Error
|
|
@@ -2278,22 +2310,21 @@ export const buildPackage = (target_1, target2_1, ...args_1) => __awaiter(void 0
|
|
|
2278
2310
|
symbol: chalk.red('✖'),
|
|
2279
2311
|
// text: 'Build failed',
|
|
2280
2312
|
});
|
|
2313
|
+
console.log(msg);
|
|
2281
2314
|
}
|
|
2282
2315
|
else {
|
|
2283
2316
|
console.error(chalk.red(packagePath.split('/').pop(), ' - Build failed:'));
|
|
2284
2317
|
console.error(err);
|
|
2285
|
-
return msg;
|
|
2286
2318
|
}
|
|
2287
|
-
|
|
2319
|
+
//a failed build always resolves to false, never to a truthy message:
|
|
2320
|
+
//callers decide success by the return value.
|
|
2321
|
+
return false;
|
|
2288
2322
|
});
|
|
2289
|
-
|
|
2290
|
-
if (typeof success !== 'undefined' && success !== false) {
|
|
2323
|
+
if (success === true) {
|
|
2291
2324
|
if (logResults) {
|
|
2292
2325
|
spinner.stopAndPersist({
|
|
2293
2326
|
symbol: chalk.greenBright('✔'),
|
|
2294
|
-
text:
|
|
2295
|
-
? 'Build successful'
|
|
2296
|
-
: 'Build successful with warnings',
|
|
2327
|
+
text: warned ? 'Build successful with warnings' : 'Build successful',
|
|
2297
2328
|
});
|
|
2298
2329
|
}
|
|
2299
2330
|
}
|
|
@@ -2305,46 +2336,31 @@ export const buildPackage = (target_1, target2_1, ...args_1) => __awaiter(void 0
|
|
|
2305
2336
|
});
|
|
2306
2337
|
}
|
|
2307
2338
|
}
|
|
2308
|
-
|
|
2339
|
+
//true only when every step succeeded (warnings included); false otherwise.
|
|
2340
|
+
return success === true;
|
|
2309
2341
|
});
|
|
2310
|
-
// The ordered `linked build` steps for a linkedPackage.
|
|
2311
|
-
//
|
|
2312
|
-
//
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
apply: () => checkImports(packagePath + '/src'),
|
|
2321
|
-
});
|
|
2322
|
-
}
|
|
2323
|
-
steps.push({
|
|
2342
|
+
// The ordered `linked build` steps for a linkedPackage. Source may use
|
|
2343
|
+
// extensionless relative imports: once `lib/esm` holds everything it will ship,
|
|
2344
|
+
// every package gets `.js` added to the relative specifiers in it (JS and
|
|
2345
|
+
// declarations). For a package that already writes `.js` this is a no-op.
|
|
2346
|
+
export const planBuildSteps = (pkgJson, packagePath) => [
|
|
2347
|
+
{
|
|
2348
|
+
name: 'Checking imports',
|
|
2349
|
+
apply: () => checkImports(packagePath + '/src'),
|
|
2350
|
+
},
|
|
2351
|
+
{
|
|
2324
2352
|
name: 'Compiling ESM',
|
|
2325
2353
|
apply: () => __awaiter(void 0, void 0, void 0, function* () {
|
|
2326
2354
|
return compilePackageESM(packagePath);
|
|
2327
2355
|
}),
|
|
2328
|
-
}
|
|
2329
|
-
|
|
2330
|
-
steps.push({
|
|
2331
|
-
name: 'Rewriting ESM import specifiers',
|
|
2332
|
-
apply: () => __awaiter(void 0, void 0, void 0, function* () {
|
|
2333
|
-
const libEsm = path.join(packagePath, 'lib', 'esm');
|
|
2334
|
-
if (fs.existsSync(libEsm)) {
|
|
2335
|
-
yield rewriteExtensionlessImports(libEsm);
|
|
2336
|
-
}
|
|
2337
|
-
return true;
|
|
2338
|
-
}),
|
|
2339
|
-
});
|
|
2340
|
-
}
|
|
2341
|
-
steps.push({
|
|
2356
|
+
},
|
|
2357
|
+
{
|
|
2342
2358
|
name: 'Compiling CJS',
|
|
2343
2359
|
apply: () => __awaiter(void 0, void 0, void 0, function* () {
|
|
2344
2360
|
return compilePackageCJS(packagePath);
|
|
2345
2361
|
}),
|
|
2346
|
-
}
|
|
2347
|
-
|
|
2362
|
+
},
|
|
2363
|
+
{
|
|
2348
2364
|
name: 'Copying files to lib folder',
|
|
2349
2365
|
apply: () => __awaiter(void 0, void 0, void 0, function* () {
|
|
2350
2366
|
const files = yield glob(packagePath + '/src/**/*.{json,d.ts,css,scss}');
|
|
@@ -2366,8 +2382,8 @@ export const planBuildSteps = (pkgJson, packagePath) => {
|
|
|
2366
2382
|
return allResults.every((r) => r === true);
|
|
2367
2383
|
});
|
|
2368
2384
|
}),
|
|
2369
|
-
}
|
|
2370
|
-
|
|
2385
|
+
},
|
|
2386
|
+
{
|
|
2371
2387
|
name: 'Dual package support',
|
|
2372
2388
|
apply: () => {
|
|
2373
2389
|
// Skip if no tsconfig files (e.g. pure-CSS packages).
|
|
@@ -2381,19 +2397,48 @@ export const planBuildSteps = (pkgJson, packagePath) => {
|
|
|
2381
2397
|
return res === '';
|
|
2382
2398
|
});
|
|
2383
2399
|
},
|
|
2384
|
-
}
|
|
2385
|
-
|
|
2400
|
+
},
|
|
2401
|
+
{
|
|
2386
2402
|
name: 'Removing old files from lib folder',
|
|
2387
2403
|
apply: () => __awaiter(void 0, void 0, void 0, function* () {
|
|
2388
2404
|
return removeOldFiles(packagePath);
|
|
2389
2405
|
}),
|
|
2390
|
-
}
|
|
2391
|
-
|
|
2406
|
+
},
|
|
2407
|
+
{
|
|
2408
|
+
// MUST run after 'Copying files to lib folder' and after 'Removing old
|
|
2409
|
+
// files from lib folder', because the rewrite resolves each specifier
|
|
2410
|
+
// against the files actually present in lib/esm:
|
|
2411
|
+
// - the copy step brings in the assets (`./x.scss`) and hand-written
|
|
2412
|
+
// `.d.ts` from src; before it, an asset import looks unresolvable (a
|
|
2413
|
+
// spurious "build with warnings") and a copied `.d.ts` is never rewritten;
|
|
2414
|
+
// - the cleanup step deletes stale output; before it, a leftover `x.js`
|
|
2415
|
+
// makes './x' resolve to './x.js' and the cleanup then removes the file
|
|
2416
|
+
// the specifier now points at.
|
|
2417
|
+
name: 'Rewriting ESM import specifiers',
|
|
2418
|
+
apply: () => __awaiter(void 0, void 0, void 0, function* () {
|
|
2419
|
+
// No tsconfig-esm.json means the ESM compile was skipped (e.g. pure-CSS
|
|
2420
|
+
// packages), so there is nothing to rewrite and nothing to fail over.
|
|
2421
|
+
if (!fs.existsSync(path.join(packagePath, 'tsconfig-esm.json'))) {
|
|
2422
|
+
return true;
|
|
2423
|
+
}
|
|
2424
|
+
const libEsm = path.join(packagePath, 'lib', 'esm');
|
|
2425
|
+
if (!fs.existsSync(libEsm)) {
|
|
2426
|
+
return {
|
|
2427
|
+
error: 'lib/esm was not emitted while tsconfig-esm.json is present. Check the ESM compile.',
|
|
2428
|
+
};
|
|
2429
|
+
}
|
|
2430
|
+
const { changed, unresolved } = yield rewriteExtensionlessImports(libEsm);
|
|
2431
|
+
if (unresolved.length > 0) {
|
|
2432
|
+
return `could not resolve ${unresolved.length} import(s), left unchanged: ${unresolved.join(', ')}`;
|
|
2433
|
+
}
|
|
2434
|
+
return changed > 0 ? { info: `rewrote ${changed} file(s)` } : true;
|
|
2435
|
+
}),
|
|
2436
|
+
},
|
|
2437
|
+
{
|
|
2392
2438
|
name: 'Checking dependencies',
|
|
2393
2439
|
apply: () => depCheck(packagePath),
|
|
2394
|
-
}
|
|
2395
|
-
|
|
2396
|
-
};
|
|
2440
|
+
},
|
|
2441
|
+
];
|
|
2397
2442
|
export const compilePackage = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (packagePath = process.cwd()) {
|
|
2398
2443
|
//echo 'compiling CJS' && tsc -p tsconfig-cjs.json && echo 'compiling ESM' && tsc -p tsconfig-esm.json
|
|
2399
2444
|
// let cjsConfig = fs.existsSync(path.join(packagePath,'tsconfig-cjs.json'));
|
|
@@ -2717,12 +2762,10 @@ export var buildUpdated = function (back_1, target_1, target2_1) {
|
|
|
2717
2762
|
// log('path: ' + pathToBuild);
|
|
2718
2763
|
return buildPackage(null, null, pathToBuild, false)
|
|
2719
2764
|
.then((res) => {
|
|
2720
|
-
//
|
|
2721
|
-
//
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
if (typeof res === 'undefined' || typeof res === 'string') {
|
|
2725
|
-
logError('Failed to build ' + pkg.packageName + '. ' + res ? res : '');
|
|
2765
|
+
//buildPackage returns true only when the build succeeded
|
|
2766
|
+
//(warnings included); anything else is a failure.
|
|
2767
|
+
if (res !== true) {
|
|
2768
|
+
logError('Failed to build ' + pkg.packageName);
|
|
2726
2769
|
process.exit(1);
|
|
2727
2770
|
}
|
|
2728
2771
|
else {
|