@stim-cli/metro 1.0.0-rc.4 → 1.0.0-rc.6
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/README.md +35 -67
- package/dist/index.d.mts +13 -4
- package/dist/index.mjs +54 -2
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -1,91 +1,59 @@
|
|
|
1
1
|
# @stim-cli/metro
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
Optional Metro integration for Stim. It exports a transform cache shared across
|
|
4
|
+
worktrees and an NDJSON reporter for structured Metro and client logs.
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
Metro: one transform cache shared by every worktree on the machine, and a
|
|
8
|
-
reporter that writes the dev server's events as NDJSON.
|
|
6
|
+
If Stim is not installed globally, replace `stim` with `npx stim-cli`.
|
|
9
7
|
|
|
10
8
|
```bash
|
|
11
|
-
npm
|
|
9
|
+
npm install --save-dev @stim-cli/metro
|
|
12
10
|
```
|
|
13
11
|
|
|
14
|
-
##
|
|
15
|
-
|
|
16
|
-
Metro's default cache lives under the project, so a second worktree starts cold
|
|
17
|
-
and re-transforms the whole module graph — thousands of modules, every time.
|
|
18
|
-
Pointing every checkout at one store means only the first one pays.
|
|
12
|
+
## Shared transforms
|
|
19
13
|
|
|
20
14
|
```js
|
|
21
|
-
// metro.config.js
|
|
22
15
|
const { sharedCacheStores } = require('@stim-cli/metro');
|
|
23
16
|
|
|
24
|
-
|
|
25
|
-
config.cacheStores = sharedCacheStores('myapp');
|
|
26
|
-
module.exports = config;
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
The `FileStore` itself is six lines; what this packages is the housekeeping.
|
|
30
|
-
**Metro's cache has no eviction logic whatsoever**, so left alone it grows until
|
|
31
|
-
the disk does. Registering it with
|
|
32
|
-
[`stim-cli`](https://www.npmjs.com/package/stim-cli) makes it visible:
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
stim gc # what it has grown to (reported on every run)
|
|
36
|
-
stim gc --delete --older-than 30 # drop entries unused for 30 days
|
|
17
|
+
config.cacheStores = sharedCacheStores('my-app');
|
|
37
18
|
```
|
|
38
19
|
|
|
39
|
-
|
|
40
|
-
only the entries nothing has touched, not the whole cache.
|
|
20
|
+
Set `STIM_METRO_CACHE` to override the shared cache location.
|
|
41
21
|
|
|
42
|
-
|
|
43
|
-
just invisible to housekeeping.
|
|
22
|
+
## Optional second tier
|
|
44
23
|
|
|
45
|
-
The
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
`<parent>/-scope-app`. The CLI and this package resolve both identically.
|
|
24
|
+
The filesystem cache above is always the first tier. When the project selects a
|
|
25
|
+
cache provider, the exported store reads it after a local miss, writes provider
|
|
26
|
+
hits back to the filesystem, and queues new transforms for the provider without
|
|
27
|
+
blocking Metro. Provider failures are misses.
|
|
50
28
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"cache": {
|
|
32
|
+
"provider": "./tools/cache-provider.cjs",
|
|
33
|
+
"options": { "bucket": "mobile-cache" }
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
```
|
|
59
37
|
|
|
60
|
-
|
|
38
|
+
Under `stim start` the supervisor passes the resolved selection to Metro. A
|
|
39
|
+
Metro process outside Stim reads the nearest committed `.stim.json`. See
|
|
40
|
+
[`@stim-cli/cache`](https://www.npmjs.com/package/@stim-cli/cache) for the
|
|
41
|
+
provider contract. `clear()` only clears the local tier.
|
|
61
42
|
|
|
62
|
-
|
|
63
|
-
server emits as one JSON object per line: bundler events and transform failures
|
|
64
|
-
into `<dir>/metro.ndjson`, forwarded in-app console logs and redboxes into
|
|
65
|
-
`<dir>/client.ndjson`.
|
|
43
|
+
## Log reporter
|
|
66
44
|
|
|
67
45
|
```js
|
|
68
46
|
const { ndjsonReporter } = require('@stim-cli/metro');
|
|
69
47
|
|
|
70
|
-
config.reporter = ndjsonReporter({
|
|
71
|
-
dir: '~/.stim-cli/workspaces/my-app--<16hex-path-digest>/logs',
|
|
72
|
-
});
|
|
73
|
-
await Metro.runServer(config, { host, port });
|
|
48
|
+
config.reporter = ndjsonReporter({ dir: '/absolute/log/directory' });
|
|
74
49
|
```
|
|
75
50
|
|
|
76
|
-
|
|
77
|
-
React Native
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
errors from). When used by stim-cli, `dir` defaults to
|
|
86
|
-
`$STIM_CLI_HOME/workspaces/<readable-project-slug>--<16hex-path-digest>/logs`
|
|
87
|
-
(by default `~/.stim-cli/workspaces/...`), outside the working directory.
|
|
88
|
-
|
|
89
|
-
A logging failure is never a server failure: an unwritable directory or an event
|
|
90
|
-
shape from a Metro version this package has never seen is counted on
|
|
91
|
-
`reporter.drops` and swallowed, not thrown into Metro's build pipeline.
|
|
51
|
+
The reporter must be attached to the config passed directly to
|
|
52
|
+
`Metro.runServer`. React Native and Expo CLIs can replace a reporter declared in
|
|
53
|
+
`metro.config.js`.
|
|
54
|
+
|
|
55
|
+
Stim supplies this integration automatically for Stim-managed servers. Add the
|
|
56
|
+
package directly only for Metro processes that run outside Stim.
|
|
57
|
+
|
|
58
|
+
See the [cache package documentation](https://appandflow.github.io/stim/docs/cache-packages)
|
|
59
|
+
for current usage and cleanup guidance.
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
|
+
import { CacheProviderConfig, LoadCacheProviderResult, WarnOnce } from "@stim-cli/cache";
|
|
1
2
|
//#region index.d.ts
|
|
2
3
|
type FileStoreCtor = new (options: {
|
|
3
4
|
root: string;
|
|
4
5
|
}) => object;
|
|
6
|
+
interface SharedCacheStoresOptions {
|
|
7
|
+
FileStore?: FileStoreCtor;
|
|
8
|
+
env?: NodeJS.ProcessEnv;
|
|
9
|
+
cwd?: string;
|
|
10
|
+
loadProvider?: (input: {
|
|
11
|
+
projectRoot: string;
|
|
12
|
+
config: CacheProviderConfig;
|
|
13
|
+
}) => Promise<LoadCacheProviderResult>;
|
|
14
|
+
warn?: WarnOnce;
|
|
15
|
+
}
|
|
5
16
|
interface MetroEvent {
|
|
6
17
|
type?: string;
|
|
7
18
|
level?: unknown;
|
|
@@ -19,11 +30,9 @@ interface NdjsonReporter {
|
|
|
19
30
|
readonly drops: number;
|
|
20
31
|
}
|
|
21
32
|
declare function cacheRoot(name?: string | null): string;
|
|
22
|
-
declare function sharedCacheStores(name?: string, { FileStore }?:
|
|
23
|
-
FileStore?: FileStoreCtor;
|
|
24
|
-
}): object[];
|
|
33
|
+
declare function sharedCacheStores(name?: string, { FileStore, env, cwd, loadProvider, warn }?: SharedCacheStoresOptions): object[];
|
|
25
34
|
declare function ndjsonReporter({ dir }?: {
|
|
26
35
|
dir?: string;
|
|
27
36
|
}): NdjsonReporter;
|
|
28
37
|
//#endregion
|
|
29
|
-
export { NdjsonReporter, cacheRoot, ndjsonReporter, sharedCacheStores };
|
|
38
|
+
export { NdjsonReporter, SharedCacheStoresOptions, cacheRoot, ndjsonReporter, sharedCacheStores };
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
|
+
import { cacheProviderConfigFromEnv, cacheProviderEnvIsSet, createTieredMetroStore, loadCacheProvider } from "@stim-cli/cache";
|
|
4
5
|
import { METRO_NAMED_CACHE_LAYOUT, metroCacheRoot, registerCache, tagSharedStore, workspaceLogDir } from "@stim-cli/core";
|
|
5
6
|
//#region index.ts
|
|
6
7
|
const requireFromHere = createRequire(import.meta.url);
|
|
@@ -18,7 +19,45 @@ function registerOnce(dir, replaces = []) {
|
|
|
18
19
|
replaces
|
|
19
20
|
});
|
|
20
21
|
}
|
|
21
|
-
function
|
|
22
|
+
function isPlainObject(value) {
|
|
23
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
24
|
+
}
|
|
25
|
+
function repositoryRoot(startDir) {
|
|
26
|
+
let dir = startDir;
|
|
27
|
+
for (;;) {
|
|
28
|
+
if (fs.existsSync(path.join(dir, ".git"))) return dir;
|
|
29
|
+
const parent = path.dirname(dir);
|
|
30
|
+
if (parent === dir) return null;
|
|
31
|
+
dir = parent;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function committedProviderConfig(startDir) {
|
|
35
|
+
const start = path.resolve(startDir);
|
|
36
|
+
const stop = repositoryRoot(start) ?? start;
|
|
37
|
+
let dir = start;
|
|
38
|
+
for (;;) {
|
|
39
|
+
let parsed;
|
|
40
|
+
try {
|
|
41
|
+
parsed = JSON.parse(fs.readFileSync(path.join(dir, ".stim.json"), "utf-8"));
|
|
42
|
+
} catch {
|
|
43
|
+
parsed = null;
|
|
44
|
+
}
|
|
45
|
+
const cache = isPlainObject(parsed) && isPlainObject(parsed.cache) ? parsed.cache : null;
|
|
46
|
+
const reference = cache?.provider;
|
|
47
|
+
if (typeof reference === "string" && reference.trim() !== "") return {
|
|
48
|
+
provider: reference.trim(),
|
|
49
|
+
options: isPlainObject(cache?.options) ? cache.options : {},
|
|
50
|
+
baseDir: dir
|
|
51
|
+
};
|
|
52
|
+
const parent = path.dirname(dir);
|
|
53
|
+
if (dir === stop || parent === dir) return null;
|
|
54
|
+
dir = parent;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function warnToStderr(_code, message) {
|
|
58
|
+
process.stderr.write(`warning: ${message}\n`);
|
|
59
|
+
}
|
|
60
|
+
function sharedCacheStores(name = "app", { FileStore, env = process.env, cwd = process.cwd(), loadProvider = loadCacheProvider, warn = warnToStderr } = {}) {
|
|
22
61
|
const Store = FileStore || requireFromHere("metro-cache").FileStore;
|
|
23
62
|
const parent = cacheRoot();
|
|
24
63
|
const root = cacheRoot(name);
|
|
@@ -29,7 +68,20 @@ function sharedCacheStores(name = "app", { FileStore } = {}) {
|
|
|
29
68
|
entriesDepth: 2,
|
|
30
69
|
layout: null
|
|
31
70
|
}]);
|
|
32
|
-
|
|
71
|
+
const local = tagSharedStore(new Store({ root }), root);
|
|
72
|
+
const config = cacheProviderConfigFromEnv(env) ?? (cacheProviderEnvIsSet(env) ? null : committedProviderConfig(cwd));
|
|
73
|
+
if (!config) return [local];
|
|
74
|
+
const tiered = createTieredMetroStore({
|
|
75
|
+
local,
|
|
76
|
+
projectRoot: path.resolve(cwd),
|
|
77
|
+
cacheName: name,
|
|
78
|
+
loadProvider: () => loadProvider({
|
|
79
|
+
projectRoot: path.resolve(cwd),
|
|
80
|
+
config
|
|
81
|
+
}),
|
|
82
|
+
warn
|
|
83
|
+
});
|
|
84
|
+
return [tagSharedStore(tiered, root)];
|
|
33
85
|
}
|
|
34
86
|
const NDJSON_LEVELS = /* @__PURE__ */ new Set([
|
|
35
87
|
"debug",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stim-cli/metro",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
4
|
-
"description": "Metro integration for
|
|
3
|
+
"version": "1.0.0-rc.6",
|
|
4
|
+
"description": "Metro integration for Stim: shared transforms across worktrees and structured logs.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
"build": "tsdown"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@stim-cli/
|
|
31
|
+
"@stim-cli/cache": "^1.0.0-rc.6",
|
|
32
|
+
"@stim-cli/core": "^1.0.0-rc.6"
|
|
32
33
|
},
|
|
33
34
|
"peerDependencies": {
|
|
34
35
|
"metro-cache": "*"
|