@_linked/cli 1.14.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 CHANGED
@@ -1,5 +1,53 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.15.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#86](https://github.com/linked-cm/cli/pull/86) [`1f8908f`](https://github.com/linked-cm/cli/commit/1f8908fa276a5b65ed3ffe1c1e3bc23417ef9043) Thanks [@flyon](https://github.com/flyon)! - Always rewrite emitted ESM import specifiers
8
+
9
+ `linked build` appends `.js` (or `/index.js`) to relative specifiers in `lib/esm` for every package, with no
10
+ opt-in. The rewrite covers the emitted `.d.ts` declarations as well as the `.js`, so consumers on TypeScript
11
+ `node16`/`nodenext` resolution get valid declarations. For a package that already writes `.js` specifiers the
12
+ rewrite is a no-op.
13
+
14
+ It runs at the end of the build, after the assets and hand-written declarations have been copied into `lib` and
15
+ after stale output has been removed, so every specifier is resolved against the files the package actually ships.
16
+ Asset imports such as `./styles.scss` resolve and are left as written, copied `.d.ts` files are rewritten too, and
17
+ a leftover `x.js` can no longer make `./x` point at a file the cleanup then deletes.
18
+
19
+ Also in this release:
20
+
21
+ - The `missing_extension` rule is gone from the import check, in the build gate and in `linked check-imports`.
22
+ Extensionless relative imports in source no longer fail the build; the rewrite warns about any relative
23
+ specifier it cannot resolve, and Vite, Metro and `tsc` catch the rest. `outside_package` and the
24
+ internal-import rule remain hard errors for every package.
25
+ - The rule that stops a package reaching into another Linked package's internals now actually fires. It matched
26
+ only import paths containing the literal string `lincd`, so after the rename to the `@_linked/*` scope it was a
27
+ no-op for every current package: `@_linked/core/lib/esm/utils/Shape` passed. It now matches `@_linked/<pkg>/...`
28
+ as well as `lincd`-prefixed package names, on a `/src/` or `/lib/` path segment, and is called
29
+ `isInternalLinkedImport`. This can fail builds that previously passed — which is the point: such an import
30
+ breaks when the other package changes its build layout and bypasses its exports map. Import the public subpath
31
+ instead. Relative specifiers are exempt, so a local `./lib/helpers` is still fine.
32
+ - Both import rules now see every form that names a module — `export ... from`, `import()` in value and type
33
+ position, and `import x = require()` — not just `import ... from`.
34
+ - `linked check-imports` prints the report and exits 1 when an import is invalid, instead of exiting 0.
35
+ - `linked build` reports failures accurately: a step that fails names itself instead of a bare "Build failed",
36
+ and a failed build always exits non-zero, including under `--silent` and when building updated packages.
37
+ - `isImportOutsideOfPackage` normalises the path before judging it, so `./a..b` is no longer flagged and
38
+ `../a/../b` is counted as the one level it actually climbs.
39
+ - A relative specifier with a trailing slash (`./file/`) names a directory, so it resolves to `./file/index.js`
40
+ and never to a sibling `./file.js`.
41
+
42
+ A package without a `tsconfig-esm.json` has no ESM build, so the rewrite step is skipped rather than failing. When
43
+ `tsconfig-esm.json` is present but `lib/esm` was not emitted, the build fails.
44
+
45
+ ## 1.14.1
46
+
47
+ ### Patch Changes
48
+
49
+ - [#83](https://github.com/linked-cm/cli/pull/83) [`566cb44`](https://github.com/linked-cm/cli/commit/566cb44f8728f25e852987ed4426063df9575492) Thanks [@flyon](https://github.com/flyon)! - React Native template: the integration test setup now tells apart "Docker is not installed", "Docker Compose is unavailable" and "Compose Fuseki is not running" (unit-tested in the scaffold); the integration Jest config comment says "Integration tests". README: document that `linked build` exits 1 whenever the build does not succeed (including in a `linkedApp` or a package without `linkedPackage: true`), and 0 with warnings. Reworded a stale migration comment in `linked start`.
50
+
3
51
  ## 1.14.0
4
52
 
5
53
  ### Minor Changes
package/README.md CHANGED
@@ -41,6 +41,10 @@ linked build-updated # incremental: only packages that changed sinc
41
41
  linked build-package <file> # walk up from a file path to find its package and rebuild
42
42
  ```
43
43
 
44
+ `linked build` exits with code 1 whenever the build does not succeed, including when it is run in a `linkedApp` or
45
+ in a package without `"linkedPackage": true` (it used to exit 0 there). A build that finishes with warnings still
46
+ exits 0.
47
+
44
48
  ### Publishing / release
45
49
 
46
50
  ```bash
@@ -89,28 +93,21 @@ The CLI recognizes two flags in `package.json`:
89
93
 
90
94
  The legacy `lincd: true` / `lincdApp: true` flags are no longer read. Migrate to `linkedPackage` / `linkedApp`.
91
95
 
92
- ### `"linked": {"extensionlessImports": true}`
93
-
94
- ```json
95
- {
96
- "linkedPackage": true,
97
- "type": "module",
98
- "linked": {"extensionlessImports": true}
99
- }
100
- ```
96
+ ### Extensionless relative imports
101
97
 
102
- By default `linked build` rejects relative imports without an extension (`./shapes/Example`), because Node's ESM
103
- loader cannot resolve them. Set this flag when the package source must use extensionless imports, for example a
104
- shapes package consumed as TypeScript source by Metro (which does not map `.js` specifiers to `.ts` files).
105
- With the flag, `linked build`:
98
+ Package source may use extensionless relative imports (`./shapes/Example` rather than `./shapes/Example.js`) —
99
+ useful for a shapes package consumed as TypeScript source by Metro, which does not map `.js` specifiers to `.ts`
100
+ files. No configuration is needed. After compiling ESM, `linked build` rewrites every relative specifier in
101
+ `lib/esm` — in the emitted `.js` and in the `.d.ts` declarations beside them, so consumers on TypeScript
102
+ `node16`/`nodenext` resolution get valid declarations — to `./x.js` or `./dir/index.js`, so Node can load the
103
+ output. For a package that already writes `.js` specifiers the rewrite is a no-op.
106
104
 
107
- - skips the import check;
108
- - after compiling ESM, rewrites every relative specifier in `lib/esm` (static imports and exports, `export * as`,
109
- side-effect imports and `import()` with a literal) to `./x.js` or `./dir/index.js`, so Node can load the output;
110
- - fails if `lib/esm` was not emitted;
111
- - finishes "with warnings" and lists each specifier it could not resolve (left unchanged).
105
+ The build finishes "with warnings" and lists each relative specifier it could not resolve (left unchanged), and
106
+ fails when `tsconfig-esm.json` is present but `lib/esm` was not emitted. A package without a `tsconfig-esm.json`
107
+ has no ESM build, so the step is skipped.
112
108
 
113
- Requirements: `"linkedPackage": true`, `"type": "module"` and a `tsconfig-esm.json` in the package.
109
+ The import check (`linked check-imports`, also run as the first build step) still fails the build for imports
110
+ that reach outside the package source root, and for imports into another linked package's `/src/` or `/lib/`.
114
111
 
115
112
  ## API-only backend
116
113
 
@@ -168,8 +165,8 @@ workspaces monorepo for Expo SDK 57 / React Native 0.86 / React 19.2 with an API
168
165
  src/shell/ env.ts (API URL), storage.ts (BackendAPIStore)
169
166
  src/components/ PersonOverview / PersonPreview: example add/edit/delete screen
170
167
  __tests__/ unit tests; __tests__/integration/ runs against the API and Fuseki
171
- packages/<prefix>-shapes/ Linked shapes package: TypeScript source, extensionless imports,
172
- "linked": {"extensionlessImports": true} so `linked build` emits Node-loadable lib/esm
168
+ packages/<prefix>-shapes/ Linked shapes package: TypeScript source with extensionless imports; `linked build`
169
+ rewrites the emitted specifiers so lib/esm is Node-loadable
173
170
  services/api/ API-only backend (`linked start --api-only`) on @_linked/server, Fuseki through
174
171
  linked.backend.datasets.json, node --test unit tests
175
172
  ```
@@ -87,9 +87,9 @@ cd apps/mobile && npx expo export --platform ios --output-dir /tmp/export
87
87
  `@_linked/server/shapes/quadstores/BackendAPIStore`): the root barrel pulls express, webpack and react-dom.
88
88
  ESLint `no-restricted-imports` enforces it.
89
89
  - **Shapes package imports are extensionless** (`./shapes/Example`, not `./shapes/Example.js`): Metro does not
90
- map `.js` specifiers to `.ts` source. `"linked": {"extensionlessImports": true}` in its `package.json` makes
91
- `linked build` skip the import check and add `.js` to the emitted `lib/esm` specifiers. The app, Jest and the
92
- API in development consume `src/` through the `react-native` and `development` export conditions.
90
+ map `.js` specifiers to `.ts` source. No configuration is needed — `linked build` always adds `.js` to the
91
+ relative specifiers in the emitted `lib/esm` JS and declarations. The app, Jest and the API in development
92
+ consume `src/` through the `react-native` and `development` export conditions.
93
93
  - **Decorators** work with the stock `babel-preset-expo`. The one custom Babel plugin,
94
94
  `apps/mobile/babel/stripJsonImportAttributes.js`, strips `with { type: 'json' }` from dynamic `import()`, which
95
95
  Metro rejects and Linked ontology packages use; `__tests__/stripJsonImportAttributes.test.ts` covers it. After
@@ -0,0 +1,33 @@
1
+ import { describeComposePortFailure } from './integration/apiEnv';
2
+
3
+ describe('describeComposePortFailure', () => {
4
+ test('docker not installed', () => {
5
+ const error = Object.assign(new Error('spawnSync docker ENOENT'), { code: 'ENOENT' });
6
+ expect(describeComposePortFailure({ error, status: null })).toMatch(/^Docker is not installed/);
7
+ });
8
+
9
+ test('docker compose unavailable', () => {
10
+ const message = describeComposePortFailure({
11
+ status: 1,
12
+ stderr: "docker: 'compose' is not a docker command.\nSee 'docker --help'",
13
+ });
14
+ expect(message).toMatch(/^Docker Compose is not available/);
15
+ expect(message).toContain('is not a docker command');
16
+ });
17
+
18
+ test('non-zero exit mentioning compose', () => {
19
+ expect(describeComposePortFailure({ status: 125, stderr: 'unknown command: docker compose' })).toMatch(
20
+ /^Docker Compose is not available/,
21
+ );
22
+ });
23
+
24
+ test('service not running', () => {
25
+ const message = describeComposePortFailure({ status: 1, stderr: 'service "fuseki" is not running' });
26
+ expect(message).toMatch(/Compose Fuseki is not running/);
27
+ expect(message).toContain('npm run fuseki:up');
28
+ });
29
+
30
+ test('exit 0 without a port counts as not running', () => {
31
+ expect(describeComposePortFailure({ status: 0, stdout: '' })).toMatch(/Compose Fuseki is not running/);
32
+ });
33
+ });
@@ -28,7 +28,33 @@ export function readApiEnvFile(): Record<string, string> {
28
28
  return existsSync(envFile) ? parseEnvFile(readFileSync(envFile, 'utf8')) : {};
29
29
  }
30
30
 
31
- export type FusekiEnv = { baseUrl: string; user: string; password: string };
31
+ /** The parts of a `spawnSync('docker', ['compose', 'port', 'fuseki', '3030'])` result that explain a failure. */
32
+ export type ComposePortResult = {
33
+ error?: (Error & { code?: string }) | undefined;
34
+ status: number | null;
35
+ stdout?: string | null;
36
+ stderr?: string | null;
37
+ };
38
+
39
+ /**
40
+ * Why `docker compose port fuseki 3030` gave no port: Docker is not installed, Docker Compose is unavailable, or
41
+ * this repo's Compose Fuseki is not running.
42
+ */
43
+ export function describeComposePortFailure(result: ComposePortResult): string {
44
+ const output = (result.stderr || result.error?.message || result.stdout || '').trim();
45
+ if (result.error?.code === 'ENOENT') {
46
+ return 'Docker is not installed or not on PATH (`docker` could not be started). Install Docker, then run `npm run fuseki:up`.';
47
+ }
48
+ const composeMissing =
49
+ /is not a docker command/i.test(output) ||
50
+ (result.status !== 0 && /compose/i.test(output) && !/not running|no container/i.test(output));
51
+ if (composeMissing) {
52
+ return `Docker Compose is not available (\`docker compose port fuseki 3030\`: ${output}). Install the Docker Compose plugin, then run \`npm run fuseki:up\`.`;
53
+ }
54
+ return `this repo's Compose Fuseki is not running (\`docker compose port fuseki 3030\`: ${output}). Run \`npm run fuseki:up\`.`;
55
+ }
56
+
57
+ export type FusekiEnv ={ baseUrl: string; user: string; password: string };
32
58
 
