@backtickjs/react-native-client 0.1.9 → 0.1.10

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 CHANGED
@@ -12,18 +12,21 @@ npm install @backtickjs/react-native-client
12
12
 
13
13
  ## Usage
14
14
 
15
- Give `evaluate` the module map: the modules a bundle may require, each loaded the first time one does. Then fetch a screen and draw it. Hold the request, a promise, in state in a component that doesn't suspend, so it outlives the render that waits for it, and draw it with React's `use` under `<Suspense>`:
15
+ Give `evaluate` the module map: the modules a bundle may require, imported as the app starts. Then fetch a screen and draw it. Hold the request, a promise, in state in a component that doesn't suspend, so it outlives the render that waits for it, and draw it with React's `use` under `<Suspense>`:
16
16
 
17
17
  ```tsx
18
18
  import { evaluate } from "@backtickjs/react-native-client";
19
+ import * as React from "react";
19
20
  import { Suspense, use, useState } from "react";
21
+ import * as JSXRuntime from "react/jsx-runtime";
22
+ import * as ReactNative from "react-native";
20
23
  import { ActivityIndicator } from "react-native";
21
24
 
22
25
  // What a screen may require: the packages this app was built with.
23
26
  const moduleMap = {
24
- react: () => require("react"),
25
- "react/jsx-runtime": () => require("react/jsx-runtime"),
26
- "react-native": () => require("react-native"),
27
+ react: React,
28
+ "react/jsx-runtime": JSXRuntime,
29
+ "react-native": ReactNative,
27
30
  };
28
31
 
29
32
  async function fetchScreen(url: string) {
@@ -35,9 +38,7 @@ async function fetchScreen(url: string) {
35
38
  }
36
39
 
37
40
  export default function App() {
38
- const [screen] = useState(() =>
39
- fetchScreen("https://api.example.com/screens/home"),
40
- );
41
+ const [screen] = useState(() => fetchScreen("https://api.example.com/"));
41
42
  return (
42
43
  <Suspense fallback={<ActivityIndicator />}>
43
44
  <Screen screen={screen} />
@@ -58,7 +59,7 @@ The server bundles for the versions the app runs: it passes them to `bundler.bui
58
59
 
59
60
  ### `evaluate(code: string, moduleMap: ModuleMap): unknown`
60
61
 
61
- Runs `code` as a CommonJS module, with `require` answered from `moduleMap`, and returns what it exports: for a Backtick screen, the element to draw. Each module loads the first time a bundle requires it, once for every bundle run with the same map. A bundle that requires a specifier missing from `moduleMap` throws:
62
+ Runs `code` as a CommonJS module, with `require` answered from `moduleMap`, and returns what it exports: for a Backtick screen, the element to draw. A bundle that requires a specifier missing from `moduleMap` throws:
62
63
 
63
64
  ```
64
65
  The bundle requires "expo-haptics", which this app doesn't provide.
@@ -69,10 +70,10 @@ Errors thrown while the bundle runs propagate to the caller.
69
70
  ### `ModuleMap`
70
71
 
71
72
  ```ts
