@exodus/stasis 1.0.0-beta.1 → 1.0.0-beta.2
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/bin/stasis.js +31 -5
- package/package.json +3 -3
- package/src/cmd/build.js +4 -3
- package/src/cmd/bundle.js +4 -2
- package/src/metro-transformer.js +3 -2
package/bin/stasis.js
CHANGED
|
@@ -8,6 +8,7 @@ import { basename, dirname, resolve } from 'node:path'
|
|
|
8
8
|
import { existsSync, realpathSync } from 'node:fs'
|
|
9
9
|
import { constants as osConstants } from 'node:os'
|
|
10
10
|
import assert from 'node:assert/strict'
|
|
11
|
+
import { parseBrotliQuality } from '@exodus/stasis-core/util'
|
|
11
12
|
import pkg from '../package.json' with { type: 'json' }
|
|
12
13
|
|
|
13
14
|
const argv = [...process.argv]
|
|
@@ -20,14 +21,15 @@ assert(basename(jsname) === 'stasis' || pathsEqual(jsname, fileURLToPath(import.
|
|
|
20
21
|
|
|
21
22
|
function usage(prefix = '') {
|
|
22
23
|
console.error(`${prefix}\nUsage:
|
|
23
|
-
stasis run --lock=(add|replace|frozen|ignore) [--bundle=(add|replace|load|frozen|ignore)] [--bundle-file=path/to/bundle.br] [--resources-bundle-file=path/to/resources.br] [--dependencies] [--child-process] [--mock] [--fs=(sync|async)] [--resources=ext,ext] path/to/file.js ...
|
|
24
|
+
stasis run --lock=(add|replace|frozen|ignore) [--bundle=(add|replace|load|frozen|ignore)] [--bundle-file=path/to/bundle.br] [--resources-bundle-file=path/to/resources.br] [--dependencies] [--child-process] [--mock] [--fs=(sync|async)] [--resources=ext,ext] [--brotli-quality=0..11] path/to/file.js ...
|
|
24
25
|
stasis bundle [--mapping=path/to/remappings(.txt|.toml)] [--output=(path|-)] path/to/file.sol ...
|
|
25
26
|
stasis bundle [--output=(path|-)] path/to/file.php ...
|
|
26
27
|
stasis bundle [--scope=(node_modules|full)] [--conditions=cond1,cond2] [--mainFields=field1,field2] [--lockfile=path/to/stasis.lock.json] [--output=(path|-)] path/to/file.(js|ts) ...
|
|
27
28
|
stasis bundle --metro --platforms=ios,android [--platforms=web] [--lockfile=path/to/stasis.lock.json] [--output=(path|-)] path/to/file.(js|ts) ...
|
|
28
29
|
stasis bundle [--output=(path|-)] path/to/file.(sh|bash) ...
|
|
29
30
|
stasis bundle [--output=(path|-)] path/to/file.rs ...
|
|
30
|
-
(stasis bundle writes to stasis.code.br by default; --output=- streams to stdout
|
|
31
|
+
(stasis bundle writes to stasis.code.br by default; --output=- streams to stdout;
|
|
32
|
+
--brotli-quality=0..11 tunes bundle compression for any entry language, default 11 = smallest/slowest)
|
|
31
33
|
stasis build --output=(dir|file.js) [--format=(esm|cjs|iife)] [--platform=(node|browser|neutral)] [--minify] [--sourcemap] [--define=K=V ...] [--external=pkg ...] [--loader=.ext:name ...] path/to/(stasis.code.br|stasis.lock.json) [entry]
|
|
32
34
|
stasis extract [--output=path/to/dir] path/to/bundle.stasis.code.br
|
|
33
35
|
stasis diff --stat [--imports] path/to/(lockfile|bundle) path/to/(lockfile|bundle)
|
|
@@ -52,7 +54,7 @@ if (command === '-v' || command === '--version') {
|
|
|
52
54
|
process.exit(0)
|
|
53
55
|
} else if (command === 'run') {
|
|
54
56
|
const flags = []
|
|
55
|
-
const valueFlags = new Set(['--bundle', '--bundle-file', '--resources-bundle-file', '--lock', '--resources'])
|
|
57
|
+
const valueFlags = new Set(['--bundle', '--bundle-file', '--resources-bundle-file', '--lock', '--resources', '--brotli-quality'])
|
|
56
58
|
while (argv.length > 0 && (argv[0].startsWith('-') || valueFlags.has(flags.at(-1)))) {
|
|
57
59
|
flags.push(argv.shift())
|
|
58
60
|
}
|
|
@@ -68,6 +70,7 @@ if (command === '-v' || command === '--version') {
|
|
|
68
70
|
mock: { type: 'boolean' },
|
|
69
71
|
fs: { type: 'string' },
|
|
70
72
|
resources: { type: 'string' },
|
|
73
|
+
'brotli-quality': { type: 'string' },
|
|
71
74
|
}
|
|
72
75
|
|
|
73
76
|
let values
|
|
@@ -104,10 +107,19 @@ if (command === '-v' || command === '--version') {
|
|
|
104
107
|
// --resources: comma-separated extension/filename allowlist for `--fs` resource captures
|
|
105
108
|
// (e.g. png,svg,LICENSE). The child's Config validates each entry via parseResourcesOption.
|
|
106
109
|
const resources = values.resources ?? ''
|
|
110
|
+
// --brotli-quality: bundle compression quality (0..11; unset = brotli's default 11).
|
|
111
|
+
let brotliQuality
|
|
112
|
+
if (values['brotli-quality'] !== undefined) {
|
|
113
|
+
try {
|
|
114
|
+
brotliQuality = parseBrotliQuality('--brotli-quality', values['brotli-quality'])
|
|
115
|
+
} catch (cause) {
|
|
116
|
+
usage(`Error: ${cause.message}`)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
107
119
|
// --child-process: forward forked-child (e.g. Metro transform worker) capture to the root
|
|
108
120
|
// via per-pid shards. Opt-in -- it stands up a process-coordination channel, off by default.
|
|
109
121
|
const childProcess = values['child-process'] ? '1' : ''
|
|
110
|
-
console.warn('[stasis] Running stasis with config:', { lock, scope, bundle, ...(bundleFile && { bundleFile }), ...(resourcesBundleFile && { resourcesBundleFile }), ...(childProcess && { childProcess: true }), ...(values.mock && { mock: true }), ...(values.fs && { fs: values.fs }), ...(resources && { resources }) })
|
|
122
|
+
console.warn('[stasis] Running stasis with config:', { lock, scope, bundle, ...(bundleFile && { bundleFile }), ...(resourcesBundleFile && { resourcesBundleFile }), ...(childProcess && { childProcess: true }), ...(values.mock && { mock: true }), ...(values.fs && { fs: values.fs }), ...(resources && { resources }), ...(brotliQuality !== undefined && { brotliQuality }) })
|
|
111
123
|
if (debug) console.warn(`[stasis] Warning: stasis debug mode active`)
|
|
112
124
|
setEnv('EXODUS_STASIS_LOCK', lock)
|
|
113
125
|
setEnv('EXODUS_STASIS_SCOPE', scope)
|
|
@@ -118,6 +130,9 @@ if (command === '-v' || command === '--version') {
|
|
|
118
130
|
setEnv('EXODUS_STASIS_CHILD_PROCESS', childProcess)
|
|
119
131
|
setEnv('EXODUS_STASIS_FS', captureFs)
|
|
120
132
|
setEnv('EXODUS_STASIS_RESOURCES', resources)
|
|
133
|
+
// Only set when given, so an ambient EXODUS_STASIS_BROTLI_QUALITY still passes through
|
|
134
|
+
// to the child (an unconditional setEnv('') would reject it as a conflict).
|
|
135
|
+
if (brotliQuality !== undefined) setEnv('EXODUS_STASIS_BROTLI_QUALITY', String(brotliQuality))
|
|
121
136
|
// --mock: capture imports by running user code with side-effects denied,
|
|
122
137
|
// fail-closed. Node's permission system blocks fs writes, child processes,
|
|
123
138
|
// worker threads, native addons (no --allow-addons -- addons would bypass
|
|
@@ -173,7 +188,7 @@ if (command === '-v' || command === '--version') {
|
|
|
173
188
|
process.exitCode = code ?? 128 + (osConstants.signals[signal] ?? 0)
|
|
174
189
|
} else if (command === 'bundle') {
|
|
175
190
|
const flags = []
|
|
176
|
-
const valueFlags = new Set(['--mapping', '--output', '--scope', '--lockfile', '--conditions', '--mainFields', '--platforms', '-o'])
|
|
191
|
+
const valueFlags = new Set(['--mapping', '--output', '--scope', '--lockfile', '--conditions', '--mainFields', '--platforms', '--brotli-quality', '-o'])
|
|
177
192
|
while (argv.length > 0 && (argv[0].startsWith('-') || valueFlags.has(flags.at(-1)))) {
|
|
178
193
|
flags.push(argv.shift())
|
|
179
194
|
}
|
|
@@ -186,6 +201,7 @@ if (command === '-v' || command === '--version') {
|
|
|
186
201
|
mainFields: { type: 'string' },
|
|
187
202
|
metro: { type: 'boolean' },
|
|
188
203
|
platforms: { type: 'string', multiple: true },
|
|
204
|
+
'brotli-quality': { type: 'string' },
|
|
189
205
|
}
|
|
190
206
|
let values
|
|
191
207
|
try {
|
|
@@ -255,6 +271,15 @@ if (command === '-v' || command === '--version') {
|
|
|
255
271
|
} else if (platforms.length > 0) {
|
|
256
272
|
usage('Error: --platforms is only valid with --metro')
|
|
257
273
|
}
|
|
274
|
+
// --brotli-quality: output-encoding knob, valid for every entry language (no allJs gate).
|
|
275
|
+
let brotliQuality
|
|
276
|
+
if (values['brotli-quality'] !== undefined) {
|
|
277
|
+
try {
|
|
278
|
+
brotliQuality = parseBrotliQuality('--brotli-quality', values['brotli-quality'])
|
|
279
|
+
} catch (cause) {
|
|
280
|
+
usage(`Error: ${cause.message}`)
|
|
281
|
+
}
|
|
282
|
+
}
|
|
258
283
|
const { bundleCommand } = await import('../src/cmd/bundle.js')
|
|
259
284
|
await bundleCommand({
|
|
260
285
|
cwd: process.cwd(),
|
|
@@ -267,6 +292,7 @@ if (command === '-v' || command === '--version') {
|
|
|
267
292
|
mainFields,
|
|
268
293
|
metro,
|
|
269
294
|
platforms,
|
|
295
|
+
brotliQuality,
|
|
270
296
|
})
|
|
271
297
|
} else if (command === 'build') {
|
|
272
298
|
const flags = []
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/stasis",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.2",
|
|
4
4
|
"description": "File-level source bundles and lockfiles",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -68,8 +68,8 @@
|
|
|
68
68
|
},
|
|
69
69
|
"homepage": "https://github.com/ExodusOSS/stasis#readme",
|
|
70
70
|
"dependencies": {
|
|
71
|
-
"@exodus/stasis-core": "1.0.0-beta.
|
|
72
|
-
"@exodus/stasis-plugins": "1.0.0-beta.
|
|
71
|
+
"@exodus/stasis-core": "1.0.0-beta.2",
|
|
72
|
+
"@exodus/stasis-plugins": "1.0.0-beta.2",
|
|
73
73
|
"oxc-parser": "^0.94.0"
|
|
74
74
|
},
|
|
75
75
|
"peerDependencies": {
|
package/src/cmd/build.js
CHANGED
|
@@ -21,13 +21,14 @@ export { bundleFromLockfile }
|
|
|
21
21
|
const JS_EXTS = new Set(['.js', '.cjs', '.mjs', '.ts', '.cts', '.mts', '.jsx', '.tsx'])
|
|
22
22
|
|
|
23
23
|
// Allowlist (NOT a blocklist) of per-file formats `stasis build` accepts in an artifact:
|
|
24
|
-
// the JS/TS/JSON code formats esbuild builds, plus the non-code
|
|
25
|
-
//
|
|
24
|
+
// the JS/TS/JSON code formats esbuild builds, plus the non-code formats -- resource/
|
|
25
|
+
// directory payloads and the payload-free stat records (`--fs` lstat/stat captures) --
|
|
26
|
+
// that are inert unless the SELECTED entry imports them. An allowlist
|
|
26
27
|
// so a new language format added to `stasis bundle` later (e.g. a future `go`) is rejected
|
|
27
28
|
// here by default, rather than slipping through to a cryptic esbuild failure in the build.
|
|
28
29
|
const BUILDABLE_FORMATS = new Set([
|
|
29
30
|
'module', 'commonjs', 'json', 'module-typescript', 'commonjs-typescript',
|
|
30
|
-
'resource', 'resource:base64', 'directory',
|
|
31
|
+
'resource', 'resource:base64', 'directory', 'stat:file', 'stat:directory',
|
|
31
32
|
])
|
|
32
33
|
|
|
33
34
|
// esbuild is an OPTIONAL peer dependency: `stasis build` is the only command that
|
package/src/cmd/bundle.js
CHANGED
|
@@ -1020,7 +1020,9 @@ const DEFAULT_BUNDLE_FILE = 'stasis.code.br'
|
|
|
1020
1020
|
// so it resolves different files on disk and fails closed (correctly -- the lockfile
|
|
1021
1021
|
// genuinely attests a different graph). Pair such a lockfile with `--bundle=load`, or
|
|
1022
1022
|
// replay the same `--conditions` at run time, so the attested and observed graphs agree.
|
|
1023
|
-
|
|
1023
|
+
// `brotliQuality` (integer 0..11, optional; unset = brotli's default 11) tunes the
|
|
1024
|
+
// output compression, forwarded to brotliOptions().
|
|
1025
|
+
export async function bundleCommand({ cwd = process.cwd(), entries, mappingFile, output, scope, lockfile, conditions, mainFields, platforms, metro, brotliQuality } = {}) {
|
|
1024
1026
|
const kind = classifyEntries('bundleCommand', { entries, mappingFile, scope, lockfile, conditions, mainFields, platforms, metro })
|
|
1025
1027
|
|
|
1026
1028
|
let bundle
|
|
@@ -1053,7 +1055,7 @@ export async function bundleCommand({ cwd = process.cwd(), entries, mappingFile,
|
|
|
1053
1055
|
const files = [...bundle.sources.keys()]
|
|
1054
1056
|
const modules = bundle.modules
|
|
1055
1057
|
|
|
1056
|
-
const data = brotliCompressSync(serialized, brotliOptions())
|
|
1058
|
+
const data = brotliCompressSync(serialized, brotliOptions(brotliQuality))
|
|
1057
1059
|
// Default to writing stasis.code.br in cwd; `-` is the conventional opt-in
|
|
1058
1060
|
// for streaming the raw brotli bytes to stdout (e.g. to pipe somewhere else).
|
|
1059
1061
|
const target = output ?? DEFAULT_BUNDLE_FILE
|
package/src/metro-transformer.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Public-export adapter: backs `@exodus/stasis/metro-transformer`. The transformer
|
|
2
2
|
// lives in @exodus/stasis-plugins (which depends on @exodus/stasis-core for State; it
|
|
3
|
-
// drives load-mode getFile directly). Wire it as Metro's
|
|
4
|
-
//
|
|
3
|
+
// drives load-mode getFile directly). Wire it permanently as Metro's top-level
|
|
4
|
+
// `transformerPath`; it only acts under bundle=load (transparent pass-through
|
|
5
|
+
// otherwise). See the source for the load asymmetry that lets this run per-worker
|
|
5
6
|
// without cross-worker state sync.
|
|
6
7
|
export * from '@exodus/stasis-plugins/metro-transformer'
|