@absolutejs/absolute 0.20.0-beta.4 → 0.20.0-beta.5
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/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
- package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
- package/dist/angular/index.js +341 -22
- package/dist/angular/index.js.map +8 -5
- package/dist/angular/server.js +341 -22
- package/dist/angular/server.js.map +8 -5
- package/dist/build.js +94 -22
- package/dist/build.js.map +9 -9
- package/dist/cli/index.js +986 -557
- package/dist/dev/client/cssUtils.ts +16 -2
- package/dist/dev/client/handlers/rebuild.ts +11 -1
- package/dist/dev/client/hmrTiming.ts +14 -7
- package/dist/index.js +364 -191
- package/dist/index.js.map +17 -17
- package/dist/mobile/browser.js +14 -1
- package/dist/mobile/browser.js.map +3 -3
- package/dist/mobile/index.js +588 -99
- package/dist/mobile/index.js.map +15 -13
- package/dist/mobile/remoteMacAgentEntry.js +8 -8
- package/dist/src/angular/pageHandler.d.ts +3 -0
- package/dist/src/cli/config/server.d.ts +1 -1
- package/dist/src/core/pageHandlers.d.ts +11 -2
- package/dist/src/mobile/androidEmulatorController.d.ts +6 -1
- package/dist/src/mobile/buildPipeline.d.ts +1 -0
- package/dist/src/mobile/capacitorBundle.d.ts +11 -1
- package/dist/src/mobile/client.d.ts +4 -0
- package/dist/src/mobile/index.d.ts +1 -0
- package/dist/src/mobile/nativeAuth.d.ts +17 -0
- package/dist/src/mobile/releaseArtifact.d.ts +2 -0
- package/dist/src/mobile/shellAuth.d.ts +8 -0
- package/dist/src/mobile/shellBootstrap.d.ts +11 -1
- package/dist/src/mobile/shellSync.d.ts +2 -0
- package/dist/src/mobile/staticDocument.d.ts +5 -0
- package/dist/src/mobile/transport.d.ts +9 -1
- package/dist/src/plugins/imageOptimizer.d.ts +1 -1
- package/dist/src/svelte/pageHandler.d.ts +3 -0
- package/dist/src/vue/pageHandler.d.ts +3 -0
- package/dist/svelte/index.js +312 -23
- package/dist/svelte/index.js.map +7 -4
- package/dist/svelte/server.js +307 -18
- package/dist/svelte/server.js.map +7 -4
- package/dist/vue/index.js +312 -23
- package/dist/vue/index.js.map +7 -4
- package/dist/vue/server.js +307 -18
- package/dist/vue/server.js.map +7 -4
- package/package.json +20 -8
package/dist/mobile/index.js
CHANGED
|
@@ -159,6 +159,14 @@ var init_startupBanner = __esm(() => {
|
|
|
159
159
|
];
|
|
160
160
|
});
|
|
161
161
|
|
|
162
|
+
// src/utils/stringModifiers.ts
|
|
163
|
+
var normalizeSlug = (str) => str.trim().replace(/\s+/g, "-").replace(/[^A-Za-z0-9\-_]+/g, "").replace(/[-_]{2,}/g, "-"), toKebab = (str) => normalizeSlug(str).replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), toPascal = (str) => {
|
|
164
|
+
if (!str.includes("-") && !str.includes("_")) {
|
|
165
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
166
|
+
}
|
|
167
|
+
return normalizeSlug(str).split(/[-_]/).filter(Boolean).map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1).toLowerCase()).join("");
|
|
168
|
+
};
|
|
169
|
+
|
|
162
170
|
// src/mobile/artifactStore.ts
|
|
163
171
|
import { createHash as createHash2 } from "crypto";
|
|
164
172
|
import {
|
|
@@ -249,13 +257,19 @@ var parseCompatibilityPage = (value) => {
|
|
|
249
257
|
if (!isCanonicalRecord(value) || !isPageFramework(value.framework)) {
|
|
250
258
|
throw new TypeError("Compatibility artifact contains an invalid page.");
|
|
251
259
|
}
|
|
260
|
+
const styleBundleHash = typeof value.styleBundleHash === "string" ? value.styleBundleHash : undefined;
|
|
261
|
+
const styleBundlePath = typeof value.styleBundlePath === "string" ? value.styleBundlePath : undefined;
|
|
262
|
+
if (Boolean(styleBundleHash) !== Boolean(styleBundlePath)) {
|
|
263
|
+
throw new TypeError("Compatibility page style hash and path must be provided together.");
|
|
264
|
+
}
|
|
252
265
|
return {
|
|
253
266
|
bundleHash: readString(value.bundleHash, "page.bundleHash"),
|
|
254
267
|
bundlePath: readString(value.bundlePath, "page.bundlePath"),
|
|
255
268
|
contract: readString(value.contract, "page.contract"),
|
|
256
269
|
framework: value.framework,
|
|
257
270
|
pageId: readString(value.pageId, "page.pageId"),
|
|
258
|
-
propsSchemaHash: readString(value.propsSchemaHash, "page.propsSchemaHash")
|
|
271
|
+
propsSchemaHash: readString(value.propsSchemaHash, "page.propsSchemaHash"),
|
|
272
|
+
...styleBundleHash && styleBundlePath ? { styleBundleHash, styleBundlePath } : {}
|
|
259
273
|
};
|
|
260
274
|
};
|
|
261
275
|
var parseCompatibilityRoute = (value) => {
|
|
@@ -287,14 +301,23 @@ var validateProducerModule = (module) => {
|
|
|
287
301
|
}
|
|
288
302
|
return module;
|
|
289
303
|
};
|
|
290
|
-
var normalizePage = (page) =>
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
304
|
+
var normalizePage = (page) => {
|
|
305
|
+
if (Boolean(page.styleBundleHash) !== Boolean(page.styleBundlePath)) {
|
|
306
|
+
throw new TypeError("Compatibility page style hash and path must be provided together.");
|
|
307
|
+
}
|
|
308
|
+
return {
|
|
309
|
+
bundleHash: requireNonEmpty(page.bundleHash, "page.bundleHash"),
|
|
310
|
+
bundlePath: requireNonEmpty(page.bundlePath, "page.bundlePath"),
|
|
311
|
+
contract: requireNonEmpty(page.contract, "page.contract"),
|
|
312
|
+
framework: page.framework,
|
|
313
|
+
pageId: requireNonEmpty(page.pageId, "page.pageId"),
|
|
314
|
+
propsSchemaHash: requireNonEmpty(page.propsSchemaHash, "page.propsSchemaHash"),
|
|
315
|
+
...page.styleBundleHash && page.styleBundlePath ? {
|
|
316
|
+
styleBundleHash: requireNonEmpty(page.styleBundleHash, "page.styleBundleHash"),
|
|
317
|
+
styleBundlePath: requireNonEmpty(page.styleBundlePath, "page.styleBundlePath")
|
|
318
|
+
} : {}
|
|
319
|
+
};
|
|
320
|
+
};
|
|
298
321
|
var normalizeRoute = (route) => {
|
|
299
322
|
if (!route.pattern.startsWith("/")) {
|
|
300
323
|
throw new TypeError("route.pattern must start with /.");
|
|
@@ -1059,11 +1082,11 @@ var hashNativeTree = async (root, label, ignorePublicBundle) => {
|
|
|
1059
1082
|
const records = await collectNativeDirectory(resolvedRoot, label, resolvedRoot, ignorePublicBundle);
|
|
1060
1083
|
return createHash3("sha256").update(records.join("")).digest("hex");
|
|
1061
1084
|
};
|
|
1062
|
-
var fingerprintAbsoluteAndroidNativeProject = async (project) => {
|
|
1085
|
+
var fingerprintAbsoluteAndroidNativeProject = async (project, options = {}) => {
|
|
1063
1086
|
const { dependencies } = await nativeDependencySources(project.nativeDirectory);
|
|
1064
1087
|
const roots = [
|
|
1065
1088
|
{
|
|
1066
|
-
ignorePublicBundle: true,
|
|
1089
|
+
ignorePublicBundle: options.includePublicBundle !== true,
|
|
1067
1090
|
label: "android",
|
|
1068
1091
|
source: project.nativeDirectory
|
|
1069
1092
|
},
|
|
@@ -3143,8 +3166,9 @@ var normalizeEntry = (entry) => {
|
|
|
3143
3166
|
};
|
|
3144
3167
|
var normalizeProductionOrigin = (value) => {
|
|
3145
3168
|
const parsed = new URL(requireText(value, "mobile.server.productionOrigin"));
|
|
3146
|
-
|
|
3147
|
-
|
|
3169
|
+
const isLoopbackHttp = parsed.protocol === "http:" && (parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1" || parsed.hostname === "[::1]");
|
|
3170
|
+
if (parsed.protocol !== "https:" && !isLoopbackHttp) {
|
|
3171
|
+
throw new TypeError("mobile.server.productionOrigin must use HTTPS, except for a loopback development origin.");
|
|
3148
3172
|
}
|
|
3149
3173
|
if (parsed.username || parsed.password || parsed.pathname !== "/" || parsed.search || parsed.hash) {
|
|
3150
3174
|
throw new TypeError("mobile.server.productionOrigin must be an origin without credentials, path, query, or hash.");
|
|
@@ -3168,9 +3192,8 @@ var normalizeHosts = (hosts, productionOrigin) => {
|
|
|
3168
3192
|
}
|
|
3169
3193
|
return value;
|
|
3170
3194
|
};
|
|
3171
|
-
const
|
|
3172
|
-
|
|
3173
|
-
]);
|
|
3195
|
+
const productionHostname = new URL(productionOrigin).hostname;
|
|
3196
|
+
const normalized = new Set(productionHostname === "[::1]" ? [] : [normalizeHostname(productionHostname)]);
|
|
3174
3197
|
for (const host of hosts ?? []) {
|
|
3175
3198
|
normalized.add(normalizeHostname(host));
|
|
3176
3199
|
}
|
|
@@ -3208,7 +3231,7 @@ var normalizeAbsoluteMobileConfig = (config, projectRoot) => {
|
|
|
3208
3231
|
throw new TypeError("mobile.appId must use reverse-domain notation, for example com.example.app.");
|
|
3209
3232
|
}
|
|
3210
3233
|
const productionOrigin = normalizeProductionOrigin(config.server.productionOrigin);
|
|
3211
|
-
const deepLinkScheme = config.deepLinks?.scheme
|
|
3234
|
+
const deepLinkScheme = (config.deepLinks?.scheme ?? appId).trim().toLowerCase();
|
|
3212
3235
|
if (deepLinkScheme && !SCHEME_PATTERN.test(deepLinkScheme)) {
|
|
3213
3236
|
throw new TypeError("mobile.deepLinks.scheme is not a valid URL scheme.");
|
|
3214
3237
|
}
|
|
@@ -3472,14 +3495,22 @@ var parseAbsoluteMobileBuildPageMetadata = (value) => {
|
|
|
3472
3495
|
};
|
|
3473
3496
|
// src/mobile/buildPipeline.ts
|
|
3474
3497
|
import { readFile as readFile13 } from "fs/promises";
|
|
3475
|
-
import { join as
|
|
3498
|
+
import { join as join12, resolve as resolve10 } from "path";
|
|
3476
3499
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
3477
3500
|
|
|
3478
3501
|
// src/mobile/buildRelease.ts
|
|
3479
3502
|
import { createHash as createHash8 } from "crypto";
|
|
3480
|
-
import { readFile as readFile10 } from "fs/promises";
|
|
3481
|
-
import { join as join8, relative as relative7, resolve as resolve8 } from "path";
|
|
3503
|
+
import { mkdir as mkdir8, readFile as readFile10, writeFile as writeFile9 } from "fs/promises";
|
|
3504
|
+
import { basename as basename2, dirname as dirname6, extname, join as join8, relative as relative7, resolve as resolve8 } from "path";
|
|
3482
3505
|
var sha256 = (bytes) => createHash8("sha256").update(bytes).digest("hex");
|
|
3506
|
+
var STATIC_SCRIPT_PATTERN = /(<script\b[^>]*?\bsrc\s*=\s*["'])(\/[^"']+\.(?:js|ts))(["'][^>]*>)/giu;
|
|
3507
|
+
var rewriteStaticScriptPaths = (source, manifest) => source.replace(STATIC_SCRIPT_PATTERN, (match, prefix, path, suffix) => {
|
|
3508
|
+
if (path.endsWith("/htmx.min.js"))
|
|
3509
|
+
return match;
|
|
3510
|
+
const key = toPascal(basename2(path, extname(path)));
|
|
3511
|
+
const builtPath = manifest[key];
|
|
3512
|
+
return builtPath ? `${prefix}${builtPath}${suffix}` : match;
|
|
3513
|
+
});
|
|
3483
3514
|
var readPageMetadata = (route) => parseAbsoluteMobileBuildPageMetadata(route.hooks?.detail?.[ABSOLUTE_MOBILE_ROUTE_DETAIL]);
|
|
3484
3515
|
var resolveAssetPath = (buildDirectory, assetPath) => {
|
|
3485
3516
|
const resolvedBuildDirectory = resolve8(buildDirectory);
|
|
@@ -3494,16 +3525,38 @@ var pageFor = async (metadata, manifest, buildDirectory) => {
|
|
|
3494
3525
|
if (!assetPath) {
|
|
3495
3526
|
throw new TypeError(`Mobile page ${metadata.pageId} references missing manifest asset ${metadata.bundleKey}.`);
|
|
3496
3527
|
}
|
|
3497
|
-
|
|
3498
|
-
|
|
3528
|
+
let resolvedAssetPath = resolveAssetPath(buildDirectory, assetPath);
|
|
3529
|
+
if (metadata.framework === "html" || metadata.framework === "htmx") {
|
|
3530
|
+
const source = await readFile10(resolvedAssetPath, "utf8");
|
|
3531
|
+
const rewritten = rewriteStaticScriptPaths(source, manifest);
|
|
3532
|
+
const documentHash = sha256(new TextEncoder().encode(rewritten));
|
|
3533
|
+
resolvedAssetPath = join8(buildDirectory, ".absolutejs", "mobile-pages", `${documentHash}.html`);
|
|
3534
|
+
await mkdir8(dirname6(resolvedAssetPath), { recursive: true });
|
|
3535
|
+
await writeFile9(resolvedAssetPath, rewritten);
|
|
3536
|
+
}
|
|
3537
|
+
const pageAssetKey = metadata.bundleKey.replace(/Index$/u, "");
|
|
3538
|
+
const styleAssetPath = [
|
|
3539
|
+
`${pageAssetKey}BundledCSS`,
|
|
3540
|
+
`${pageAssetKey}CompiledCSS`
|
|
3541
|
+
].map((key) => manifest[key]).find((path) => typeof path === "string");
|
|
3542
|
+
const resolvedStylePath = styleAssetPath ? resolveAssetPath(buildDirectory, styleAssetPath) : undefined;
|
|
3543
|
+
const [bytes, styleBytes] = await Promise.all([
|
|
3544
|
+
readFile10(resolvedAssetPath),
|
|
3545
|
+
resolvedStylePath ? readFile10(resolvedStylePath) : undefined
|
|
3546
|
+
]);
|
|
3499
3547
|
const bundlePath = `/${relative7(resolve8(buildDirectory), resolvedAssetPath).replaceAll("\\", "/")}`;
|
|
3548
|
+
const styleBundlePath = resolvedStylePath ? `/${relative7(resolve8(buildDirectory), resolvedStylePath).replaceAll("\\", "/")}` : undefined;
|
|
3500
3549
|
return {
|
|
3501
3550
|
bundleHash: sha256(bytes),
|
|
3502
3551
|
bundlePath,
|
|
3503
3552
|
contract: metadata.contract,
|
|
3504
3553
|
framework: metadata.framework,
|
|
3505
3554
|
pageId: metadata.pageId,
|
|
3506
|
-
propsSchemaHash: metadata.propsSchemaHash
|
|
3555
|
+
propsSchemaHash: metadata.propsSchemaHash,
|
|
3556
|
+
...styleBytes && styleBundlePath ? {
|
|
3557
|
+
styleBundleHash: sha256(styleBytes),
|
|
3558
|
+
styleBundlePath
|
|
3559
|
+
} : {}
|
|
3507
3560
|
};
|
|
3508
3561
|
};
|
|
3509
3562
|
var buildAbsoluteMobileCompatibilityRelease = async (options) => {
|
|
@@ -3525,11 +3578,19 @@ var buildAbsoluteMobileCompatibilityRelease = async (options) => {
|
|
|
3525
3578
|
const pages = await Promise.all([...metadataByPage.values()].map((metadata) => pageFor(metadata, options.manifest, options.buildDirectory)));
|
|
3526
3579
|
const producerHash = sha256(producerBytes);
|
|
3527
3580
|
const appBuild = `ambuild_${sha256(new TextEncoder().encode(JSON.stringify({
|
|
3528
|
-
pages: pages.map(({
|
|
3581
|
+
pages: pages.map(({
|
|
3582
|
+
bundleHash,
|
|
3583
|
+
bundlePath,
|
|
3584
|
+
contract,
|
|
3585
|
+
pageId,
|
|
3586
|
+
styleBundleHash,
|
|
3587
|
+
styleBundlePath
|
|
3588
|
+
}) => ({
|
|
3529
3589
|
bundleHash,
|
|
3530
3590
|
bundlePath,
|
|
3531
3591
|
contract,
|
|
3532
|
-
pageId
|
|
3592
|
+
pageId,
|
|
3593
|
+
...styleBundleHash && styleBundlePath ? { styleBundleHash, styleBundlePath } : {}
|
|
3533
3594
|
})),
|
|
3534
3595
|
producerHash,
|
|
3535
3596
|
runtime: options.runtime
|
|
@@ -3589,16 +3650,17 @@ var captureAbsoluteMobileRouteGraph = async (app) => {
|
|
|
3589
3650
|
|
|
3590
3651
|
// src/mobile/capacitorBundle.ts
|
|
3591
3652
|
import {
|
|
3653
|
+
cp,
|
|
3592
3654
|
copyFile as copyFile5,
|
|
3593
|
-
mkdir as
|
|
3655
|
+
mkdir as mkdir9,
|
|
3594
3656
|
mkdtemp as mkdtemp4,
|
|
3595
3657
|
readFile as readFile11,
|
|
3596
3658
|
rename as rename9,
|
|
3597
3659
|
rm as rm7,
|
|
3598
|
-
writeFile as
|
|
3660
|
+
writeFile as writeFile10
|
|
3599
3661
|
} from "fs/promises";
|
|
3600
3662
|
import { existsSync as existsSync2 } from "fs";
|
|
3601
|
-
import { basename as
|
|
3663
|
+
import { basename as basename3, dirname as dirname7, extname as extname2, join as join9, relative as relative8, resolve as resolve9 } from "path";
|
|
3602
3664
|
|
|
3603
3665
|
// src/mobile/routeMatcher.ts
|
|
3604
3666
|
var REGEXP_SPECIAL_CHARACTERS = /[.*+?^${}()|[\]\\]/g;
|
|
@@ -3871,6 +3933,13 @@ class AbsoluteMobilePageProtocolError extends Error {
|
|
|
3871
3933
|
this.code = code;
|
|
3872
3934
|
}
|
|
3873
3935
|
}
|
|
3936
|
+
var disposeAbsoluteMobilePage = async (target = window) => {
|
|
3937
|
+
const dispose = target.__ABSOLUTE_PAGE_DISPOSE__;
|
|
3938
|
+
target.__ABSOLUTE_PAGE_DISPOSE__ = undefined;
|
|
3939
|
+
target.__ABSOLUTE_PAGE_READY__ = undefined;
|
|
3940
|
+
if (dispose)
|
|
3941
|
+
await dispose();
|
|
3942
|
+
};
|
|
3874
3943
|
var frameworks4 = new Set([
|
|
3875
3944
|
"angular",
|
|
3876
3945
|
"ember",
|
|
@@ -3926,12 +3995,17 @@ var activateAbsoluteMobilePage = async (value, options) => {
|
|
|
3926
3995
|
throw new AbsoluteMobilePageProtocolError("invalid-envelope", "Expected a renderable mobile page response.");
|
|
3927
3996
|
}
|
|
3928
3997
|
const target = options.target ?? window;
|
|
3998
|
+
await disposeAbsoluteMobilePage(target);
|
|
3929
3999
|
target.__INITIAL_PROPS__ = envelope.response.props;
|
|
4000
|
+
target.__ABS_ANGULAR_REQUEST_CONTEXT__ = envelope.response.props;
|
|
3930
4001
|
target.__ABSOLUTE_PAGE_RENDER_MODE__ = "client";
|
|
3931
4002
|
await options.loadPage({
|
|
3932
4003
|
contract: envelope.response.contract,
|
|
3933
4004
|
pageId: envelope.response.pageId
|
|
3934
4005
|
});
|
|
4006
|
+
if (target.__ABSOLUTE_PAGE_READY__) {
|
|
4007
|
+
await target.__ABSOLUTE_PAGE_READY__;
|
|
4008
|
+
}
|
|
3935
4009
|
return {
|
|
3936
4010
|
contract: envelope.response.contract,
|
|
3937
4011
|
kind: "rendered",
|
|
@@ -4024,12 +4098,32 @@ var resolveAbsoluteMobileDeepLink = (manifest, value) => {
|
|
|
4024
4098
|
}
|
|
4025
4099
|
return `${url.pathname || "/"}${url.search}${url.hash}`;
|
|
4026
4100
|
};
|
|
4101
|
+
var resolveAbsoluteMobileNavigation = (manifest, value, localOrigin) => {
|
|
4102
|
+
const url = new URL(value, `${localOrigin}/`);
|
|
4103
|
+
const local = new URL(localOrigin);
|
|
4104
|
+
const production = new URL(manifest.productionOrigin);
|
|
4105
|
+
const matches = (candidate, allowed) => candidate.protocol === allowed.protocol && candidate.host === allowed.host;
|
|
4106
|
+
if (!matches(url, local) && !matches(url, production)) {
|
|
4107
|
+
return;
|
|
4108
|
+
}
|
|
4109
|
+
return `${url.pathname}${url.search}${url.hash}`;
|
|
4110
|
+
};
|
|
4027
4111
|
|
|
4028
4112
|
// src/mobile/capacitorBundle.ts
|
|
4029
4113
|
var MANIFEST_FILE = "absolute-mobile-manifest.json";
|
|
4030
4114
|
var BOOTSTRAP_FILE = "absolute-mobile-bootstrap.js";
|
|
4031
4115
|
var INDEX_FILE = "index.html";
|
|
4032
|
-
var
|
|
4116
|
+
var CLIENT_CSS_DEPENDENCY_PATTERN = /(?:@import\s+(?:url\(\s*)?|url\(\s*)["']?((?:\/|\.\.\/|\.\/)[^"')\s]+)["']?\s*\)?/gu;
|
|
4117
|
+
var CLIENT_MARKUP_DEPENDENCY_PATTERN = /<(?:script\b[^>]*\bsrc|link\b[^>]*\bhref|img\b[^>]*\bsrc|source\b[^>]*\bsrcset)\s*=\s*["']((?:\/|\.\.\/|\.\/)[^"',\s]+)/giu;
|
|
4118
|
+
var CAPACITOR_CLIENT_FRAMEWORKS = new Set([
|
|
4119
|
+
"angular",
|
|
4120
|
+
"html",
|
|
4121
|
+
"htmx",
|
|
4122
|
+
"react",
|
|
4123
|
+
"svelte",
|
|
4124
|
+
"vue"
|
|
4125
|
+
]);
|
|
4126
|
+
var CLIENT_ASSET_DIRECTORIES = ["assets", "html", "htmx", "indexes"];
|
|
4033
4127
|
var errorHasCode2 = (error, code) => typeof error === "object" && error !== null && Reflect.get(error, "code") === code;
|
|
4034
4128
|
var shellBootstrapModule = () => {
|
|
4035
4129
|
const candidate = ["js", "ts"].map((extension) => join9(import.meta.dir, `shellBootstrap.${extension}`)).find(existsSync2);
|
|
@@ -4037,6 +4131,18 @@ var shellBootstrapModule = () => {
|
|
|
4037
4131
|
return candidate;
|
|
4038
4132
|
throw new TypeError("AbsoluteJS mobile shell bootstrap module is missing.");
|
|
4039
4133
|
};
|
|
4134
|
+
var shellAuthModule = () => {
|
|
4135
|
+
const candidate = ["js", "ts"].map((extension) => join9(import.meta.dir, `shellAuth.${extension}`)).find(existsSync2);
|
|
4136
|
+
if (candidate)
|
|
4137
|
+
return candidate;
|
|
4138
|
+
throw new TypeError("AbsoluteJS mobile auth shell module is missing.");
|
|
4139
|
+
};
|
|
4140
|
+
var shellSyncModule = () => {
|
|
4141
|
+
const candidate = ["js", "ts"].map((extension) => join9(import.meta.dir, `shellSync.${extension}`)).find(existsSync2);
|
|
4142
|
+
if (candidate)
|
|
4143
|
+
return candidate;
|
|
4144
|
+
throw new TypeError("AbsoluteJS mobile Sync shell module is missing.");
|
|
4145
|
+
};
|
|
4040
4146
|
var escapeHtml = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """);
|
|
4041
4147
|
var indexHtml = (appName) => `<!doctype html>
|
|
4042
4148
|
<html>
|
|
@@ -4060,11 +4166,16 @@ var sourceAssetPath = (buildDirectory, bundlePath) => {
|
|
|
4060
4166
|
}
|
|
4061
4167
|
return asset;
|
|
4062
4168
|
};
|
|
4063
|
-
var buildShellBootstrap = async (staging) => {
|
|
4169
|
+
var buildShellBootstrap = async (staging, auth, sync) => {
|
|
4064
4170
|
const modulePath = shellBootstrapModule();
|
|
4171
|
+
const authImport = auth ? `import { createAbsoluteMobileShellAuth } from ${JSON.stringify(shellAuthModule())};
|
|
4172
|
+
` : "";
|
|
4173
|
+
const options = auth ? `{ createAuth: createAbsoluteMobileShellAuth${sync ? ", installSync: installAbsoluteMobileShellSync" : ""} }` : "";
|
|
4174
|
+
const syncImport = sync ? `import { installAbsoluteMobileShellSync } from ${JSON.stringify(shellSyncModule())};
|
|
4175
|
+
` : "";
|
|
4065
4176
|
const entryPath = join9(staging, ".absolute-mobile-entry.ts");
|
|
4066
|
-
await
|
|
4067
|
-
void startAbsoluteMobileShell();
|
|
4177
|
+
await writeFile10(entryPath, `import { startAbsoluteMobileShell } from ${JSON.stringify(modulePath)};
|
|
4178
|
+
${authImport}${syncImport}void startAbsoluteMobileShell(${options});
|
|
4068
4179
|
`);
|
|
4069
4180
|
const build = await Bun.build({
|
|
4070
4181
|
entrypoints: [entryPath],
|
|
@@ -4107,21 +4218,62 @@ var installBundle = async (staging, destination) => {
|
|
|
4107
4218
|
}
|
|
4108
4219
|
};
|
|
4109
4220
|
var copyClientPage = async (page, buildDirectory, staging, copiedDependencies) => {
|
|
4110
|
-
if (page.framework
|
|
4111
|
-
throw new TypeError(`Capacitor
|
|
4221
|
+
if (!CAPACITOR_CLIENT_FRAMEWORKS.has(page.framework)) {
|
|
4222
|
+
throw new TypeError(`Capacitor client rendering does not yet support ${page.framework} page ${page.pageId}.`);
|
|
4112
4223
|
}
|
|
4113
|
-
const extension =
|
|
4224
|
+
const extension = extname2(page.bundlePath) || ".js";
|
|
4114
4225
|
const localBundlePath = `./pages/${page.bundleHash}${extension}`;
|
|
4115
4226
|
const source = sourceAssetPath(buildDirectory, page.bundlePath);
|
|
4116
4227
|
await copyFile5(source, join9(staging, localBundlePath));
|
|
4117
4228
|
await copyAbsoluteClientDependencies(source, buildDirectory, staging, copiedDependencies);
|
|
4118
|
-
|
|
4229
|
+
let localStylePath;
|
|
4230
|
+
if (page.styleBundlePath && page.styleBundleHash) {
|
|
4231
|
+
const styleExtension = extname2(page.styleBundlePath) || ".css";
|
|
4232
|
+
localStylePath = `./styles/${page.styleBundleHash}${styleExtension}`;
|
|
4233
|
+
const styleSource = sourceAssetPath(buildDirectory, page.styleBundlePath);
|
|
4234
|
+
await mkdir9(dirname7(join9(staging, localStylePath)), {
|
|
4235
|
+
recursive: true
|
|
4236
|
+
});
|
|
4237
|
+
await copyFile5(styleSource, join9(staging, localStylePath));
|
|
4238
|
+
await copyAbsoluteClientDependencies(styleSource, buildDirectory, staging, copiedDependencies);
|
|
4239
|
+
}
|
|
4240
|
+
return {
|
|
4241
|
+
...page,
|
|
4242
|
+
localBundlePath,
|
|
4243
|
+
...localStylePath ? { localStylePath } : {}
|
|
4244
|
+
};
|
|
4119
4245
|
};
|
|
4120
|
-
var absoluteClientImports = async (sourcePath) => {
|
|
4246
|
+
var absoluteClientImports = async (sourcePath, buildDirectory) => {
|
|
4121
4247
|
const source = await readFile11(sourcePath, "utf8");
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4248
|
+
const extension = extname2(sourcePath).toLowerCase();
|
|
4249
|
+
let scriptLoader;
|
|
4250
|
+
if (extension === ".tsx")
|
|
4251
|
+
scriptLoader = "tsx";
|
|
4252
|
+
else if (extension === ".ts")
|
|
4253
|
+
scriptLoader = "ts";
|
|
4254
|
+
else if (extension === ".jsx")
|
|
4255
|
+
scriptLoader = "jsx";
|
|
4256
|
+
else if ([".js", ".mjs", ".cjs"].includes(extension))
|
|
4257
|
+
scriptLoader = "js";
|
|
4258
|
+
const scriptImports = scriptLoader ? new Bun.Transpiler({ loader: scriptLoader }).scanImports(source).map(({ path }) => path) : [];
|
|
4259
|
+
const cssImports = extension === ".css" ? [...source.matchAll(CLIENT_CSS_DEPENDENCY_PATTERN)].flatMap((match) => match[1] ?? []) : [];
|
|
4260
|
+
const markupImports = extension === ".html" ? [...source.matchAll(CLIENT_MARKUP_DEPENDENCY_PATTERN)].flatMap((match) => match[1] ?? []) : [];
|
|
4261
|
+
return [...scriptImports, ...cssImports, ...markupImports].flatMap((specifier) => {
|
|
4262
|
+
if (!specifier)
|
|
4263
|
+
return [];
|
|
4264
|
+
if (!specifier.startsWith("/") && !specifier.startsWith("./") && !specifier.startsWith("../")) {
|
|
4265
|
+
return [];
|
|
4266
|
+
}
|
|
4267
|
+
const clean = specifier.split(/[?#]/u, 1)[0] ?? specifier;
|
|
4268
|
+
if (clean.startsWith("/"))
|
|
4269
|
+
return [clean];
|
|
4270
|
+
const resolved = resolve9(dirname7(sourcePath), clean);
|
|
4271
|
+
const root = resolve9(buildDirectory);
|
|
4272
|
+
const relativePath = relative8(root, resolved).replaceAll("\\", "/");
|
|
4273
|
+
if (relativePath === ".." || relativePath.startsWith("../")) {
|
|
4274
|
+
throw new TypeError(`Mobile client dependency escaped the build directory: ${specifier}`);
|
|
4275
|
+
}
|
|
4276
|
+
return [`/${relativePath}`];
|
|
4125
4277
|
});
|
|
4126
4278
|
};
|
|
4127
4279
|
var copyAbsoluteClientDependency = async (specifier, buildDirectory, staging, copied) => {
|
|
@@ -4130,12 +4282,12 @@ var copyAbsoluteClientDependency = async (specifier, buildDirectory, staging, co
|
|
|
4130
4282
|
copied.add(specifier);
|
|
4131
4283
|
const source = sourceAssetPath(buildDirectory, specifier);
|
|
4132
4284
|
const destination = join9(staging, specifier.replace(/^\/+/, ""));
|
|
4133
|
-
await
|
|
4285
|
+
await mkdir9(dirname7(destination), { recursive: true });
|
|
4134
4286
|
await copyFile5(source, destination);
|
|
4135
4287
|
await copyAbsoluteClientDependencies(source, buildDirectory, staging, copied);
|
|
4136
4288
|
};
|
|
4137
4289
|
var copyAbsoluteClientDependencies = async (sourcePath, buildDirectory, staging, copied) => {
|
|
4138
|
-
const dependencies = await absoluteClientImports(sourcePath);
|
|
4290
|
+
const dependencies = await absoluteClientImports(sourcePath, buildDirectory);
|
|
4139
4291
|
await Promise.all(dependencies.map((specifier) => copyAbsoluteClientDependency(specifier, buildDirectory, staging, copied)));
|
|
4140
4292
|
};
|
|
4141
4293
|
var materializeAbsoluteCapacitorWebBundle = async (options) => {
|
|
@@ -4143,15 +4295,20 @@ var materializeAbsoluteCapacitorWebBundle = async (options) => {
|
|
|
4143
4295
|
throw new TypeError(`mobile.entry ${options.config.entry} is not a captured mobile page route.`);
|
|
4144
4296
|
}
|
|
4145
4297
|
const destination = options.config.bundleDirectory;
|
|
4146
|
-
await
|
|
4147
|
-
const staging = await mkdtemp4(join9(
|
|
4298
|
+
await mkdir9(dirname7(destination), { recursive: true });
|
|
4299
|
+
const staging = await mkdtemp4(join9(dirname7(destination), `.${basename3(destination)}.stage-`));
|
|
4148
4300
|
try {
|
|
4149
4301
|
const pageDirectory = join9(staging, "pages");
|
|
4150
|
-
await
|
|
4302
|
+
await mkdir9(pageDirectory, { recursive: true });
|
|
4303
|
+
await Promise.all(CLIENT_ASSET_DIRECTORIES.map((directory) => ({
|
|
4304
|
+
destination: join9(staging, directory),
|
|
4305
|
+
source: join9(options.buildDirectory, directory)
|
|
4306
|
+
})).filter(({ source }) => existsSync2(source)).map(({ destination: assetDestination, source }) => cp(source, assetDestination, { recursive: true })));
|
|
4151
4307
|
const copiedDependencies = new Set;
|
|
4152
4308
|
const pages = await Promise.all(options.artifact.pages.map((page) => copyClientPage(page, options.buildDirectory, staging, copiedDependencies)));
|
|
4153
4309
|
const manifest = {
|
|
4154
4310
|
appBuild: options.artifact.appBuild,
|
|
4311
|
+
...options.auth ? { auth: options.auth } : {},
|
|
4155
4312
|
appId: options.config.appId,
|
|
4156
4313
|
appName: options.config.appName,
|
|
4157
4314
|
deepLinkHosts: options.config.deepLinkHosts,
|
|
@@ -4161,13 +4318,14 @@ var materializeAbsoluteCapacitorWebBundle = async (options) => {
|
|
|
4161
4318
|
pages,
|
|
4162
4319
|
productionOrigin: options.config.productionOrigin,
|
|
4163
4320
|
routes: options.artifact.routes,
|
|
4164
|
-
runtime: options.artifact.runtime
|
|
4321
|
+
runtime: options.artifact.runtime,
|
|
4322
|
+
...options.sync ? { sync: { socketTickets: true } } : {}
|
|
4165
4323
|
};
|
|
4166
4324
|
await Promise.all([
|
|
4167
|
-
|
|
4325
|
+
writeFile10(join9(staging, MANIFEST_FILE), `${JSON.stringify(manifest, null, "\t")}
|
|
4168
4326
|
`),
|
|
4169
|
-
|
|
4170
|
-
buildShellBootstrap(staging)
|
|
4327
|
+
writeFile10(join9(staging, INDEX_FILE), indexHtml(options.config.appName)),
|
|
4328
|
+
buildShellBootstrap(staging, options.auth !== undefined, options.auth !== undefined && options.sync === true)
|
|
4171
4329
|
]);
|
|
4172
4330
|
await installBundle(staging, destination);
|
|
4173
4331
|
return manifest;
|
|
@@ -4181,14 +4339,14 @@ var materializeAbsoluteCapacitorWebBundle = async (options) => {
|
|
|
4181
4339
|
import { createHash as createHash9 } from "crypto";
|
|
4182
4340
|
import {
|
|
4183
4341
|
access as access8,
|
|
4184
|
-
mkdir as
|
|
4342
|
+
mkdir as mkdir10,
|
|
4185
4343
|
mkdtemp as mkdtemp5,
|
|
4186
4344
|
readFile as readFile12,
|
|
4187
4345
|
rename as rename10,
|
|
4188
4346
|
rm as rm8,
|
|
4189
|
-
writeFile as
|
|
4347
|
+
writeFile as writeFile11
|
|
4190
4348
|
} from "fs/promises";
|
|
4191
|
-
import { dirname as
|
|
4349
|
+
import { dirname as dirname8, join as join10, resolve as resolvePath3 } from "path";
|
|
4192
4350
|
import { pathToFileURL } from "url";
|
|
4193
4351
|
var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1;
|
|
4194
4352
|
var CURRENT_BUNDLE_FILE = "current.json";
|
|
@@ -4230,11 +4388,11 @@ var parseBundleIndex = (value) => {
|
|
|
4230
4388
|
var writeRelease = async (root, release) => {
|
|
4231
4389
|
const directory = join10(root, release.artifact.releaseId);
|
|
4232
4390
|
const producerPath = join10(directory, release.artifact.producer.module);
|
|
4233
|
-
await
|
|
4391
|
+
await mkdir10(dirname8(producerPath), { recursive: true });
|
|
4234
4392
|
await Promise.all([
|
|
4235
|
-
|
|
4393
|
+
writeFile11(join10(directory, ARTIFACT_FILE2), `${JSON.stringify(release.artifact, null, "\t")}
|
|
4236
4394
|
`),
|
|
4237
|
-
|
|
4395
|
+
writeFile11(producerPath, new Uint8Array(await release.producer.arrayBuffer()))
|
|
4238
4396
|
]);
|
|
4239
4397
|
};
|
|
4240
4398
|
var installImmutableBundle = async (bundlesRoot, bundleId, releases) => {
|
|
@@ -4316,7 +4474,7 @@ var materializeAbsoluteMobileCompatibilityBundle = async (input) => {
|
|
|
4316
4474
|
});
|
|
4317
4475
|
const root = resolvePath3(input.root);
|
|
4318
4476
|
const bundlesRoot = join10(root, BUNDLES_DIRECTORY);
|
|
4319
|
-
await
|
|
4477
|
+
await mkdir10(bundlesRoot, { recursive: true });
|
|
4320
4478
|
const bundleId = bundleIdFor(input.currentReleaseId, artifacts);
|
|
4321
4479
|
await installImmutableBundle(bundlesRoot, bundleId, orderedReleases);
|
|
4322
4480
|
const index = {
|
|
@@ -4327,7 +4485,7 @@ var materializeAbsoluteMobileCompatibilityBundle = async (input) => {
|
|
|
4327
4485
|
};
|
|
4328
4486
|
const pointerPath = join10(root, CURRENT_BUNDLE_FILE);
|
|
4329
4487
|
const temporaryPointerPath = join10(root, `.current-${crypto.randomUUID()}.json`);
|
|
4330
|
-
await
|
|
4488
|
+
await writeFile11(temporaryPointerPath, `${JSON.stringify(index, null, "\t")}
|
|
4331
4489
|
`, { flag: "wx" });
|
|
4332
4490
|
await rename10(temporaryPointerPath, pointerPath);
|
|
4333
4491
|
return index;
|
|
@@ -4354,6 +4512,58 @@ var readAbsoluteMobileMaterializedReleases = async (root) => {
|
|
|
4354
4512
|
}
|
|
4355
4513
|
};
|
|
4356
4514
|
|
|
4515
|
+
// src/mobile/nativeAuth.ts
|
|
4516
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
4517
|
+
import { join as join11 } from "path";
|
|
4518
|
+
var ABSOLUTE_AUTH_PACKAGE = "@absolutejs/auth";
|
|
4519
|
+
var ABSOLUTE_NATIVE_AUTH_CLIENTS_ENV = "ABSOLUTE_AUTH_NATIVE_CLIENTS";
|
|
4520
|
+
var ABSOLUTE_NATIVE_AUTH_SCOPES = ["openid", "profile"];
|
|
4521
|
+
var ABSOLUTE_SYNC_PACKAGE = "@absolutejs/sync";
|
|
4522
|
+
var readPackageManifest = (projectRoot) => {
|
|
4523
|
+
try {
|
|
4524
|
+
return JSON.parse(readFileSync2(join11(projectRoot, "package.json"), "utf8"));
|
|
4525
|
+
} catch {
|
|
4526
|
+
return;
|
|
4527
|
+
}
|
|
4528
|
+
};
|
|
4529
|
+
var packageManifestHas = (manifest, packageName) => {
|
|
4530
|
+
if (typeof manifest !== "object" || manifest === null)
|
|
4531
|
+
return false;
|
|
4532
|
+
return [
|
|
4533
|
+
Reflect.get(manifest, "dependencies"),
|
|
4534
|
+
Reflect.get(manifest, "devDependencies"),
|
|
4535
|
+
Reflect.get(manifest, "optionalDependencies"),
|
|
4536
|
+
Reflect.get(manifest, "peerDependencies")
|
|
4537
|
+
].some((dependencies) => typeof dependencies === "object" && dependencies !== null && Object.hasOwn(dependencies, packageName));
|
|
4538
|
+
};
|
|
4539
|
+
var createAbsoluteMobileAuthManifest = (config) => {
|
|
4540
|
+
const scheme = config.deepLinkScheme ?? config.appId.toLowerCase();
|
|
4541
|
+
return {
|
|
4542
|
+
clientId: `absolutejs-native:${config.appId}`,
|
|
4543
|
+
issuer: config.productionOrigin,
|
|
4544
|
+
redirectUri: `${scheme}://auth/callback`,
|
|
4545
|
+
scopes: [...ABSOLUTE_NATIVE_AUTH_SCOPES]
|
|
4546
|
+
};
|
|
4547
|
+
};
|
|
4548
|
+
var installAbsoluteMobileAuthEnvironment = (projectRoot, config) => {
|
|
4549
|
+
const auth = resolveAbsoluteMobileAuthManifest(projectRoot, config);
|
|
4550
|
+
const serialized = serializeAbsoluteMobileAuthEnvironment(config, auth);
|
|
4551
|
+
if (serialized === undefined)
|
|
4552
|
+
delete process.env[ABSOLUTE_NATIVE_AUTH_CLIENTS_ENV];
|
|
4553
|
+
else
|
|
4554
|
+
process.env[ABSOLUTE_NATIVE_AUTH_CLIENTS_ENV] = serialized;
|
|
4555
|
+
return auth;
|
|
4556
|
+
};
|
|
4557
|
+
var projectUsesAbsoluteAuth = (projectRoot) => packageManifestHas(readPackageManifest(projectRoot), ABSOLUTE_AUTH_PACKAGE);
|
|
4558
|
+
var projectUsesAbsoluteSync = (projectRoot) => packageManifestHas(readPackageManifest(projectRoot), ABSOLUTE_SYNC_PACKAGE);
|
|
4559
|
+
var resolveAbsoluteMobileAuthManifest = (projectRoot, config) => projectUsesAbsoluteAuth(projectRoot) ? createAbsoluteMobileAuthManifest(config) : undefined;
|
|
4560
|
+
var serializeAbsoluteMobileAuthEnvironment = (config, auth) => auth === undefined ? undefined : JSON.stringify([
|
|
4561
|
+
{
|
|
4562
|
+
...auth,
|
|
4563
|
+
name: `${config.appName} native app`
|
|
4564
|
+
}
|
|
4565
|
+
]);
|
|
4566
|
+
|
|
4357
4567
|
// src/mobile/buildPipeline.ts
|
|
4358
4568
|
var isElysiaApp = (value) => typeof value === "object" && value !== null && typeof Reflect.get(value, "compile") === "function" && Array.isArray(Reflect.get(value, "routes"));
|
|
4359
4569
|
var isStringRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && Object.values(value).every((entry) => typeof entry === "string");
|
|
@@ -4364,12 +4574,11 @@ var serverExportName = (loaded, app) => {
|
|
|
4364
4574
|
return "app";
|
|
4365
4575
|
return "default";
|
|
4366
4576
|
};
|
|
4367
|
-
var
|
|
4368
|
-
if (previous !== undefined)
|
|
4369
|
-
process.env
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
delete process.env.ABSOLUTE_BUILD_DIR;
|
|
4577
|
+
var restoreEnvironmentVariable = (name, previous) => {
|
|
4578
|
+
if (previous !== undefined)
|
|
4579
|
+
process.env[name] = previous;
|
|
4580
|
+
else
|
|
4581
|
+
delete process.env[name];
|
|
4373
4582
|
};
|
|
4374
4583
|
var requireRelease = (releases, releaseId) => {
|
|
4375
4584
|
const release = releases.get(releaseId);
|
|
@@ -4391,9 +4600,9 @@ var loadServerApp = async (producerPath) => {
|
|
|
4391
4600
|
var finalizeAbsoluteMobileCompatibilityBuild = async (options) => {
|
|
4392
4601
|
const buildDirectory = resolve10(options.buildDirectory);
|
|
4393
4602
|
const mobile = normalizeAbsoluteMobileConfig(options.mobile, options.projectRoot);
|
|
4394
|
-
const root =
|
|
4603
|
+
const root = join12(buildDirectory, ".absolutejs", "mobile-compatibility");
|
|
4395
4604
|
const [manifestSource, previous] = await Promise.all([
|
|
4396
|
-
readFile13(
|
|
4605
|
+
readFile13(join12(buildDirectory, "manifest.json"), "utf8"),
|
|
4397
4606
|
readAbsoluteMobileMaterializedReleases(root)
|
|
4398
4607
|
]);
|
|
4399
4608
|
const manifest = JSON.parse(manifestSource);
|
|
@@ -4401,12 +4610,20 @@ var finalizeAbsoluteMobileCompatibilityBuild = async (options) => {
|
|
|
4401
4610
|
throw new TypeError("Invalid AbsoluteJS build manifest for mobile capture.");
|
|
4402
4611
|
}
|
|
4403
4612
|
const previousBuildDirectory = process.env.ABSOLUTE_BUILD_DIR;
|
|
4613
|
+
const previousCompiledRuntime = process.env.ABSOLUTE_COMPILED_RUNTIME;
|
|
4614
|
+
const previousConfigPath = process.env.ABSOLUTE_CONFIG;
|
|
4404
4615
|
process.env.ABSOLUTE_BUILD_DIR = buildDirectory;
|
|
4616
|
+
process.env.ABSOLUTE_COMPILED_RUNTIME = "1";
|
|
4617
|
+
if (options.configPath) {
|
|
4618
|
+
process.env.ABSOLUTE_CONFIG = resolve10(options.projectRoot, options.configPath);
|
|
4619
|
+
}
|
|
4405
4620
|
let loaded;
|
|
4406
4621
|
try {
|
|
4407
4622
|
loaded = await loadServerApp(resolve10(options.producerPath));
|
|
4408
4623
|
} finally {
|
|
4409
|
-
|
|
4624
|
+
restoreEnvironmentVariable("ABSOLUTE_BUILD_DIR", previousBuildDirectory);
|
|
4625
|
+
restoreEnvironmentVariable("ABSOLUTE_COMPILED_RUNTIME", previousCompiledRuntime);
|
|
4626
|
+
restoreEnvironmentVariable("ABSOLUTE_CONFIG", previousConfigPath);
|
|
4410
4627
|
}
|
|
4411
4628
|
const current = await buildAbsoluteMobileCompatibilityRelease({
|
|
4412
4629
|
app: loaded.app,
|
|
@@ -4418,6 +4635,11 @@ var finalizeAbsoluteMobileCompatibilityBuild = async (options) => {
|
|
|
4418
4635
|
producerPath: resolve10(options.producerPath),
|
|
4419
4636
|
runtime: String(ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION)
|
|
4420
4637
|
});
|
|
4638
|
+
const auth = resolveAbsoluteMobileAuthManifest(options.projectRoot, mobile);
|
|
4639
|
+
const sync = auth !== undefined && projectUsesAbsoluteSync(options.projectRoot);
|
|
4640
|
+
if (auth && !loaded.app.routes.some((route) => route.path === "/.well-known/openid-configuration")) {
|
|
4641
|
+
throw new TypeError("@absolutejs/auth is installed, but its OIDC provider is not mounted. Native authentication requires the auth oidc configuration so AbsoluteJS can provision a public PKCE client.");
|
|
4642
|
+
}
|
|
4421
4643
|
const releasesById = new Map([current, ...previous].map((release) => [
|
|
4422
4644
|
release.artifact.releaseId,
|
|
4423
4645
|
release
|
|
@@ -4430,8 +4652,10 @@ var finalizeAbsoluteMobileCompatibilityBuild = async (options) => {
|
|
|
4430
4652
|
});
|
|
4431
4653
|
await materializeAbsoluteCapacitorWebBundle({
|
|
4432
4654
|
artifact: current.artifact,
|
|
4655
|
+
...auth ? { auth } : {},
|
|
4433
4656
|
buildDirectory,
|
|
4434
|
-
config: mobile
|
|
4657
|
+
config: mobile,
|
|
4658
|
+
...sync ? { sync: true } : {}
|
|
4435
4659
|
});
|
|
4436
4660
|
return current.artifact;
|
|
4437
4661
|
};
|
|
@@ -4456,6 +4680,64 @@ var ensureProducerStorage = () => {
|
|
|
4456
4680
|
var runWithAbsoluteMobileProducer = (context, callback) => ensureProducerStorage().run(context, callback);
|
|
4457
4681
|
|
|
4458
4682
|
// src/mobile/compatibilityDispatcher.ts
|
|
4683
|
+
var MOBILE_WEBVIEW_ORIGINS = new Set([
|
|
4684
|
+
"capacitor://localhost",
|
|
4685
|
+
"http://localhost",
|
|
4686
|
+
"https://localhost"
|
|
4687
|
+
]);
|
|
4688
|
+
var MOBILE_REQUEST_HEADER_NAMES = Object.values(MOBILE_PAGE_REQUEST_HEADERS);
|
|
4689
|
+
var MOBILE_CORS_ALLOW_HEADERS = [
|
|
4690
|
+
"accept",
|
|
4691
|
+
"content-type",
|
|
4692
|
+
"authorization",
|
|
4693
|
+
"hx-current-url",
|
|
4694
|
+
"hx-request",
|
|
4695
|
+
"hx-target",
|
|
4696
|
+
"hx-trigger",
|
|
4697
|
+
"hx-trigger-name",
|
|
4698
|
+
...MOBILE_REQUEST_HEADER_NAMES
|
|
4699
|
+
].join(", ");
|
|
4700
|
+
var MOBILE_CORS_METHODS = new Set([
|
|
4701
|
+
"DELETE",
|
|
4702
|
+
"GET",
|
|
4703
|
+
"HEAD",
|
|
4704
|
+
"OPTIONS",
|
|
4705
|
+
"PATCH",
|
|
4706
|
+
"POST",
|
|
4707
|
+
"PUT"
|
|
4708
|
+
]);
|
|
4709
|
+
var mobileWebViewOrigin = (request) => {
|
|
4710
|
+
const origin = request.headers.get("origin");
|
|
4711
|
+
return origin && MOBILE_WEBVIEW_ORIGINS.has(origin) ? origin : undefined;
|
|
4712
|
+
};
|
|
4713
|
+
var applyMobileCorsHeaders = (response, origin) => {
|
|
4714
|
+
response.headers.set("access-control-allow-credentials", "true");
|
|
4715
|
+
response.headers.set("access-control-allow-origin", origin);
|
|
4716
|
+
response.headers.append("vary", "Origin");
|
|
4717
|
+
return response;
|
|
4718
|
+
};
|
|
4719
|
+
var mobilePreflightResponse = (request) => {
|
|
4720
|
+
if (request.method !== "OPTIONS")
|
|
4721
|
+
return;
|
|
4722
|
+
const origin = mobileWebViewOrigin(request);
|
|
4723
|
+
if (!origin)
|
|
4724
|
+
return;
|
|
4725
|
+
const requestedHeaders = request.headers.get("access-control-request-headers");
|
|
4726
|
+
const requestedMethod = request.headers.get("access-control-request-method")?.toUpperCase() ?? "";
|
|
4727
|
+
if (!MOBILE_CORS_METHODS.has(requestedMethod))
|
|
4728
|
+
return;
|
|
4729
|
+
return new Response(null, {
|
|
4730
|
+
headers: {
|
|
4731
|
+
"access-control-allow-credentials": "true",
|
|
4732
|
+
"access-control-allow-headers": requestedHeaders || MOBILE_CORS_ALLOW_HEADERS,
|
|
4733
|
+
"access-control-allow-methods": [...MOBILE_CORS_METHODS].join(", "),
|
|
4734
|
+
"access-control-allow-origin": origin,
|
|
4735
|
+
"access-control-max-age": "600",
|
|
4736
|
+
vary: "Origin, Access-Control-Request-Headers"
|
|
4737
|
+
},
|
|
4738
|
+
status: 204
|
|
4739
|
+
});
|
|
4740
|
+
};
|
|
4459
4741
|
var artifactOwnsRequest = (artifact, pageId, request) => {
|
|
4460
4742
|
const { pathname } = new URL(request.url);
|
|
4461
4743
|
return artifact.routes.some((route) => route.pageId === pageId && route.method === request.method && matchesAbsoluteMobileRoutePattern(route.pattern, pathname));
|
|
@@ -4483,6 +4765,9 @@ var createAbsoluteMobileCompatibilityDispatcher = (options) => {
|
|
|
4483
4765
|
return new Elysia2({ name: "absolutejs-mobile-compatibility-dispatcher" }).request(async ({ request }) => {
|
|
4484
4766
|
if (getCurrentAbsoluteMobileProducerContext())
|
|
4485
4767
|
return;
|
|
4768
|
+
const preflight = mobilePreflightResponse(request);
|
|
4769
|
+
if (preflight)
|
|
4770
|
+
return preflight;
|
|
4486
4771
|
const parsed = parseAbsoluteMobilePageRequest(request);
|
|
4487
4772
|
if (parsed.kind !== "mobile")
|
|
4488
4773
|
return;
|
|
@@ -4506,11 +4791,16 @@ var createAbsoluteMobileCompatibilityDispatcher = (options) => {
|
|
|
4506
4791
|
console.error(`[Mobile] Failed to load retained producer ${resolved.artifact.releaseId}:`, error);
|
|
4507
4792
|
return createAbsoluteMobilePageErrorResponse(parsed.client.pageId);
|
|
4508
4793
|
}
|
|
4794
|
+
}).afterHandle("global", ({ request, responseValue }) => {
|
|
4795
|
+
const origin = mobileWebViewOrigin(request);
|
|
4796
|
+
if (!origin || !(responseValue instanceof Response))
|
|
4797
|
+
return;
|
|
4798
|
+
applyMobileCorsHeaders(responseValue, origin);
|
|
4509
4799
|
}).as("global");
|
|
4510
4800
|
};
|
|
4511
4801
|
// src/mobile/nativeDeepLinks.ts
|
|
4512
|
-
import { readFile as readFile14, rename as rename11, writeFile as
|
|
4513
|
-
import { join as
|
|
4802
|
+
import { readFile as readFile14, rename as rename11, writeFile as writeFile12 } from "fs/promises";
|
|
4803
|
+
import { join as join13 } from "path";
|
|
4514
4804
|
var START_MARKER = "<!-- absolutejs:deep-links:start -->";
|
|
4515
4805
|
var END_MARKER = "<!-- absolutejs:deep-links:end -->";
|
|
4516
4806
|
var IOS_ENTITLEMENTS = "App/AbsoluteJS.entitlements";
|
|
@@ -4521,7 +4811,7 @@ var writeChangedFile = async (path, source) => {
|
|
|
4521
4811
|
if (current === source)
|
|
4522
4812
|
return false;
|
|
4523
4813
|
const temporary = `${path}.${crypto.randomUUID()}.tmp`;
|
|
4524
|
-
await
|
|
4814
|
+
await writeFile12(temporary, source, { flag: "wx" });
|
|
4525
4815
|
await rename11(temporary, path);
|
|
4526
4816
|
return true;
|
|
4527
4817
|
};
|
|
@@ -4567,7 +4857,7 @@ ${hosts}
|
|
|
4567
4857
|
`;
|
|
4568
4858
|
};
|
|
4569
4859
|
var configureAndroid = async (config) => {
|
|
4570
|
-
const path =
|
|
4860
|
+
const path = join13(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
|
|
4571
4861
|
const source = await readFile14(path, "utf8");
|
|
4572
4862
|
const mainActivity = source.indexOf('android:name=".MainActivity"');
|
|
4573
4863
|
if (mainActivity === NOT_FOUND) {
|
|
@@ -4593,7 +4883,7 @@ var iosSchemeRegion = (scheme) => ` ${START_MARKER}
|
|
|
4593
4883
|
${END_MARKER}
|
|
4594
4884
|
`;
|
|
4595
4885
|
var configureIosInfo = async (config) => {
|
|
4596
|
-
const path =
|
|
4886
|
+
const path = join13(config.nativeProjectDirectory, "ios/App/App/Info.plist");
|
|
4597
4887
|
const source = await readFile14(path, "utf8");
|
|
4598
4888
|
const region = config.deepLinkScheme ? iosSchemeRegion(config.deepLinkScheme) : ` ${START_MARKER}
|
|
4599
4889
|
${END_MARKER}
|
|
@@ -4617,7 +4907,7 @@ ${domains}
|
|
|
4617
4907
|
`;
|
|
4618
4908
|
};
|
|
4619
4909
|
var configureIosEntitlements = async (config) => {
|
|
4620
|
-
const path =
|
|
4910
|
+
const path = join13(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
|
|
4621
4911
|
let current = "";
|
|
4622
4912
|
try {
|
|
4623
4913
|
current = await readFile14(path, "utf8");
|
|
@@ -4630,12 +4920,12 @@ var configureIosEntitlements = async (config) => {
|
|
|
4630
4920
|
if (current === source)
|
|
4631
4921
|
return false;
|
|
4632
4922
|
const temporary = `${path}.${crypto.randomUUID()}.tmp`;
|
|
4633
|
-
await
|
|
4923
|
+
await writeFile12(temporary, source, { flag: "wx" });
|
|
4634
4924
|
await rename11(temporary, path);
|
|
4635
4925
|
return true;
|
|
4636
4926
|
};
|
|
4637
4927
|
var configureIosProject = async (config) => {
|
|
4638
|
-
const path =
|
|
4928
|
+
const path = join13(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
|
|
4639
4929
|
const source = await readFile14(path, "utf8");
|
|
4640
4930
|
const declarations = [
|
|
4641
4931
|
...source.matchAll(/CODE_SIGN_ENTITLEMENTS = ([^;]+);/g)
|
|
@@ -4675,7 +4965,7 @@ var applyAbsoluteNativeDeepLinks = async (config, platforms = config.platforms)
|
|
|
4675
4965
|
};
|
|
4676
4966
|
// src/mobile/releasePublisher.ts
|
|
4677
4967
|
import { access as access9 } from "fs/promises";
|
|
4678
|
-
import { isAbsolute as isAbsolute6, relative as
|
|
4968
|
+
import { isAbsolute as isAbsolute6, relative as relative9, resolve as resolve11, sep as sep6 } from "path";
|
|
4679
4969
|
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
4680
4970
|
var prepareAbsoluteIosRelease = async (publisher, options) => {
|
|
4681
4971
|
if (typeof publisher.prepareIosRelease !== "function") {
|
|
@@ -4703,7 +4993,7 @@ var isPublisher = (value) => isRecord8(value) && typeof value.publish === "funct
|
|
|
4703
4993
|
var publisherModulePath = (projectRoot, requested) => {
|
|
4704
4994
|
const root = resolve11(projectRoot);
|
|
4705
4995
|
const path = resolve11(root, requested);
|
|
4706
|
-
const projectRelative =
|
|
4996
|
+
const projectRelative = relative9(root, path);
|
|
4707
4997
|
if (projectRelative === ".." || projectRelative.startsWith(`..${sep6}`) || isAbsolute6(projectRelative)) {
|
|
4708
4998
|
throw new TypeError("mobile publish --registry must remain inside the project.");
|
|
4709
4999
|
}
|
|
@@ -4772,14 +5062,59 @@ var publishAbsoluteIosRelease = async (options) => {
|
|
|
4772
5062
|
return publication;
|
|
4773
5063
|
};
|
|
4774
5064
|
// src/mobile/routeMetadataTransform.ts
|
|
4775
|
-
import { existsSync as existsSync3, readFileSync as
|
|
4776
|
-
import { dirname as
|
|
5065
|
+
import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
|
|
5066
|
+
import { dirname as dirname9, extname as extname3, relative as relative10, resolve as resolve12 } from "path";
|
|
4777
5067
|
import ts from "typescript";
|
|
4778
5068
|
var ROUTE_METHODS = new Set(["get", "head"]);
|
|
4779
5069
|
var SOURCE_FILTER = /\.[cm]?[jt]sx?$/;
|
|
4780
|
-
var
|
|
5070
|
+
var PAGE_HANDLERS = new Map([
|
|
5071
|
+
[
|
|
5072
|
+
"handleHTMLPageRequest",
|
|
5073
|
+
{ framework: "html", inputKind: "static", propsProperty: "props" }
|
|
5074
|
+
],
|
|
5075
|
+
[
|
|
5076
|
+
"handleHTMXPageRequest",
|
|
5077
|
+
{ framework: "htmx", inputKind: "static", propsProperty: "props" }
|
|
5078
|
+
],
|
|
5079
|
+
[
|
|
5080
|
+
"handleAngularPageRequest",
|
|
5081
|
+
{
|
|
5082
|
+
bundleProperty: "indexPath",
|
|
5083
|
+
framework: "angular",
|
|
5084
|
+
propsProperty: "requestContext",
|
|
5085
|
+
sourceProperty: "pagePath"
|
|
5086
|
+
}
|
|
5087
|
+
],
|
|
5088
|
+
[
|
|
5089
|
+
"handleReactPageRequest",
|
|
5090
|
+
{
|
|
5091
|
+
bundleProperty: "index",
|
|
5092
|
+
framework: "react",
|
|
5093
|
+
pageProperty: "Page",
|
|
5094
|
+
propsProperty: "props"
|
|
5095
|
+
}
|
|
5096
|
+
],
|
|
5097
|
+
[
|
|
5098
|
+
"handleSveltePageRequest",
|
|
5099
|
+
{
|
|
5100
|
+
bundleProperty: "indexPath",
|
|
5101
|
+
framework: "svelte",
|
|
5102
|
+
propsProperty: "props",
|
|
5103
|
+
sourceProperty: "pagePath"
|
|
5104
|
+
}
|
|
5105
|
+
],
|
|
5106
|
+
[
|
|
5107
|
+
"handleVuePageRequest",
|
|
5108
|
+
{
|
|
5109
|
+
bundleProperty: "indexPath",
|
|
5110
|
+
framework: "vue",
|
|
5111
|
+
propsProperty: "props",
|
|
5112
|
+
sourceProperty: "pagePath"
|
|
5113
|
+
}
|
|
5114
|
+
]
|
|
5115
|
+
]);
|
|
4781
5116
|
var posixPath = (value) => value.replace(/\\/g, "/");
|
|
4782
|
-
var findTsconfig = (entry, projectRoot) => ts.findConfigFile(
|
|
5117
|
+
var findTsconfig = (entry, projectRoot) => ts.findConfigFile(dirname9(entry), existsSync3, "tsconfig.json") ?? ts.findConfigFile(projectRoot, existsSync3, "tsconfig.json");
|
|
4783
5118
|
var createProgram = (entry, projectRoot) => {
|
|
4784
5119
|
const configPath = findTsconfig(entry, projectRoot);
|
|
4785
5120
|
if (!configPath) {
|
|
@@ -4791,7 +5126,7 @@ var createProgram = (entry, projectRoot) => {
|
|
|
4791
5126
|
target: ts.ScriptTarget.ESNext
|
|
4792
5127
|
});
|
|
4793
5128
|
}
|
|
4794
|
-
const parsed = ts.parseJsonConfigFileContent(ts.readConfigFile(configPath, (path) =>
|
|
5129
|
+
const parsed = ts.parseJsonConfigFileContent(ts.readConfigFile(configPath, (path) => readFileSync3(path, "utf8")).config, ts.sys, dirname9(configPath));
|
|
4795
5130
|
if (!parsed.fileNames.includes(entry))
|
|
4796
5131
|
parsed.fileNames.push(entry);
|
|
4797
5132
|
return ts.createProgram(parsed.fileNames, parsed.options);
|
|
@@ -4897,7 +5232,7 @@ var resolvePageIdentity = (expression, sourceFile, checker, projectRoot) => {
|
|
|
4897
5232
|
const declaration = symbol?.declarations?.[0];
|
|
4898
5233
|
const file = declaration?.getSourceFile().fileName ?? sourceFile.fileName;
|
|
4899
5234
|
const exportedName = symbol?.name ?? expression.getText(sourceFile);
|
|
4900
|
-
const source = posixPath(
|
|
5235
|
+
const source = posixPath(relative10(projectRoot, file));
|
|
4901
5236
|
return `${source}#${exportedName}`;
|
|
4902
5237
|
};
|
|
4903
5238
|
var resolveAlias = (symbol, checker) => {
|
|
@@ -4929,13 +5264,108 @@ var assetKey = (expression, checker, seen = new Set) => {
|
|
|
4929
5264
|
const [, key] = expression.arguments;
|
|
4930
5265
|
return key && ts.isStringLiteralLike(key) ? key.text : undefined;
|
|
4931
5266
|
};
|
|
5267
|
+
var staticString = (expression, bindings) => {
|
|
5268
|
+
if (ts.isStringLiteralLike(expression))
|
|
5269
|
+
return expression.text;
|
|
5270
|
+
if (ts.isIdentifier(expression))
|
|
5271
|
+
return bindings.get(expression.text);
|
|
5272
|
+
if (ts.isNoSubstitutionTemplateLiteral(expression))
|
|
5273
|
+
return expression.text;
|
|
5274
|
+
if (!ts.isTemplateExpression(expression))
|
|
5275
|
+
return;
|
|
5276
|
+
let value = expression.head.text;
|
|
5277
|
+
for (const span of expression.templateSpans) {
|
|
5278
|
+
const substitution = staticString(span.expression, bindings);
|
|
5279
|
+
if (substitution === undefined)
|
|
5280
|
+
return;
|
|
5281
|
+
value += substitution + span.literal.text;
|
|
5282
|
+
}
|
|
5283
|
+
return value;
|
|
5284
|
+
};
|
|
5285
|
+
var assetKeyWithBindings = (expression, checker, bindings = new Map) => {
|
|
5286
|
+
if (!expression)
|
|
5287
|
+
return;
|
|
5288
|
+
if (ts.isCallExpression(expression) && ts.isIdentifier(expression.expression) && expression.expression.text === "asset") {
|
|
5289
|
+
const [, key] = expression.arguments;
|
|
5290
|
+
return key ? staticString(key, bindings) : undefined;
|
|
5291
|
+
}
|
|
5292
|
+
return assetKey(expression, checker);
|
|
5293
|
+
};
|
|
5294
|
+
var callableObject = (call, checker) => {
|
|
5295
|
+
const symbol = checker.getSymbolAtLocation(call.expression);
|
|
5296
|
+
const resolved = symbol ? resolveAlias(symbol, checker) : undefined;
|
|
5297
|
+
const declaration = resolved?.valueDeclaration ?? resolved?.declarations?.[0];
|
|
5298
|
+
let callable;
|
|
5299
|
+
if (declaration && ts.isFunctionDeclaration(declaration)) {
|
|
5300
|
+
callable = declaration;
|
|
5301
|
+
} else if (declaration && ts.isVariableDeclaration(declaration) && declaration.initializer && (ts.isArrowFunction(declaration.initializer) || ts.isFunctionExpression(declaration.initializer))) {
|
|
5302
|
+
callable = declaration.initializer;
|
|
5303
|
+
}
|
|
5304
|
+
if (!callable)
|
|
5305
|
+
return;
|
|
5306
|
+
const bindings = new Map;
|
|
5307
|
+
callable.parameters.forEach((parameter, index) => {
|
|
5308
|
+
if (!ts.isIdentifier(parameter.name))
|
|
5309
|
+
return;
|
|
5310
|
+
const argument = call.arguments[index];
|
|
5311
|
+
if (!argument)
|
|
5312
|
+
return;
|
|
5313
|
+
const value = staticString(argument, new Map);
|
|
5314
|
+
if (value !== undefined)
|
|
5315
|
+
bindings.set(parameter.name.text, value);
|
|
5316
|
+
});
|
|
5317
|
+
const { body } = callable;
|
|
5318
|
+
if (!body)
|
|
5319
|
+
return;
|
|
5320
|
+
const expressionBody = ts.isParenthesizedExpression(body) ? body.expression : body;
|
|
5321
|
+
if (ts.isObjectLiteralExpression(expressionBody)) {
|
|
5322
|
+
return { bindings, object: expressionBody };
|
|
5323
|
+
}
|
|
5324
|
+
if (ts.isBlock(body)) {
|
|
5325
|
+
const returned = body.statements.find(ts.isReturnStatement)?.expression;
|
|
5326
|
+
if (returned && ts.isObjectLiteralExpression(returned)) {
|
|
5327
|
+
return { bindings, object: returned };
|
|
5328
|
+
}
|
|
5329
|
+
}
|
|
5330
|
+
return;
|
|
5331
|
+
};
|
|
5332
|
+
var spreadObject = (expression, checker, bindings) => {
|
|
5333
|
+
if (ts.isObjectLiteralExpression(expression)) {
|
|
5334
|
+
return { bindings, object: expression };
|
|
5335
|
+
}
|
|
5336
|
+
if (!ts.isCallExpression(expression))
|
|
5337
|
+
return;
|
|
5338
|
+
return callableObject(expression, checker);
|
|
5339
|
+
};
|
|
5340
|
+
var objectAssetKey = (object, name, checker, bindings = new Map) => {
|
|
5341
|
+
for (const property of [...object.properties].reverse()) {
|
|
5342
|
+
if (propertyName(property) === name && ts.isShorthandPropertyAssignment(property)) {
|
|
5343
|
+
return assetKeyWithBindings(property.name, checker, bindings);
|
|
5344
|
+
}
|
|
5345
|
+
if (propertyName(property) === name && ts.isPropertyAssignment(property)) {
|
|
5346
|
+
return assetKeyWithBindings(property.initializer, checker, bindings);
|
|
5347
|
+
}
|
|
5348
|
+
if (!ts.isSpreadAssignment(property))
|
|
5349
|
+
continue;
|
|
5350
|
+
const nestedObject = spreadObject(property.expression, checker, bindings);
|
|
5351
|
+
if (!nestedObject)
|
|
5352
|
+
continue;
|
|
5353
|
+
const nested = objectAssetKey(nestedObject.object, name, checker, nestedObject.bindings);
|
|
5354
|
+
if (nested)
|
|
5355
|
+
return nested;
|
|
5356
|
+
}
|
|
5357
|
+
return;
|
|
5358
|
+
};
|
|
4932
5359
|
var findPageCall = (nodes) => {
|
|
4933
5360
|
let found;
|
|
4934
5361
|
const visit = (candidate) => {
|
|
4935
5362
|
if (found)
|
|
4936
5363
|
return;
|
|
4937
|
-
if (ts.isCallExpression(candidate) && ts.isIdentifier(candidate.expression) && candidate.expression.text
|
|
4938
|
-
|
|
5364
|
+
if (ts.isCallExpression(candidate) && ts.isIdentifier(candidate.expression) && PAGE_HANDLERS.has(candidate.expression.text)) {
|
|
5365
|
+
const definition = PAGE_HANDLERS.get(candidate.expression.text);
|
|
5366
|
+
if (!definition)
|
|
5367
|
+
return;
|
|
5368
|
+
found = { definition, node: candidate };
|
|
4939
5369
|
return;
|
|
4940
5370
|
}
|
|
4941
5371
|
ts.forEachChild(candidate, visit);
|
|
@@ -4954,30 +5384,67 @@ var analyzeRouteCall = (node, sourceFile, checker, projectRoot) => {
|
|
|
4954
5384
|
const [routePath] = node.arguments;
|
|
4955
5385
|
if (!routePath || !ts.isStringLiteralLike(routePath))
|
|
4956
5386
|
return;
|
|
4957
|
-
const
|
|
5387
|
+
const foundPageCall = findPageCall(node.arguments.slice(1));
|
|
5388
|
+
const pageCall = foundPageCall?.node;
|
|
5389
|
+
const definition = foundPageCall?.definition;
|
|
4958
5390
|
const [input] = pageCall?.arguments ?? [];
|
|
4959
|
-
if (!pageCall || !input
|
|
5391
|
+
if (!pageCall || !input) {
|
|
4960
5392
|
return;
|
|
4961
5393
|
}
|
|
4962
|
-
|
|
4963
|
-
|
|
5394
|
+
if (!definition)
|
|
5395
|
+
return;
|
|
5396
|
+
if (definition.inputKind === "static") {
|
|
5397
|
+
const bundleKey2 = assetKey(input, checker);
|
|
5398
|
+
if (!bundleKey2)
|
|
5399
|
+
return;
|
|
5400
|
+
const pageId2 = `${definition.framework}:${bundleKey2}`;
|
|
5401
|
+
const propsSchemaHash2 = hashAbsoluteMobilePropsSchema({
|
|
5402
|
+
properties: {},
|
|
5403
|
+
type: "object"
|
|
5404
|
+
});
|
|
5405
|
+
return {
|
|
5406
|
+
inputKind: "static",
|
|
5407
|
+
metadata: {
|
|
5408
|
+
bundleKey: bundleKey2,
|
|
5409
|
+
contract: `${definition.framework}:${pageId2}:${propsSchemaHash2}`,
|
|
5410
|
+
framework: definition.framework,
|
|
5411
|
+
pageId: pageId2,
|
|
5412
|
+
propsSchemaHash: propsSchemaHash2
|
|
5413
|
+
},
|
|
5414
|
+
pageCallStart: pageCall.getStart(sourceFile),
|
|
5415
|
+
routeCallSpan: `${node.getStart(sourceFile)}:${node.end}`
|
|
5416
|
+
};
|
|
5417
|
+
}
|
|
5418
|
+
if (!ts.isObjectLiteralExpression(input) || !definition.bundleProperty) {
|
|
5419
|
+
return;
|
|
5420
|
+
}
|
|
5421
|
+
const page = definition.pageProperty ? objectPropertyExpression(input, definition.pageProperty) : undefined;
|
|
5422
|
+
const source = definition.sourceProperty ? objectAssetKey(input, definition.sourceProperty, checker) : undefined;
|
|
5423
|
+
if (definition.pageProperty && !page)
|
|
5424
|
+
return;
|
|
5425
|
+
if (definition.sourceProperty && !source)
|
|
4964
5426
|
return;
|
|
4965
|
-
const props = objectPropertyExpression(input,
|
|
4966
|
-
const
|
|
4967
|
-
const bundleKey = assetKey(index, checker);
|
|
5427
|
+
const props = objectPropertyExpression(input, definition.propsProperty);
|
|
5428
|
+
const bundleKey = objectAssetKey(input, definition.bundleProperty, checker);
|
|
4968
5429
|
if (!bundleKey)
|
|
4969
5430
|
return;
|
|
4970
|
-
const pageId = resolvePageIdentity(page, sourceFile, checker, projectRoot)
|
|
4971
|
-
|
|
5431
|
+
const pageId = page ? resolvePageIdentity(page, sourceFile, checker, projectRoot) : `${definition.framework}:${source}`;
|
|
5432
|
+
let propsType;
|
|
5433
|
+
if (page)
|
|
5434
|
+
propsType = pagePropsType(page, props, checker);
|
|
5435
|
+
else if (props)
|
|
5436
|
+
propsType = checker.getTypeAtLocation(props);
|
|
5437
|
+
const schema = propsType ? serializeType(propsType, checker) : { properties: {}, type: "object" };
|
|
4972
5438
|
const propsSchemaHash = hashAbsoluteMobilePropsSchema(schema);
|
|
4973
5439
|
const metadata = {
|
|
4974
5440
|
bundleKey,
|
|
4975
|
-
contract:
|
|
4976
|
-
framework:
|
|
5441
|
+
contract: `${definition.framework}:${pageId}:${propsSchemaHash}`,
|
|
5442
|
+
framework: definition.framework,
|
|
4977
5443
|
pageId,
|
|
4978
5444
|
propsSchemaHash
|
|
4979
5445
|
};
|
|
4980
5446
|
const result = {
|
|
5447
|
+
inputKind: "object",
|
|
4981
5448
|
metadata,
|
|
4982
5449
|
pageCallStart: pageCall.getStart(sourceFile),
|
|
4983
5450
|
routeCallSpan: `${node.getStart(sourceFile)}:${node.end}`
|
|
@@ -5034,6 +5501,16 @@ var routeOptions = (existing, metadata) => {
|
|
|
5034
5501
|
var transformPageCall = (node, page) => {
|
|
5035
5502
|
if (!page)
|
|
5036
5503
|
return;
|
|
5504
|
+
if (page.inputKind === "static") {
|
|
5505
|
+
const [pagePath, existingOptions, ...rest] = node.arguments;
|
|
5506
|
+
if (!pagePath)
|
|
5507
|
+
return;
|
|
5508
|
+
const options = ts.factory.createObjectLiteralExpression([
|
|
5509
|
+
...existingOptions ? [ts.factory.createSpreadAssignment(existingOptions)] : [],
|
|
5510
|
+
ts.factory.createPropertyAssignment("__absoluteMobile", metadataExpression(page.metadata))
|
|
5511
|
+
]);
|
|
5512
|
+
return ts.factory.updateCallExpression(node, node.expression, node.typeArguments, [pagePath, options, ...rest]);
|
|
5513
|
+
}
|
|
5037
5514
|
const [input] = node.arguments;
|
|
5038
5515
|
if (!input || !ts.isObjectLiteralExpression(input))
|
|
5039
5516
|
return;
|
|
@@ -5100,7 +5577,7 @@ var createAbsoluteMobileRouteMetadataPlugin = (options) => {
|
|
|
5100
5577
|
const source = await Bun.file(path).text();
|
|
5101
5578
|
return {
|
|
5102
5579
|
contents: transformFile(source, path, analysis),
|
|
5103
|
-
loader:
|
|
5580
|
+
loader: extname3(path).endsWith("x") ? "tsx" : "ts"
|
|
5104
5581
|
};
|
|
5105
5582
|
});
|
|
5106
5583
|
}
|
|
@@ -5111,7 +5588,7 @@ var inspectAbsoluteMobileRouteMetadata = (options) => {
|
|
|
5111
5588
|
const entry = resolve12(options.entry);
|
|
5112
5589
|
const analyzed = analyzeProgram(createProgram(entry, projectRoot), projectRoot);
|
|
5113
5590
|
return [...analyzed.entries()].flatMap(([file, analysis]) => [...analysis.byRouteCall.values()].map(({ metadata }) => ({
|
|
5114
|
-
file: posixPath(
|
|
5591
|
+
file: posixPath(relative10(projectRoot, file)),
|
|
5115
5592
|
metadata
|
|
5116
5593
|
})));
|
|
5117
5594
|
};
|
|
@@ -5125,17 +5602,22 @@ export {
|
|
|
5125
5602
|
syncAbsoluteRemoteMacProject,
|
|
5126
5603
|
startAbsoluteRemoteIosDevSession,
|
|
5127
5604
|
startAbsoluteIosDevSession,
|
|
5605
|
+
serializeAbsoluteMobileAuthEnvironment,
|
|
5128
5606
|
runWithAbsoluteMobileProducer,
|
|
5129
5607
|
retainAbsoluteMobileCompatibilityArtifacts,
|
|
5130
5608
|
resolveAbsoluteMobileRoute,
|
|
5609
|
+
resolveAbsoluteMobileNavigation,
|
|
5131
5610
|
resolveAbsoluteMobileDeepLink,
|
|
5132
5611
|
resolveAbsoluteMobileCompatibilityRelease,
|
|
5612
|
+
resolveAbsoluteMobileAuthManifest,
|
|
5133
5613
|
repairAbsoluteIosDevSession,
|
|
5134
5614
|
removeAbsoluteRemoteMacProfile,
|
|
5135
5615
|
redactAbsoluteIosLog,
|
|
5136
5616
|
readAbsoluteMobileMaterializedReleases,
|
|
5137
5617
|
publishAbsoluteIosRelease,
|
|
5138
5618
|
publishAbsoluteAndroidRelease,
|
|
5619
|
+
projectUsesAbsoluteSync,
|
|
5620
|
+
projectUsesAbsoluteAuth,
|
|
5139
5621
|
prepareAbsoluteIosRelease,
|
|
5140
5622
|
prepareAbsoluteIosDevProject,
|
|
5141
5623
|
prepareAbsoluteAndroidRelease,
|
|
@@ -5161,6 +5643,7 @@ export {
|
|
|
5161
5643
|
listAbsoluteRemoteMacProfiles,
|
|
5162
5644
|
isAbsoluteIosNativeRootInput,
|
|
5163
5645
|
installAbsoluteRemoteMacAgent,
|
|
5646
|
+
installAbsoluteMobileAuthEnvironment,
|
|
5164
5647
|
inspectAbsoluteRemoteMac,
|
|
5165
5648
|
inspectAbsoluteMobileRouteMetadata,
|
|
5166
5649
|
hashAbsoluteMobilePropsSchema,
|
|
@@ -5171,6 +5654,7 @@ export {
|
|
|
5171
5654
|
finalizeAbsoluteMobilePage,
|
|
5172
5655
|
finalizeAbsoluteMobileCompatibilityBuild,
|
|
5173
5656
|
fetchAbsoluteMobilePage,
|
|
5657
|
+
disposeAbsoluteMobilePage,
|
|
5174
5658
|
createAbsoluteRemoteIosDevProject,
|
|
5175
5659
|
createAbsoluteMobileUpgradeResponse,
|
|
5176
5660
|
createAbsoluteMobileRouteMetadataPlugin,
|
|
@@ -5181,6 +5665,7 @@ export {
|
|
|
5181
5665
|
createAbsoluteMobileCompatibilityDispatcher,
|
|
5182
5666
|
createAbsoluteMobileCompatibilityArtifact,
|
|
5183
5667
|
createAbsoluteMobileBlobArtifactStore,
|
|
5668
|
+
createAbsoluteMobileAuthManifest,
|
|
5184
5669
|
createAbsoluteMobileAssociationPlugin,
|
|
5185
5670
|
createAbsoluteMobileAssociationDocuments,
|
|
5186
5671
|
createAbsoluteIosNativeWatcher,
|
|
@@ -5198,8 +5683,11 @@ export {
|
|
|
5198
5683
|
AbsoluteMobilePageProtocolError,
|
|
5199
5684
|
APPLE_ASSOCIATION_PATH,
|
|
5200
5685
|
ANDROID_ASSOCIATION_PATH,
|
|
5686
|
+
ABSOLUTE_SYNC_PACKAGE,
|
|
5201
5687
|
ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION,
|
|
5202
5688
|
ABSOLUTE_REMOTE_MAC_EVENT_PREFIX,
|
|
5689
|
+
ABSOLUTE_NATIVE_AUTH_SCOPES,
|
|
5690
|
+
ABSOLUTE_NATIVE_AUTH_CLIENTS_ENV,
|
|
5203
5691
|
ABSOLUTE_MOBILE_TRANSFORM_PROTOCOL,
|
|
5204
5692
|
ABSOLUTE_MOBILE_ROUTE_DETAIL,
|
|
5205
5693
|
ABSOLUTE_MOBILE_RETAINED_GENERATIONS,
|
|
@@ -5210,8 +5698,9 @@ export {
|
|
|
5210
5698
|
ABSOLUTE_MOBILE_CLIENT_MANIFEST_FORMAT,
|
|
5211
5699
|
ABSOLUTE_IOS_SIMULATOR_NAME,
|
|
5212
5700
|
ABSOLUTE_IOS_RELEASE_FORMAT,
|
|
5701
|
+
ABSOLUTE_AUTH_PACKAGE,
|
|
5213
5702
|
ABSOLUTE_ANDROID_RELEASE_FORMAT
|
|
5214
5703
|
};
|
|
5215
5704
|
|
|
5216
|
-
//# debugId=
|
|
5705
|
+
//# debugId=7AFC88B0A927AFE564756E2164756E21
|
|
5217
5706
|
//# sourceMappingURL=index.js.map
|