@frockbot/computer-host-runtime 0.3.12 → 0.3.13

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frockbot/computer-host-runtime",
3
- "version": "0.3.12",
3
+ "version": "0.3.13",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "exports": {
@@ -459,10 +459,26 @@ state running`);
459
459
  const updateDocument = UPDATE_PHASES.map((phase) => phase.body).join("\n");
460
460
  expect(updateDocument).not.toContain("apt-get");
461
461
  expect(updateDocument).not.toContain("playwright-core/cli.js install");
462
- // An in-place update swaps names over files it owns and reaches no
463
- // network: the `applets` phase installs the shim and leaves the SDK's
462
+ // An in-place update swaps names over files it owns and leaves the SDK's
464
463
  // dependency tree — which an `applet dev` may be running out of — alone.
465
- expect(updateDocument).not.toContain("npm install");
464
+ // The one install it carries is the SDK itself, and only while the SDK
465
+ // is absent, which is exactly when nothing can be running out of it.
466
+ expect(updateDocument).not.toContain("miniflare@");
467
+ const installs = updateDocument
468
+ .split("\n")
469
+ .filter((line) => line.includes("npm install"));
470
+ expect(installs).toEqual([
471
+ ` if npm install --prefix ${APPLETS_ROOT} --no-audit --no-fund @frockbot/applet-sdk@${APPLET_SDK_VERSION}; then`,
472
+ ]);
473
+ expect(updateDocument).toContain(
474
+ `if [ ! -d ${APPLETS_ROOT}/node_modules/@frockbot/applet-sdk ]; then`,
475
+ );
476
+ });
477
+
478
+ test("the SDK install follows the published dist-tag, not a number", () => {
479
+ // v0.3.12 published `@frockbot/applet-sdk` as 0.3.12; a pinned "0.1.0"
480
+ // never existed and left every Computer without an SDK.
481
+ expect(APPLET_SDK_VERSION).toBe("latest");
466
482
  });
467
483
  });
468
484
 
package/src/runtime.ts CHANGED
@@ -146,8 +146,18 @@ export const APPLET_SHIM_PATH = `${BIN_ROOT}/applet`;
146
146
  * reported fact, not a Computer nobody can open.
147
147
  */
148
148
  export const APPLETS_SDK_FAILURE_PATH = `${APPLETS_ROOT}/.sdk-unavailable`;
149
- /** The Applets SDK the Computer authors and previews an Applet with. */
150
- export const APPLET_SDK_VERSION = "0.1.0";
149
+ /**
150
+ * The Applets SDK the Computer authors and previews an Applet with.
151
+ *
152
+ * A dist-tag, not a number: the release workflow stamps every published
153
+ * Package with the tag's version (v0.3.12 published `@frockbot/applet-sdk`
154
+ * as 0.3.12), and this document has no way to learn that version at
155
+ * provisioning time. A pinned "0.1.0" here never existed on npm, so every
156
+ * Computer provisioned before this line was written reported the SDK as
157
+ * unavailable. `latest` follows each release; a Computer installs it once
158
+ * and keeps that tree until it is provisioned again.
159
+ */
160
+ export const APPLET_SDK_VERSION = "latest";
151
161
  /** Pinned with the SDK: `applet dev` embeds this Miniflare, never wrangler. */
152
162
  export const MINIFLARE_VERSION = "5.20260828.0-alpha";
153
163
 
@@ -1632,6 +1642,29 @@ fi
1632
1642
  exec "$APPLET" "$@"
1633
1643
  `;
1634
1644
 
1645
+ /**
1646
+ * Installs the Applets SDK when, and only when, it is absent.
1647
+ *
1648
+ * Guarded, and deliberately not fatal: a Computer that cannot fetch the SDK
1649
+ * is still a Computer — it browses, execs, and syncs — so the failure is
1650
+ * recorded as a file the doctor reports under `applets-sdk` rather than as a
1651
+ * phase that fails and leaves the whole run resumable-but-unfinished.
1652
+ *
1653
+ * The `[ ! -d ]` guard is also what makes this safe inside an in-place
1654
+ * update. The only thing that runs out of `${APPLETS_ROOT}` is `applet dev`,
1655
+ * and the shim refuses to start it while the SDK is missing, so an install
1656
+ * that runs only when the SDK is missing never touches a tree a process is
1657
+ * using. Once the SDK is present neither provisioning nor an update installs
1658
+ * again; a newer SDK arrives with the next provisioning adoption.
1659
+ */
1660
+ export const appletSdkInstallScript = `if [ ! -d ${APPLETS_ROOT}/node_modules/@frockbot/applet-sdk ]; then
1661
+ if npm install --prefix ${APPLETS_ROOT} --no-audit --no-fund @frockbot/applet-sdk@${APPLET_SDK_VERSION}; then
1662
+ rm -f ${APPLETS_SDK_FAILURE_PATH}
1663
+ else
1664
+ printf '%s\\n' "npm could not install @frockbot/applet-sdk@${APPLET_SDK_VERSION}" > ${APPLETS_SDK_FAILURE_PATH}
1665
+ fi
1666
+ fi`;
1667
+
1635
1668
  /** The files the `applets` phase installs, with their modes. */
1636
1669
  export const APPLETS_RUNTIME_FILES: readonly {
1637
1670
  readonly path: string;
@@ -2071,18 +2104,7 @@ fi`,
2071
2104
  if [ ! -d ${APPLETS_ROOT}/node_modules/miniflare ]; then
2072
2105
  npm install --prefix ${APPLETS_ROOT} --no-audit --no-fund miniflare@${MINIFLARE_VERSION}
2073
2106
  fi
2074
- # Guarded, and deliberately not fatal. \`@frockbot/applet-sdk\` is not on npm
2075
- # yet, and a Computer that cannot fetch it is still a Computer: it browses,
2076
- # execs, and syncs. The failure is recorded as a file the doctor reports under
2077
- # \`applets-sdk\` rather than as a phase that fails and leaves the whole
2078
- # provisioning run resumable-but-unfinished.
2079
- if [ ! -d ${APPLETS_ROOT}/node_modules/@frockbot/applet-sdk ]; then
2080
- if npm install --prefix ${APPLETS_ROOT} --no-audit --no-fund @frockbot/applet-sdk@${APPLET_SDK_VERSION}; then
2081
- rm -f ${APPLETS_SDK_FAILURE_PATH}
2082
- else
2083
- printf '%s\\n' "npm could not install @frockbot/applet-sdk@${APPLET_SDK_VERSION}" > ${APPLETS_SDK_FAILURE_PATH}
2084
- fi
2085
- fi
2107
+ ${appletSdkInstallScript}
2086
2108
  ${installDeclaredFiles(APPLETS_RUNTIME_FILES)}`,
2087
2109
  },
2088
2110
  {
@@ -2119,12 +2141,18 @@ export const UPDATE_PHASES: readonly {
2119
2141
  {
2120
2142
  name: "applets",
2121
2143
  label: "Updating the Applets command",
2122
- // The shim and nothing else. The provisioning phase beside it also runs
2123
- // `npm install`, which is a network fetch into a dependency tree an
2124
- // `applet dev` may be running out of right now; an in-place update
2125
- // replaces files atomically and must not do that. A Computer picks up a
2126
- // newly published SDK on its next provisioning adoption, not here.
2127
- body: installDeclaredFiles(APPLETS_RUNTIME_FILES),
2144
+ // The shim, plus the SDK only if this Computer has none. The provisioning
2145
+ // phase beside it also installs Miniflare, a network fetch into a
2146
+ // dependency tree an `applet dev` may be running out of right now; an
2147
+ // in-place update replaces files atomically and must not do that. The SDK
2148
+ // install is different: it runs only while the SDK is absent, and nothing
2149
+ // runs out of that tree until the SDK is there (see
2150
+ // `appletSdkInstallScript`). This is how a Computer provisioned while the
2151
+ // SDK was unpublished gets it without being provisioned again. A newer
2152
+ // SDK still waits for the next provisioning adoption.
2153
+ body: `mkdir -p ${APPLETS_ROOT}
2154
+ ${appletSdkInstallScript}
2155
+ ${installDeclaredFiles(APPLETS_RUNTIME_FILES)}`,
2128
2156
  },
2129
2157
  {
2130
2158
  name: "reference",