@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 +11 -10
- package/dist/index.d.ts +16 -13
- package/dist/index.js +1 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +17 -25
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,
|
|
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:
|
|
25
|
-
"react/jsx-runtime":
|
|
26
|
-
"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.
|
|
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,
|
|
73
|
+
type ModuleMap = Readonly<Record<string, unknown>>;
|
|
73
74
|
```
|
|
74
75
|
|
|
75
|
-
What a bundle may require, by specifier, each as
|
|
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
|
|
3
|
-
*
|
|
4
|
-
* At least React, React Native and React's JSX
|
|
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
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
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
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
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,
|
|
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
|
-
|
|
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":"
|
|
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
package/src/index.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* What a bundle may import, by specifier
|
|
3
|
-
*
|
|
4
|
-
* At least React, React Native and React's JSX
|
|
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
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
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
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
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,
|
|
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
|
-
|
|
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)(
|