@tileflow/react-native 0.0.0-bootstrap.0 → 0.1.0-alpha.1
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 +216 -4
- package/TileflowNativeAdmission.podspec +34 -0
- package/android/build.gradle +43 -0
- package/android/src/main/AndroidManifest.xml +3 -0
- package/android/src/main/java/dev/tileflow/reactnative/AdmissionBootstrap.kt +144 -0
- package/android/src/main/java/dev/tileflow/reactnative/AdmissionBootstrapOkHttpNetwork.kt +89 -0
- package/android/src/main/java/dev/tileflow/reactnative/AdmissionCatalog.kt +137 -0
- package/android/src/main/java/dev/tileflow/reactnative/AdmissionDocumentScope.kt +22 -0
- package/android/src/main/java/dev/tileflow/reactnative/AdmissionEngine.kt +335 -0
- package/android/src/main/java/dev/tileflow/reactnative/AdmissionModuleProvider.kt +68 -0
- package/android/src/main/java/dev/tileflow/reactnative/AdmissionOkHttpNetwork.kt +86 -0
- package/android/src/main/java/dev/tileflow/reactnative/AdmissionProviderLease.kt +56 -0
- package/android/src/main/java/dev/tileflow/reactnative/AdmissionTypes.kt +85 -0
- package/android/src/main/java/dev/tileflow/reactnative/AdmissionUrl.kt +100 -0
- package/android/src/main/java/dev/tileflow/reactnative/HandlerAdmissionScheduler.kt +16 -0
- package/android/src/main/java/dev/tileflow/reactnative/MobileConfiguration.kt +95 -0
- package/android/src/main/java/dev/tileflow/reactnative/MobileConfigurationResources.kt +43 -0
- package/android/src/main/java/dev/tileflow/reactnative/NativeDocumentOkHttpNetwork.kt +101 -0
- package/android/src/main/java/dev/tileflow/reactnative/NativeDocumentRegistry.kt +136 -0
- package/android/src/main/java/dev/tileflow/reactnative/NativeSurfaceState.kt +115 -0
- package/android/src/main/java/dev/tileflow/reactnative/TileflowNativeAdmissionModule.kt +236 -0
- package/android/src/main/java/dev/tileflow/reactnative/TileflowNativeAdmissionPackage.kt +16 -0
- package/android/src/main/java/dev/tileflow/reactnative/TileflowNativeConfigurationModule.kt +43 -0
- package/android/src/main/java/dev/tileflow/reactnative/TileflowNativeDocumentsModule.kt +82 -0
- package/android/src/main/java/dev/tileflow/reactnative/TileflowNativeSurfaceModule.kt +277 -0
- package/android/src/main/res/raw/tileflow_configuration_keep.xml +3 -0
- package/dist/contract-DWs-lDPo.d.ts +144 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +6989 -0
- package/dist/internal/camera.d.ts +65 -0
- package/dist/internal/camera.js +325 -0
- package/dist/internal/hosted-binding.d.ts +18 -0
- package/dist/internal/hosted-binding.js +277 -0
- package/dist/internal/initial-view.d.ts +11 -0
- package/dist/internal/initial-view.js +8 -0
- package/dist/internal/interactions.d.ts +76 -0
- package/dist/internal/interactions.js +794 -0
- package/dist/internal/native-admission-bridge.d.ts +29 -0
- package/dist/internal/native-admission-bridge.js +351 -0
- package/dist/internal/native-admission.d.ts +78 -0
- package/dist/internal/native-admission.js +1614 -0
- package/dist/internal/native-appearance.d.ts +21 -0
- package/dist/internal/native-appearance.js +110 -0
- package/dist/internal/native-configuration-bridge.d.ts +9 -0
- package/dist/internal/native-configuration-bridge.js +343 -0
- package/dist/internal/session.d.ts +125 -0
- package/dist/internal/session.js +887 -0
- package/dist/internal/source-state.d.ts +11 -0
- package/dist/internal/source-state.js +26 -0
- package/dist/native-admission-contract-k7LKE1vW.d.ts +89 -0
- package/docs/native-admission.md +108 -0
- package/docs/native-configuration.md +210 -0
- package/docs/native-interactions.md +161 -0
- package/docs/native-location.md +148 -0
- package/ios/TFAdmissionBootstrap.h +17 -0
- package/ios/TFAdmissionBootstrap.mm +168 -0
- package/ios/TFAdmissionCatalog.h +13 -0
- package/ios/TFAdmissionCatalog.mm +193 -0
- package/ios/TFAdmissionDocumentScope.h +7 -0
- package/ios/TFAdmissionDocumentScope.mm +45 -0
- package/ios/TFAdmissionEngine.h +57 -0
- package/ios/TFAdmissionEngine.mm +371 -0
- package/ios/TFAdmissionInstallation.h +27 -0
- package/ios/TFAdmissionInstallation.mm +117 -0
- package/ios/TFAdmissionNetwork.h +16 -0
- package/ios/TFAdmissionNetwork.mm +268 -0
- package/ios/TFAdmissionURL.mm +116 -0
- package/ios/TFDocumentBounds.h +9 -0
- package/ios/TFDocumentBounds.mm +19 -0
- package/ios/TFMobileConfiguration.h +23 -0
- package/ios/TFMobileConfiguration.mm +139 -0
- package/ios/TFNativeAdmissionURLProtocol.mm +69 -0
- package/ios/TFNativeDocumentRegistry.h +28 -0
- package/ios/TFNativeDocumentRegistry.mm +193 -0
- package/ios/TFNativeDocumentURL.h +6 -0
- package/ios/TFNativeSurfaceState.h +28 -0
- package/ios/TFNativeSurfaceState.mm +128 -0
- package/ios/TileflowNativeAdmission.h +9 -0
- package/ios/TileflowNativeAdmission.mm +184 -0
- package/ios/TileflowNativeConfiguration.mm +41 -0
- package/ios/TileflowNativeDocuments.h +12 -0
- package/ios/TileflowNativeDocuments.mm +105 -0
- package/ios/TileflowNativeSurface.mm +403 -0
- package/ios/tileflow_native_admission.rb +45 -0
- package/package.json +51 -7
- package/react-native.config.cjs +13 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { HostedNativeSessionFetch } from './session.js';
|
|
2
|
+
import { N as NativeAdmissionEvent, a as NativeAdmissionResource, b as NativeContextAck, c as NativeAdmissionResult, d as NativeRemovalAck } from '../native-admission-contract-k7LKE1vW.js';
|
|
3
|
+
|
|
4
|
+
declare function createReactNativeAdmissionTransport(): Readonly<{
|
|
5
|
+
bridge: Readonly<{
|
|
6
|
+
subscribe(listener: (event: NativeAdmissionEvent) => void): () => void;
|
|
7
|
+
install(): Promise<Readonly<{
|
|
8
|
+
installation: string;
|
|
9
|
+
}>>;
|
|
10
|
+
registerContext(installation: string, registration: Readonly<{
|
|
11
|
+
mapId: string | null;
|
|
12
|
+
resources: readonly NativeAdmissionResource[];
|
|
13
|
+
}>): Promise<NativeContextAck>;
|
|
14
|
+
extendContext?(installation: string, context: string, resources: readonly NativeAdmissionResource[]): Promise<Readonly<{
|
|
15
|
+
resources: number;
|
|
16
|
+
}>>;
|
|
17
|
+
retireContext(installation: string, context: string): Promise<Readonly<{
|
|
18
|
+
retired: true;
|
|
19
|
+
}>>;
|
|
20
|
+
completeBatch(installation: string, context: string, generation: number, batch: string, results: readonly NativeAdmissionResult[]): Promise<Readonly<{
|
|
21
|
+
accepted: number;
|
|
22
|
+
}>>;
|
|
23
|
+
remove(installation: string): Promise<NativeRemovalAck>;
|
|
24
|
+
}>;
|
|
25
|
+
fetchForContext: (context: string) => HostedNativeSessionFetch;
|
|
26
|
+
subscribeLifecycle(listener: (foreground: boolean) => void): () => void;
|
|
27
|
+
}>;
|
|
28
|
+
|
|
29
|
+
export { createReactNativeAdmissionTransport };
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
|
|
5
|
+
// src/native-admission-bridge.ts
|
|
6
|
+
import { NativeEventEmitter, NativeModules } from "react-native";
|
|
7
|
+
|
|
8
|
+
// src/native-admission-url.ts
|
|
9
|
+
import {
|
|
10
|
+
resolveTileflowNativeManifestUrl,
|
|
11
|
+
resolveTileflowNativeResourceUrl
|
|
12
|
+
} from "@tileflow/core/native";
|
|
13
|
+
|
|
14
|
+
// src/native-admission-contract.ts
|
|
15
|
+
var nativeAdmissionLimits = Object.freeze({
|
|
16
|
+
contexts: 16,
|
|
17
|
+
resources: 128,
|
|
18
|
+
queueDepth: 128,
|
|
19
|
+
batchSize: 8,
|
|
20
|
+
urlCharacters: 2048,
|
|
21
|
+
bridgeBytes: 524288,
|
|
22
|
+
grantCharacters: 24576,
|
|
23
|
+
waitMs: 3e4,
|
|
24
|
+
validitySafetyMs: 1e3,
|
|
25
|
+
redirects: 3,
|
|
26
|
+
responseBytes: 8388608
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// src/native-admission-url.ts
|
|
30
|
+
var isNativeToken = (value) => typeof value === "string" && /^[A-Za-z0-9_.-]{1,96}$/u.test(value) && !value.startsWith("tf_");
|
|
31
|
+
|
|
32
|
+
// src/native-admission-owner.ts
|
|
33
|
+
var NativeAdmissionError = class extends Error {
|
|
34
|
+
constructor(code) {
|
|
35
|
+
super("Native resource admission failed.");
|
|
36
|
+
__publicField(this, "code");
|
|
37
|
+
this.name = "NativeAdmissionError";
|
|
38
|
+
this.code = code;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// src/native-bootstrap-contract.ts
|
|
43
|
+
var nativeBootstrapLimits = Object.freeze({
|
|
44
|
+
queueDepth: 32,
|
|
45
|
+
requestBytes: 2048,
|
|
46
|
+
responseBytes: 65536,
|
|
47
|
+
timeoutMs: 3e4
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// src/native-admission-wire.ts
|
|
51
|
+
var unavailable = () => new NativeAdmissionError("NATIVE_ADMISSION_UNAVAILABLE");
|
|
52
|
+
var invalid = () => new NativeAdmissionError("NATIVE_ADMISSION_INVALID");
|
|
53
|
+
var cancelled = () => new NativeAdmissionError("NATIVE_ADMISSION_CANCELLED");
|
|
54
|
+
function decodeBoundedBase64(value) {
|
|
55
|
+
if (typeof value !== "string" || value.length > Math.ceil(nativeBootstrapLimits.responseBytes / 3) * 4 || !/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/u.test(value))
|
|
56
|
+
throw invalid();
|
|
57
|
+
const padding = value.endsWith("==") ? 2 : value.endsWith("=") ? 1 : 0;
|
|
58
|
+
const length = value.length / 4 * 3 - padding;
|
|
59
|
+
if (length > nativeBootstrapLimits.responseBytes) throw invalid();
|
|
60
|
+
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
61
|
+
const bytes = new Uint8Array(length);
|
|
62
|
+
let offset = 0;
|
|
63
|
+
for (let index = 0; index < value.length; index += 4) {
|
|
64
|
+
const a = alphabet.indexOf(value[index]);
|
|
65
|
+
const b = alphabet.indexOf(value[index + 1]);
|
|
66
|
+
const c = value[index + 2] === "=" ? 0 : alphabet.indexOf(value[index + 2]);
|
|
67
|
+
const d = value[index + 3] === "=" ? 0 : alphabet.indexOf(value[index + 3]);
|
|
68
|
+
if (index + 4 === value.length && (padding === 2 && (b & 15) !== 0 || padding === 1 && (c & 3) !== 0))
|
|
69
|
+
throw invalid();
|
|
70
|
+
const word = a * 262144 + b * 4096 + c * 64 + d;
|
|
71
|
+
if (offset < length) bytes[offset++] = word >>> 16 & 255;
|
|
72
|
+
if (offset < length) bytes[offset++] = word >>> 8 & 255;
|
|
73
|
+
if (offset < length) bytes[offset++] = word & 255;
|
|
74
|
+
}
|
|
75
|
+
return bytes;
|
|
76
|
+
}
|
|
77
|
+
function responseFromWire(reply, isAborted, release) {
|
|
78
|
+
if (!reply || !Number.isInteger(reply.status) || reply.status < 100 || reply.status > 599 || typeof reply.cacheControl !== "string" || reply.cacheControl.length > 1024)
|
|
79
|
+
throw invalid();
|
|
80
|
+
const status = reply.status;
|
|
81
|
+
const cacheControl = reply.cacheControl;
|
|
82
|
+
let bytes = decodeBoundedBase64(reply.bodyBase64);
|
|
83
|
+
let readerTaken = false;
|
|
84
|
+
let done = false;
|
|
85
|
+
const clear = () => {
|
|
86
|
+
bytes.fill(0);
|
|
87
|
+
bytes = new Uint8Array(0);
|
|
88
|
+
done = true;
|
|
89
|
+
release();
|
|
90
|
+
};
|
|
91
|
+
const response = Object.freeze({
|
|
92
|
+
status,
|
|
93
|
+
headers: Object.freeze({
|
|
94
|
+
get(name) {
|
|
95
|
+
return name.toLowerCase() === "cache-control" ? cacheControl : null;
|
|
96
|
+
}
|
|
97
|
+
}),
|
|
98
|
+
body: Object.freeze({
|
|
99
|
+
getReader() {
|
|
100
|
+
if (readerTaken) throw invalid();
|
|
101
|
+
readerTaken = true;
|
|
102
|
+
return Object.freeze({
|
|
103
|
+
async read() {
|
|
104
|
+
if (isAborted()) {
|
|
105
|
+
clear();
|
|
106
|
+
throw cancelled();
|
|
107
|
+
}
|
|
108
|
+
if (done) return { done: true };
|
|
109
|
+
done = true;
|
|
110
|
+
const value = bytes;
|
|
111
|
+
bytes = new Uint8Array(0);
|
|
112
|
+
release();
|
|
113
|
+
return { done: false, value };
|
|
114
|
+
},
|
|
115
|
+
cancel: clear
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
})
|
|
119
|
+
});
|
|
120
|
+
return { response, clear };
|
|
121
|
+
}
|
|
122
|
+
function createNativeAdmissionWire(native, listen) {
|
|
123
|
+
let installation = null;
|
|
124
|
+
let sequence = 0;
|
|
125
|
+
const reservations = /* @__PURE__ */ new Set();
|
|
126
|
+
const lifecycle = /* @__PURE__ */ new Set();
|
|
127
|
+
async function safe(action) {
|
|
128
|
+
try {
|
|
129
|
+
return await action();
|
|
130
|
+
} catch {
|
|
131
|
+
throw unavailable();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
function retireContext(context) {
|
|
135
|
+
const gate = installation?.contexts.get(context);
|
|
136
|
+
if (!gate) return;
|
|
137
|
+
gate.live = false;
|
|
138
|
+
for (const abort of [...gate.cancel]) abort();
|
|
139
|
+
installation?.contexts.delete(context);
|
|
140
|
+
}
|
|
141
|
+
function retireInstallation() {
|
|
142
|
+
if (!installation) return;
|
|
143
|
+
for (const context of [...installation.contexts.keys()]) retireContext(context);
|
|
144
|
+
installation = null;
|
|
145
|
+
}
|
|
146
|
+
function publishLifecycle(foreground) {
|
|
147
|
+
for (const listener of [...lifecycle]) {
|
|
148
|
+
try {
|
|
149
|
+
listener(foreground);
|
|
150
|
+
} catch {
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
const bridge = Object.freeze({
|
|
155
|
+
subscribe(listener) {
|
|
156
|
+
return listen((event) => {
|
|
157
|
+
if (event && event.installation === installation?.id) {
|
|
158
|
+
if (event.kind === "retired") retireContext(event.context);
|
|
159
|
+
if (event.kind === "ownershipLost") retireInstallation();
|
|
160
|
+
if (event.kind === "lifecycle") {
|
|
161
|
+
if (!event.foreground) {
|
|
162
|
+
for (const gate of installation?.contexts.values() ?? [])
|
|
163
|
+
for (const abort of [...gate.cancel]) abort();
|
|
164
|
+
}
|
|
165
|
+
publishLifecycle(event.foreground === true);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
listener(event);
|
|
169
|
+
});
|
|
170
|
+
},
|
|
171
|
+
async install() {
|
|
172
|
+
const ack = await safe(() => native.install());
|
|
173
|
+
if (!ack || !isNativeToken(ack.installation)) throw invalid();
|
|
174
|
+
retireInstallation();
|
|
175
|
+
installation = { id: ack.installation, contexts: /* @__PURE__ */ new Map() };
|
|
176
|
+
return Object.freeze({ installation: ack.installation });
|
|
177
|
+
},
|
|
178
|
+
registerContext: (id, registration) => safe(() => native.registerContext(id, registration)),
|
|
179
|
+
extendContext: (id, context, resources) => safe(() => {
|
|
180
|
+
if (!native.extendContext) throw unavailable();
|
|
181
|
+
return native.extendContext(id, context, resources);
|
|
182
|
+
}),
|
|
183
|
+
retireContext(id, context) {
|
|
184
|
+
if (id === installation?.id) retireContext(context);
|
|
185
|
+
return safe(() => native.retireContext(id, context));
|
|
186
|
+
},
|
|
187
|
+
completeBatch: (id, context, generation, batch, results) => safe(() => native.completeBatch(id, context, generation, batch, results)),
|
|
188
|
+
remove(id) {
|
|
189
|
+
if (id === installation?.id) retireInstallation();
|
|
190
|
+
return safe(() => native.remove(id));
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
function fetchForContext(context) {
|
|
194
|
+
const installed = installation;
|
|
195
|
+
if (!installed || !isNativeToken(context)) throw invalid();
|
|
196
|
+
let gate = installed.contexts.get(context);
|
|
197
|
+
if (!gate) {
|
|
198
|
+
if (installed.contexts.size >= nativeAdmissionLimits.contexts) throw unavailable();
|
|
199
|
+
gate = { live: true, cancel: /* @__PURE__ */ new Set() };
|
|
200
|
+
installed.contexts.set(context, gate);
|
|
201
|
+
}
|
|
202
|
+
const scope = gate;
|
|
203
|
+
return (url, init) => {
|
|
204
|
+
const active = () => installation === installed && scope.live && !init.signal.aborted;
|
|
205
|
+
if (!active()) return Promise.reject(cancelled());
|
|
206
|
+
if (reservations.size >= nativeBootstrapLimits.queueDepth)
|
|
207
|
+
return Promise.reject(unavailable());
|
|
208
|
+
const credential = init.headers["X-Tileflow-Mobile-Client"];
|
|
209
|
+
if (init.method !== "POST" || init.credentials !== "omit" || typeof init.body !== "string" || init.body.length > nativeBootstrapLimits.requestBytes || typeof credential !== "string" || !/^tf_public_[0-9a-f]{48}$/u.test(credential) || sequence >= Number.MAX_SAFE_INTEGER)
|
|
210
|
+
return Promise.reject(invalid());
|
|
211
|
+
const request = `${installed.id}.${++sequence}`;
|
|
212
|
+
reservations.add(request);
|
|
213
|
+
return new Promise((resolve, reject) => {
|
|
214
|
+
let settled = false;
|
|
215
|
+
let aborted = false;
|
|
216
|
+
let dispatched = false;
|
|
217
|
+
let nativeFinished = false;
|
|
218
|
+
let bodyFinished = true;
|
|
219
|
+
let clearBody;
|
|
220
|
+
const cleanup = () => init.signal.removeEventListener("abort", abort);
|
|
221
|
+
const release = () => {
|
|
222
|
+
if (!nativeFinished || !bodyFinished) return;
|
|
223
|
+
reservations.delete(request);
|
|
224
|
+
scope.cancel.delete(abort);
|
|
225
|
+
cleanup();
|
|
226
|
+
clearBody = void 0;
|
|
227
|
+
};
|
|
228
|
+
const abort = () => {
|
|
229
|
+
if (aborted) return;
|
|
230
|
+
aborted = true;
|
|
231
|
+
cleanup();
|
|
232
|
+
clearBody?.();
|
|
233
|
+
bodyFinished = true;
|
|
234
|
+
if (dispatched && !nativeFinished)
|
|
235
|
+
void safe(() => native.cancelBootstrap(installed.id, context, request)).catch(
|
|
236
|
+
() => void 0
|
|
237
|
+
);
|
|
238
|
+
if (!settled) {
|
|
239
|
+
settled = true;
|
|
240
|
+
reject(cancelled());
|
|
241
|
+
}
|
|
242
|
+
release();
|
|
243
|
+
};
|
|
244
|
+
scope.cancel.add(abort);
|
|
245
|
+
init.signal.addEventListener("abort", abort, { once: true });
|
|
246
|
+
if (!active()) {
|
|
247
|
+
nativeFinished = true;
|
|
248
|
+
abort();
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
let pending;
|
|
252
|
+
try {
|
|
253
|
+
dispatched = true;
|
|
254
|
+
pending = Promise.resolve(
|
|
255
|
+
native.bootstrap(installed.id, context, request, url, credential, init.body)
|
|
256
|
+
);
|
|
257
|
+
} catch {
|
|
258
|
+
nativeFinished = true;
|
|
259
|
+
settled = true;
|
|
260
|
+
cleanup();
|
|
261
|
+
release();
|
|
262
|
+
reject(unavailable());
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
pending.then(
|
|
266
|
+
(reply) => {
|
|
267
|
+
nativeFinished = true;
|
|
268
|
+
if (settled) {
|
|
269
|
+
release();
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
if (!active()) {
|
|
273
|
+
abort();
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
settled = true;
|
|
277
|
+
try {
|
|
278
|
+
const result = responseFromWire(
|
|
279
|
+
reply,
|
|
280
|
+
() => aborted || !active(),
|
|
281
|
+
() => {
|
|
282
|
+
bodyFinished = true;
|
|
283
|
+
release();
|
|
284
|
+
}
|
|
285
|
+
);
|
|
286
|
+
bodyFinished = false;
|
|
287
|
+
clearBody = result.clear;
|
|
288
|
+
resolve(result.response);
|
|
289
|
+
} catch {
|
|
290
|
+
release();
|
|
291
|
+
reject(invalid());
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
() => {
|
|
295
|
+
nativeFinished = true;
|
|
296
|
+
if (!settled) {
|
|
297
|
+
settled = true;
|
|
298
|
+
cleanup();
|
|
299
|
+
reject(unavailable());
|
|
300
|
+
}
|
|
301
|
+
release();
|
|
302
|
+
}
|
|
303
|
+
);
|
|
304
|
+
});
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
return Object.freeze({
|
|
308
|
+
bridge,
|
|
309
|
+
fetchForContext,
|
|
310
|
+
subscribeLifecycle(listener) {
|
|
311
|
+
if (typeof listener !== "function") throw invalid();
|
|
312
|
+
lifecycle.add(listener);
|
|
313
|
+
let live = true;
|
|
314
|
+
return () => {
|
|
315
|
+
if (!live) return;
|
|
316
|
+
live = false;
|
|
317
|
+
lifecycle.delete(listener);
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// src/native-admission-bridge.ts
|
|
324
|
+
function createReactNativeAdmissionTransport() {
|
|
325
|
+
const module = NativeModules.TileflowNativeAdmission;
|
|
326
|
+
for (const name of [
|
|
327
|
+
"install",
|
|
328
|
+
"registerContext",
|
|
329
|
+
"retireContext",
|
|
330
|
+
"completeBatch",
|
|
331
|
+
"remove",
|
|
332
|
+
"bootstrap",
|
|
333
|
+
"cancelBootstrap",
|
|
334
|
+
"addListener",
|
|
335
|
+
"removeListeners"
|
|
336
|
+
]) {
|
|
337
|
+
if (!module || typeof module[name] !== "function")
|
|
338
|
+
throw new NativeAdmissionError("NATIVE_ADMISSION_UNAVAILABLE");
|
|
339
|
+
}
|
|
340
|
+
const emitter = new NativeEventEmitter(module);
|
|
341
|
+
return createNativeAdmissionWire(module, (listener) => {
|
|
342
|
+
const subscription = emitter.addListener(
|
|
343
|
+
"TileflowNativeAdmissionEvent",
|
|
344
|
+
(event) => listener(event)
|
|
345
|
+
);
|
|
346
|
+
return () => subscription.remove();
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
export {
|
|
350
|
+
createReactNativeAdmissionTransport
|
|
351
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { e as NativeAdmissionCode, a as NativeAdmissionResource, f as NativeAdmissionBridge, d as NativeRemovalAck } from '../native-admission-contract-k7LKE1vW.js';
|
|
2
|
+
import { HostedNativeResourcePolicy, createHostedNativeSessionController, HostedNativeSessionFetch, HostedNativeSessionController } from './session.js';
|
|
3
|
+
|
|
4
|
+
type SessionInput = Parameters<typeof createHostedNativeSessionController>[0];
|
|
5
|
+
type NativeMapAdmissionInput = Omit<SessionInput, 'fetch' | 'sessionIdFactory'> & Readonly<{
|
|
6
|
+
fetch?: HostedNativeSessionFetch;
|
|
7
|
+
sessionIdFactory?: () => string;
|
|
8
|
+
resources: readonly NativeAdmissionResource[];
|
|
9
|
+
onRetired?: () => void;
|
|
10
|
+
}>;
|
|
11
|
+
type NativeMapAdmission = Readonly<{
|
|
12
|
+
context: string;
|
|
13
|
+
generation: number;
|
|
14
|
+
scope: Readonly<{
|
|
15
|
+
installation: string;
|
|
16
|
+
context: string;
|
|
17
|
+
}>;
|
|
18
|
+
readonly state: Readonly<{
|
|
19
|
+
status: 'active' | 'retired';
|
|
20
|
+
context: string;
|
|
21
|
+
}>;
|
|
22
|
+
prepare(): Promise<HostedNativeResourcePolicy | null>;
|
|
23
|
+
discriminate(url: string): string;
|
|
24
|
+
discriminateForTest(url: string): string;
|
|
25
|
+
extendResources(resources: readonly NativeAdmissionResource[]): Promise<Readonly<{
|
|
26
|
+
resources: number;
|
|
27
|
+
}>>;
|
|
28
|
+
retire(): Promise<Readonly<{
|
|
29
|
+
retired: true;
|
|
30
|
+
}>>;
|
|
31
|
+
}>;
|
|
32
|
+
declare class NativeAdmissionError extends Error {
|
|
33
|
+
readonly code: NativeAdmissionCode;
|
|
34
|
+
constructor(code: NativeAdmissionCode);
|
|
35
|
+
}
|
|
36
|
+
declare function createNativeAdmissionOwner(options: {
|
|
37
|
+
bridge: NativeAdmissionBridge;
|
|
38
|
+
sessionFetch?: (context: string) => HostedNativeSessionFetch;
|
|
39
|
+
createController?: (input: SessionInput) => HostedNativeSessionController;
|
|
40
|
+
onObservation?: (observation: Readonly<{
|
|
41
|
+
context: string;
|
|
42
|
+
status: number;
|
|
43
|
+
}>) => void;
|
|
44
|
+
}): Readonly<{
|
|
45
|
+
install: () => Promise<Readonly<{
|
|
46
|
+
installation: string;
|
|
47
|
+
}>>;
|
|
48
|
+
openMap: (input: NativeMapAdmissionInput) => Promise<NativeMapAdmission>;
|
|
49
|
+
replaceMap(previous: NativeMapAdmission, input: NativeMapAdmissionInput): Promise<Readonly<{
|
|
50
|
+
context: string;
|
|
51
|
+
generation: number;
|
|
52
|
+
scope: Readonly<{
|
|
53
|
+
installation: string;
|
|
54
|
+
context: string;
|
|
55
|
+
}>;
|
|
56
|
+
readonly state: Readonly<{
|
|
57
|
+
status: "active" | "retired";
|
|
58
|
+
context: string;
|
|
59
|
+
}>;
|
|
60
|
+
prepare(): Promise<HostedNativeResourcePolicy | null>;
|
|
61
|
+
discriminate(url: string): string;
|
|
62
|
+
discriminateForTest(url: string): string;
|
|
63
|
+
extendResources(resources: readonly NativeAdmissionResource[]): Promise<Readonly<{
|
|
64
|
+
resources: number;
|
|
65
|
+
}>>;
|
|
66
|
+
retire(): Promise<Readonly<{
|
|
67
|
+
retired: true;
|
|
68
|
+
}>>;
|
|
69
|
+
}>>;
|
|
70
|
+
dispose: () => Promise<NativeRemovalAck>;
|
|
71
|
+
readonly state: Readonly<{
|
|
72
|
+
status: "ready" | "error" | "disposed" | "idle" | "installing";
|
|
73
|
+
contexts: number;
|
|
74
|
+
pendingRegistrations: number;
|
|
75
|
+
}>;
|
|
76
|
+
}>;
|
|
77
|
+
|
|
78
|
+
export { NativeAdmissionError, type NativeMapAdmission, type NativeMapAdmissionInput, createNativeAdmissionOwner };
|