@absolutejs/absolute 0.20.0-beta.179 → 0.20.0-beta.180

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.
Files changed (125) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/changelog.json +45 -0
  3. package/dist/angular/browser.js +2 -2
  4. package/dist/angular/browser.js.map +3 -3
  5. package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
  6. package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
  7. package/dist/angular/index.js +21 -6
  8. package/dist/angular/index.js.map +6 -6
  9. package/dist/angular/server.js +21 -6
  10. package/dist/angular/server.js.map +6 -6
  11. package/dist/build.js +5357 -4945
  12. package/dist/build.js.map +27 -24
  13. package/dist/cli/build-fntmf42w.js +495 -0
  14. package/dist/cli/{buildDepVendor-qvsh6dsj.js → buildDepVendor-qnwfct22.js} +5 -3
  15. package/dist/cli/buildReactServerComponents-fq6mw10d.js +13 -0
  16. package/dist/cli/{compile-p5yv6ecp.js → compile-54rb8szn.js} +94 -125
  17. package/dist/cli/config/server.js +10 -5
  18. package/dist/cli/{dev-2hbcsvkp.js → dev-6s6g5tnk.js} +13 -14
  19. package/dist/cli/{expoProject-1qtw97js.js → expoProject-acgfaj3f.js} +2 -1
  20. package/dist/cli/generatedDir-239r7csr.js +9 -0
  21. package/dist/cli/{index-cksezef8.js → index-0gd30trc.js} +105 -851
  22. package/dist/cli/index-2wvysvjc.js +40 -0
  23. package/dist/cli/index-42xjh6gg.js +282 -0
  24. package/dist/cli/{index-qw98g1p6.js → index-47e8fwha.js} +4 -1
  25. package/dist/cli/index-65kqn88a.js +8 -0
  26. package/dist/cli/{index-2bxfhs32.js → index-6f448d7m.js} +0 -26
  27. package/dist/cli/index-972xxwgj.js +16 -0
  28. package/dist/cli/index-aqe25w4h.js +39 -0
  29. package/dist/cli/index-assqancr.js +51 -0
  30. package/dist/cli/{index-2shf4aya.js → index-c8rcfe5a.js} +4 -6
  31. package/dist/cli/index-cba1cemz.js +8 -0
  32. package/dist/cli/{index-3ff5ztt3.js → index-djkrb7pc.js} +1 -7
  33. package/dist/cli/index-dkfwkpc8.js +138 -0
  34. package/dist/cli/{index-92g14j47.js → index-dw44xa4x.js} +2 -1
  35. package/dist/cli/index-evsnq0n2.js +17 -0
  36. package/dist/cli/index-fxwf3n2v.js +224 -0
  37. package/dist/cli/{index-zyd80s3h.js → index-js2hksgv.js} +21 -295
  38. package/dist/cli/{index-bp60baze.js → index-jyap0bhv.js} +1 -1
  39. package/dist/cli/{index-9dzdbbfc.js → index-kx2d067c.js} +8 -6
  40. package/dist/cli/index-pb31zan6.js +9 -0
  41. package/dist/cli/index-sq0478b0.js +281 -0
  42. package/dist/cli/index-va274tsf.js +7 -0
  43. package/dist/cli/{index-yd672jyq.js → index-w6xsk8cv.js} +4 -1
  44. package/dist/cli/index-w79snsxv.js +461 -0
  45. package/dist/cli/index-x1vvn549.js +835 -0
  46. package/dist/cli/index-xf9sfr8a.js +243 -0
  47. package/dist/cli/index-ycqdxy55.js +754 -0
  48. package/dist/cli/index-z74cqxz0.js +131 -0
  49. package/dist/cli/index.js +10 -9
  50. package/dist/cli/{islands-6zgb7501.js → islands-17tfx8jf.js} +6 -17
  51. package/dist/cli/{ls-0hfx323m.js → ls-0wr74w0b.js} +10 -58
  52. package/dist/cli/{mobile-93vaawcz.js → mobile-hpqpy61f.js} +11 -8
  53. package/dist/cli/{prerender-010z771p.js → prerender-w65xp6h8.js} +2 -1
  54. package/dist/cli/{rewriteImports-z6629aww.js → rewriteImports-np2d2kvc.js} +4 -11
  55. package/dist/cli/rewriteImportsPlugin-c6hcb3x6.js +12 -0
  56. package/dist/cli/{start-asxb79rc.js → start-mbn2zgs2.js} +6 -4
  57. package/dist/cli/staticAnalyzeSpaRoutes-2nev05m1.js +8 -0
  58. package/dist/cli/staticAnalyzeSpaRoutes-6vgzp0rs.js +8 -0
  59. package/dist/cli/staticAnalyzeSpaRoutes-f85q9dqk.js +8 -0
  60. package/dist/cli/staticAnalyzeSpaRoutes-yakmg22g.js +7 -0
  61. package/dist/cli/{typecheck-m2j4tkdk.js → typecheck-488txsfc.js} +92 -18
  62. package/dist/cli/vueCompiler-8bzdmf08.js +7 -0
  63. package/dist/client/chunks/{react-khr6ewhr.js → react-g8r290b8.js} +37 -2
  64. package/dist/client/chunks/react-g8r290b8.js.map +10 -0
  65. package/dist/client/chunks/vue-zcpmka32.js +85 -0
  66. package/dist/client/chunks/vue-zcpmka32.js.map +10 -0
  67. package/dist/client/index.js +58 -10
  68. package/dist/client/index.js.map +4 -4
  69. package/dist/dev/client/handlers/vue.ts +116 -0
  70. package/dist/index.js +2472 -2058
  71. package/dist/index.js.map +26 -23
  72. package/dist/islands/browser.js +2 -2
  73. package/dist/islands/browser.js.map +3 -3
  74. package/dist/islands/index.js +2 -2
  75. package/dist/islands/index.js.map +3 -3
  76. package/dist/react/browser.js +2 -2
  77. package/dist/react/browser.js.map +3 -3
  78. package/dist/react/index.js +42 -11
  79. package/dist/react/index.js.map +10 -10
  80. package/dist/react/server.js +42 -11
  81. package/dist/react/server.js.map +10 -10
  82. package/dist/src/angular/ssrRender.d.ts +2 -2
  83. package/dist/src/angular/staticAnalyzeSpaRoutes.d.ts +6 -1
  84. package/dist/src/build/generateManifest.d.ts +15 -0
  85. package/dist/src/build/manifestKeys.d.ts +22 -0
  86. package/dist/src/cli/add/dependencies.d.ts +1 -1
  87. package/dist/src/cli/scripts/typecheck.d.ts +11 -0
  88. package/dist/src/client/hydrators/react.d.ts +10 -0
  89. package/dist/src/client/hydrators/vue.d.ts +13 -0
  90. package/dist/src/client/islandRuntime.d.ts +1 -1
  91. package/dist/src/core/islandManifest.d.ts +4 -0
  92. package/dist/src/core/islandPageContext.d.ts +8 -2
  93. package/dist/src/core/lookup.d.ts +16 -1
  94. package/dist/src/dev/importCost/instrument.d.ts +1 -1
  95. package/dist/src/dev/manifestKeysRefresher.d.ts +6 -0
  96. package/dist/src/dev/spaRouteRefresh.d.ts +13 -0
  97. package/dist/src/mobile/androidConformance.d.ts +1 -1
  98. package/dist/src/react/staticAnalyzeSpaRoutes.d.ts +6 -1
  99. package/dist/src/svelte/staticAnalyzeSpaRoutes.d.ts +1 -0
  100. package/dist/src/utils/logger.d.ts +5 -0
  101. package/dist/src/utils/spaRouteManifest.d.ts +1 -0
  102. package/dist/src/vue/components/Image.d.ts +4 -4
  103. package/dist/src/vue/components/StreamSlot.d.ts +1 -1
  104. package/dist/src/vue/components/SuspenseSlot.d.ts +2 -2
  105. package/dist/src/vue/staticAnalyzeSpaRoutes.d.ts +4 -0
  106. package/dist/svelte/browser.js +2 -2
  107. package/dist/svelte/browser.js.map +3 -3
  108. package/dist/svelte/index.js +25 -9
  109. package/dist/svelte/index.js.map +8 -8
  110. package/dist/svelte/server.js +25 -9
  111. package/dist/svelte/server.js.map +8 -8
  112. package/dist/types/globals.d.ts +4 -0
  113. package/dist/types/index.d.ts +1 -0
  114. package/dist/types/island.d.ts +1 -1
  115. package/dist/types/manifest.d.ts +25 -0
  116. package/dist/vue/browser.js +2 -2
  117. package/dist/vue/browser.js.map +3 -3
  118. package/dist/vue/index.js +21 -6
  119. package/dist/vue/index.js.map +6 -6
  120. package/dist/vue/server.js +21 -6
  121. package/dist/vue/server.js.map +6 -6
  122. package/package.json +1 -1
  123. package/dist/client/chunks/react-khr6ewhr.js.map +0 -10
  124. package/dist/client/chunks/vue-db6ppn1f.js +0 -32
  125. package/dist/client/chunks/vue-db6ppn1f.js.map +0 -10
@@ -10,8 +10,10 @@ import {
10
10
  resolveAbsoluteMobileAuthManifest2
11
11
  } from "./index-pch0v1z6.js";
12
12
  import {
13
- lazyTypescript
14
- } from "./index-4j1twret.js";
13
+ discoverAbsoluteSyncSchema,
14
+ absoluteDeviceNativeRequirements,
15
+ resolveAbsoluteDeviceCapabilityPlan
16
+ } from "./index-ycqdxy55.js";
15
17
 
16
18
  // src/mobile/expoProject.ts
17
19
  import {
@@ -25,7 +27,7 @@ import {
25
27
  writeFile as writeFile2
26
28
  } from "fs/promises";
27
29
  import { createHash as createHash3 } from "crypto";
28
- import { basename, dirname as dirname4, join as join8, relative as relative3, resolve as resolve5, sep } from "path";
30
+ import { basename, dirname as dirname3, join as join6, relative as relative2, resolve as resolve3, sep } from "path";
29
31
 
30
32
  // src/mobile/nativePackages.ts
31
33
  import { readFile } from "fs/promises";
@@ -100,754 +102,6 @@ var packagesNeedingExactInstall = async (projectRoot, specs, installed, exactPac
100
102
  return spec;
101
103
  }))).filter((spec) => spec !== undefined);
102
104
 
