@mercury-fw/cli 0.38.0 → 0.38.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 +8 -0
- package/README.md +1 -1
- package/dist/src/app/local-packages.d.ts +11 -5
- package/package.json +4 -4
- package/src/app/local-packages.ts +23 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @mercury-fw/cli
|
|
2
2
|
|
|
3
|
+
## 0.38.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 972a17f: - `mfw local-packages` and `mfw create --local-packages` name each tarball in `.packs/` after its content, so a package repacked at the same version is installed anew instead of kept from Bun's cache or refused by the lockfile's integrity check
|
|
8
|
+
- @mercury-fw/core@0.38.1
|
|
9
|
+
- @mercury-fw/utils@0.38.1
|
|
10
|
+
|
|
3
11
|
## 0.38.0
|
|
4
12
|
|
|
5
13
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -222,7 +222,7 @@ Makes the app install `@mercury-fw/*` packages from local tarballs instead of th
|
|
|
222
222
|
|
|
223
223
|
Overrides, and not the dependencies themselves, because a packed package names the packages it depends on by version, and the registry has those versions too: only an override sends them to the tarballs as well (a packed `@mercury-fw/core` depends on `@mercury-fw/plugin-types`, for example). The Dockerfile `mfw create` writes copies `.packs/` before installing, so the image gets the same packages (an app created before 0.31.0 needs `COPY --chown=mercury:mercury .pack[s] ./.packs/` added after the line copying `package.json`); `.gitignore` leaves it out of the repository.
|
|
224
224
|
|
|
225
|
-
Run it again after packing anew: it replaces the tarballs and the overrides of the previous run, and leaves alone the overrides you wrote yourself. `--off` takes the app back to the registry: the overrides it wrote and `.packs/` go, then `bun install`. After either, `mfw start` rebuilds the image with the packages now installed.
|
|
225
|
+
Run it again after packing anew: it replaces the tarballs and the overrides of the previous run, and leaves alone the overrides you wrote yourself. In `.packs/` each tarball is named after its content (`mercury-fw-core-0.38.0-1a2b3c4d.tgz`): Bun doesn't look again at a tarball whose override didn't change, it keeps what its lockfile and its cache hold, so a repack at the same version needs a new name to be installed. `--off` takes the app back to the registry: the overrides it wrote and `.packs/` go, then `bun install`. After either, `mfw start` rebuilds the image with the packages now installed.
|
|
226
226
|
|
|
227
227
|
```bash
|
|
228
228
|
mfw local-packages ../mercury-fw/apps/testbed/.packs
|
|
@@ -4,7 +4,10 @@
|
|
|
4
4
|
* which the image copies before `bun install`. Overrides, and not the
|
|
5
5
|
* dependencies themselves, because a packed package names its siblings by
|
|
6
6
|
* version, which the registry has too: only an override sends those
|
|
7
|
-
* transitive dependencies to the tarballs as well.
|
|
7
|
+
* transitive dependencies to the tarballs as well. Each tarball is named
|
|
8
|
+
* after its content there: Bun takes a `file:` tarball whose spec didn't
|
|
9
|
+
* change for the one in its lockfile, so a repack at the same version needs
|
|
10
|
+
* another name to be installed.
|
|
8
11
|
*/
|
|
9
12
|
/** The tarballs' folder inside the app, as the Dockerfile copies it. */
|
|
10
13
|
export declare const LOCAL_PACKS_DIR = ".packs";
|
|
@@ -20,8 +23,10 @@ export declare function withLocalOverrides(pkg: Manifest, packs: Array<{
|
|
|
20
23
|
/** `pkg` without the overrides this command writes; without `overrides` at
|
|
21
24
|
* all when none of the user's own is left. */
|
|
22
25
|
export declare function withoutLocalOverrides(pkg: Manifest): Manifest;
|
|
23
|
-
/** A local tarball: its file name in the folder,
|
|
26
|
+
/** A local tarball: its file name in the folder (`source`), its name in the
|
|
27
|
+
* app's `.packs/` (`file`), and the package it holds. */
|
|
24
28
|
export type Pack = {
|
|
29
|
+
source: string;
|
|
25
30
|
file: string;
|
|
26
31
|
name: string;
|
|
27
32
|
version: string;
|
|
@@ -33,9 +38,10 @@ export declare function packageOf(tarball: string): Promise<{
|
|
|
33
38
|
version: string;
|
|
34
39
|
}>;
|
|
35
40
|
/** The tarballs in `from`, in file-name order, each with the package it
|
|
36
|
-
* holds, for an app in `appDir`. Throws when
|
|
37
|
-
* tarball, or is the app's own `.packs/`
|
|
41
|
+
* holds and its name after its content, for an app in `appDir`. Throws when
|
|
42
|
+
* `from` doesn't exist, holds no tarball, or is the app's own `.packs/`
|
|
43
|
+
* (which the copy replaces). */
|
|
38
44
|
export declare function readPacks(from: string, appDir: string): Promise<Pack[]>;
|
|
39
|
-
/** Copies `packs` from `from` into the app's `.packs
|
|
45
|
+
/** Copies `packs` from `from` into the app's `.packs/` under their content names, in place of whatever was there. */
|
|
40
46
|
export declare function copyPacks(from: string, appDir: string, packs: Pack[]): void;
|
|
41
47
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mercury-fw/cli",
|
|
3
|
-
"version": "0.38.
|
|
3
|
+
"version": "0.38.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
"comment:shape": "The Mercury CLI (`mfw`). `mfw create <dir>` writes a new Mercury app from the template. The framework packages move in lockstep with it, so a new app gets them at the CLI's own version; plugins and channels at the registry's latest. The plugin and channel packages are devDependencies only for the catalog test. `main(argv)` is exported for create-mercury-agent.",
|
|
42
42
|
"dependencies": {
|
|
43
43
|
"@clack/prompts": "^1.8.1",
|
|
44
|
-
"@mercury-fw/core": "0.38.
|
|
45
|
-
"@mercury-fw/utils": "0.38.
|
|
44
|
+
"@mercury-fw/core": "0.38.1",
|
|
45
|
+
"@mercury-fw/utils": "0.38.1",
|
|
46
46
|
"commander": "^15.0.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"@mercury-fw/channel-http": "0.4.0",
|
|
51
51
|
"@mercury-fw/auth-oidc": "0.1.0",
|
|
52
52
|
"@mercury-fw/auth-static": "0.1.0",
|
|
53
|
-
"@mercury-fw/formatter": "0.38.
|
|
53
|
+
"@mercury-fw/formatter": "0.38.1",
|
|
54
54
|
"@mercury-fw/plugin-atlassian-admin": "0.1.2",
|
|
55
55
|
"@mercury-fw/plugin-bitbucket": "0.1.2",
|
|
56
56
|
"@mercury-fw/plugin-jira": "0.4.3",
|
|
@@ -4,10 +4,14 @@
|
|
|
4
4
|
* which the image copies before `bun install`. Overrides, and not the
|
|
5
5
|
* dependencies themselves, because a packed package names its siblings by
|
|
6
6
|
* version, which the registry has too: only an override sends those
|
|
7
|
-
* transitive dependencies to the tarballs as well.
|
|
7
|
+
* transitive dependencies to the tarballs as well. Each tarball is named
|
|
8
|
+
* after its content there: Bun takes a `file:` tarball whose spec didn't
|
|
9
|
+
* change for the one in its lockfile, so a repack at the same version needs
|
|
10
|
+
* another name to be installed.
|
|
8
11
|
*/
|
|
9
12
|
|
|
10
|
-
import {
|
|
13
|
+
import { createHash } from "node:crypto";
|
|
14
|
+
import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync } from "node:fs";
|
|
11
15
|
import { join, resolve } from "node:path";
|
|
12
16
|
|
|
13
17
|
/** The tarballs' folder inside the app, as the Dockerfile copies it. */
|
|
@@ -38,8 +42,15 @@ export function withoutLocalOverrides(pkg: Manifest): Manifest {
|
|
|
38
42
|
return Object.keys(own).length > 0 ? { ...rest, overrides: own } : rest;
|
|
39
43
|
}
|
|
40
44
|
|
|
41
|
-
/** A local tarball: its file name in the folder,
|
|
42
|
-
|
|
45
|
+
/** A local tarball: its file name in the folder (`source`), its name in the
|
|
46
|
+
* app's `.packs/` (`file`), and the package it holds. */
|
|
47
|
+
export type Pack = { source: string; file: string; name: string; version: string };
|
|
48
|
+
|
|
49
|
+
/** `file`'s name with the first 8 hex digits of `tarball`'s sha256 before `.tgz`. */
|
|
50
|
+
function contentName(file: string, tarball: string): string {
|
|
51
|
+
const hash = createHash("sha256").update(readFileSync(tarball)).digest("hex").slice(0, 8);
|
|
52
|
+
return `${file.slice(0, -".tgz".length)}-${hash}.tgz`;
|
|
53
|
+
}
|
|
43
54
|
|
|
44
55
|
/** The package name and version in a `bun pm pack` tarball, read from its
|
|
45
56
|
* `package/package.json`. */
|
|
@@ -58,8 +69,9 @@ export async function packageOf(tarball: string): Promise<{ name: string; versio
|
|
|
58
69
|
}
|
|
59
70
|
|
|
60
71
|
/** The tarballs in `from`, in file-name order, each with the package it
|
|
61
|
-
* holds, for an app in `appDir`. Throws when
|
|
62
|
-
* tarball, or is the app's own `.packs/`
|
|
72
|
+
* holds and its name after its content, for an app in `appDir`. Throws when
|
|
73
|
+
* `from` doesn't exist, holds no tarball, or is the app's own `.packs/`
|
|
74
|
+
* (which the copy replaces). */
|
|
63
75
|
export async function readPacks(from: string, appDir: string): Promise<Pack[]> {
|
|
64
76
|
const source = resolve(from);
|
|
65
77
|
if (source === join(resolve(appDir), LOCAL_PACKS_DIR)) {
|
|
@@ -68,13 +80,15 @@ export async function readPacks(from: string, appDir: string): Promise<Pack[]> {
|
|
|
68
80
|
if (!existsSync(source)) throw new Error(`${source} doesn't exist.`);
|
|
69
81
|
const files = readdirSync(source).filter((f) => f.endsWith(".tgz")).sort();
|
|
70
82
|
if (files.length === 0) throw new Error(`No .tgz in ${source}: pack the packages there first (bun pm pack).`);
|
|
71
|
-
return Promise.all(
|
|
83
|
+
return Promise.all(
|
|
84
|
+
files.map(async (file) => ({ source: file, file: contentName(file, join(source, file)), ...(await packageOf(join(source, file))) })),
|
|
85
|
+
);
|
|
72
86
|
}
|
|
73
87
|
|
|
74
|
-
/** Copies `packs` from `from` into the app's `.packs
|
|
88
|
+
/** Copies `packs` from `from` into the app's `.packs/` under their content names, in place of whatever was there. */
|
|
75
89
|
export function copyPacks(from: string, appDir: string, packs: Pack[]): void {
|
|
76
90
|
const target = join(appDir, LOCAL_PACKS_DIR);
|
|
77
91
|
rmSync(target, { recursive: true, force: true });
|
|
78
92
|
mkdirSync(target);
|
|
79
|
-
for (const { file } of packs) cpSync(join(resolve(from),
|
|
93
|
+
for (const { source, file } of packs) cpSync(join(resolve(from), source), join(target, file));
|
|
80
94
|
}
|