@_linked/cli 1.19.2 → 1.21.1
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 +64 -0
- package/lib/esm/app-release/build-backend.d.ts +88 -0
- package/lib/esm/app-release/build-backend.d.ts.map +1 -0
- package/lib/esm/app-release/build-backend.js +292 -0
- package/lib/esm/app-release/build-backend.js.map +1 -0
- package/lib/esm/cli-methods.d.ts +13 -0
- package/lib/esm/cli-methods.d.ts.map +1 -1
- package/lib/esm/cli-methods.js +36 -41
- package/lib/esm/cli-methods.js.map +1 -1
- package/lib/esm/lifecycle.d.ts +28 -6
- package/lib/esm/lifecycle.d.ts.map +1 -1
- package/lib/esm/lifecycle.js +47 -9
- package/lib/esm/lifecycle.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,69 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.21.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#109](https://github.com/linked-fw/cli/pull/109) [`2c6918c`](https://github.com/linked-fw/cli/commit/2c6918c0fefe08c65290b7cd28f7ab0b5b31aa4f) Thanks [@flyon](https://github.com/flyon)! - Stop `buildFrontend` calling the deprecated `LinkedFileStorage.getDefaultDataset`, and publish CDN assets under the names they were built with.
|
|
8
|
+
|
|
9
|
+
The legacy `public/` upload path was the last caller of a `Dataset`-era alias in
|
|
10
|
+
this package. Core forwards it to `getDefaultStore` today, but the aliases are
|
|
11
|
+
removed in core's next major, so this was a dated build break. The swap is
|
|
12
|
+
behaviour-free: `getDefaultStore` returns the same value, `undefined` included,
|
|
13
|
+
so the truthiness guard reads the same.
|
|
14
|
+
|
|
15
|
+
The same path published every file with a bare two-argument `saveFile`, leaving
|
|
16
|
+
`preventDuplicates` unspecified. It now passes `false` explicitly, because a CDN
|
|
17
|
+
publish is the one case where the key _is_ the address: `main-hwqwrAvA.css` has
|
|
18
|
+
to land as `main-hwqwrAvA.css` or the name compiled into the HTML does not
|
|
19
|
+
resolve, and republishing an unchanged build has to overwrite in place rather
|
|
20
|
+
than leave a second copy behind under a different key.
|
|
21
|
+
|
|
22
|
+
## 1.21.0
|
|
23
|
+
|
|
24
|
+
### Minor Changes
|
|
25
|
+
|
|
26
|
+
- [#106](https://github.com/linked-fw/cli/pull/106) [`587b764`](https://github.com/linked-fw/cli/commit/587b7641cd90c853147bd42f9b13c8792b3b2a1f) Thanks [@flyon](https://github.com/flyon)! - Compile the app backend with Vite instead of bare `tsc`.
|
|
27
|
+
|
|
28
|
+
`linked start` already loads `src/backend.ts`, `src/App.tsx` and
|
|
29
|
+
`src/routes.tsx` through `vite.ssrLoadModule`, so production was resolving the
|
|
30
|
+
same source a different way. `tsc` could not follow the workspace resolver or
|
|
31
|
+
an extensionless relative import, it inferred `rootDir` from whatever happened
|
|
32
|
+
to be in the program (so `lib/backend.js` could land in `lib/src/`), and being
|
|
33
|
+
a typechecker first it failed the build on any type error anywhere in the app —
|
|
34
|
+
including in files the backend never loads. Emitting and typechecking are
|
|
35
|
+
separate concerns.
|
|
36
|
+
|
|
37
|
+
Workspace packages are named in `ssr.external`. Vite will not externalize them
|
|
38
|
+
on its own: a workspace symlink realpaths out of `node_modules`, and Vite
|
|
39
|
+
refuses to externalize anything that does not look like it lives there, so they
|
|
40
|
+
were all compiled into `lib/` — giving the app a second copy of
|
|
41
|
+
`@_linked/core` and splitting `LinkedStorage`'s routing state from the one the
|
|
42
|
+
storage config configures. A post-build check now fails the build if any
|
|
43
|
+
workspace package ends up inlined, rather than leaving it to surface as a
|
|
44
|
+
storage-routing error at boot.
|
|
45
|
+
|
|
46
|
+
Note the consequence: a release build resolves workspace packages through their
|
|
47
|
+
published exports, so **their `lib/` must be built and current**. A stale one
|
|
48
|
+
fails the build with a message saying so.
|
|
49
|
+
|
|
50
|
+
## 1.20.0
|
|
51
|
+
|
|
52
|
+
### Minor Changes
|
|
53
|
+
|
|
54
|
+
- [#105](https://github.com/linked-fw/cli/pull/105) [`5263cc3`](https://github.com/linked-fw/cli/commit/5263cc3c5c596499507df7581205f1a92523fa35) Thanks [@flyon](https://github.com/flyon)! - Read `.env` before `.env-cmdrc.json`, and warn that the profile file is deprecated.
|
|
55
|
+
|
|
56
|
+
The order was the other way round, which made migrating awkward: an app that
|
|
57
|
+
added a flat `.env` next to its existing profile file saw none of it, silently.
|
|
58
|
+
Now `.env` wins, so adding it _is_ the migration — the profile file can be
|
|
59
|
+
deleted whenever convenient.
|
|
60
|
+
|
|
61
|
+
`.env-cmdrc.json` is still read when it is the only file present, so no app
|
|
62
|
+
breaks. It now warns that it, and the `--env` flag that exists only to serve
|
|
63
|
+
it, are going away: a flat `.env` plus whatever the deployment injects into the
|
|
64
|
+
environment replaces both. An app holding both files is told explicitly that
|
|
65
|
+
the profile file and any `--env` name passed with it are being ignored.
|
|
66
|
+
|
|
3
67
|
## 1.19.2
|
|
4
68
|
|
|
5
69
|
### Patch Changes
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
export declare const resolveBackendEntries: (appRoot: string, exists?: (p: string) => boolean) => Record<string, string>;
|
|
2
|
+
/**
|
|
3
|
+
* Workspace package names to list as `ssr.external`.
|
|
4
|
+
*
|
|
5
|
+
* Vite will not externalise these on its own, and the reason is worth
|
|
6
|
+
* recording because it is entirely non-obvious. `node_modules/@_linked/core`
|
|
7
|
+
* is a symlink into `packages/core`; Vite resolves package data with
|
|
8
|
+
* `preserveSymlinks: false`, so the resolved id realpaths *out* of
|
|
9
|
+
* `node_modules`; and Vite refuses to externalise anything that does not look
|
|
10
|
+
* like it lives there:
|
|
11
|
+
*
|
|
12
|
+
* if (!configuredAsExternal && !isInNodeModules(resolved.id)) return false;
|
|
13
|
+
*
|
|
14
|
+
* So every workspace package got compiled into `lib/`. That is not merely
|
|
15
|
+
* wasteful — `linked.backend.storage.js` is loaded from the APP ROOT by a raw
|
|
16
|
+
* Node `import()` and resolves `@_linked/core` through node_modules, so the
|
|
17
|
+
* storage config configured one copy of `LinkedStorage` while the compiled
|
|
18
|
+
* backend queried another. `LinkedStorage`'s routing state is a per-copy
|
|
19
|
+
* static, so the app's single-instance guard refuses to boot. The old `tsc`
|
|
20
|
+
* build never hit this: it emitted bare specifiers and Node converged on one
|
|
21
|
+
* copy. Naming the packages here restores that.
|
|
22
|
+
*
|
|
23
|
+
* `configuredAsExternal` is the one thing that overrides the symlink rule, and
|
|
24
|
+
* it is keyed on exact package names — no regexes.
|
|
25
|
+
*/
|
|
26
|
+
export declare const workspacePackagesToExternalize: (appRoot: string, discover?: (globs: string[], cwd: string) => Promise<{
|
|
27
|
+
name: string;
|
|
28
|
+
}[]>) => Promise<string[]>;
|
|
29
|
+
/**
|
|
30
|
+
* A relative import from `lib/` into `packages/` means a workspace package was
|
|
31
|
+
* compiled in after all.
|
|
32
|
+
*
|
|
33
|
+
* Worth failing the build over rather than leaving to be discovered: the
|
|
34
|
+
* output is perfectly valid JavaScript, and the symptom is the app refusing to
|
|
35
|
+
* boot with a message about storage routing that points nowhere near here.
|
|
36
|
+
*/
|
|
37
|
+
export declare const findInlinedWorkspaceImports: (source: string) => string[];
|
|
38
|
+
export declare const assertNoInlinedWorkspaces: (appRoot: string, readFile?: (p: string) => Promise<string>) => Promise<void>;
|
|
39
|
+
/**
|
|
40
|
+
* Turn Rollup's unresolved-import error into one that names the actual cause.
|
|
41
|
+
*
|
|
42
|
+
* Externalizing a workspace package means the build now resolves it through
|
|
43
|
+
* its published `exports` — its `lib/`, not its `src/`. A package whose `lib/`
|
|
44
|
+
* is stale therefore fails here, on a file that plainly exists in source.
|
|
45
|
+
* Rollup's own message ("failed to resolve import X") sends you looking at the
|
|
46
|
+
* import, which is fine.
|
|
47
|
+
*/
|
|
48
|
+
export declare const explainUnresolvedWorkspaceImport: (message: string, externalWorkspaces: string[]) => string | null;
|
|
49
|
+
/**
|
|
50
|
+
* Compile the app's backend to `lib/`.
|
|
51
|
+
*
|
|
52
|
+
* This runs Vite in SSR mode against the app's own `vite.config`, which is the
|
|
53
|
+
* point: `linked start` already loads `src/backend.ts`, `src/App.tsx` and
|
|
54
|
+
* `src/routes.tsx` through `vite.ssrLoadModule`, so a production build that
|
|
55
|
+
* used anything else was resolving the same source differently from dev. The
|
|
56
|
+
* workspace resolver, the decorator transform and extensionless relative
|
|
57
|
+
* imports all come along for free.
|
|
58
|
+
*
|
|
59
|
+
* `preserveModules` keeps `src/`'s file layout in `lib/`, so the entry paths
|
|
60
|
+
* stay where `serve-app` and `startServer` look for them and lazily imported
|
|
61
|
+
* pages keep their own files. `manualChunks` is cleared because Rollup refuses
|
|
62
|
+
* to run it alongside `preserveModules` — and it is a client-side concern
|
|
63
|
+
* anyway.
|
|
64
|
+
*
|
|
65
|
+
* Workspace packages are named as `ssr.external` explicitly; see
|
|
66
|
+
* `workspacePackagesToExternalize` for why Vite does not do it on its own.
|
|
67
|
+
* Node's built-ins are listed by hand for a related reason: Vite externalises
|
|
68
|
+
* them for SSR only when it recognises the specifier, and a bare `crypto` —
|
|
69
|
+
* which a backend written for Node may perfectly well import — resolved
|
|
70
|
+
* instead to the abandoned `crypto` shim package sitting in node_modules, and
|
|
71
|
+
* failed the build.
|
|
72
|
+
*
|
|
73
|
+
* `copyPublicDir` is off because `public/` is the client build's output, not
|
|
74
|
+
* the backend's. Left on, it copied 38MB of already-built bundles into `lib/`.
|
|
75
|
+
*/
|
|
76
|
+
export declare const buildBackendWithVite: (options?: {
|
|
77
|
+
appRoot?: string;
|
|
78
|
+
}, dependencies?: {
|
|
79
|
+
viteBuild?: (config: any) => Promise<unknown>;
|
|
80
|
+
}) => Promise<void>;
|
|
81
|
+
/**
|
|
82
|
+
* Copy `src`'s CSS next to the compiled backend.
|
|
83
|
+
*
|
|
84
|
+
* The server reads stylesheets like `lib/css/theme.css` off disk by path, so
|
|
85
|
+
* they have to exist as files whether or not any module imported them.
|
|
86
|
+
*/
|
|
87
|
+
export declare const copyBackendStylesheets: (appRoot: string, listCssFiles: (dir: string) => Promise<string[]>) => Promise<number>;
|
|
88
|
+
//# sourceMappingURL=build-backend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-backend.d.ts","sourceRoot":"","sources":["../../../src/app-release/build-backend.ts"],"names":[],"mappings":"AA+BA,eAAO,MAAM,qBAAqB,GAChC,SAAS,MAAM,EACf,SAAQ,CAAC,CAAC,EAAE,MAAM,KAAK,OAAuB,KAC7C,MAAM,CAAC,MAAM,EAAE,MAAM,CAWvB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,8BAA8B,GACzC,SAAS,MAAM,EACf,WAAU,CACR,KAAK,EAAE,MAAM,EAAE,EACf,GAAG,EAAE,MAAM,KACR,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAC,EAAE,CAG5B,KACA,OAAO,CAAC,MAAM,EAAE,CAGlB,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,GAAI,QAAQ,MAAM,KAAG,MAAM,EAQlE,CAAC;AAEF,eAAO,MAAM,yBAAyB,GACpC,SAAS,MAAM,EACf,WAAU,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAiC,KACvE,OAAO,CAAC,IAAI,CAwBd,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,gCAAgC,GAC3C,SAAS,MAAM,EACf,oBAAoB,MAAM,EAAE,KAC3B,MAAM,GAAG,IAgBX,CAAC;AAqBF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,oBAAoB,GAC/B,UAAS;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAM,EAChC,eAAc;IAAC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CAAM,KACjE,OAAO,CAAC,IAAI,CAqFd,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,GACjC,SAAS,MAAM,EACf,cAAc,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,KAC/C,OAAO,CAAC,MAAM,CAYhB,CAAC"}
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
11
|
+
var t = {};
|
|
12
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
13
|
+
t[p] = s[p];
|
|
14
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
15
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
16
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
17
|
+
t[p[i]] = s[p[i]];
|
|
18
|
+
}
|
|
19
|
+
return t;
|
|
20
|
+
};
|
|
21
|
+
import { builtinModules } from 'module';
|
|
22
|
+
import fs from 'fs-extra';
|
|
23
|
+
import path from 'path';
|
|
24
|
+
/**
|
|
25
|
+
* The backend entry points a compiled app is started from.
|
|
26
|
+
*
|
|
27
|
+
* `serve-app` requires all three on disk and `startServer` imports `lib/App.js`
|
|
28
|
+
* and `lib/routes.js` by those exact paths, so the names are a contract, not a
|
|
29
|
+
* convention.
|
|
30
|
+
*/
|
|
31
|
+
const BACKEND_ENTRIES = {
|
|
32
|
+
backend: ['src/backend.ts', 'src/backend.tsx'],
|
|
33
|
+
App: ['src/App.tsx', 'src/App.ts'],
|
|
34
|
+
routes: ['src/routes.tsx', 'src/routes.ts'],
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Vite's default server conditions minus the `development|production` token.
|
|
38
|
+
*
|
|
39
|
+
* See the note at the `resolve` option below: dropping the token is what stops
|
|
40
|
+
* a workspace package resolving to its TypeScript source.
|
|
41
|
+
*/
|
|
42
|
+
const SERVER_CONDITIONS = ['module', 'node'];
|
|
43
|
+
/** Both spellings, because a backend may use either. */
|
|
44
|
+
const NODE_BUILTINS = [
|
|
45
|
+
...builtinModules,
|
|
46
|
+
...builtinModules.map((name) => `node:${name}`),
|
|
47
|
+
];
|
|
48
|
+
export const resolveBackendEntries = (appRoot, exists = fs.existsSync) => {
|
|
49
|
+
const entries = {};
|
|
50
|
+
for (const [name, candidates] of Object.entries(BACKEND_ENTRIES)) {
|
|
51
|
+
const found = candidates.find((candidate) => exists(path.join(appRoot, candidate)));
|
|
52
|
+
if (found) {
|
|
53
|
+
entries[name] = path.join(appRoot, found);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return entries;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Workspace package names to list as `ssr.external`.
|
|
60
|
+
*
|
|
61
|
+
* Vite will not externalise these on its own, and the reason is worth
|
|
62
|
+
* recording because it is entirely non-obvious. `node_modules/@_linked/core`
|
|
63
|
+
* is a symlink into `packages/core`; Vite resolves package data with
|
|
64
|
+
* `preserveSymlinks: false`, so the resolved id realpaths *out* of
|
|
65
|
+
* `node_modules`; and Vite refuses to externalise anything that does not look
|
|
66
|
+
* like it lives there:
|
|
67
|
+
*
|
|
68
|
+
* if (!configuredAsExternal && !isInNodeModules(resolved.id)) return false;
|
|
69
|
+
*
|
|
70
|
+
* So every workspace package got compiled into `lib/`. That is not merely
|
|
71
|
+
* wasteful — `linked.backend.storage.js` is loaded from the APP ROOT by a raw
|
|
72
|
+
* Node `import()` and resolves `@_linked/core` through node_modules, so the
|
|
73
|
+
* storage config configured one copy of `LinkedStorage` while the compiled
|
|
74
|
+
* backend queried another. `LinkedStorage`'s routing state is a per-copy
|
|
75
|
+
* static, so the app's single-instance guard refuses to boot. The old `tsc`
|
|
76
|
+
* build never hit this: it emitted bare specifiers and Node converged on one
|
|
77
|
+
* copy. Naming the packages here restores that.
|
|
78
|
+
*
|
|
79
|
+
* `configuredAsExternal` is the one thing that overrides the symlink rule, and
|
|
80
|
+
* it is keyed on exact package names — no regexes.
|
|
81
|
+
*/
|
|
82
|
+
export const workspacePackagesToExternalize = (appRoot_1, ...args_1) => __awaiter(void 0, [appRoot_1, ...args_1], void 0, function* (appRoot, discover = (globs, cwd) => __awaiter(void 0, void 0, void 0, function* () {
|
|
83
|
+
const { discoverWorkspaces } = yield import('../vite-config.js');
|
|
84
|
+
return discoverWorkspaces(globs, cwd);
|
|
85
|
+
})) {
|
|
86
|
+
const workspaces = yield discover([], appRoot);
|
|
87
|
+
return [...new Set(workspaces.map((w) => w.name))].sort();
|
|
88
|
+
});
|
|
89
|
+
/**
|
|
90
|
+
* A relative import from `lib/` into `packages/` means a workspace package was
|
|
91
|
+
* compiled in after all.
|
|
92
|
+
*
|
|
93
|
+
* Worth failing the build over rather than leaving to be discovered: the
|
|
94
|
+
* output is perfectly valid JavaScript, and the symptom is the app refusing to
|
|
95
|
+
* boot with a message about storage routing that points nowhere near here.
|
|
96
|
+
*/
|
|
97
|
+
export const findInlinedWorkspaceImports = (source) => {
|
|
98
|
+
// Both static `from "…"` and dynamic `import("…")`: a lazily imported page
|
|
99
|
+
// can drag a workspace package in on its own, and only the second form
|
|
100
|
+
// appears in the output for it.
|
|
101
|
+
const matches = source.matchAll(/(?:from|import)\s*\(?\s*["'](\.[^"']*\/packages\/[^"']+)["']/g);
|
|
102
|
+
return [...new Set([...matches].map((m) => m[1]))].sort();
|
|
103
|
+
};
|
|
104
|
+
export const assertNoInlinedWorkspaces = (appRoot_1, ...args_1) => __awaiter(void 0, [appRoot_1, ...args_1], void 0, function* (appRoot, readFile = (p) => fs.readFile(p, 'utf8')) {
|
|
105
|
+
// Every entry, not just the backend: `App.js` and `routes.js` reach code the
|
|
106
|
+
// backend never imports, so a package can be inlined through either of them.
|
|
107
|
+
const inlined = new Set();
|
|
108
|
+
for (const name of Object.keys(BACKEND_ENTRIES)) {
|
|
109
|
+
const entryPath = path.join(appRoot, 'lib', `${name}.js`);
|
|
110
|
+
if (!fs.existsSync(entryPath))
|
|
111
|
+
continue;
|
|
112
|
+
for (const found of findInlinedWorkspaceImports(yield readFile(entryPath))) {
|
|
113
|
+
inlined.add(found);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (inlined.size === 0)
|
|
117
|
+
return;
|
|
118
|
+
const named = [...inlined].sort();
|
|
119
|
+
throw new Error('The compiled backend inlined workspace packages instead of importing ' +
|
|
120
|
+
'them: ' +
|
|
121
|
+
named.slice(0, 3).join(', ') +
|
|
122
|
+
(named.length > 3 ? `, and ${named.length - 3} more` : '') +
|
|
123
|
+
'. Each one is a second copy of that package, and a second copy of ' +
|
|
124
|
+
'@_linked/core splits LinkedStorage\'s routing state from the one the ' +
|
|
125
|
+
'storage config configures. Check that the package is discoverable as a ' +
|
|
126
|
+
'workspace, so it can be named in ssr.external.');
|
|
127
|
+
});
|
|
128
|
+
/**
|
|
129
|
+
* Turn Rollup's unresolved-import error into one that names the actual cause.
|
|
130
|
+
*
|
|
131
|
+
* Externalizing a workspace package means the build now resolves it through
|
|
132
|
+
* its published `exports` — its `lib/`, not its `src/`. A package whose `lib/`
|
|
133
|
+
* is stale therefore fails here, on a file that plainly exists in source.
|
|
134
|
+
* Rollup's own message ("failed to resolve import X") sends you looking at the
|
|
135
|
+
* import, which is fine.
|
|
136
|
+
*/
|
|
137
|
+
export const explainUnresolvedWorkspaceImport = (message, externalWorkspaces) => {
|
|
138
|
+
const match = message.match(/failed to resolve import "([^"]+)"/i);
|
|
139
|
+
if (!match)
|
|
140
|
+
return null;
|
|
141
|
+
const specifier = match[1];
|
|
142
|
+
const pkg = externalWorkspaces.find((name) => specifier === name || specifier.startsWith(`${name}/`));
|
|
143
|
+
if (!pkg)
|
|
144
|
+
return null;
|
|
145
|
+
return (`${message}\n\n` +
|
|
146
|
+
`"${pkg}" is a workspace package, so a release build resolves it through its ` +
|
|
147
|
+
`published exports — its lib/, not its src/. If this file exists in ` +
|
|
148
|
+
`${pkg}/src but not in its build output, that package's lib/ is stale. ` +
|
|
149
|
+
`Build it first (\`linked build\` in the package, or \`linked build-workspace\`) ` +
|
|
150
|
+
`and run build-app again.`);
|
|
151
|
+
};
|
|
152
|
+
/**
|
|
153
|
+
* Strip the client build's `manualChunks` from the SSR output options.
|
|
154
|
+
*
|
|
155
|
+
* Rollup refuses `manualChunks` together with `preserveModules`, and passing
|
|
156
|
+
* `undefined` in the inline config does not remove it — Vite's config merge
|
|
157
|
+
* keeps the app's value. So it is cleared in the output hook instead, after
|
|
158
|
+
* the merge. Chunk grouping is a client concern; the backend wants one output
|
|
159
|
+
* file per source file.
|
|
160
|
+
*/
|
|
161
|
+
const dropManualChunks = () => ({
|
|
162
|
+
name: 'linked:backend-no-manual-chunks',
|
|
163
|
+
enforce: 'post',
|
|
164
|
+
outputOptions(options) {
|
|
165
|
+
if (!options.manualChunks)
|
|
166
|
+
return null;
|
|
167
|
+
const { manualChunks: _dropped } = options, rest = __rest(options, ["manualChunks"]);
|
|
168
|
+
return rest;
|
|
169
|
+
},
|
|
170
|
+
});
|
|
171
|
+
/**
|
|
172
|
+
* Compile the app's backend to `lib/`.
|
|
173
|
+
*
|
|
174
|
+
* This runs Vite in SSR mode against the app's own `vite.config`, which is the
|
|
175
|
+
* point: `linked start` already loads `src/backend.ts`, `src/App.tsx` and
|
|
176
|
+
* `src/routes.tsx` through `vite.ssrLoadModule`, so a production build that
|
|
177
|
+
* used anything else was resolving the same source differently from dev. The
|
|
178
|
+
* workspace resolver, the decorator transform and extensionless relative
|
|
179
|
+
* imports all come along for free.
|
|
180
|
+
*
|
|
181
|
+
* `preserveModules` keeps `src/`'s file layout in `lib/`, so the entry paths
|
|
182
|
+
* stay where `serve-app` and `startServer` look for them and lazily imported
|
|
183
|
+
* pages keep their own files. `manualChunks` is cleared because Rollup refuses
|
|
184
|
+
* to run it alongside `preserveModules` — and it is a client-side concern
|
|
185
|
+
* anyway.
|
|
186
|
+
*
|
|
187
|
+
* Workspace packages are named as `ssr.external` explicitly; see
|
|
188
|
+
* `workspacePackagesToExternalize` for why Vite does not do it on its own.
|
|
189
|
+
* Node's built-ins are listed by hand for a related reason: Vite externalises
|
|
190
|
+
* them for SSR only when it recognises the specifier, and a bare `crypto` —
|
|
191
|
+
* which a backend written for Node may perfectly well import — resolved
|
|
192
|
+
* instead to the abandoned `crypto` shim package sitting in node_modules, and
|
|
193
|
+
* failed the build.
|
|
194
|
+
*
|
|
195
|
+
* `copyPublicDir` is off because `public/` is the client build's output, not
|
|
196
|
+
* the backend's. Left on, it copied 38MB of already-built bundles into `lib/`.
|
|
197
|
+
*/
|
|
198
|
+
export const buildBackendWithVite = (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (options = {}, dependencies = {}) {
|
|
199
|
+
const appRoot = options.appRoot || process.cwd();
|
|
200
|
+
const entries = resolveBackendEntries(appRoot);
|
|
201
|
+
if (!entries.backend) {
|
|
202
|
+
throw new Error('No backend entry found: expected src/backend.ts in ' + appRoot);
|
|
203
|
+
}
|
|
204
|
+
const viteBuild = dependencies.viteBuild ||
|
|
205
|
+
((config) => __awaiter(void 0, void 0, void 0, function* () {
|
|
206
|
+
const { build } = yield import('vite');
|
|
207
|
+
return build(config);
|
|
208
|
+
}));
|
|
209
|
+
const externalWorkspaces = yield workspacePackagesToExternalize(appRoot);
|
|
210
|
+
try {
|
|
211
|
+
yield viteBuild({
|
|
212
|
+
root: appRoot,
|
|
213
|
+
mode: 'production',
|
|
214
|
+
isProduction: true,
|
|
215
|
+
// The client build sets `base` to the release URL. The backend emits no
|
|
216
|
+
// asset URLs of its own, so it must not inherit one.
|
|
217
|
+
base: '/',
|
|
218
|
+
// Never resolve a `development` export condition in a release build.
|
|
219
|
+
//
|
|
220
|
+
// The workspace-source convention is
|
|
221
|
+
// "development": "./src/*.ts", "import": "./lib/esm/*.js"
|
|
222
|
+
// and Vite expands its `development|production` token from NODE_ENV —
|
|
223
|
+
// which during a release build is whatever the app's `.env` says,
|
|
224
|
+
// routinely `development`. The package then resolves to TypeScript, which
|
|
225
|
+
// cannot be externalised because Node could not load it, so it is
|
|
226
|
+
// compiled in regardless of what `ssr.external` says.
|
|
227
|
+
//
|
|
228
|
+
// Dropping the token (rather than pinning it to `production`) leaves
|
|
229
|
+
// `import` — which Vite always appends last — to win. Same treatment
|
|
230
|
+
// `createViteConfig` already applies to a standalone install, for the
|
|
231
|
+
// mirror-image reason.
|
|
232
|
+
//
|
|
233
|
+
// All three lists have to say it: `ssr.resolve.conditions` does not
|
|
234
|
+
// inherit from `resolve.conditions` here, and `externalConditions`
|
|
235
|
+
// governs the packages that end up external.
|
|
236
|
+
resolve: { conditions: SERVER_CONDITIONS },
|
|
237
|
+
ssr: {
|
|
238
|
+
// Merged with the app's own ssr.external rather than replacing it.
|
|
239
|
+
external: externalWorkspaces,
|
|
240
|
+
resolve: {
|
|
241
|
+
conditions: SERVER_CONDITIONS,
|
|
242
|
+
externalConditions: SERVER_CONDITIONS,
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
plugins: [dropManualChunks()],
|
|
246
|
+
build: {
|
|
247
|
+
ssr: true,
|
|
248
|
+
outDir: 'lib',
|
|
249
|
+
emptyOutDir: true,
|
|
250
|
+
copyPublicDir: false,
|
|
251
|
+
manifest: false,
|
|
252
|
+
sourcemap: true,
|
|
253
|
+
rollupOptions: {
|
|
254
|
+
input: entries,
|
|
255
|
+
external: NODE_BUILTINS,
|
|
256
|
+
output: {
|
|
257
|
+
format: 'es',
|
|
258
|
+
preserveModules: true,
|
|
259
|
+
preserveModulesRoot: path.join(appRoot, 'src'),
|
|
260
|
+
entryFileNames: '[name].js',
|
|
261
|
+
chunkFileNames: '[name].js',
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
catch (err) {
|
|
268
|
+
const explained = explainUnresolvedWorkspaceImport(err instanceof Error ? err.message : String(err), externalWorkspaces);
|
|
269
|
+
if (!explained)
|
|
270
|
+
throw err;
|
|
271
|
+
throw new Error(explained);
|
|
272
|
+
}
|
|
273
|
+
yield assertNoInlinedWorkspaces(appRoot);
|
|
274
|
+
});
|
|
275
|
+
/**
|
|
276
|
+
* Copy `src`'s CSS next to the compiled backend.
|
|
277
|
+
*
|
|
278
|
+
* The server reads stylesheets like `lib/css/theme.css` off disk by path, so
|
|
279
|
+
* they have to exist as files whether or not any module imported them.
|
|
280
|
+
*/
|
|
281
|
+
export const copyBackendStylesheets = (appRoot, listCssFiles) => __awaiter(void 0, void 0, void 0, function* () {
|
|
282
|
+
const sourceFolder = path.join(appRoot, 'src');
|
|
283
|
+
const targetFolder = path.join(appRoot, 'lib');
|
|
284
|
+
const cssFiles = yield listCssFiles(sourceFolder);
|
|
285
|
+
yield Promise.all(cssFiles.map((file) => {
|
|
286
|
+
const targetFile = file.replace(sourceFolder, targetFolder);
|
|
287
|
+
fs.mkdirpSync(path.dirname(targetFile));
|
|
288
|
+
return fs.copyFile(file, targetFile);
|
|
289
|
+
}));
|
|
290
|
+
return cssFiles.length;
|
|
291
|
+
});
|
|
292
|
+
//# sourceMappingURL=build-backend.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-backend.js","sourceRoot":"","sources":["../../../src/app-release/build-backend.ts"],"names":[],"mappings":"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"}
|
package/lib/esm/cli-methods.d.ts
CHANGED
|
@@ -117,6 +117,19 @@ export declare const runMethod: (packageName: string, method: string, options: {
|
|
|
117
117
|
export declare const startServer: (initOnly?: boolean, ServerClass?: any) => Promise<any>;
|
|
118
118
|
export declare const buildApp: () => Promise<never>;
|
|
119
119
|
export declare const buildFrontend: () => Promise<void>;
|
|
120
|
+
/**
|
|
121
|
+
* Compile the app's backend into `lib/`.
|
|
122
|
+
*
|
|
123
|
+
* Vite, in SSR mode, against the app's own `vite.config` — the same transform
|
|
124
|
+
* `linked start` applies through `vite.ssrLoadModule`. It used to be a bare
|
|
125
|
+
* `tsc`, which meant dev and production resolved the same source two different
|
|
126
|
+
* ways: `tsc` could not follow the workspace resolver or an extensionless
|
|
127
|
+
* relative import, it inferred `rootDir` from whatever happened to be in the
|
|
128
|
+
* program (so `lib/backend.js` could land in `lib/src/`), and being a
|
|
129
|
+
* typechecker first it failed the build on any type error anywhere in the app,
|
|
130
|
+
* including in files the backend never loads. Typechecking is a separate
|
|
131
|
+
* concern from emitting, and belongs in its own command.
|
|
132
|
+
*/
|
|
120
133
|
export declare const buildBackend: () => Promise<boolean>;
|
|
121
134
|
export declare const upgradePackages: () => Promise<void>;
|
|
122
135
|
export declare const createPackage: (name: any, uriBase?: any, basePath?: string) => Promise<void>;
|
|
@@ -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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"}
|
package/lib/esm/cli-methods.js
CHANGED
|
@@ -1774,9 +1774,9 @@ export const buildFrontend = () => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1774
1774
|
}
|
|
1775
1775
|
// load the storage config
|
|
1776
1776
|
const storageConfig = yield loadBackendStorageConfig();
|
|
1777
|
-
// check if
|
|
1778
|
-
// if yes: copy all the files in the build folder over with
|
|
1779
|
-
if (LinkedFileStorage.
|
|
1777
|
+
// check if LinkedFileStorage has a default FileStore
|
|
1778
|
+
// if yes: copy all the files in the build folder over with LinkedFileStorage
|
|
1779
|
+
if (LinkedFileStorage.getDefaultStore()) {
|
|
1780
1780
|
// get public directory
|
|
1781
1781
|
const rootDirectory = 'public';
|
|
1782
1782
|
const pathDir = path.join(process.cwd(), rootDirectory);
|
|
@@ -1798,8 +1798,16 @@ export const buildFrontend = () => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1798
1798
|
// replace pathDir with rootDirectory in filePath to get pathname
|
|
1799
1799
|
// example: /Users/username/project/www/index.html -> /project/www/index.html
|
|
1800
1800
|
const pathname = filePath.replace(pathDir, `/${rootDirectory}`);
|
|
1801
|
-
// upload file to storage
|
|
1802
|
-
|
|
1801
|
+
// upload file to storage.
|
|
1802
|
+
//
|
|
1803
|
+
// preventDuplicates: false because this publishes a public/ folder to a
|
|
1804
|
+
// CDN, where the key is the address: `main-hwqwrAvA.css` has to land as
|
|
1805
|
+
// `main-hwqwrAvA.css` or the name baked into the HTML does not resolve,
|
|
1806
|
+
// and republishing an unchanged build has to overwrite in place rather
|
|
1807
|
+
// than accumulate a second copy under a new key.
|
|
1808
|
+
yield LinkedFileStorage.saveFile(pathname, fileContent, {
|
|
1809
|
+
preventDuplicates: false,
|
|
1810
|
+
})
|
|
1803
1811
|
.then(() => {
|
|
1804
1812
|
clearSpinner.text = `${counter++}/${files.length}: - Published ${pathname} `;
|
|
1805
1813
|
})
|
|
@@ -1810,59 +1818,46 @@ export const buildFrontend = () => __awaiter(void 0, void 0, void 0, function* (
|
|
|
1810
1818
|
}
|
|
1811
1819
|
}));
|
|
1812
1820
|
});
|
|
1821
|
+
/**
|
|
1822
|
+
* Compile the app's backend into `lib/`.
|
|
1823
|
+
*
|
|
1824
|
+
* Vite, in SSR mode, against the app's own `vite.config` — the same transform
|
|
1825
|
+
* `linked start` applies through `vite.ssrLoadModule`. It used to be a bare
|
|
1826
|
+
* `tsc`, which meant dev and production resolved the same source two different
|
|
1827
|
+
* ways: `tsc` could not follow the workspace resolver or an extensionless
|
|
1828
|
+
* relative import, it inferred `rootDir` from whatever happened to be in the
|
|
1829
|
+
* program (so `lib/backend.js` could land in `lib/src/`), and being a
|
|
1830
|
+
* typechecker first it failed the build on any type error anywhere in the app,
|
|
1831
|
+
* including in files the backend never loads. Typechecking is a separate
|
|
1832
|
+
* concern from emitting, and belongs in its own command.
|
|
1833
|
+
*/
|
|
1813
1834
|
export const buildBackend = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
1814
1835
|
console.log(chalk.magenta(`🛠 Preparing ${process.env.NODE_ENV} backend`));
|
|
1815
|
-
//run tsc in the backend folder
|
|
1816
1836
|
yield ensureEnvironmentLoaded();
|
|
1817
|
-
const
|
|
1818
|
-
const
|
|
1819
|
-
// Step 1:
|
|
1820
|
-
const clearSpinner = ora({
|
|
1821
|
-
discardStdin: true,
|
|
1822
|
-
text: 'Clearing lib folder',
|
|
1823
|
-
}).start();
|
|
1824
|
-
try {
|
|
1825
|
-
if (fs.existsSync(targetFolder)) {
|
|
1826
|
-
yield fs.remove(targetFolder);
|
|
1827
|
-
}
|
|
1828
|
-
clearSpinner.succeed('Lib folder cleared');
|
|
1829
|
-
}
|
|
1830
|
-
catch (e) {
|
|
1831
|
-
console.error(e);
|
|
1832
|
-
clearSpinner.fail('Failed to clear lib folder');
|
|
1833
|
-
return;
|
|
1834
|
-
}
|
|
1835
|
-
// Step 2: Compile TS files
|
|
1837
|
+
const appRoot = process.cwd();
|
|
1838
|
+
const { buildBackendWithVite, copyBackendStylesheets } = yield import('./app-release/build-backend.js');
|
|
1839
|
+
// Step 1: Compile with Vite (it empties lib/ itself)
|
|
1836
1840
|
const compileSpinner = ora({
|
|
1837
1841
|
discardStdin: true,
|
|
1838
|
-
text: 'Compiling backend
|
|
1842
|
+
text: 'Compiling backend with Vite',
|
|
1839
1843
|
}).start();
|
|
1840
1844
|
try {
|
|
1841
|
-
yield
|
|
1842
|
-
compileSpinner.succeed('Backend
|
|
1845
|
+
yield buildBackendWithVite({ appRoot });
|
|
1846
|
+
compileSpinner.succeed('Backend compiled');
|
|
1843
1847
|
}
|
|
1844
1848
|
catch (e) {
|
|
1845
1849
|
console.error(e);
|
|
1846
|
-
compileSpinner.fail('Failed to compile backend
|
|
1850
|
+
compileSpinner.fail('Failed to compile the backend');
|
|
1847
1851
|
return;
|
|
1848
1852
|
}
|
|
1849
|
-
// Step
|
|
1853
|
+
// Step 2: Copy CSS files the server reads off disk by path
|
|
1850
1854
|
const copySpinner = ora({
|
|
1851
1855
|
discardStdin: true,
|
|
1852
1856
|
text: 'Copying CSS files',
|
|
1853
1857
|
}).start();
|
|
1854
1858
|
try {
|
|
1855
|
-
const
|
|
1856
|
-
|
|
1857
|
-
const targetFile = file.replace(sourceFolder, targetFolder);
|
|
1858
|
-
//ensure the target folder exists
|
|
1859
|
-
const targetDir = path.dirname(targetFile);
|
|
1860
|
-
if (!fs.existsSync(targetDir)) {
|
|
1861
|
-
fs.mkdirSync(targetDir, { recursive: true });
|
|
1862
|
-
}
|
|
1863
|
-
return fs.copyFile(file, targetFile);
|
|
1864
|
-
}));
|
|
1865
|
-
copySpinner.succeed(`${cssFiles.length} CSS files copied`);
|
|
1859
|
+
const copied = yield copyBackendStylesheets(appRoot, (dir) => getFiles(dir, '.css'));
|
|
1860
|
+
copySpinner.succeed(`${copied} CSS files copied`);
|
|
1866
1861
|
}
|
|
1867
1862
|
catch (e) {
|
|
1868
1863
|
console.error(e);
|