72
- type ModuleMap = Readonly<Record<string, () => unknown>>;
73
+ type ModuleMap = Readonly<Record<string, unknown>>;
73
74
  ```
74
75
 
75
- What a bundle may require, by specifier, each as a function that returns its module. It does for an app what a web page's import map does, with modules for values instead of URLs. At least `react`, `react/jsx-runtime` and `react-native`; add any other package the app chooses to offer its screens. Keep the functions' `require` calls inside them: Metro still bundles each one, and Node tools can then read the specifiers without loading React Native.
76
+ What a bundle may require, by specifier, each as the module the app imported for it. It does for an app what a web page's import map does, with modules for values instead of URLs. At least `react`, `react/jsx-runtime` and `react-native`; add any other package the app chooses to offer its screens. Imported at the top of a file, the modules load as the app starts, so one that fails to load fails then, rather than on the first screen that needs it.
76
77
 
77
78
  ### `buildIdFrom(extra: unknown, platform: string): string`
78
79
 
package/dist/index.d.ts CHANGED
@@ -1,20 +1,23 @@
1
1
  /**
2
- * What a bundle may import, by specifier, and how this app loads each: a
3
- * function returning the module, called the first time a bundle requires it.
4
- * At least React, React Native and React's JSX runtime:
2
+ * What a bundle may import, by specifier: each the module the app imported
3
+ * for it. What a web page's import map does, for an app, with modules for
4
+ * values instead of URLs. At least React, React Native and React's JSX
5
+ * runtime:
5
6
  *
6
- * const moduleMap = {
7
- * react: () => require("react"),
8
- * "react/jsx-runtime": () => require("react/jsx-runtime"),
9
- * "react-native": () => require("react-native"),
10
- * };
7
+ * import * as React from "react";
8
+ * import * as JSXRuntime from "react/jsx-runtime";
9
+ * import * as ReactNative from "react-native";
11
10
  *
12
- * What a web page's import map does, for an app: the values are modules,
13
- * not URLs.
14
- * Loaded lazily, so a module no screen uses never loads, and Node can read
15
- * the specifiers without loading React Native.
11
+ * export const moduleMap = {
12
+ * react: React,
13
+ * "react/jsx-runtime": JSXRuntime,
14
+ * "react-native": ReactNative,
15
+ * } satisfies ModuleMap;
16
+ *
17
+ * Imported as the app starts, so a module that fails to load fails then, not
18
+ * on the first screen that needs it.
16
19
  */
17
- export type ModuleMap = Readonly<Record<string, () => unknown>>;
20
+ export type ModuleMap = Readonly<Record<string, unknown>>;
18
21
  /**
19
22
  * A bundle's code, run as CommonJS with `require` answered from `moduleMap`:
20
23
  * what it exports, the screen to draw. What a web page's import map and
package/dist/index.js CHANGED
@@ -1,5 +1,3 @@
1
- // Each map's modules, once loaded: one instance of each, as `require` gives.
2
- const loaded = new WeakMap();
3
1
  /**
4
2
  * A bundle's code, run as CommonJS with `require` answered from `moduleMap`:
5
3
  * what it exports, the screen to draw. What a web page's import map and
@@ -8,19 +6,11 @@ const loaded = new WeakMap();
8
6
  * throws.
9
7
  */
10
8
  export function evaluate(code, moduleMap) {
11
- let modules = loaded.get(moduleMap);
12
- if (modules === undefined) {
13
- modules = new Map();
14
- loaded.set(moduleMap, modules);
15
- }
16
9
  const require = (specifier) => {
17
10
  if (!Object.hasOwn(moduleMap, specifier)) {
18
11
  throw new Error(`The bundle requires "${specifier}", which this app doesn't provide.`);
19
12
  }
20
- if (!modules.has(specifier)) {
21
- modules.set(specifier, moduleMap[specifier]());
22
- }
23
- return modules.get(specifier);
13
+ return moduleMap[specifier];
24
14
  };
25
15
  const module = { exports: {} };
26
16
  new Function("module", "exports", "require", code)(module, module.exports, require);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAkBA,6EAA6E;AAC7E,MAAM,MAAM,GAAG,IAAI,OAAO,EAAmC,CAAC;AAE9D;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,SAAoB;IACzD,IAAI,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACpC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,GAAG,IAAI,GAAG,EAAE,CAAC;QACpB,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACjC,CAAC;IACD,MAAM,OAAO,GAAG,CAAC,SAAiB,EAAW,EAAE;QAC7C,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,CAAC;YACzC,MAAM,IAAI,KAAK,CACb,wBAAwB,SAAS,oCAAoC,CACtE,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,SAAS,CAAE,EAAE,CAAC,CAAC;QAClD,CAAC;QACD,OAAO,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAChC,CAAC,CAAC;IACF,MAAM,MAAM,GAAG,EAAE,OAAO,EAAE,EAAa,EAAE,CAAC;IAC1C,IAAI,QAAQ,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,CAChD,MAAM,EACN,MAAM,CAAC,OAAO,EACd,OAAO,CACR,CAAC;IACF,OAAO,MAAM,CAAC,OAAO,CAAC;AACxB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW,CAAC,KAAc,EAAE,QAAgB;IAC1D,MAAM,GAAG,GAAI,KAA4D;QACvE,EAAE,QAAQ,CAAC;IACb,MAAM,EAAE,GAAG,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC;IAC3B,IAAI,OAAO,EAAE,KAAK,QAAQ,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CACb,mBAAmB,QAAQ,+EAA+E,CAC3G,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAqBA;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,SAAoB;IACzD,MAAM,OAAO,GAAG,CAAC,SAAiB,EAAW,EAAE;QAC7C,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,CAAC;YACzC,MAAM,IAAI,KAAK,CACb,wBAAwB,SAAS,oCAAoC,CACtE,CAAC;QACJ,CAAC;QACD,OAAO,SAAS,CAAC,SAAS,CAAC,CAAC;IAC9B,CAAC,CAAC;IACF,MAAM,MAAM,GAAG,EAAE,OAAO,EAAE,EAAa,EAAE,CAAC;IAC1C,IAAI,QAAQ,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,CAChD,MAAM,EACN,MAAM,CAAC,OAAO,EACd,OAAO,CACR,CAAC;IACF,OAAO,MAAM,CAAC,OAAO,CAAC;AACxB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW,CAAC,KAAc,EAAE,QAAgB;IAC1D,MAAM,GAAG,GAAI,KAA4D;QACvE,EAAE,QAAQ,CAAC;IACb,MAAM,EAAE,GAAG,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC;IAC3B,IAAI,OAAO,EAAE,KAAK,QAAQ,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CACb,mBAAmB,QAAQ,+EAA+E,CAC3G,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backtickjs/react-native-client",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "description": "Runs a Backtick server's screens in a React Native app, with the app's own packages",
