@_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 +48 -0
- package/README.md +18 -21
- package/defaults/app-react-native/README.md +3 -3
- package/defaults/app-react-native/apps/mobile/__tests__/composePort.test.ts +33 -0
- package/defaults/app-react-native/apps/mobile/__tests__/integration/apiEnv.ts +27 -1
- package/defaults/app-react-native/apps/mobile/__tests__/integration/globalSetup.ts +11 -7
- package/defaults/app-react-native/apps/mobile/jest.integration.config.js +1 -1
- package/defaults/app-react-native/packages/app-shapes/package.json +0 -3
- package/lib/esm/cli-methods.d.ts +1 -1
- package/lib/esm/cli-methods.d.ts.map +1 -1
- package/lib/esm/cli-methods.js +111 -102
- package/lib/esm/cli-methods.js.map +1 -1
- package/lib/esm/cli.js +17 -7
- package/lib/esm/cli.js.map +1 -1
- package/lib/esm/commands/start.d.ts.map +1 -1
- package/lib/esm/commands/start.js +5 -1
- package/lib/esm/commands/start.js.map +1 -1
- package/lib/esm/utils/esmSpecifiers.d.ts +5 -1
- package/lib/esm/utils/esmSpecifiers.d.ts.map +1 -1
- package/lib/esm/utils/esmSpecifiers.js +44 -10
- package/lib/esm/utils/esmSpecifiers.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/package.json +1 -1
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
|
-
###
|
|
93
|
-
|
|
94
|
-
```json
|
|
95
|
-
{
|
|
96
|
-
"linkedPackage": true,
|
|
97
|
-
"type": "module",
|
|
98
|
-
"linked": {"extensionlessImports": true}
|
|
99
|
-
}
|
|
100
|
-
```
|
|
96
|
+
### Extensionless relative imports
|
|
101
97
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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
|
-
|
|
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
|
|
172
|
-
|
|
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. `
|
|
91
|
-
|
|
92
|
-
|
|
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
|
-
|
|
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 {
|
|
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
|
-
//
|
|
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.
|
package/lib/esm/cli-methods.d.ts
CHANGED
|
@@ -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<
|
|
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":"
|
|
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';
|
|
@@ -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
|
-
//
|
|
1404
|
-
//
|
|
1405
|
-
//
|
|
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
|
-
//
|
|
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 (
|
|
1451
|
+
if (isInternalLinkedImport(i)) {
|
|
1458
1452
|
invalidImports.get(filename).push({
|
|
1459
|
-
type: '
|
|
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 === '
|
|
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
|
-
|
|
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
|
|
1496
|
-
//
|
|
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
|
-
|
|
1500
|
-
|
|
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 (
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
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.
|
|
2339
|
-
//
|
|
2340
|
-
//
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
2755
|
-
//
|
|
2756
|
-
|
|
2757
|
-
|
|
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 {
|