103
- // src/mobile/syncSchema.ts
104
- import { readFileSync } from "fs";
105
- import { dirname as dirname2, join as join2, resolve as resolve2 } from "path";
106
-
107
- // node_modules/@absolutejs/sync/dist/client/index.js
108
- var pools = new Map;
109
- class SyncLocalDataPolicyError extends Error {
110
- code;
111
- constructor(code, message) {
112
- super(message);
113
- this.name = "SyncLocalDataPolicyError";
114
- this.code = code;
115
- }
116
- }
117
-
118
- class SyncLocalStoreSchemaError extends Error {
119
- code;
120
- storedVersion;
121
- targetVersion;
122
- constructor(code, message, versions = {}) {
123
- super(message);
124
- this.name = "SyncLocalStoreSchemaError";
125
- this.code = code;
126
- this.storedVersion = versions.storedVersion;
127
- this.targetVersion = versions.targetVersion;
128
- }
129
- }
130
- var positiveVersion = (value, label) => {
131
- if (!Number.isSafeInteger(value) || value < 1)
132
- throw new SyncLocalStoreSchemaError("INVALID_PLAN", `${label} must be a positive safe integer`);
133
- return value;
134
- };
135
- var isSchemaBundle = (schema) => ("components" in schema);
136
- var validatePolicyMatch = (match, label) => {
137
- if (match.length === 0 || match.trim() !== match || /^\*+$/.test(match) || match.includes("**"))
138
- throw new SyncLocalDataPolicyError("INVALID_POLICY", `${label}.match must be an exact name or a non-empty glob without adjacent wildcards.`);
139
- };
140
- var validateSyncLocalDataPolicy = (policy, label = "localData") => {
141
- if (policy.maxBytesPerNamespace !== undefined && (!Number.isSafeInteger(policy.maxBytesPerNamespace) || policy.maxBytesPerNamespace < 1))
142
- throw new SyncLocalDataPolicyError("INVALID_POLICY", `${label}.maxBytesPerNamespace must be a positive safe integer.`);
143
- for (const [index, rule] of (policy.collections ?? []).entries()) {
144
- validatePolicyMatch(rule.match, `${label}.collections[${index}]`);
145
- if (rule.maxAgeMs !== undefined && (!Number.isSafeInteger(rule.maxAgeMs) || rule.maxAgeMs < 1))
146
- throw new SyncLocalDataPolicyError("INVALID_POLICY", `${label}.collections[${index}].maxAgeMs must be a positive safe integer.`);
147
- if (rule.persistence === "memory-only" && rule.protection === "required")
148
- throw new SyncLocalDataPolicyError("INVALID_POLICY", `${label}.collections[${index}] cannot require at-rest protection when it is memory-only.`);
149
- if (rule.sensitivity !== undefined && rule.sensitivity !== "public" && rule.protection !== "required" && rule.persistence !== "memory-only")
150
- throw new SyncLocalDataPolicyError("INVALID_POLICY", `${label}.collections[${index}] declares ${rule.sensitivity} data without required protection or memory-only persistence.`);
151
- }
152
- for (const [index, rule] of (policy.mutations ?? []).entries()) {
153
- validatePolicyMatch(rule.match, `${label}.mutations[${index}]`);
154
- if (rule.conflict !== undefined && rule.conflict.strategy !== "client-wins" && rule.conflict.strategy !== "manual" && rule.conflict.strategy !== "server-wins")
155
- throw new SyncLocalDataPolicyError("INVALID_POLICY", `${label}.mutations[${index}].conflict.strategy is invalid.`);
156
- if (rule.conflict?.maxAttempts !== undefined && (!Number.isSafeInteger(rule.conflict.maxAttempts) || rule.conflict.maxAttempts < 1))
157
- throw new SyncLocalDataPolicyError("INVALID_POLICY", `${label}.mutations[${index}].conflict.maxAttempts must be a positive safe integer.`);
158
- if (rule.conflict?.maxAttempts !== undefined && rule.conflict.strategy !== "client-wins")
159
- throw new SyncLocalDataPolicyError("INVALID_POLICY", `${label}.mutations[${index}].conflict.maxAttempts is only valid for client-wins.`);
160
- if (rule.persistence === "memory-only" && rule.protection === "required")
161
- throw new SyncLocalDataPolicyError("INVALID_POLICY", `${label}.mutations[${index}] cannot require at-rest protection when it is memory-only.`);
162
- if (rule.sensitivity !== undefined && rule.sensitivity !== "public" && rule.protection !== "required" && rule.persistence !== "memory-only")
163
- throw new SyncLocalDataPolicyError("INVALID_POLICY", `${label}.mutations[${index}] declares ${rule.sensitivity} arguments without required protection.`);
164
- }
165
- return policy;
166
- };
167
- var normalizeSyncLocalSchemaComponents = (schema = { version: 1 }) => {
168
- const components = isSchemaBundle(schema) ? [...schema.components] : [{ ...schema, id: "@absolutejs/app" }];
169
- const ids = new Set;
170
- for (const component of components) {
171
- if (typeof component.id !== "string" || component.id.trim() !== component.id || component.id.length === 0)
172
- throw new SyncLocalStoreSchemaError("INVALID_PLAN", "Sync schema component id must be non-empty and trimmed");
173
- if (ids.has(component.id))
174
- throw new SyncLocalStoreSchemaError("INVALID_PLAN", `Sync schema component "${component.id}" is declared more than once`);
175
- ids.add(component.id);
176
- if (component.localData)
177
- validateSyncLocalDataPolicy(component.localData, `${component.id}.localData`);
178
- }
179
- return components.sort((a, b) => a.id.localeCompare(b.id));
180
- };
181
- var resolveSyncLocalSchemaComponents = (storedVersions, schema = { version: 1 }) => {
182
- const components = normalizeSyncLocalSchemaComponents(schema).map((component) => {
183
- const current = resolveSyncLocalMigrations(component.version, component);
184
- return {
185
- id: component.id,
186
- ...resolveSyncLocalMigrations(storedVersions[component.id] ?? current.minimumCompatibleVersion, component)
187
- };
188
- });
189
- const active = new Set(components.map((component) => component.id));
190
- const orphanedComponents = Object.keys(storedVersions).filter((id) => !active.has(id)).sort();
191
- return { components, orphanedComponents };
192
- };
193
- var resolveSyncLocalMigrations = (storedVersion, schema = { version: 1 }) => {
194
- positiveVersion(storedVersion, "Stored Sync schema version");
195
- const targetVersion = positiveVersion(schema.version, "Target Sync schema version");
196
- const migrations = [...schema.migrations ?? []].sort((a, b) => a.toVersion - b.toVersion);
197
- const versions = new Set;
198
- for (const migration of migrations) {
199
- positiveVersion(migration.toVersion, "Sync migration toVersion");
200
- if (versions.has(migration.toVersion))
201
- throw new SyncLocalStoreSchemaError("INVALID_PLAN", `Sync migration ${migration.toVersion} is declared more than once`);
202
- versions.add(migration.toVersion);
203
- }
204
- const inferredMinimum = migrations[0] ? migrations[0].toVersion - 1 : targetVersion;
205
- const minimumCompatibleVersion = positiveVersion(schema.minimumCompatibleVersion ?? inferredMinimum, "Minimum compatible Sync schema version");
206
- if (minimumCompatibleVersion > targetVersion)
207
- throw new SyncLocalStoreSchemaError("INVALID_PLAN", "Minimum compatible Sync schema version cannot exceed its target");
208
- if (storedVersion > targetVersion)
209
- throw new SyncLocalStoreSchemaError("SCHEMA_TOO_NEW", `Stored Sync schema ${storedVersion} is newer than this runtime's schema ${targetVersion}`, { storedVersion, targetVersion });
210
- if (storedVersion < minimumCompatibleVersion)
211
- throw new SyncLocalStoreSchemaError("SCHEMA_TOO_OLD", `Stored Sync schema ${storedVersion} is older than the minimum compatible schema ${minimumCompatibleVersion}`, { storedVersion, targetVersion });
212
- const steps = [];
213
- for (let version = storedVersion + 1;version <= targetVersion; version++) {
214
- const migration = migrations.find((candidate) => candidate.toVersion === version);
215
- if (migration === undefined)
216
- throw new SyncLocalStoreSchemaError("MIGRATION_MISSING", `Sync migration ${version - 1} -> ${version} is missing`, { storedVersion, targetVersion });
217
- steps.push(migration);
218
- }
219
- return { minimumCompatibleVersion, steps, targetVersion };
220
- };
221
- var RUNTIME_TRANSPORT = Symbol.for("@absolutejs/sync/client-runtime-transport");
222
- var host = globalThis;
223
- var isRegistry = (value) => typeof value === "object" && value !== null && Array.isArray(Reflect.get(value, "installations")) && Array.isArray(Reflect.get(value, "clients"));
224
- var registry = (() => {
225
- const existing = host[RUNTIME_TRANSPORT];
226
- if (isRegistry(existing))
227
- return existing;
228
- if (typeof existing === "object" && existing !== null && Array.isArray(Reflect.get(existing, "installations"))) {
229
- Reflect.set(existing, "clients", []);
230
- return existing;
231
- }
232
- const created = { clients: [], installations: [] };
233
- Object.defineProperty(host, RUNTIME_TRANSPORT, {
234
- configurable: false,
235
- enumerable: false,
236
- value: created,
237
- writable: false
238
- });
239
- return created;
240
- })();
241
-
242
- // src/mobile/syncSchema.ts
243
- var object = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
244
- var manifestAt = (path) => {
245
- try {
246
- const value = JSON.parse(readFileSync(path, "utf8"));
247
- return object(value) ? value : undefined;
248
- } catch {
249
- return;
250
- }
251
- };
252
- var localSchemaMetadata = (manifest) => {
253
- const absolutejs = Reflect.get(manifest, "absolutejs");
254
- if (!object(absolutejs))
255
- return;
256
- const sync = Reflect.get(absolutejs, "sync");
257
- if (!object(sync))
258
- return;
259
- return Reflect.get(sync, "localSchema");
260
- };
261
- var packageManifestPath = (projectRoot, packageName) => {
262
- let directory = resolve2(projectRoot);
263
- while (true) {
264
- const candidate = join2(directory, "node_modules", packageName, "package.json");
265
- const manifest = manifestAt(candidate);
266
- if (manifest && Reflect.get(manifest, "name") === packageName)
267
- return candidate;
268
- const parent = dirname2(directory);
269
- if (parent === directory)
270
- return;
271
- directory = parent;
272
- }
273
- };
274
- var metadataError = (id, detail) => new TypeError(`Invalid AbsoluteJS Sync schema metadata for ${id}: ${detail}`);
275
- var positiveVersion2 = (value, id, field) => {
276
- if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 1)
277
- throw metadataError(id, `${field} must be a positive safe integer.`);
278
- return value;
279
- };
280
- var nonEmpty = (value, id, field) => {
281
- if (typeof value !== "string" || value.trim() !== value || value.length === 0)
282
- throw metadataError(id, `${field} must be a non-empty trimmed string.`);
283
- return value;
284
- };
285
- var requireObject = (value, id, detail) => {
286
- if (!object(value))
287
- throw metadataError(id, detail);
288
- return value;
289
- };
290
- var unknownField = (record, key) => record[key];
291
- var normalizeJsonValue = (value, id, field) => {
292
- if (value === null || typeof value === "string" || typeof value === "boolean")
293
- return value;
294
- if (typeof value === "number" && Number.isFinite(value))
295
- return value;
296
- if (Array.isArray(value))
297
- return value.map((entry) => normalizeJsonValue(entry, id, field));
298
- if (object(value))
299
- return Object.fromEntries(Object.entries(value).map(([key, entry]) => [
300
- key,
301
- normalizeJsonValue(entry, id, field)
302
- ]));
303
- throw metadataError(id, `${field} must be JSON-safe.`);
304
- };
305
- var operation = (value, id, index) => {
306
- const record = requireObject(value, id, `migration operation ${index} must be an object.`);
307
- const type = Reflect.get(record, "type");
308
- const collection = nonEmpty(Reflect.get(record, "collection"), id, `operation ${index}.collection`);
309
- if (type === "delete-collection")
310
- return { collection, type };
311
- if (type === "rename-field")
312
- return {
313
- collection,
314
- from: nonEmpty(Reflect.get(record, "from"), id, `operation ${index}.from`),
315
- to: nonEmpty(Reflect.get(record, "to"), id, `operation ${index}.to`),
316
- type
317
- };
318
- const field = nonEmpty(Reflect.get(record, "field"), id, `operation ${index}.field`);
319
- if (type === "remove-field")
320
- return { collection, field, type };
321
- if (type === "set-default")
322
- return {
323
- collection,
324
- field,
325
- type,
326
- value: normalizeJsonValue(Reflect.get(record, "value"), id, `operation ${index}.value`)
327
- };
328
- throw metadataError(id, `operation ${index}.type is not supported.`);
329
- };
330
- var migration = (value, id, index) => {
331
- const record = requireObject(value, id, `migration ${index} must be an object.`);
332
- const allowed = new Set(["operations", "toVersion"]);
333
- const unsupported = Object.keys(record).find((key) => !allowed.has(key));
334
- if (unsupported)
335
- throw metadataError(id, `migration ${index}.${unsupported} is not declarative metadata.`);
336
- const declaredOperations = Reflect.get(record, "operations");
337
- if (declaredOperations !== undefined && !Array.isArray(declaredOperations))
338
- throw metadataError(id, `migration ${index}.operations must be an array.`);
339
- const operations = Array.isArray(declaredOperations) ? declaredOperations : [];
340
- return {
341
- operations: operations.map((entry, operationIndex) => operation(entry, id, operationIndex)),
342
- toVersion: positiveVersion2(Reflect.get(record, "toVersion"), id, `migration ${index}.toVersion`)
343
- };
344
- };
345
- var localDataPolicy = (value, id) => {
346
- const record = requireObject(value, id, "localData must be an object.");
347
- const allowed = new Set([
348
- "collections",
349
- "maxBytesPerNamespace",
350
- "mutations"
351
- ]);
352
- const unsupported = Object.keys(record).find((key) => !allowed.has(key));
353
- if (unsupported)
354
- throw metadataError(id, `localData.${unsupported} is not supported.`);
355
- const collectionRules = Reflect.get(record, "collections");
356
- const mutationRules = Reflect.get(record, "mutations");
357
- if (collectionRules !== undefined && !Array.isArray(collectionRules))
358
- throw metadataError(id, "localData.collections must be an array.");
359
- if (mutationRules !== undefined && !Array.isArray(mutationRules))
360
- throw metadataError(id, "localData.mutations must be an array.");
361
- const collections = Array.isArray(collectionRules) ? collectionRules.map((entry, index) => {
362
- const rule = requireObject(entry, id, `localData.collections[${index}] must be an object.`);
363
- const allowedRuleKeys = new Set([
364
- "evictionPriority",
365
- "match",
366
- "maxAgeMs",
367
- "onProtectionUnavailable",
368
- "persistence",
369
- "protection",
370
- "sensitivity"
371
- ]);
372
- const unsupportedRuleKey = Object.keys(rule).find((key) => !allowedRuleKeys.has(key));
373
- if (unsupportedRuleKey)
374
- throw metadataError(id, `localData.collections[${index}].${unsupportedRuleKey} is not supported.`);
375
- const match = nonEmpty(Reflect.get(rule, "match"), id, `localData.collections[${index}].match`);
376
- const persistence = unknownField(rule, "persistence");
377
- const sensitivity = unknownField(rule, "sensitivity");
378
- const protection = unknownField(rule, "protection");
379
- const onProtectionUnavailable = unknownField(rule, "onProtectionUnavailable");
380
- const evictionPriority = unknownField(rule, "evictionPriority");
381
- const maxAge = unknownField(rule, "maxAgeMs");
382
- if (persistence !== undefined && persistence !== "durable" && persistence !== "memory-only")
383
- throw metadataError(id, `localData.collections[${index}].persistence is invalid.`);
384
- if (sensitivity !== undefined && sensitivity !== "public" && sensitivity !== "private" && sensitivity !== "secret")
385
- throw metadataError(id, `localData.collections[${index}].sensitivity is invalid.`);
386
- if (protection !== undefined && protection !== "none" && protection !== "required")
387
- throw metadataError(id, `localData.collections[${index}].protection is invalid.`);
388
- if (onProtectionUnavailable !== undefined && onProtectionUnavailable !== "error" && onProtectionUnavailable !== "memory-only")
389
- throw metadataError(id, `localData.collections[${index}].onProtectionUnavailable is invalid.`);
390
- if (evictionPriority !== undefined && evictionPriority !== "critical" && evictionPriority !== "normal" && evictionPriority !== "disposable")
391
- throw metadataError(id, `localData.collections[${index}].evictionPriority is invalid.`);
392
- return {
393
- match,
394
- ...sensitivity ? { sensitivity } : {},
395
- ...persistence ? { persistence } : {},
396
- ...protection ? { protection } : {},
397
- ...onProtectionUnavailable ? {
398
- onProtectionUnavailable
399
- } : {},
400
- ...evictionPriority ? { evictionPriority } : {},
401
- ...maxAge === undefined ? {} : {
402
- maxAgeMs: positiveVersion2(maxAge, id, `localData.collections[${index}].maxAgeMs`)
403
- }
404
- };
405
- }) : undefined;
406
- const mutations = Array.isArray(mutationRules) ? mutationRules.map((entry, index) => {
407
- const rule = requireObject(entry, id, `localData.mutations[${index}] must be an object.`);
408
- const allowedRuleKeys = new Set([
409
- "conflict",
410
- "match",
411
- "onProtectionUnavailable",
412
- "persistence",
413
- "protection",
414
- "sensitivity"
415
- ]);
416
- const unsupportedRuleKey = Object.keys(rule).find((key) => !allowedRuleKeys.has(key));
417
- if (unsupportedRuleKey)
418
- throw metadataError(id, `localData.mutations[${index}].${unsupportedRuleKey} is not supported.`);
419
- const protection = unknownField(rule, "protection");
420
- const sensitivity = unknownField(rule, "sensitivity");
421
- const persistence = unknownField(rule, "persistence");
422
- const onProtectionUnavailable = unknownField(rule, "onProtectionUnavailable");
423
- const declaredConflict = unknownField(rule, "conflict");
424
- let conflict;
425
- if (declaredConflict !== undefined) {
426
- const conflictRecord = requireObject(declaredConflict, id, `localData.mutations[${index}].conflict must be an object.`);
427
- const unsupportedConflictKey = Object.keys(conflictRecord).find((key) => key !== "maxAttempts" && key !== "strategy");
428
- if (unsupportedConflictKey)
429
- throw metadataError(id, `localData.mutations[${index}].conflict.${unsupportedConflictKey} is not supported.`);
430
- const strategy = unknownField(conflictRecord, "strategy");
431
- if (strategy !== "client-wins" && strategy !== "manual" && strategy !== "server-wins")
432
- throw metadataError(id, `localData.mutations[${index}].conflict.strategy is invalid.`);
433
- const maxAttempts = unknownField(conflictRecord, "maxAttempts");
434
- if (maxAttempts !== undefined && strategy !== "client-wins")
435
- throw metadataError(id, `localData.mutations[${index}].conflict.maxAttempts requires client-wins.`);
436
- conflict = {
437
- strategy,
438
- ...maxAttempts === undefined ? {} : {
439
- maxAttempts: positiveVersion2(maxAttempts, id, `localData.mutations[${index}].conflict.maxAttempts`)
440
- }
441
- };
442
- }
443
- if (protection !== undefined && protection !== "none" && protection !== "required")
444
- throw metadataError(id, `localData.mutations[${index}].protection is invalid.`);
445
- if (sensitivity !== undefined && sensitivity !== "public" && sensitivity !== "private" && sensitivity !== "secret")
446
- throw metadataError(id, `localData.mutations[${index}].sensitivity is invalid.`);
447
- if (onProtectionUnavailable !== undefined && onProtectionUnavailable !== "error" && onProtectionUnavailable !== "memory-only")
448
- throw metadataError(id, `localData.mutations[${index}].onProtectionUnavailable is invalid.`);
449
- if (persistence !== undefined && persistence !== "durable" && persistence !== "memory-only")
450
- throw metadataError(id, `localData.mutations[${index}].persistence is invalid.`);
451
- return {
452
- match: nonEmpty(Reflect.get(rule, "match"), id, `localData.mutations[${index}].match`),
453
- ...conflict ? { conflict } : {},
454
- ...sensitivity ? { sensitivity } : {},
455
- ...onProtectionUnavailable ? { onProtectionUnavailable } : {},
456
- ...persistence ? {
457
- persistence
458
- } : {},
459
- ...protection ? { protection } : {}
460
- };
461
- }) : undefined;
462
- const quota = Reflect.get(record, "maxBytesPerNamespace");
463
- return {
464
- ...collections ? { collections } : {},
465
- ...mutations ? { mutations } : {},
466
- ...quota === undefined ? {} : {
467
- maxBytesPerNamespace: positiveVersion2(quota, id, "localData.maxBytesPerNamespace")
468
- }
469
- };
470
- };
471
- var component = (id, value) => {
472
- const record = requireObject(value, id, "localSchema must be an object.");
473
- const allowed = new Set([
474
- "localData",
475
- "migrations",
476
- "minimumCompatibleVersion",
477
- "version"
478
- ]);
479
- const unsupported = Object.keys(record).find((key) => !allowed.has(key));
480
- if (unsupported)
481
- throw metadataError(id, `${unsupported} is not supported.`);
482
- const version = positiveVersion2(Reflect.get(record, "version"), id, "version");
483
- const declaredMinimum = Reflect.get(record, "minimumCompatibleVersion");
484
- const minimumCompatibleVersion = declaredMinimum === undefined ? Math.max(1, version - 2) : positiveVersion2(declaredMinimum, id, "minimumCompatibleVersion");
485
- const declaredMigrations = Reflect.get(record, "migrations");
486
- const declaredLocalData = Reflect.get(record, "localData");
487
- if (declaredMigrations !== undefined && !Array.isArray(declaredMigrations))
488
- throw metadataError(id, "migrations must be an array.");
489
- const migrations = Array.isArray(declaredMigrations) ? declaredMigrations : undefined;
490
- return {
491
- id,
492
- ...declaredLocalData === undefined ? {} : { localData: localDataPolicy(declaredLocalData, id) },
493
- minimumCompatibleVersion,
494
- ...Array.isArray(migrations) ? {
495
- migrations: migrations.map((entry, index) => migration(entry, id, index))
496
- } : {},
497
- version
498
- };
499
- };
500
- var dependencyNames = (manifest) => [
501
- Reflect.get(manifest, "dependencies"),
502
- Reflect.get(manifest, "optionalDependencies"),
503
- Reflect.get(manifest, "devDependencies"),
504
- Reflect.get(manifest, "peerDependencies")
505
- ].flatMap((dependencies) => object(dependencies) ? Object.keys(dependencies) : []).filter((name, index, names) => names.indexOf(name) === index).sort();
506
- var discoverAbsoluteSyncSchema = (projectRoot) => {
507
- const appManifestPath = join2(resolve2(projectRoot), "package.json");
508
- const appManifest = manifestAt(appManifestPath);
509
- if (!appManifest)
510
- return {
511
- components: [
512
- {
513
- id: "@absolutejs/app",
514
- minimumCompatibleVersion: 1,
515
- version: 1
516
- }
517
- ],
518
- sources: []
519
- };
520
- const appMetadata = localSchemaMetadata(appManifest);
521
- const components = [
522
- appMetadata === undefined ? { id: "@absolutejs/app", minimumCompatibleVersion: 1, version: 1 } : component("@absolutejs/app", appMetadata)
523
- ];
524
- const sources = [
525
- { id: "@absolutejs/app", manifestPath: appManifestPath }
526
- ];
527
- for (const name of dependencyNames(appManifest)) {
528
- const manifestPath = packageManifestPath(projectRoot, name);
529
- if (!manifestPath)
530
- continue;
531
- const manifest = manifestAt(manifestPath);
532
- if (!manifest)
533
- continue;
534
- const metadata = localSchemaMetadata(manifest);
535
- if (metadata === undefined)
536
- continue;
537
- components.push(component(name, metadata));
538
- sources.push({ id: name, manifestPath });
539
- }
540
- components.sort((left, right) => left.id.localeCompare(right.id));
541
- sources.sort((left, right) => left.id.localeCompare(right.id));
542
- resolveSyncLocalSchemaComponents({}, { components });
543
- return { components, sources };
544
- };
545
-
546
- // src/mobile/deviceCapabilities.ts
547
- import { existsSync, readFileSync as readFileSync2 } from "fs";
548
- import { extname, join as join3, relative, resolve as resolve3 } from "path";
549
- import { fileURLToPath } from "url";
550
- var DEVICES_PACKAGE = "@absolutejs/devices";
551
- var ABSOLUTE_MOBILE_SHELL_DEVICE_CAPABILITIES = [
552
- "keyboard",
553
- "systemBars"
554
- ];
555
- var ADAPTERS = {
556
- capacitor: "@absolutejs/devices-capacitor",
557
- expo: "@absolutejs/devices-expo"
558
- };
559
- var SOURCE_GLOB = new Bun.Glob("**/*.{js,jsx,ts,tsx,svelte,vue}");
560
- var IGNORED_DIRECTORIES = new Set([
561
- ".absolutejs",
562
- ".git",
563
- ".test-builds",
564
- ".test-shards",
565
- "build",
566
- "dist",
567
- "node_modules",
568
- "test",
569
- "tests"
570
- ]);
571
- var IDENTIFIER_PATTERN = /^[A-Za-z_$][\w$]*$/u;
572
- var providerModulePattern = (provider) => new RegExp(`^@absolutejs/devices-${provider}/[a-z][a-z0-9-]*$`, "u");
573
- var providerPackagePattern = (provider) => provider === "capacitor" ? /^@capacitor\/[a-z][a-z0-9-]*@\d+\.\d+\.\d+$/u : /^(?:expo-[a-z][a-z0-9-]*|@react-native-[a-z0-9-]+\/[a-z][a-z0-9-]*)@\d+\.\d+\.\d+$/u;
574
- var providerLabel = (provider) => provider === "capacitor" ? "Capacitor" : "Expo";
575
- var ANDROID_PERMISSION_PATTERN = /^android\.permission\.[A-Z][A-Z0-9_]*$/u;
576
- var IOS_USAGE_DESCRIPTIONS = new Set([
577
- "camera",
578
- "location-always",
579
- "location-when-in-use",
580
- "photo-library",
581
- "photo-library-add"
582
- ]);
583
- var IOS_PRIVACY_ACCESSED_API_REASONS = {
584
- NSPrivacyAccessedAPICategoryFileTimestamp: new Set(["C617.1"])
585
- };
586
- var IOS_PRIVACY_ACCESSED_APIS = [
587
- "NSPrivacyAccessedAPICategoryFileTimestamp"
588
- ];
589
- var object2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
590
- var readJson = (path) => {
591
- const value = JSON.parse(readFileSync2(path, "utf8"));
592
- if (!object2(value))
593
- throw new TypeError(`${path} must contain an object.`);
594
- return value;
595
- };
596
- var text = (value, field) => {
597
- if (typeof value !== "string" || value.length === 0)
598
- throw new TypeError(`${field} must be a non-empty string.`);
599
- return value;
600
- };
601
- var androidPermissions = (value, field) => {
602
- if (value === undefined)
603
- return;
604
- if (!object2(value))
605
- throw new TypeError(`${field} must be an object.`);
606
- const { permissions } = value;
607
- if (!Array.isArray(permissions) || !permissions.every((permission) => typeof permission === "string" && ANDROID_PERMISSION_PATTERN.test(permission)))
608
- throw new TypeError(`${field}.permissions must contain Android permission names.`);
609
- return [...permissions];
610
- };
611
- var iosPrivacyAccessedApis = (value, field) => {
612
- if (value === undefined)
613
- return;
614
- if (!object2(value))
615
- throw new TypeError(`${field} must be an object.`);
616
- const privacy = {};
617
- for (const api of IOS_PRIVACY_ACCESSED_APIS) {
618
- const reasons = value[api];
619
- if (reasons === undefined)
620
- continue;
621
- const supported = IOS_PRIVACY_ACCESSED_API_REASONS[api];
622
- if (!Array.isArray(reasons) || reasons.length === 0 || !reasons.every((reason) => typeof reason === "string" && supported.has(reason)))
623
- throw new TypeError(`${field} contains an unsupported API or reason.`);
624
- privacy[api] = [...reasons];
625
- }
626
- if (Object.keys(value).some((api) => !IOS_PRIVACY_ACCESSED_APIS.some((known) => known === api)))
627
- throw new TypeError(`${field} contains an unsupported API or reason.`);
628
- return privacy;
629
- };
630
- var iosNativeRequirements = (value, field) => {
631
- if (value === undefined)
632
- return;
633
- if (!object2(value))
634
- throw new TypeError(`${field} must be an object.`);
635
- const {
636
- privacyAccessedApis,
637
- pushNotifications,
638
- systemBars,
639
- usageDescriptions
640
- } = value;
641
- if (pushNotifications !== undefined && pushNotifications !== true)
642
- throw new TypeError(`${field}.pushNotifications must be true.`);
643
- if (systemBars !== undefined && systemBars !== true)
644
- throw new TypeError(`${field}.systemBars must be true.`);
645
- if (usageDescriptions !== undefined && (!Array.isArray(usageDescriptions) || !usageDescriptions.every((purpose) => typeof purpose === "string" && IOS_USAGE_DESCRIPTIONS.has(purpose))))
646
- throw new TypeError(`${field}.usageDescriptions contains an unsupported purpose.`);
647
- const privacy = iosPrivacyAccessedApis(privacyAccessedApis, `${field}.privacyAccessedApis`);
648
- return {
649
- ...privacy === undefined ? {} : { privacyAccessedApis: privacy },
650
- ...pushNotifications === true ? { pushNotifications: true } : {},
651
- ...systemBars === true ? { systemBars: true } : {},
652
- ...usageDescriptions === undefined ? {} : { usageDescriptions: [...usageDescriptions] }
653
- };
654
- };
655
- var parseProvider = (name, value, providerName) => {
656
- if (!IDENTIFIER_PATTERN.test(name))
657
- throw new TypeError("Device capability names must be identifiers.");
658
- if (!object2(value))
659
- throw new TypeError(`Device capability ${name} must be an object.`);
660
- const factory = text(value.factory, `${name}.factory`);
661
- const module = text(value.module, `${name}.module`);
662
- if (!IDENTIFIER_PATTERN.test(factory))
663
- throw new TypeError(`${name}.factory must be a JavaScript identifier.`);
664
- if (!providerModulePattern(providerName).test(module))
665
- throw new TypeError(`${name}.module must be an official devices-${providerName} subpath.`);
666
- if (!Array.isArray(value.packages) || !value.packages.every((spec) => typeof spec === "string" && providerPackagePattern(providerName).test(spec)))
667
- throw new TypeError(`${name}.packages must contain exact official ${providerLabel(providerName)} package versions.`);
668
- const { plugins } = value;
669
- if (plugins !== undefined && (!Array.isArray(plugins) || !plugins.every((plugin) => typeof plugin === "string" && /^expo-[a-z][a-z0-9-]*$/u.test(plugin))))
670
- throw new TypeError(`${name}.plugins must contain Expo config plugin names.`);
671
- let native;
672
- const { native: nativeMetadata } = value;
673
- if (nativeMetadata !== undefined) {
674
- if (!object2(nativeMetadata))
675
- throw new TypeError(`${name}.native must be an object.`);
676
- const { android, ios } = nativeMetadata;
677
- const permissions = androidPermissions(android, `${name}.native.android`);
678
- const iosRequirements = iosNativeRequirements(ios, `${name}.native.ios`);
679
- native = {
680
- ...permissions === undefined ? {} : { android: { permissions } },
681
- ...iosRequirements === undefined ? {} : { ios: iosRequirements }
682
- };
683
- }
684
- return {
685
- factory,
686
- module,
687
- ...native === undefined ? {} : { native },
688
- ...plugins === undefined ? {} : { plugins: [...plugins] },
689
- packages: [...value.packages]
690
- };
691
- };
692
- var absoluteDeviceNativeRequirements = (plan) => {
693
- const privacy = plan.capabilities.reduce((requirements, name) => {
694
- for (const api of IOS_PRIVACY_ACCESSED_APIS) {
695
- const reasons = plan.providers[name]?.native?.ios?.privacyAccessedApis?.[api] ?? [];
696
- if (reasons.length === 0)
697
- continue;
698
- const current = requirements[api] ?? new Set;
699
- for (const reason of reasons)
700
- current.add(reason);
701
- requirements[api] = current;
702
- }
703
- return requirements;
704
- }, {});
705
- return {
706
- androidPermissions: [
707
- ...new Set(plan.capabilities.flatMap((name) => plan.providers[name]?.native?.android?.permissions ?? []))
708
- ].sort(),
709
- iosPrivacyAccessedApis: IOS_PRIVACY_ACCESSED_APIS.flatMap((api) => {
710
- const reasons = privacy[api];
711
- return reasons ? [{ api, reasons: [...reasons].sort() }] : [];
712
- }),
713
- iosPushNotifications: plan.capabilities.some((name) => plan.providers[name]?.native?.ios?.pushNotifications === true),
714
- iosSystemBars: plan.capabilities.some((name) => plan.providers[name]?.native?.ios?.systemBars === true),
715
- iosUsageDescriptions: [
716
- ...new Set(plan.capabilities.flatMap((name) => plan.providers[name]?.native?.ios?.usageDescriptions ?? []))
717
- ].sort()
718
- };
719
- };
720
- var resolveAdapterManifest = (adapter, provider) => {
721
- try {
722
- return fileURLToPath(import.meta.resolve(`${adapter}/package.json`));
723
- } catch {
724
- throw new TypeError(`${adapter} is not installed. Run \`absolute mobile init\` to install the ${provider === "expo" ? "Expo" : "Capacitor"} device adapters.`);
725
- }
726
- };
727
- var loadAbsoluteDeviceCapabilityProviders = (projectRoot, provider = "capacitor") => {
728
- const adapter = ADAPTERS[provider];
729
- let path = join3(resolve3(projectRoot), "node_modules", adapter, "package.json");
730
- try {
731
- readFileSync2(path, "utf8");
732
- } catch {
733
- path = resolveAdapterManifest(adapter, provider);
734
- }
735
- const manifest = readJson(path);
736
- const { absolutejs } = manifest;
737
- const devices = object2(absolutejs) ? absolutejs.devices : undefined;
738
- if (!object2(devices) || devices.format !== 1 || devices.provider !== provider || !object2(devices.capabilities))
739
- throw new TypeError(`${adapter} does not publish supported capability metadata.`);
740
- const entries = Object.entries(devices.capabilities).map(([name, capability]) => ({
741
- name,
742
- provider: parseProvider(name, capability, provider)
743
- }));
744
- return Object.fromEntries(entries.sort((left, right) => left.name.localeCompare(right.name)).map(({ name, provider: capabilityProvider }) => [
745
- name,
746
- capabilityProvider
747
- ]));
748
- };
749
- var isIgnored = (path) => path.split("/").some((segment) => IGNORED_DIRECTORIES.has(segment));
750
- var importedCapabilities = (source, file) => {
751
- const names = new Set;
752
- const namespaces = new Set;
753
- const visit = (node) => {
754
- if (lazyTypescript.isImportDeclaration(node) && lazyTypescript.isStringLiteral(node.moduleSpecifier) && node.moduleSpecifier.text === DEVICES_PACKAGE && !node.importClause?.isTypeOnly) {
755
- const bindings = node.importClause?.namedBindings;
756
- if (bindings && lazyTypescript.isNamedImports(bindings)) {
757
- for (const element of bindings.elements)
758
- if (!element.isTypeOnly)
759
- names.add((element.propertyName ?? element.name).text);
760
- }
761
- if (bindings && lazyTypescript.isNamespaceImport(bindings))
762
- namespaces.add(bindings.name.text);
763
- }
764
- if (lazyTypescript.isExportDeclaration(node) && !node.isTypeOnly && node.moduleSpecifier !== undefined && lazyTypescript.isStringLiteral(node.moduleSpecifier) && node.moduleSpecifier.text === DEVICES_PACKAGE && node.exportClause && lazyTypescript.isNamedExports(node.exportClause)) {
765
- for (const element of node.exportClause.elements)
766
- if (!element.isTypeOnly)
767
- names.add((element.propertyName ?? element.name).text);
768
- }
769
- if (lazyTypescript.isPropertyAccessExpression(node) && lazyTypescript.isIdentifier(node.expression) && namespaces.has(node.expression.text))
770
- names.add(node.name.text);
771
- lazyTypescript.forEachChild(node, visit);
772
- };
773
- const extension = extname(file).toLowerCase();
774
- const sources = extension === ".svelte" || extension === ".vue" ? [...source.matchAll(/<script\b[^>]*>([\s\S]*?)<\/script\s*>/giu)].map((match) => match[1]).filter((value) => value !== undefined) : [source];
775
- for (const [index, script] of sources.entries())
776
- visit(lazyTypescript.createSourceFile(`${file}#script-${index}`, script, lazyTypescript.ScriptTarget.Latest, true, lazyTypescript.ScriptKind.TSX));
777
- return names;
778
- };
779
- var assertAbsoluteDeviceCapabilityPackages = (projectRoot, plan) => {
780
- const missing = missingAbsoluteDeviceCapabilityPackages(plan, directAbsoluteProjectPackages(projectRoot));
781
- const mismatched = plan.requiredPackages.filter((spec) => {
782
- const separator = spec.lastIndexOf("@");
783
- const packageName = spec.slice(0, separator);
784
- if (missing.includes(spec))
785
- return false;
786
- try {
787
- return readJson(join3(resolve3(projectRoot), "node_modules", packageName, "package.json")).version !== spec.slice(separator + 1);
788
- } catch {
789
- return true;
790
- }
791
- });
792
- const unmet = [...missing, ...mismatched];
793
- if (unmet.length > 0)
794
- throw new TypeError(`Device capabilities ${plan.capabilities.join(", ")} require ${unmet.join(", ")}. Run absolute mobile sync and approve the detected capability plugins.`);
795
- };
796
- var directAbsoluteProjectPackages = (projectRoot) => {
797
- const manifest = readJson(join3(resolve3(projectRoot), "package.json"));
798
- const packages = new Set;
799
- for (const field of ["dependencies", "devDependencies"]) {
800
- const dependencies = manifest[field];
801
- if (object2(dependencies))
802
- for (const name of Object.keys(dependencies))
803
- packages.add(name);
804
- }
805
- return packages;
806
- };
807
- var discoverAbsoluteDeviceCapabilities = (projectRoot, providers = loadAbsoluteDeviceCapabilityProviders(projectRoot)) => {
808
- const root = resolve3(projectRoot);
809
- if (!existsSync(root))
810
- return [];
811
- const known = new Set(Object.keys(providers));
812
- const capabilities = new Set;
813
- for (const path of SOURCE_GLOB.scanSync({ cwd: root })) {
814
- const portable = relative(root, resolve3(root, path)).replaceAll("\\", "/");
815
- if (isIgnored(portable))
816
- continue;
817
- const source = readFileSync2(resolve3(root, portable), "utf8");
818
- for (const name of importedCapabilities(source, portable))
819
- if (known.has(name))
820
- capabilities.add(name);
821
- }
822
- return [...capabilities].sort();
823
- };
824
- var missingAbsoluteDeviceCapabilityPackages = (plan, directPackages) => plan.requiredPackages.filter((spec) => {
825
- const packageName = spec.slice(0, spec.lastIndexOf("@"));
826
- return !directPackages.has(packageName);
827
- });
828
- var resolveAbsoluteDeviceCapabilityPlan = (projectRoot, provider = "capacitor") => {
829
- const allProviders = loadAbsoluteDeviceCapabilityProviders(projectRoot, provider);
830
- const capabilities = discoverAbsoluteDeviceCapabilities(projectRoot, allProviders);
831
- for (const capability of ABSOLUTE_MOBILE_SHELL_DEVICE_CAPABILITIES) {
832
- if (allProviders[capability] && !capabilities.includes(capability))
833
- capabilities.push(capability);
834
- }
835
- capabilities.sort();
836
- const providers = {};
837
- for (const name of capabilities) {
838
- const capabilityProvider = allProviders[name];
839
- if (capabilityProvider)
840
- providers[name] = capabilityProvider;
841
- }
842
- return {
843
- capabilities,
844
- providers,
845
- requiredPackages: [
846
- ...new Set(capabilities.flatMap((name) => providers[name]?.packages ?? []))
847
- ].sort()
848
- };
849
- };
850
-
851
105
  // src/mobile/updateRuntime.ts