33
59
  /**
34
60
  * The Fuseki the tests talk to. services/api/.env is the source, and the shell wins: FUSEKI_BASE_URL, or
@@ -4,7 +4,16 @@
4
4
  import { type ChildProcess, spawn, spawnSync } from 'node:child_process';
5
5
  import { resolve } from 'node:path';
6
6
 
7
- import { API_PORT, API_URL, FUSEKI_DATASET, apiDir, readApiEnvFile, repoRoot, resolveFusekiEnv } from './apiEnv';
7
+ import {
8
+ API_PORT,
9
+ API_URL,
10
+ FUSEKI_DATASET,
11
+ apiDir,
12
+ describeComposePortFailure,
13
+ readApiEnvFile,
14
+ repoRoot,
15
+ resolveFusekiEnv,
16
+ } from './apiEnv';
8
17
 
9
18
  // The variables that select S3FileStore (services/api/src/fileStoreEnv.ts); blanked even when unset anywhere.
10
19
  const S3_ENV_KEYS = ['AWS_ACCESS_KEY_ID', 'AWS_SECRET_ACCESS_KEY', 'AWS_REGION', 'S3_BUCKET_ENDPOINT', 'S3_FILES_BUCKET_NAME'];
@@ -40,12 +49,7 @@ function assertSafeTarget(baseUrl: string) {
40
49
 
41
50
  const compose = spawnSync('docker', ['compose', 'port', 'fuseki', '3030'], { cwd: repoRoot, encoding: 'utf8' });
42
51
  const composePort = compose.status === 0 ? /:(\d+)\s*$/.exec(compose.stdout.trim())?.[1] : undefined;
43
- if (!composePort) {
44
- refuse(
45
- `this repo's Compose Fuseki is not running (\`docker compose port fuseki 3030\`: ` +
46
- `${(compose.stderr || compose.error?.message || compose.stdout || '').trim()}). Run \`npm run fuseki:up\`.`,
47
- );
48
- }
52
+ if (!composePort) refuse(describeComposePortFailure(compose));
49
53
  if (composePort !== urlPort) {
50
54
  refuse(`port ${urlPort} is not the Compose Fuseki port ${composePort}. Set FUSEKI_PORT=${composePort}.`);
51
55
  }
@@ -1,4 +1,4 @@
1
- // Round-trip tests against a real API and Fuseki: `npm run fuseki:up && npm run test:integration`.
1
+ // Integration tests against a real API and Fuseki: `npm run fuseki:up && npm run test:integration`.
2
2
  // Same preset, transforms and module mapping as the unit config in package.json. jest-expo replaces the global
3
3
  // fetch with a stubbed `expo/fetch` that never sends a request (it is not a jest mock), so the environment saves
4
4
  // Node's fetch and restoreNodeFetch.ts reinstates it.
@@ -4,9 +4,6 @@
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "linkedPackage": true,
7
- "linked": {
8
- "extensionlessImports": true
9
- },
10
7
  "exports": {
11
8
  ".": {
12
9
  "types": "./src/index.ts",
@@ -93,7 +93,7 @@ export declare const buildBackend: () => Promise<boolean>;
93
93
  export declare const upgradePackages: () => Promise<void>;
94
94
  export declare const createPackage: (name: any, uriBase?: any, basePath?: string) => Promise<void>;
95
95
  export declare const register: (registryURL: any) => Promise<void>;
96
- export declare const buildPackage: (target: any, target2: any, packagePath?: string, logResults?: boolean) => Promise<any>;
96
+ export declare const buildPackage: (target: any, target2: any, packagePath?: string, logResults?: boolean) => Promise<boolean>;
97
97
  type BuildStep = {
98
98
  name: string;
99
99
  apply: () => Promise<unknown>;
@@ -1 +1 @@
1
- {"version":3,"file":"cli-methods.d.ts","sourceRoot":"","sources":["../../src/cli-methods.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli-methods.d.ts","sourceRoot":"","sources":["../../src/cli-methods.ts"],"names":[],"mappings":"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"}
@@ -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, isImportWithMissingExtension, isInvalidLINCDImport, needsRebuilding, } from './utils.js';
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';
@@ -1400,9 +1400,10 @@ export const createComponent = (name_1, ...args_1) => __awaiter(void 0, [name_1,
1400
1400
  log(`Added an import of this file from ${chalk.magenta(indexPath)}`);
1401
1401
  }
1402
1402
  });
1403
- //read the source of all ts/tsx files in the src folder
1404
- //if there is an import that imports a lincd package with /src/ in it, then warn
1405
- //if there is an import that imports something from outside the src folder, then warn
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.
1406
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
1407
1408
  invalidImports = new Map()) {
1408
1409
  if (!fs.existsSync(sourceFolder)) {
@@ -1413,12 +1414,8 @@ invalidImports = new Map()) {
1413
1414
  // Start checking each file in the source folder
1414
1415
  for (const file of dir) {
1415
1416
  const filename = path.join(sourceFolder, file);
1416
- // Skip test sources. Test files (and their helpers/probes)
1417
- // are not part of the shipped ESM contract, so the missing-extension rule
1418
- // isn't load-bearing for them; enforcing it only blocks `linked build`
1419
- // (the real ESM-output gate stays in force for shipped source). This is
1420
- // what makes `linked build` green for packages whose tests use
1421
- // 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.
1422
1419
  if (/(?:^|[\\/])(?:tests?|__tests__|test-helpers)(?:[\\/]|$)/.test(filename) ||
1423
1420
  /\.(?:test|spec)\.tsx?$/.test(file) ||
1424
1421
  /^type-probe.*\.tsx?$/.test(file)) {
@@ -1432,16 +1429,13 @@ invalidImports = new Map()) {
1432
1429
  if (statSync(filename).isDirectory()) {
1433
1430
  yield checkImports(filename, depth + 1, invalidImports);
1434
1431
  }
1435
- else {
1436
- // Ignore all files that aren't one of the following:
1437
- // - .ts
1438
- // - .tsx
1439
- continue;
1440
- }
1441
1432
  }
1442
1433
  catch (e) {
1443
1434
  console.log(e);
1444
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;
1445
1439
  }
1446
1440
  const allImports = yield getFileImports(filename);
1447
1441
  if (!invalidImports.has(filename)) {
@@ -1454,15 +1448,9 @@ invalidImports = new Map()) {
1454
1448
  importPath: i,
1455
1449
  });
1456
1450
  }
1457
- if (isInvalidLINCDImport(i, depth)) {
1451
+ if (isInternalLinkedImport(i)) {
1458
1452
  invalidImports.get(filename).push({
1459
- type: 'lincd',
1460
- importPath: i,
1461
- });
1462
- }
1463
- if (isImportWithMissingExtension(i)) {
1464
- invalidImports.get(filename).push({
1465
- type: 'missing_extension',
1453
+ type: 'internal_linked',
1466
1454
  importPath: i,
1467
1455
  });
1468
1456
  }
@@ -1481,26 +1469,22 @@ invalidImports = new Map()) {
1481
1469
  if (type === 'outside_package') {
1482
1470
  message += ' which is outside the package source root';
1483
1471
  }
1484
- if (type === 'lincd') {
1485
- message +=
1486
- ' which should not contain /src/ or /lib/ in the import path';
1487
- }
1488
- if (type === 'missing_extension') {
1472
+ if (type === 'internal_linked') {
1489
1473
  message +=
1490
- ' which should end with a file extension. Like .js or .scss';
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.';
1491
1477
  }
1492
1478
  res += chalk.red(message + '\n');
1493
1479
  });
1494
1480
  });
1495
- // Throw so buildStep aborts the compile pipeline — relative imports MUST
1496
- // have .js (or .scss) extensions for native-ESM-compatible output.
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.
1497
1484
  throw res;
1498
1485
  }
1499
- else if (depth === 0 && invalidImports.size === 0) {
1500
- // console.info('All imports OK');
1501
- // process.exit(0);
1502
- return true;
1503
- }
1486
+ // Nothing invalid: all imports OK.
1487
+ return true;
1504
1488
  });
1505
1489
  export const depCheckStaged = () => __awaiter(void 0, void 0, void 0, function* () {
1506
1490
  console.log('Checking dependencies of staged files');
@@ -2202,7 +2186,6 @@ export const register = function (registryURL) {
2202
2186
  }
2203
2187
  };
2204
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) {
2205
- var _a;
2206
2189
  // Ensure packagePath is absolute and points to a directory containing package.json; if not, go up until we find one
2207
2190
  // First, resolve to absolute path
2208
2191
  let currentPath = path.isAbsolute(packagePath)
@@ -2276,7 +2259,20 @@ export const buildPackage = (target_1, target2_1, ...args_1) => __awaiter(void 0
2276
2259
  }
2277
2260
  return previousResult && true;
2278
2261
  }
2279
- else if (typeof stepResult === 'object' && stepResult.error) {
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) {
2280
2276
  if (logResults) {
2281
2277
  spinner.fail(step.name + ' - ' + stepResult.error);
2282
2278
  spinner.stop();
@@ -2287,13 +2283,21 @@ export const buildPackage = (target_1, target2_1, ...args_1) => __awaiter(void 0
2287
2283
  //failed and should stop
2288
2284
  return false;
2289
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;
2290
2298
  });
2291
2299
  });
2292
2300
  };
2293
- if (((_a = pkgJson.linked) === null || _a === void 0 ? void 0 : _a.extensionlessImports) === true) {
2294
- const skipped = "Skipping the import check: package.json sets 'linked.extensionlessImports'";
2295
- logResults ? spinner.info(skipped) : console.log(skipped);
2296
- }
2297
2301
  planBuildSteps(pkgJson, packagePath).forEach(buildStep);
2298
2302
  let success = yield buildProcess.catch((err) => {
2299
2303
  let msg = typeof err === 'string' || err instanceof Error
@@ -2306,22 +2310,21 @@ export const buildPackage = (target_1, target2_1, ...args_1) => __awaiter(void 0
2306
2310
  symbol: chalk.red('✖'),
2307
2311
  // text: 'Build failed',
2308
2312
  });
2313
+ console.log(msg);
2309
2314
  }
2310
2315
  else {
2311
2316
  console.error(chalk.red(packagePath.split('/').pop(), ' - Build failed:'));
2312
2317
  console.error(err);
2313
- return msg;
2314
2318
  }
2315
- console.log(msg);
2319
+ //a failed build always resolves to false, never to a truthy message:
2320
+ //callers decide success by the return value.
2321
+ return false;
2316
2322
  });
2317
- //will be undefined if there was an error
2318
- if (typeof success !== 'undefined' && success !== false) {
2323
+ if (success === true) {
2319
2324
  if (logResults) {
2320
2325
  spinner.stopAndPersist({
2321
2326
  symbol: chalk.greenBright('✔'),
2322
- text: success === true && !warned
2323
- ? 'Build successful'
2324
- : 'Build successful with warnings',
2327
+ text: warned ? 'Build successful with warnings' : 'Build successful',
2325
2328
  });
2326
2329
  }
2327
2330
  }
@@ -2333,52 +2336,31 @@ export const buildPackage = (target_1, target2_1, ...args_1) => __awaiter(void 0
2333
2336
  });
2334
2337
  }
2335
2338
  }
2336
- return success;
2339
+ //true only when every step succeeded (warnings included); false otherwise.
2340
+ return success === true;
2337
2341
  });
2338
- // The ordered `linked build` steps for a linkedPackage. A package whose source
2339
- // uses extensionless relative imports (`"linked": {"extensionlessImports": true}`)
2340
- // skips the import check and gets `.js` added to its emitted ESM specifiers.
2341
- export const planBuildSteps = (pkgJson, packagePath) => {
2342
- var _a;
2343
- const extensionlessImports = ((_a = pkgJson.linked) === null || _a === void 0 ? void 0 : _a.extensionlessImports) === true;
2344
- const steps = [];
2345
- if (!extensionlessImports) {
2346
- steps.push({
2347
- name: 'Checking imports',
2348
- apply: () => checkImports(packagePath + '/src'),
2349
- });
2350
- }
2351
- 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
+ {
2352
2352
  name: 'Compiling ESM',
2353
2353
  apply: () => __awaiter(void 0, void 0, void 0, function* () {
2354
2354
  return compilePackageESM(packagePath);
2355
2355
  }),
2356
- });
2357
- if (extensionlessImports) {
2358
- steps.push({
2359
- name: 'Rewriting ESM import specifiers',
2360
- apply: () => __awaiter(void 0, void 0, void 0, function* () {
2361
- const libEsm = path.join(packagePath, 'lib', 'esm');
2362
- if (!fs.existsSync(libEsm)) {
2363
- return {
2364
- error: "lib/esm was not emitted. 'linked.extensionlessImports' needs an ESM build: add tsconfig-esm.json to the package.",
2365
- };
2366
- }
2367
- const { unresolved } = yield rewriteExtensionlessImports(libEsm);
2368
- if (unresolved.length > 0) {
2369
- return `could not resolve ${unresolved.length} import(s), left unchanged: ${unresolved.join(', ')}`;
2370
- }
2371
- return true;
2372
- }),
2373
- });
2374
- }
2375
- steps.push({
2356
+ },
2357
+ {
2376
2358
  name: 'Compiling CJS',
2377
2359
  apply: () => __awaiter(void 0, void 0, void 0, function* () {
2378
2360
  return compilePackageCJS(packagePath);
2379
2361
  }),
2380
- });
2381
- steps.push({
2362
+ },
2363
+ {
2382
2364
  name: 'Copying files to lib folder',
2383
2365
  apply: () => __awaiter(void 0, void 0, void 0, function* () {
2384
2366
  const files = yield glob(packagePath + '/src/**/*.{json,d.ts,css,scss}');