5
5
  "keywords": [
6
6
  "backtick",
package/src/index.ts CHANGED
@@ -1,23 +1,23 @@
1
1
  /**
2
- * What a bundle may import, by specifier, and how this app loads each: a
3
- * function returning the module, called the first time a bundle requires it.
4
- * At least React, React Native and React's JSX runtime:
2
+ * What a bundle may import, by specifier: each the module the app imported
3
+ * for it. What a web page's import map does, for an app, with modules for
4
+ * values instead of URLs. At least React, React Native and React's JSX
5
+ * runtime:
5
6
  *
6
- * const moduleMap = {
7
- * react: () => require("react"),
8
- * "react/jsx-runtime": () => require("react/jsx-runtime"),
9
- * "react-native": () => require("react-native"),
10
- * };
7
+ * import * as React from "react";
8
+ * import * as JSXRuntime from "react/jsx-runtime";
9
+ * import * as ReactNative from "react-native";
11
10
  *
12
- * What a web page's import map does, for an app: the values are modules,
13
- * not URLs.
14
- * Loaded lazily, so a module no screen uses never loads, and Node can read
15
- * the specifiers without loading React Native.
11
+ * export const moduleMap = {
12
+ * react: React,
13
+ * "react/jsx-runtime": JSXRuntime,
14
+ * "react-native": ReactNative,
15
+ * } satisfies ModuleMap;
16
+ *
17
+ * Imported as the app starts, so a module that fails to load fails then, not
18
+ * on the first screen that needs it.
16
19
  */
17
- export type ModuleMap = Readonly<Record<string, () => unknown>>;
18
-
19
- // Each map's modules, once loaded: one instance of each, as `require` gives.
20
- const loaded = new WeakMap<ModuleMap, Map<string, unknown>>();
20
+ export type ModuleMap = Readonly<Record<string, unknown>>;
21
21
 
22
22
  /**
23
23
  * A bundle's code, run as CommonJS with `require` answered from `moduleMap`:
@@ -27,21 +27,13 @@ const loaded = new WeakMap<ModuleMap, Map<string, unknown>>();
27
27
  * throws.
28
28
  */
29
29
  export function evaluate(code: string, moduleMap: ModuleMap): unknown {
30
- let modules = loaded.get(moduleMap);
31
- if (modules === undefined) {
32
- modules = new Map();
33
- loaded.set(moduleMap, modules);
34
- }
35
30
  const require = (specifier: string): unknown => {
36
31
  if (!Object.hasOwn(moduleMap, specifier)) {
37
32
  throw new Error(
38
33
  `The bundle requires "${specifier}", which this app doesn't provide.`,
39
34
  );
40
35
  }
41
- if (!modules.has(specifier)) {
42
- modules.set(specifier, moduleMap[specifier]!());
43
- }
44
- return modules.get(specifier);
36
+ return moduleMap[specifier];
45
37
  };
46
38
  const module = { exports: {} as unknown };
47
39
  new Function("module", "exports", "require", code)(