852
106
  import { createHash } from "crypto";
853
107
 
@@ -862,11 +116,11 @@ var RELEASE_PATTERN = /^amu_[a-f0-9]{64}$/u;
862
116
  var KEY_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/u;
863
117
  var CHANNEL_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/u;
864
118
  var isClassification = (value) => value === "bug-fix" || value === "content" || value === "security";
865
- var object3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
119
+ var object = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
866
120
  var canonicalValue = (value) => {
867
121
  if (Array.isArray(value))
868
122
  return value.map(canonicalValue);
869
- if (!object3(value))
123
+ if (!object(value))
870
124
  return value;
871
125
  return Object.fromEntries(Object.keys(value).sort().map((key) => [key, canonicalValue(value[key])]));
872
126
  };
@@ -885,7 +139,7 @@ var normalizeAbsoluteMobileUpdatePath = (value) => {
885
139
  return path;
886
140
  };
887
141
  var parseFile = (value) => {
888
- if (!object3(value))
142
+ if (!object(value))
889
143
  throw new TypeError("Update files must be objects.");
890
144
  const path = normalizeAbsoluteMobileUpdatePath(value.path);
891
145
  if (typeof value.bytes !== "number" || !Number.isSafeInteger(value.bytes) || value.bytes < 0 || value.bytes > ABSOLUTE_MOBILE_UPDATE_MAX_FILE_BYTES) {
@@ -896,7 +150,7 @@ var parseFile = (value) => {
896
150
  return { bytes: value.bytes, path, sha256: value.sha256 };
897
151
  };
898
152
  var parseAbsoluteMobileUnsignedUpdateManifest = (value) => {
899
- if (!object3(value) || value.format !== ABSOLUTE_MOBILE_UPDATE_FORMAT)
153
+ if (!object(value) || value.format !== ABSOLUTE_MOBILE_UPDATE_FORMAT)
900
154
  throw new TypeError("Invalid AbsoluteJS mobile update manifest.");
901
155
  const appId = requireText(value.appId, "Update appId");
902
156
  const channel = requireText(value.channel, "Update channel");
@@ -938,11 +192,11 @@ var parseAbsoluteMobileUnsignedUpdateManifest = (value) => {
938
192
  };
939
193
  };
940
194
  var parseAbsoluteMobileUpdateManifest = (value) => {
941
- if (!object3(value))
195
+ if (!object(value))
942
196
  throw new TypeError("Invalid AbsoluteJS mobile update manifest.");
943
197
  const { signature: signatureValue, ...unsignedValue } = value;
944
198
  const unsigned = parseAbsoluteMobileUnsignedUpdateManifest(unsignedValue);
945
- if (!object3(signatureValue))
199
+ if (!object(signatureValue))
946
200
  throw new TypeError("Update signature is missing.");
947
201
  if (signatureValue.algorithm !== ABSOLUTE_MOBILE_UPDATE_SIGNATURE_ALGORITHM)
948
202
  throw new TypeError("Update signature algorithm is unsupported.");
@@ -1013,7 +267,7 @@ var resolveAbsoluteMobileUpdateRuntime = (config, projectRoot) => {
1013
267
  };
1014
268
 
1015
269
  // src/mobile/expoNativeObservability.ts
1016
- import { join as join4 } from "path";
270
+ import { join as join2 } from "path";
1017
271
  var HEADER = `// Generated by AbsoluteJS. Edit absolute.config.ts, then run absolute mobile sync.
1018
272
  `;
1019
273
  var XML_HEADER = `<!-- Generated by AbsoluteJS. Edit absolute.config.ts, then run absolute mobile sync. -->
@@ -1455,31 +709,31 @@ export const enqueueAbsoluteExpoNativeObservabilityForTesting = async (testId: s
1455
709
  `;
1456
710
  var absoluteExpoNativeObservabilityFiles = (project) => new Map([
1457
711
  [
1458
- join4(project, "modules/absolute-mobile-observability/expo-module.config.json"),
712
+ join2(project, "modules/absolute-mobile-observability/expo-module.config.json"),
1459
713
  moduleConfig
1460
714
  ],
1461
715
  [
1462
- join4(project, "modules/absolute-mobile-observability/ios/AbsoluteMobileObservability.podspec"),
716
+ join2(project, "modules/absolute-mobile-observability/ios/AbsoluteMobileObservability.podspec"),
1463
717
  podspec
1464
718
  ],
1465
719
  [
1466
- join4(project, "modules/absolute-mobile-observability/ios/AbsoluteMobileObservabilityModule.swift"),
720
+ join2(project, "modules/absolute-mobile-observability/ios/AbsoluteMobileObservabilityModule.swift"),
1467
721
  iosModule
1468
722
  ],
1469
723
  [
1470
- join4(project, "modules/absolute-mobile-observability/android/build.gradle"),
724
+ join2(project, "modules/absolute-mobile-observability/android/build.gradle"),
1471
725
  androidBuild
1472
726
  ],
1473
727
  [
1474
- join4(project, "modules/absolute-mobile-observability/android/src/main/AndroidManifest.xml"),
728
+ join2(project, "modules/absolute-mobile-observability/android/src/main/AndroidManifest.xml"),
1475
729
  androidManifest
1476
730
  ],
1477
731
  [
1478
- join4(project, "modules/absolute-mobile-observability/android/src/main/java/expo/modules/absolutemobileobservability/AbsoluteMobileObservabilityModule.kt"),
732
+ join2(project, "modules/absolute-mobile-observability/android/src/main/java/expo/modules/absolutemobileobservability/AbsoluteMobileObservabilityModule.kt"),
1479
733
  androidModule
1480
734
  ],
1481
735
  [
1482
- join4(project, "src/generated/AbsoluteNativeObservability.ts"),
736
+ join2(project, "src/generated/AbsoluteNativeObservability.ts"),
1483
737
  expoNativeObservabilityRuntimeSource
1484
738
  ]
1485
739
  ]);
@@ -1488,7 +742,7 @@ var absoluteExpoNativeObservabilityPaths = (project) => [
1488
742
  ];
1489
743
 
1490
744
  // src/mobile/expoActivityResultRecovery.ts
1491
- import { join as join5 } from "path";
745
+ import { join as join3 } from "path";
1492
746
  var HEADER2 = `// Generated by AbsoluteJS. Edit absolute.config.ts, then run absolute mobile sync.
1493
747
  `;
1494
748
  var XML_HEADER2 = `<!-- Generated by AbsoluteJS. Edit absolute.config.ts, then run absolute mobile sync. -->
@@ -1725,37 +979,37 @@ export const takeAbsoluteActivityResultCancellation = () =>
1725
979
  `;
1726
980
  var absoluteExpoActivityResultRecoveryFiles = (project) => new Map([
1727
981
  [
1728
- join5(project, "modules/absolute-activity-result-recovery/expo-module.config.json"),
982
+ join3(project, "modules/absolute-activity-result-recovery/expo-module.config.json"),
1729
983
  moduleConfig2
1730
984
  ],
1731
985
  [
1732
- join5(project, "modules/absolute-activity-result-recovery/ios/AbsoluteActivityResultRecovery.podspec"),
986
+ join3(project, "modules/absolute-activity-result-recovery/ios/AbsoluteActivityResultRecovery.podspec"),
1733
987
  podspec2
1734
988
  ],
1735
989
  [
1736
- join5(project, "modules/absolute-activity-result-recovery/ios/AbsoluteActivityResultRecoveryModule.swift"),
990
+ join3(project, "modules/absolute-activity-result-recovery/ios/AbsoluteActivityResultRecoveryModule.swift"),
1737
991
  iosModule2
1738
992
  ],
1739
993
  [
1740
- join5(project, "modules/absolute-activity-result-recovery/android/build.gradle"),
994
+ join3(project, "modules/absolute-activity-result-recovery/android/build.gradle"),
1741
995
  androidBuild2
1742
996
  ],
1743
997
  [
1744
- join5(project, "modules/absolute-activity-result-recovery/android/src/main/AndroidManifest.xml"),
998
+ join3(project, "modules/absolute-activity-result-recovery/android/src/main/AndroidManifest.xml"),
1745
999
  androidManifest2
1746
1000
  ],
1747
1001
  [
1748
- join5(project, "modules/absolute-activity-result-recovery/android/src/main/java/expo/modules/absoluteactivityresultrecovery/AbsoluteActivityResultRecoveryModule.kt"),
1002
+ join3(project, "modules/absolute-activity-result-recovery/android/src/main/java/expo/modules/absoluteactivityresultrecovery/AbsoluteActivityResultRecoveryModule.kt"),
1749
1003
  androidModule2
1750
1004
  ],
1751
1005
  [
1752
- join5(project, "src/generated/AbsoluteActivityResultRecovery.ts"),
1006
+ join3(project, "src/generated/AbsoluteActivityResultRecovery.ts"),
1753
1007
  runtime
1754
1008
  ]
1755
1009
  ]);
1756
1010
 
1757
1011
  // src/mobile/expoEmbeddedAssets.ts
1758
- import { join as join6 } from "path";
1012
+ import { join as join4 } from "path";
1759
1013
  var header = `// Generated by AbsoluteJS. Edit absolute.config.ts, then run absolute mobile sync.
1760
1014
  `;
1761
1015
  var android = `${header}package expo.modules.absoluteembeddedassets
@@ -1969,10 +1223,10 @@ export const registerAbsoluteEmbeddedBundle = async (rootUri: string, paths: str
1969
1223
  };
1970
1224
  `;
1971
1225
  var absoluteExpoEmbeddedAssetsFiles = (project) => {
1972
- const root = join6(project, "modules/absolute-embedded-assets");
1226
+ const root = join4(project, "modules/absolute-embedded-assets");
1973
1227
  return new Map([
1974
1228
  [
1975
- join6(root, "expo-module.config.json"),
1229
+ join4(root, "expo-module.config.json"),
1976
1230
  `${JSON.stringify({
1977
1231
  android: {
1978
1232
  modules: [
@@ -1984,7 +1238,7 @@ var absoluteExpoEmbeddedAssetsFiles = (project) => {
1984
1238
  `
1985
1239
  ],
1986
1240
  [
1987
- join6(root, "android/build.gradle"),
1241
+ join4(root, "android/build.gradle"),
1988
1242
  `${header}plugins { id 'com.android.library'; id 'expo-module-gradle-plugin' }
1989
1243
  group = 'expo.modules.absoluteembeddedassets'
1990
1244
  version = '0.0.1'
@@ -2000,16 +1254,16 @@ dependencies {
2000
1254
  `
2001
1255
  ],
2002
1256
  [
2003
- join6(root, "android/src/main/AndroidManifest.xml"),
1257
+ join4(root, "android/src/main/AndroidManifest.xml"),
2004
1258
  `<manifest xmlns:android="http://schemas.android.com/apk/res/android" />
2005
1259
  `
2006
1260
  ],
2007
1261
  [
2008
- join6(root, "android/src/main/java/expo/modules/absoluteembeddedassets/AbsoluteEmbeddedAssetsModule.kt"),
1262
+ join4(root, "android/src/main/java/expo/modules/absoluteembeddedassets/AbsoluteEmbeddedAssetsModule.kt"),
2009
1263
  android
2010
1264
  ],
2011
- [join6(project, "plugins/withAbsoluteEmbeddedAssets.js"), plugin],
2012
- [join6(project, "src/generated/AbsoluteEmbeddedAssets.ts"), runtime2]
1265
+ [join4(project, "plugins/withAbsoluteEmbeddedAssets.js"), plugin],
1266
+ [join4(project, "src/generated/AbsoluteEmbeddedAssets.ts"), runtime2]
2013
1267
  ]);
2014
1268
  };
2015
1269
 
@@ -2024,7 +1278,7 @@ import {
2024
1278
  rm,
2025
1279
  writeFile
2026
1280
  } from "fs/promises";
2027
- import { dirname as dirname3, join as join7, relative as relative2, resolve as resolve4 } from "path";
1281
+ import { dirname as dirname2, join as join5, relative, resolve as resolve2 } from "path";
2028
1282
  var ABSOLUTE_MOBILE_BRANDING_FORMAT = 1;
2029
1283
  var ABSOLUTE_CAPACITOR_ASSETS_VERSION = "3.0.5";
2030
1284
  var ABSOLUTE_CAPACITOR_ASSETS_SPEC = `@capacitor/assets@${ABSOLUTE_CAPACITOR_ASSETS_VERSION}`;
@@ -2047,8 +1301,8 @@ var exists = async (path) => {
2047
1301
  return false;
2048
1302
  }
2049
1303
  };
2050
- var portableRelative = (root, path) => relative2(root, path).replaceAll("\\", "/");
2051
- var absoluteMobileBrandingManifestPath = (projectRoot) => join7(resolve4(projectRoot), ".absolutejs", "mobile", "branding", "manifest.json");
1304
+ var portableRelative = (root, path) => relative(root, path).replaceAll("\\", "/");
1305
+ var absoluteMobileBrandingManifestPath = (projectRoot) => join5(resolve2(projectRoot), ".absolutejs", "mobile", "branding", "manifest.json");
2052
1306
  var brandingEntries = (branding) => [
2053
1307
  { kind: "icon", path: branding.icon, size: ICON_SIZE },
2054
1308
  branding.android.foreground ? {
@@ -2141,7 +1395,7 @@ var createAbsoluteMobileBrandingManifest = async (config, projectRoot) => {
2141
1395
  };
2142
1396
  var writeManifest = async (projectRoot, manifest) => {
2143
1397
  const destination = absoluteMobileBrandingManifestPath(projectRoot);
2144
- await mkdir(dirname3(destination), { recursive: true });
1398
+ await mkdir(dirname2(destination), { recursive: true });
2145
1399
  const temporary = `${destination}.${crypto.randomUUID()}.tmp`;
2146
1400
  await writeFile(temporary, `${JSON.stringify(manifest, null, 2)}
2147
1401
  `, {
@@ -2151,7 +1405,7 @@ var writeManifest = async (projectRoot, manifest) => {
2151
1405
  return destination;
2152
1406
  };
2153
1407
  var copyManaged = async (source, destination) => {
2154
- await mkdir(dirname3(destination), { recursive: true });
1408
+ await mkdir(dirname2(destination), { recursive: true });
2155
1409
  await copyFile(source, destination);
2156
1410
  };
2157
1411
  var absoluteExpoBrandingConfig = (config) => {
@@ -2195,10 +1449,10 @@ var writeAbsoluteExpoBrandingInputs = async (config, projectRoot) => {
2195
1449
  if (!branding)
2196
1450
  return;
2197
1451
  const manifest = await createAbsoluteMobileBrandingManifest(config, projectRoot);
2198
- const destination = join7(config.nativeProjectDirectory, "assets", "absolute-branding");
1452
+ const destination = join5(config.nativeProjectDirectory, "assets", "absolute-branding");
2199
1453
  await rm(destination, { force: true, recursive: true });
2200
1454
  await mkdir(destination, { recursive: true });
2201
- await copyManaged(branding.icon, join7(destination, "icon.png"));
1455
+ await copyManaged(branding.icon, join5(destination, "icon.png"));
2202
1456
  const copies = [
2203
1457
  [branding.android.backgroundImage, "android-background.png"],
2204
1458
  [branding.android.foreground, "android-foreground.png"],
@@ -2208,19 +1462,19 @@ var writeAbsoluteExpoBrandingInputs = async (config, projectRoot) => {
2208
1462
  [branding.splash.image, "splash-light.png"],
2209
1463
  [branding.splash.darkImage, "splash-dark.png"]
2210
1464
  ];
2211
- await Promise.all(copies.map(([source, name]) => source ? copyManaged(source, join7(destination, name)) : undefined));
1465
+ await Promise.all(copies.map(([source, name]) => source ? copyManaged(source, join5(destination, name)) : undefined));
2212
1466
  await writeManifest(projectRoot, manifest);
2213
1467
  return { manifest, path: destination };
2214
1468
  };
2215
1469
  var stageCapacitorInputs = async (branding, projectRoot) => {
2216
- const destination = join7(projectRoot, ".absolutejs", "mobile", "branding", "input");
1470
+ const destination = join5(projectRoot, ".absolutejs", "mobile", "branding", "input");
2217
1471
  await rm(destination, { force: true, recursive: true });
2218
1472
  await mkdir(destination, { recursive: true });
2219
- await copyManaged(branding.icon, join7(destination, "logo.png"));
1473
+ await copyManaged(branding.icon, join5(destination, "logo.png"));
2220
1474
  if (branding.splash.image)
2221
- await copyManaged(branding.splash.image, join7(destination, "splash.png"));
1475
+ await copyManaged(branding.splash.image, join5(destination, "splash.png"));
2222
1476
  if (branding.splash.darkImage)
2223
- await copyManaged(branding.splash.darkImage, join7(destination, "splash-dark.png"));
1477
+ await copyManaged(branding.splash.darkImage, join5(destination, "splash-dark.png"));
2224
1478
  return destination;
2225
1479
  };
2226
1480
  var defaultRunner = async (command, options) => {
@@ -2247,20 +1501,20 @@ ${stderr}`))
2247
1501
  };
2248
1502
  var resizePng = async (source, destination, size) => {
2249
1503
  const output = await new Bun.Image(await readFile2(source)).resize(size, size).png({ compressionLevel: 9 }).toBuffer();
2250
- await mkdir(dirname3(destination), { recursive: true });
1504
+ await mkdir(dirname2(destination), { recursive: true });
2251
1505
  await writeFile(destination, output);
2252
1506
  };
2253
1507
  var applyAndroidLayers = async (branding, nativeDirectory) => {
2254
- const resources = join7(nativeDirectory, "android", "app", "src", "main", "res");
1508
+ const resources = join5(nativeDirectory, "android", "app", "src", "main", "res");
2255
1509
  await Promise.all(ANDROID_ADAPTIVE_SIZES.flatMap(([density, size]) => [
2256
1510
  ...branding.android.foreground ? [
2257
- resizePng(branding.android.foreground, join7(resources, `mipmap-${density}`, "ic_launcher_foreground.png"), size)
1511
+ resizePng(branding.android.foreground, join5(resources, `mipmap-${density}`, "ic_launcher_foreground.png"), size)
2258
1512
  ] : [],
2259
1513
  ...branding.android.backgroundImage ? [
2260
- resizePng(branding.android.backgroundImage, join7(resources, `mipmap-${density}`, "ic_launcher_background.png"), size)
1514
+ resizePng(branding.android.backgroundImage, join5(resources, `mipmap-${density}`, "ic_launcher_background.png"), size)
2261
1515
  ] : [],
2262
1516
  ...branding.android.monochrome ? [
2263
- resizePng(branding.android.monochrome, join7(resources, `mipmap-${density}`, "ic_launcher_monochrome.png"), size)
1517
+ resizePng(branding.android.monochrome, join5(resources, `mipmap-${density}`, "ic_launcher_monochrome.png"), size)
2264
1518
  ] : []
2265
1519
  ]));
2266
1520
  if (!branding.android.monochrome)
@@ -2272,13 +1526,13 @@ var applyAndroidLayers = async (branding, nativeDirectory) => {
2272
1526
  <monochrome android:drawable="@mipmap/ic_launcher_monochrome" />
2273
1527
  </adaptive-icon>
2274
1528
  `;
2275
- await Promise.all(["ic_launcher.xml", "ic_launcher_round.xml"].map((name) => writeFile(join7(resources, "mipmap-anydpi-v26", name), iconXml)));
1529
+ await Promise.all(["ic_launcher.xml", "ic_launcher_round.xml"].map((name) => writeFile(join5(resources, "mipmap-anydpi-v26", name), iconXml)));
2276
1530
  };
2277
1531
  var applyIosAppearances = async (branding, nativeDirectory) => {
2278
1532
  if (!branding.ios.darkIcon && !branding.ios.tintedIcon)
2279
1533
  return;
2280
- const assetSet = join7(nativeDirectory, "ios", "App", "App", "Assets.xcassets", "AppIcon.appiconset");
2281
- const contentsPath = join7(assetSet, "Contents.json");
1534
+ const assetSet = join5(nativeDirectory, "ios", "App", "App", "Assets.xcassets", "AppIcon.appiconset");
1535
+ const contentsPath = join5(assetSet, "Contents.json");
2282
1536
  const contents = JSON.parse(await readFile2(contentsPath, "utf8"));
2283
1537
  const images = typeof contents === "object" && contents !== null ? Reflect.get(contents, "images") : undefined;
2284
1538
  if (typeof contents !== "object" || contents === null || !Array.isArray(images))
@@ -2291,7 +1545,7 @@ var applyIosAppearances = async (branding, nativeDirectory) => {
2291
1545
  if (!source)
2292
1546
  return;
2293
1547
  const filename = `AppIcon-1024-${appearance}.png`;
2294
- await resizePng(source, join7(assetSet, filename), ICON_SIZE);
1548
+ await resizePng(source, join5(assetSet, filename), ICON_SIZE);
2295
1549
  return {
2296
1550
  appearances: [{ appearance: "luminosity", value: appearance }],
2297
1551
  filename,
@@ -2313,7 +1567,7 @@ var applyIosAppearances = async (branding, nativeDirectory) => {
2313
1567
  await writeFile(contentsPath, `${JSON.stringify(contents, null, 2)}
2314
1568
  `);
2315
1569
  };
2316
- var nativeBrandingSentinels = (config, platforms) => platforms.map((platform) => platform === "android" ? join7(config.nativeProjectDirectory, "android", "app", "src", "main", "res", "mipmap-xxxhdpi", "ic_launcher.png") : join7(config.nativeProjectDirectory, "ios", "App", "App", "Assets.xcassets", "AppIcon.appiconset", "AppIcon-512@2x.png"));
1570
+ var nativeBrandingSentinels = (config, platforms) => platforms.map((platform) => platform === "android" ? join5(config.nativeProjectDirectory, "android", "app", "src", "main", "res", "mipmap-xxxhdpi", "ic_launcher.png") : join5(config.nativeProjectDirectory, "ios", "App", "App", "Assets.xcassets", "AppIcon.appiconset", "AppIcon-512@2x.png"));
2317
1571
  var requireGeneratedBranding = async (config, platforms) => {
2318
1572
  const missing = (await Promise.all(nativeBrandingSentinels(config, platforms).map(async (path) => ({
2319
1573
  path,
@@ -2358,9 +1612,9 @@ var generateAbsoluteCapacitorBranding = async (config, projectRoot, options = {}
2358
1612
  "--assetPath",
2359
1613
  portableRelative(projectRoot, input),
2360
1614
  "--androidProject",
2361
- portableRelative(projectRoot, join7(config.nativeProjectDirectory, "android")),
1615
+ portableRelative(projectRoot, join5(config.nativeProjectDirectory, "android")),
2362
1616
  "--iosProject",
2363
- portableRelative(projectRoot, join7(config.nativeProjectDirectory, "ios", "App")),
1617
+ portableRelative(projectRoot, join5(config.nativeProjectDirectory, "ios", "App")),
2364
1618
  "--iconBackgroundColor",
2365
1619
  branding.android.backgroundColor,
2366
1620
  "--splashBackgroundColor",
@@ -2441,7 +1695,7 @@ var inspectAbsoluteMobileBranding = async (config, projectRoot) => {
2441
1695
  status: "stale"
2442
1696
  });
2443
1697
  const nativeSentinels = config.engine === "expo" ? [
2444
- join7(config.nativeProjectDirectory, "assets", "absolute-branding", "icon.png")
1698
+ join5(config.nativeProjectDirectory, "assets", "absolute-branding", "icon.png")
2445
1699
  ] : nativeBrandingSentinels(config, config.platforms);
2446
1700
  if ((await Promise.all(nativeSentinels.map((path) => exists(path)))).some((present) => !present))
2447
1701
  return brandingInspection({
@@ -2474,7 +1728,7 @@ var renderAbsoluteMobileBrandingPreview = async (config, projectRoot) => {
2474
1728
  const { branding } = config;
2475
1729
  if (!branding)
2476
1730
  throw new TypeError("mobile.branding is not configured.");
2477
- const destination = join7(projectRoot, ".absolutejs", "mobile", "branding", "preview.html");
1731
+ const destination = join5(projectRoot, ".absolutejs", "mobile", "branding", "preview.html");
2478
1732
  const icon = `data:image/png;base64,${(await readFile2(branding.icon)).toString("base64")}`;
2479
1733
  const appName = escapeHtml(config.appName);
2480
1734
  const html = `<!doctype html>
@@ -2484,7 +1738,7 @@ var renderAbsoluteMobileBrandingPreview = async (config, projectRoot) => {
2484
1738
  <style>body{font:16px system-ui;margin:2rem;background:#eee;color:#111}main{display:flex;flex-wrap:wrap;gap:2rem}.card{background:white;border-radius:20px;padding:1.5rem;box-shadow:0 8px 30px #0002}.icon{width:192px;height:192px;object-fit:cover}.circle{border-radius:50%}.squircle{border-radius:24%}.splash{width:240px;height:480px;display:grid;place-items:center;background:${branding.splash.backgroundColor}}.splash img{width:${branding.splash.logoScale * 100}%}code{display:block;margin-top:1rem}</style>
2485
1739
  <h1>${appName}</h1><main><section class="card"><img class="icon squircle" src="${icon}" alt="Square app icon preview"><code>Apple / legacy Android</code></section><section class="card"><img class="icon circle" src="${icon}" alt="Circular Android icon preview"><code>Android circular mask</code></section><section class="card splash"><img src="${icon}" alt="Launch screen preview"></section></main><p>Fingerprint: <code>${manifest.fingerprint}</code></p>
2486
1740
  `;
2487
- await mkdir(dirname3(destination), { recursive: true });
1741
+ await mkdir(dirname2(destination), { recursive: true });
2488
1742
  await writeFile(destination, html);
2489
1743
  return destination;
2490
1744
  };
@@ -2553,7 +1807,7 @@ var expoNativeDataManifest = (value) => {
2553
1807
  };
2554
1808
  };
2555
1809
  var portableRelative2 = (from, destination) => {
2556
- const value = relative3(from, destination).replaceAll("\\", "/");
1810
+ const value = relative2(from, destination).replaceAll("\\", "/");
2557
1811
  return value.startsWith(".") ? value : `./${value}`;
2558
1812
  };
2559
1813
  var routeSegments = (route) => {
@@ -2569,7 +1823,7 @@ var routeSegments = (route) => {
2569
1823
  return segment;
2570
1824
  });
2571
1825
  };
2572
- var routeFile = (project, route) => join8(project, "app", ...routeSegments(route), "index.tsx");
1826
+ var routeFile = (project, route) => join6(project, "app", ...routeSegments(route), "index.tsx");
2573
1827
  var packageDependencies = (plan) => Object.fromEntries(plan.requiredPackages.map((spec) => {
2574
1828
  const separator = spec.lastIndexOf("@");
2575
1829
  return [spec.slice(0, separator), spec.slice(separator + 1)];
@@ -3916,8 +3170,8 @@ const styles = StyleSheet.create({
3916
3170
  error: { color: '#b91c1c', fontSize: 16, textAlign: 'center' }
3917
3171
  });
3918
3172
  `;
3919
- var nativeWrapperSource = (wrapper, module, runtime, route) => `${EXPO_GENERATED_HEADER}import ApplicationNativeRoute from ${JSON.stringify(portableRelative2(dirname4(wrapper), module).replace(/\.(?:[cm]?[jt]sx?)$/u, ""))};
3920
- import { createAbsoluteNativeRoute, createAbsoluteNativeRouteErrorBoundary } from ${JSON.stringify(portableRelative2(dirname4(wrapper), runtime).replace(/\.(?:[cm]?[jt]sx?)$/u, ""))};
3173
+ var nativeWrapperSource = (wrapper, module, runtime, route) => `${EXPO_GENERATED_HEADER}import ApplicationNativeRoute from ${JSON.stringify(portableRelative2(dirname3(wrapper), module).replace(/\.(?:[cm]?[jt]sx?)$/u, ""))};
3174
+ import { createAbsoluteNativeRoute, createAbsoluteNativeRouteErrorBoundary } from ${JSON.stringify(portableRelative2(dirname3(wrapper), runtime).replace(/\.(?:[cm]?[jt]sx?)$/u, ""))};
3921
3175
 
3922
3176
  export const ErrorBoundary = createAbsoluteNativeRouteErrorBoundary(${JSON.stringify(route)});
3923
3177
  export default createAbsoluteNativeRoute(ApplicationNativeRoute, ${JSON.stringify(route)});
@@ -3959,7 +3213,7 @@ var expoTsConfig = (projectRoot, project, auth, sync) => ({
3959
3213
  extends: "expo/tsconfig.base"
3960
3214
  });
3961
3215
  var writeManagedFile = async (path, source, force) => {
3962
- await mkdir2(dirname4(path), { recursive: true });
3216
+ await mkdir2(dirname3(path), { recursive: true });
3963
3217
  if (await exists2(path)) {
3964
3218
  const current = await readFile3(path, "utf8");
3965
3219
  if (current === source)
@@ -3986,7 +3240,7 @@ var pruneManagedFiles = async (paths) => {
3986
3240
  return removed.filter(Boolean).length;
3987
3241
  };
3988
3242
  var pruneStaleManagedExpoRoutes = async (project, expected) => {
3989
- const appDirectory = join8(project, "app");
3243
+ const appDirectory = join6(project, "app");
3990
3244
  if (!await exists2(appDirectory))
3991
3245
  return 0;
3992
3246
  const files = await walkFiles(appDirectory);
@@ -4017,7 +3271,7 @@ export const ABSOLUTE_MOBILE_MANIFEST: AbsoluteMobileManifest | undefined = unde
4017
3271
  var writeAbsoluteExpoProject2 = async (config, options) => {
4018
3272
  if (config.engine !== "expo")
4019
3273
  throw new TypeError("Expo project generation requires mobile.engine: expo.");
4020
- const projectRoot = resolve5(options.projectRoot);
3274
+ const projectRoot = resolve3(options.projectRoot);
4021
3275
  const project = config.nativeProjectDirectory;
4022
3276
  const auth = resolveAbsoluteMobileAuthManifest2(projectRoot, config);
4023
3277
  const devices = resolveAbsoluteDeviceCapabilityPlan(projectRoot, "expo");
@@ -4034,7 +3288,7 @@ var writeAbsoluteExpoProject2 = async (config, options) => {
4034
3288
  if (missing) {
4035
3289
  throw new TypeError(`Expo native route ${missing.route} references missing module ${missing.module}.`);
4036
3290
  }
4037
- const marker = join8(project, EXPO_PROJECT_MARKER);
3291
+ const marker = join6(project, EXPO_PROJECT_MARKER);
4038
3292
  if (await exists2(project) && !await exists2(marker)) {
4039
3293
  const entries = await readdir(project);
4040
3294
  if (entries.length > 0 && !options.force) {
@@ -4047,7 +3301,7 @@ var writeAbsoluteExpoProject2 = async (config, options) => {
4047
3301
  const authEnabled = Boolean(auth);
4048
3302
  const files = new Map([
4049
3303
  [
4050
- join8(project, ".gitignore"),
3304
+ join6(project, ".gitignore"),
4051
3305
  `.expo/
4052
3306
  android/
4053
3307
  ios/
@@ -4055,45 +3309,45 @@ node_modules/
4055
3309
  `
4056
3310
  ],
4057
3311
  [
4058
- join8(project, "app.json"),
3312
+ join6(project, "app.json"),
4059
3313
  jsonSource(expoAppConfig(config, authEnabled, syncEnabled, devices, runtimeFingerprint))
4060
3314
  ],
4061
- [join8(project, "app.config.js"), expoDynamicAppConfig],
3315
+ [join6(project, "app.config.js"), expoDynamicAppConfig],
4062
3316
  [
4063
- join8(project, "package.json"),
3317
+ join6(project, "package.json"),
4064
3318
  jsonSource(expoPackage(authEnabled, config.branding !== undefined, syncEnabled, devices, config.updates !== undefined))
4065
3319
  ],
4066
- [join8(project, "metro.config.js"), metroConfig(projectRoot)],
3320
+ [join6(project, "metro.config.js"), metroConfig(projectRoot)],
4067
3321
  [
4068
- join8(project, "plugins", "withAbsoluteDevelopmentCa.js"),
3322
+ join6(project, "plugins", "withAbsoluteDevelopmentCa.js"),
4069
3323
  expoDevelopmentCaPlugin
4070
3324
  ],
4071
3325
  [
4072
- join8(project, "plugins", "withAbsoluteActivityResultRecovery.js"),
3326
+ join6(project, "plugins", "withAbsoluteActivityResultRecovery.js"),
4073
3327
  expoActivityResultRecoveryPlugin
4074
3328
  ],
4075
3329
  [
4076
- join8(project, "tsconfig.json"),
3330
+ join6(project, "tsconfig.json"),
4077
3331
  jsonSource(expoTsConfig(projectRoot, project, authEnabled, syncEnabled))
4078
3332
  ],
4079
3333
  [
4080
- join8(project, "app", "_layout.tsx"),
3334
+ join6(project, "app", "_layout.tsx"),
4081
3335
  layoutSource(authEnabled, syncEnabled, config.updates !== undefined, config.observability !== undefined)
4082
3336
  ],
4083
3337
  [
4084
- join8(project, "app", "__absolute", "native", "index.tsx"),
3338
+ join6(project, "app", "__absolute", "native", "index.tsx"),
4085
3339
  nativeDiagnosticSource
4086
3340
  ],
4087
3341
  [
4088
- join8(project, "src", "generated", "AbsoluteDevices.ts"),
3342
+ join6(project, "src", "generated", "AbsoluteDevices.ts"),
4089
3343
  devicesRuntimeSource(config, devices, authEnabled)
4090
3344
  ],
4091
3345
  [
4092
- join8(project, "src", "generated", "AbsoluteNativeRoute.tsx"),
3346
+ join6(project, "src", "generated", "AbsoluteNativeRoute.tsx"),
4093
3347
  nativeRouteRuntimeSource(authEnabled)
4094
3348
  ],
4095
3349
  [
4096
- join8(project, "src", "generated", "AbsoluteWebHost.tsx"),
3350
+ join6(project, "src", "generated", "AbsoluteWebHost.tsx"),
4097
3351
  webHostSource(config, auth, syncEnabled)
4098
3352
  ]
4099
3353
  ]);
@@ -4106,31 +3360,31 @@ node_modules/
4106
3360
  files.set(path, source);
4107
3361
  }
4108
3362
  if (config.updates) {
4109
- files.set(join8(project, "src", "generated", "AbsoluteUpdates.ts"), updatesRuntimeSource(config));
3363
+ files.set(join6(project, "src", "generated", "AbsoluteUpdates.ts"), updatesRuntimeSource(config));
4110
3364
  }
4111
3365
  const expoCodeSigning = config.updates?.expoCodeSigning;
4112
3366
  if (expoCodeSigning)
4113
- files.set(join8(project, "certs", "absolute-mobile-update.pem"), expoCodeSigning.certificatePem);
3367
+ files.set(join6(project, "certs", "absolute-mobile-update.pem"), expoCodeSigning.certificatePem);
4114
3368
  if (auth) {
4115
- files.set(join8(project, "src", "generated", "AbsoluteAuth.ts"), authRuntimeSource(auth, config.appId));
3369
+ files.set(join6(project, "src", "generated", "AbsoluteAuth.ts"), authRuntimeSource(auth, config.appId));
4116
3370
  }
4117
3371
  if (syncSchema) {
4118
- files.set(join8(project, "src", "generated", "AbsoluteSync.ts"), syncRuntimeSource(config, syncSchema));
3372
+ files.set(join6(project, "src", "generated", "AbsoluteSync.ts"), syncRuntimeSource(config, syncSchema));
4119
3373
  }
4120
- const webAssetsPath = join8(project, "src", "generated", "webAssets.ts");
3374
+ const webAssetsPath = join6(project, "src", "generated", "webAssets.ts");
4121
3375
  if (!await exists2(webAssetsPath)) {
4122
3376
  files.set(webAssetsPath, emptyWebAssetsSource);
4123
3377
  }
4124
3378
  if (!config.expoNativeRoutes["/"]) {
4125
- files.set(join8(project, "app", "index.tsx"), webRouteSource);
3379
+ files.set(join6(project, "app", "index.tsx"), webRouteSource);
4126
3380
  }
4127
- files.set(join8(project, "app", "[...absolute].tsx"), catchAllRouteSource);
4128
- const nativeRouteRuntime = join8(project, "src", "generated", "AbsoluteNativeRoute.tsx");
3381
+ files.set(join6(project, "app", "[...absolute].tsx"), catchAllRouteSource);
3382
+ const nativeRouteRuntime = join6(project, "src", "generated", "AbsoluteNativeRoute.tsx");
4129
3383
  for (const [route, module] of routeModules) {
4130
- const wrapper = route === "/" ? join8(project, "app", "index.tsx") : routeFile(project, route);
3384
+ const wrapper = route === "/" ? join6(project, "app", "index.tsx") : routeFile(project, route);
4131
3385
  files.set(wrapper, nativeWrapperSource(wrapper, module, nativeRouteRuntime, route));
4132
3386
  }
4133
- const removedRoutes = await pruneStaleManagedExpoRoutes(project, new Set([...files.keys()].filter((path) => path.startsWith(`${join8(project, "app")}${sep}`))));
3387
+ const removedRoutes = await pruneStaleManagedExpoRoutes(project, new Set([...files.keys()].filter((path) => path.startsWith(`${join6(project, "app")}${sep}`))));
4134
3388
  const removedObservability = config.observability ? 0 : await pruneManagedFiles(absoluteExpoNativeObservabilityPaths(project));
4135
3389
  const changes = await Promise.all([...files].map(([path, source]) => writeManagedFile(path, source, true)));
4136
3390
  await writeAbsoluteExpoBrandingInputs(config, projectRoot);
@@ -4140,7 +3394,7 @@ node_modules/
4140
3394
  var walkFiles = async (root, directory = root) => {
4141
3395
  const entries = await readdir(directory, { withFileTypes: true });
4142
3396
  const nested = await Promise.all(entries.map((entry) => {
4143
- const path = join8(directory, entry.name);
3397
+ const path = join6(directory, entry.name);
4144
3398
  if (entry.isDirectory())
4145
3399
  return walkFiles(root, path);
4146
3400
  if (entry.isFile())
@@ -4257,11 +3511,11 @@ export const materializeAbsoluteWebBundle = async () => {
4257
3511
  var syncAbsoluteExpoWebAssets2 = async (config) => {
4258
3512
  if (config.engine !== "expo")
4259
3513
  throw new TypeError("Expo asset sync requires mobile.engine: expo.");
4260
- const marker = join8(config.nativeProjectDirectory, EXPO_PROJECT_MARKER);
3514
+ const marker = join6(config.nativeProjectDirectory, EXPO_PROJECT_MARKER);
4261
3515
  if (!await exists2(marker)) {
4262
3516
  throw new TypeError("Expo asset sync requires an AbsoluteJS-managed Expo project. Run mobile init first.");
4263
3517
  }
4264
- const manifestPath = join8(config.bundleDirectory, "absolute-mobile-manifest.json");
3518
+ const manifestPath = join6(config.bundleDirectory, "absolute-mobile-manifest.json");
4265
3519
  const manifest = JSON.parse(await readFile3(manifestPath, "utf8"));
4266
3520
  const nativeDataManifest = expoNativeDataManifest(manifest);
4267
3521
  const { appBuild } = nativeDataManifest;
@@ -4269,15 +3523,15 @@ var syncAbsoluteExpoWebAssets2 = async (config) => {
4269
3523
  const bundleHash = createHash3("sha256");
4270
3524
  const filesWithContents = await Promise.all(files.map(async (file) => ({ contents: await readFile3(file), file })));
4271
3525
  filesWithContents.forEach(({ contents, file }) => {
4272
- bundleHash.update(relative3(config.bundleDirectory, file).replaceAll("\\", "/"));
3526
+ bundleHash.update(relative2(config.bundleDirectory, file).replaceAll("\\", "/"));
4273
3527
  bundleHash.update("\x00");
4274
3528
  bundleHash.update(contents);
4275
3529
  bundleHash.update("\x00");
4276
3530
  });
4277
3531
  const bundleId = `amexpo_${bundleHash.digest("hex")}`;
4278
- const destination = join8(config.nativeProjectDirectory, "assets", "absolute");
4279
- await mkdir2(dirname4(destination), { recursive: true });
4280
- const staging = await mkdtemp(join8(dirname4(destination), `.${basename(destination)}.stage-`));
3532
+ const destination = join6(config.nativeProjectDirectory, "assets", "absolute");
3533
+ await mkdir2(dirname3(destination), { recursive: true });
3534
+ const staging = await mkdtemp(join6(dirname3(destination), `.${basename(destination)}.stage-`));
4281
3535
  let assets;
4282
3536
  let archiveAsset;
4283
3537
  let archiveMd5;
@@ -4288,7 +3542,7 @@ var syncAbsoluteExpoWebAssets2 = async (config) => {
4288
3542
  length: contents.byteLength,
4289
3543
  md5: createHash3("md5").update(contents).digest("hex"),
4290
3544
  offset,
4291
- path: relative3(config.bundleDirectory, file).replaceAll("\\", "/")
3545
+ path: relative2(config.bundleDirectory, file).replaceAll("\\", "/")
4292
3546
  };
4293
3547
  offset += contents.byteLength;
4294
3548
  return entry;
@@ -4296,16 +3550,16 @@ var syncAbsoluteExpoWebAssets2 = async (config) => {
4296
3550
  const name = `bundle${EXPO_ASSET_EXTENSION}`;
4297
3551
  const archiveContents = Buffer.concat(filesWithContents.map(({ contents }) => contents));
4298
3552
  archiveMd5 = createHash3("md5").update(archiveContents).digest("hex");
4299
- await writeFile2(join8(staging, name), archiveContents);
4300
- archiveAsset = portableRelative2(join8(config.nativeProjectDirectory, "src", "generated"), join8(destination, name));
3553
+ await writeFile2(join6(staging, name), archiveContents);
3554
+ archiveAsset = portableRelative2(join6(config.nativeProjectDirectory, "src", "generated"), join6(destination, name));
4301
3555
  await installStagedDirectory(staging, destination);
4302
3556
  } catch (error) {
4303
3557
  await rm2(staging, { force: true, recursive: true });
4304
3558
  throw error;
4305
3559
  }
4306
- const generated = join8(config.nativeProjectDirectory, "src", "generated", "webAssets.ts");
3560
+ const generated = join6(config.nativeProjectDirectory, "src", "generated", "webAssets.ts");
4307
3561
  await writeManagedFile(generated, assetModuleSource(assets, archiveAsset, bundleId, archiveMd5, nativeDataManifest), true);
4308
3562
  return { appBuild, assets: assets.length, bundleId, path: destination };
4309
3563
  };
4310
3564
 
4311
- export { ABSOLUTE_DEPLOY_VERSION, ABSOLUTE_NATIVE_EXACT_PACKAGES, CAPACITOR_PACKAGE_SPECS, CAPACITOR_SYNC_PACKAGE_SPECS, EXPO_APP_EXACT_PACKAGES, EXPO_APP_PACKAGE_SPECS, EXPO_CODE_SIGNING_PACKAGE_SPEC, assertNativePackageVersions, packageNameFromSpec, packagesNeedingExactInstall, discoverAbsoluteSyncSchema, absoluteDeviceNativeRequirements, assertAbsoluteDeviceCapabilityPackages, resolveAbsoluteDeviceCapabilityPlan, ABSOLUTE_MOBILE_UPDATE_FORMAT, absoluteMobileUpdateSigningPayload, canonicalizeAbsoluteMobileUpdate, parseAbsoluteMobileUpdateManifest, unsignedAbsoluteMobileUpdate, resolveAbsoluteMobileUpdateRuntime, ABSOLUTE_CAPACITOR_ASSETS_SPEC, generateAbsoluteCapacitorBranding, inspectAbsoluteMobileBranding, renderAbsoluteMobileBrandingPreview, writeAbsoluteExpoProject2, syncAbsoluteExpoWebAssets2 };
3565
+ export { ABSOLUTE_DEPLOY_VERSION, ABSOLUTE_NATIVE_EXACT_PACKAGES, CAPACITOR_PACKAGE_SPECS, CAPACITOR_SYNC_PACKAGE_SPECS, EXPO_APP_EXACT_PACKAGES, EXPO_APP_PACKAGE_SPECS, EXPO_CODE_SIGNING_PACKAGE_SPEC, assertNativePackageVersions, packageNameFromSpec, packagesNeedingExactInstall, ABSOLUTE_MOBILE_UPDATE_FORMAT, absoluteMobileUpdateSigningPayload, canonicalizeAbsoluteMobileUpdate, parseAbsoluteMobileUpdateManifest, unsignedAbsoluteMobileUpdate, resolveAbsoluteMobileUpdateRuntime, ABSOLUTE_CAPACITOR_ASSETS_SPEC, generateAbsoluteCapacitorBranding, inspectAbsoluteMobileBranding, renderAbsoluteMobileBrandingPreview, writeAbsoluteExpoProject2, syncAbsoluteExpoWebAssets2 };