@@ -2400,8 +2382,8 @@ export const planBuildSteps = (pkgJson, packagePath) => {
2400
2382
  return allResults.every((r) => r === true);
2401
2383
  });
2402
2384
  }),
2403
- });
2404
- steps.push({
2385
+ },
2386
+ {
2405
2387
  name: 'Dual package support',
2406
2388
  apply: () => {
2407
2389
  // Skip if no tsconfig files (e.g. pure-CSS packages).
@@ -2415,19 +2397,48 @@ export const planBuildSteps = (pkgJson, packagePath) => {
2415
2397
  return res === '';
2416
2398
  });
2417
2399
  },
2418
- });
2419
- steps.push({
2400
+ },
2401
+ {
2420
2402
  name: 'Removing old files from lib folder',
2421
2403
  apply: () => __awaiter(void 0, void 0, void 0, function* () {
2422
2404
  return removeOldFiles(packagePath);
2423
2405
  }),
2424
- });
2425
- steps.push({
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
+ {
2426
2438
  name: 'Checking dependencies',
2427
2439
  apply: () => depCheck(packagePath),
2428
- });
2429
- return steps;
2430
- };
2440
+ },
2441
+ ];
2431
2442
  export const compilePackage = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (packagePath = process.cwd()) {
2432
2443
  //echo 'compiling CJS' && tsc -p tsconfig-cjs.json && echo 'compiling ESM' && tsc -p tsconfig-esm.json
2433
2444
  // let cjsConfig = fs.existsSync(path.join(packagePath,'tsconfig-cjs.json'));
@@ -2751,12 +2762,10 @@ export var buildUpdated = function (back_1, target_1, target2_1) {
2751
2762
  // log('path: ' + pathToBuild);
2752
2763
  return buildPackage(null, null, pathToBuild, false)
2753
2764
  .then((res) => {
2754
- //empty string or true is success
2755
- //false is success with warnings
2756
- //any other string is the build error text
2757
- //undefined result means it failed
2758
- if (typeof res === 'undefined' || typeof res === 'string') {
2759
- 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);
2760
2769
  process.exit(1);
2761
2770
  }
2762
2771
  else {