beam.com 0.1.0-rc.5 → 0.1.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 +6 -6
- package/package.json +1 -1
- package/runtime/app-com.js +49 -22
- package/runtime/beam.mjs +1 -1
- package/runtime/beam.wasm +0 -0
- package/runtime/browser.js +11 -6
- package/runtime/cloudflare/durable.js +31 -2
- package/runtime/cloudflare/index.js +13 -5
- package/runtime/cloudflare/release.js +22 -1
- package/runtime/cloudflare/worker.js +515 -67
- package/runtime/deno/worker.js +515 -67
- package/runtime/deno.js +32 -9
- package/runtime/durable.js +31 -2
- package/runtime/global.js +1 -1
- package/runtime/page/app-com.js +49 -22
- package/runtime/page/beam.mjs +1 -1
- package/runtime/page/browser.js +11 -6
- package/runtime/page/main.js +9 -3
- package/runtime/page/runtime-id.js +1 -1
- package/runtime/page/vm.js +13 -9
- package/runtime/page/worker.js +515 -67
- package/runtime/release.json +1 -1
- package/runtime/runtime-id.js +1 -1
- package/runtime/worker.js +515 -67
package/README.md
CHANGED
|
@@ -74,7 +74,7 @@ On NetBSD and OpenBSD, start the file with the APE loader
|
|
|
74
74
|
|
|
75
75
|
### A custom build
|
|
76
76
|
|
|
77
|
-
Do you need more OTP applications (for example `
|
|
77
|
+
Do you need more OTP applications (for example `mnesia` or `eldap`), Hex and
|
|
78
78
|
rebar3 in the file, or a file without Elixir, SQLite or WebAssembly? Open
|
|
79
79
|
an issue with the form
|
|
80
80
|
[A custom build of beam.com](https://github.com/sntran/BEAM.com/issues/new?template=custom_build.yml).
|
|
@@ -219,7 +219,7 @@ jobs:
|
|
|
219
219
|
|
|
220
220
|
Then turn on Pages one time: Settings, Pages, Source "GitHub Actions". The
|
|
221
221
|
`GITHUB_TOKEN` cannot do this step. Until the release `v0.1.0`, use the
|
|
222
|
-
release candidate `@v0.1.0-rc.
|
|
222
|
+
release candidate `@v0.1.0-rc.6` in place of `@v0.1.0`. With `@main`, the
|
|
223
223
|
workflow uses the `edge` build of `beam.com`.
|
|
224
224
|
|
|
225
225
|
The workflow ([`pages-app.yml`](.github/workflows/pages-app.yml)) builds
|
|
@@ -240,9 +240,9 @@ run shows a warning. A pin to a commit SHA uses the release of that
|
|
|
240
240
|
commit, and stops with an error when the commit has no release tag.
|
|
241
241
|
Before the build, the workflow checks the SHA-256 of `beam.com` and its
|
|
242
242
|
provenance (`gh attestation verify`). The check stops the build when
|
|
243
|
-
`build.yml` of BEAM.com did not make the file
|
|
244
|
-
|
|
245
|
-
permission.
|
|
243
|
+
`build.yml` of BEAM.com did not make the file from the commit of the
|
|
244
|
+
release tag (or from `main`, for `edge`), or when the check cannot reach
|
|
245
|
+
GitHub or Sigstore. It needs no other permission.
|
|
246
246
|
|
|
247
247
|
The app needs an HTTP listener on `PORT` (4000 by default), and only the
|
|
248
248
|
NIFs of the WebAssembly runtime. The limits:
|
|
@@ -286,7 +286,7 @@ Each GitHub release from 0.1.0-rc.2 also holds the package, the same
|
|
|
286
286
|
file as on npm. npm installs it with no registry:
|
|
287
287
|
|
|
288
288
|
```sh
|
|
289
|
-
npm install https://github.com/sntran/BEAM.com/releases/download/v0.1.0-rc.
|
|
289
|
+
npm install https://github.com/sntran/BEAM.com/releases/download/v0.1.0-rc.6/beam.com-0.1.0-rc.6.tgz
|
|
290
290
|
```
|
|
291
291
|
|
|
292
292
|
- `BEAM_COM`: the path of a `beam.com` to use. Then nothing is
|
package/package.json
CHANGED
package/runtime/app-com.js
CHANGED
|
@@ -31,6 +31,12 @@
|
|
|
31
31
|
// the host serves before the VM (worker.js). They are not in files,
|
|
32
32
|
// except cache_manifest.json, which Phoenix reads at its start.
|
|
33
33
|
//
|
|
34
|
+
// appStatics(read, size, { runtime }) gives only that Map, with no read and
|
|
35
|
+
// no check of the other files: the front of a Worker (cloudflare/index.js)
|
|
36
|
+
// serves the static files with no VM. The check of the CRC-32 of each file
|
|
37
|
+
// of the release cost 80 to 180 ms of CPU time for a release of 16 MB, and
|
|
38
|
+
// the front pays it in each new isolate.
|
|
39
|
+
//
|
|
34
40
|
// The zip of beam.com stores each .beam file as a gzip file (the loader of
|
|
35
41
|
// ERTS reads it so, beam_com_zip), so it is a view too. A deflated .beam
|
|
36
42
|
// entry (an older app.com) becomes a gzip file with the same data, with
|
|
@@ -139,32 +145,13 @@ export async function appRelease(read, size, options = {}) {
|
|
|
139
145
|
// default uses DecompressionStream, which the global scope of a Worker
|
|
140
146
|
// cannot use (cloudflare/release.js gives inflateRawSync of node:zlib).
|
|
141
147
|
export async function appFiles(read, size, { runtime, statics: split = true, inflate: unzip = inflate } = {}) {
|
|
142
|
-
const {
|
|
143
|
-
const
|
|
144
|
-
const json = want.find((e) => e.name === `${EDGE}.release.json`);
|
|
145
|
-
if (!json) fail('no edge part (.wasm/.release.json): build it with a beam.com that has the WebAssembly runtime, and without --no-edge');
|
|
146
|
-
// One read: the entries of the release, up to the central directory.
|
|
147
|
-
const lo = Math.min(...want.map((e) => e.offset));
|
|
148
|
-
const span = await read(lo, cdAt - lo);
|
|
149
|
-
if (span.length !== cdAt - lo) fail('a short read of the release');
|
|
150
|
-
const meta = await entryData(span, lo, json, unzip);
|
|
151
|
-
const release = JSON.parse(text.decode(meta));
|
|
152
|
-
if (runtime && release.runtime !== runtime) {
|
|
153
|
-
fail(`it was built for the runtime ${String(release.runtime).slice(0, 12)}, and this runtime is ${runtime.slice(0, 12)}: `
|
|
154
|
-
+ 'use the runtime of the beam.com that built it');
|
|
155
|
-
}
|
|
156
|
-
// The static files of a Phoenix app (PHX_SERVER in the environment of
|
|
157
|
-
// the release): lib/NAME-VSN/priv/static/, for the application with the
|
|
158
|
-
// name of the release. Plug.Static serves them at the root of the site.
|
|
159
|
-
const app = split && release.env?.PHX_SERVER === 'true' && typeof release.name === 'string'
|
|
160
|
-
&& `lib/${release.name}-`;
|
|
161
|
-
const prefix = app && want.map((e) => /^lib\/[^/]+\/priv\/static\//.exec(e.name)?.[0])
|
|
162
|
-
.find((p) => p?.startsWith(app) && /^[0-9]/.test(p.slice(app.length)));
|
|
148
|
+
const { want, json, lo, span, meta, release } = await releaseHead(read, size, runtime, unzip);
|
|
149
|
+
const prefix = split && staticPrefix(release, want);
|
|
163
150
|
const statics = new Map();
|
|
164
151
|
const files = new Map();
|
|
165
152
|
for (const e of want) {
|
|
166
153
|
if (e.name.startsWith(EDGE)) continue;
|
|
167
|
-
if (prefix &&
|
|
154
|
+
if (prefix && isStatic(e, prefix)) {
|
|
168
155
|
statics.set(e.name.slice(prefix.length - 1), staticEntry(span, lo, e));
|
|
169
156
|
continue;
|
|
170
157
|
}
|
|
@@ -179,6 +166,46 @@ export async function appFiles(read, size, { runtime, statics: split = true, inf
|
|
|
179
166
|
};
|
|
180
167
|
}
|
|
181
168
|
|
|
169
|
+
export async function appStatics(read, size, { runtime, inflate: unzip = inflate } = {}) {
|
|
170
|
+
const { want, lo, span, release } = await releaseHead(read, size, runtime, unzip);
|
|
171
|
+
const prefix = staticPrefix(release, want);
|
|
172
|
+
const statics = new Map();
|
|
173
|
+
if (prefix) for (const e of want) if (isStatic(e, prefix)) statics.set(e.name.slice(prefix.length - 1), staticEntry(span, lo, e));
|
|
174
|
+
return statics;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// The entries of the release, the span of their bytes (one read, up to the
|
|
178
|
+
// central directory), and .release.json, which must be of the runtime.
|
|
179
|
+
async function releaseHead(read, size, runtime, unzip) {
|
|
180
|
+
const { entries, cdAt } = await zipEntries(read, size);
|
|
181
|
+
const want = entries.filter((e) => inRelease(e.name) && !e.name.endsWith('/'));
|
|
182
|
+
const json = want.find((e) => e.name === `${EDGE}.release.json`);
|
|
183
|
+
if (!json) fail('no edge part (.wasm/.release.json): build it with a beam.com that has the WebAssembly runtime, and without --no-edge');
|
|
184
|
+
const lo = Math.min(...want.map((e) => e.offset));
|
|
185
|
+
const span = await read(lo, cdAt - lo);
|
|
186
|
+
if (span.length !== cdAt - lo) fail('a short read of the release');
|
|
187
|
+
const meta = await entryData(span, lo, json, unzip);
|
|
188
|
+
const release = JSON.parse(text.decode(meta));
|
|
189
|
+
if (runtime && release.runtime !== runtime) {
|
|
190
|
+
fail(`it was built for the runtime ${String(release.runtime).slice(0, 12)}, and this runtime is ${runtime.slice(0, 12)}: `
|
|
191
|
+
+ 'use the runtime of the beam.com that built it');
|
|
192
|
+
}
|
|
193
|
+
return { want, json, lo, span, meta, release };
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// The static files of a Phoenix app (PHX_SERVER in the environment of the
|
|
197
|
+
// release): lib/NAME-VSN/priv/static/, for the application with the name
|
|
198
|
+
// of the release, or null. Plug.Static serves them at the root of the site.
|
|
199
|
+
function staticPrefix(release, want) {
|
|
200
|
+
const app = release.env?.PHX_SERVER === 'true' && typeof release.name === 'string' && `lib/${release.name}-`;
|
|
201
|
+
return (app && want.map((e) => /^lib\/[^/]+\/priv\/static\//.exec(e.name)?.[0])
|
|
202
|
+
.find((p) => p?.startsWith(app) && /^[0-9]/.test(p.slice(app.length)))) || null;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// A static file of the prefix. cache_manifest.json stays in the release:
|
|
206
|
+
// Phoenix reads it at its start.
|
|
207
|
+
const isStatic = (e, prefix) => e.name.startsWith(prefix) && e.name !== `${prefix}cache_manifest.json`;
|
|
208
|
+
|
|
182
209
|
// A static file: its bytes in the zip (stored or deflated), not checked
|
|
183
210
|
// here (the host checks the CRC-32 when it inflates them).
|
|
184
211
|
function staticEntry(span, base, e) {
|