akanjs 2.1.0-rc.5 → 2.1.0-rc.7
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.
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import os from "node:os";
|
|
2
|
+
import type { CapacitorConfig } from "@capacitor/cli";
|
|
3
|
+
import type { AkanMobileTargetConfig, AppScanResult } from "akanjs";
|
|
4
|
+
|
|
5
|
+
const getLocalIP = () => {
|
|
6
|
+
const interfaces = os.networkInterfaces();
|
|
7
|
+
for (const interfaceName in interfaces) {
|
|
8
|
+
const iface = interfaces[interfaceName];
|
|
9
|
+
if (!iface) continue;
|
|
10
|
+
for (const alias of iface) {
|
|
11
|
+
if (alias.family === "IPv4" && !alias.internal) return alias.address;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return "127.0.0.1";
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const normalizeBasePath = (basePath: string | undefined) => basePath?.replace(/^\/+|\/+$/g, "");
|
|
18
|
+
|
|
19
|
+
const routeBasePaths = (appInfo: AppScanResult) =>
|
|
20
|
+
new Set(
|
|
21
|
+
appInfo.routes
|
|
22
|
+
.map((route) => route.replace(/^\.\//, "").split("/")[0])
|
|
23
|
+
.filter((segment): segment is string => !!segment && !segment.startsWith("_") && !segment.startsWith("(")),
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
const resolveTarget = (appInfo: AppScanResult, targetName = process.env.AKAN_MOBILE_TARGET) => {
|
|
27
|
+
const targets = appInfo.akanConfig.mobile.targets;
|
|
28
|
+
if (!targets || Object.keys(targets).length === 0) throw new Error("Akan mobile target metadata is missing.");
|
|
29
|
+
if (targetName) {
|
|
30
|
+
const target = targets[targetName];
|
|
31
|
+
if (!target) {
|
|
32
|
+
const basePath = normalizeBasePath(targetName);
|
|
33
|
+
const [template] = Object.values(targets);
|
|
34
|
+
if (basePath && template && routeBasePaths(appInfo).has(basePath))
|
|
35
|
+
return { ...template, name: basePath, basePath };
|
|
36
|
+
throw new Error(`Akan mobile target '${targetName}' was not found.`);
|
|
37
|
+
}
|
|
38
|
+
return target;
|
|
39
|
+
}
|
|
40
|
+
const entries = Object.entries(targets);
|
|
41
|
+
if (entries.length !== 1) throw new Error("AKAN_MOBILE_TARGET is required when multiple mobile targets exist.");
|
|
42
|
+
return entries[0]?.[1] as AkanMobileTargetConfig;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const localCsrUrl = (ip: string, target: AkanMobileTargetConfig) => {
|
|
46
|
+
const basePath = normalizeBasePath(target.basePath);
|
|
47
|
+
const port = process.env.AKAN_PUBLIC_CLIENT_PORT ?? process.env.PORT ?? "8282";
|
|
48
|
+
return `http://${ip}:${port}/${basePath ? `${basePath}` : ""}?csr=true`;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export const withBase = (
|
|
52
|
+
configImp: (config: CapacitorConfig, target: AkanMobileTargetConfig) => CapacitorConfig = (config) => config,
|
|
53
|
+
appData?: AppScanResult,
|
|
54
|
+
targetName?: string,
|
|
55
|
+
) => {
|
|
56
|
+
const ip = getLocalIP();
|
|
57
|
+
const appInfo = appData;
|
|
58
|
+
if (!appInfo) throw new Error("withBase requires apps/<app>/akan.app.json metadata.");
|
|
59
|
+
const target = resolveTarget(appInfo, targetName);
|
|
60
|
+
const baseConfig: CapacitorConfig = {
|
|
61
|
+
...target,
|
|
62
|
+
appId: target.appId,
|
|
63
|
+
appName: target.appName,
|
|
64
|
+
webDir: "dist",
|
|
65
|
+
server:
|
|
66
|
+
process.env.APP_OPERATION_MODE !== "release"
|
|
67
|
+
? {
|
|
68
|
+
androidScheme: "http",
|
|
69
|
+
url: localCsrUrl(ip, target),
|
|
70
|
+
cleartext: true,
|
|
71
|
+
allowNavigation: [ip, "localhost"],
|
|
72
|
+
}
|
|
73
|
+
: {
|
|
74
|
+
allowNavigation: ["*"],
|
|
75
|
+
},
|
|
76
|
+
plugins: {
|
|
77
|
+
CapacitorCookies: { enabled: true },
|
|
78
|
+
...target.plugins,
|
|
79
|
+
},
|
|
80
|
+
android: {
|
|
81
|
+
...target.android,
|
|
82
|
+
},
|
|
83
|
+
ios: {
|
|
84
|
+
...target.ios,
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
return configImp(baseConfig, target);
|
|
88
|
+
};
|
package/client/device.ts
CHANGED
|
@@ -50,6 +50,11 @@ const getRenderMode = () => globalWithProcess.process?.env?.AKAN_PUBLIC_RENDER_E
|
|
|
50
50
|
|
|
51
51
|
const getBrowserLanguage = () => globalThis.navigator?.language?.split("-")[0] ?? "en";
|
|
52
52
|
|
|
53
|
+
const isNativeTarget = () => {
|
|
54
|
+
if (typeof window === "undefined") return false;
|
|
55
|
+
return Boolean((window as typeof window & { __AKAN_MOBILE_TARGET__?: unknown }).__AKAN_MOBILE_TARGET__);
|
|
56
|
+
};
|
|
57
|
+
|
|
53
58
|
export const isMobileDevice = () => {
|
|
54
59
|
if (typeof navigator === "undefined") return false;
|
|
55
60
|
if (typeof window !== "undefined" && window.matchMedia?.("(hover: none) and (pointer: coarse)")?.matches) return true;
|
|
@@ -88,7 +93,7 @@ export class Device {
|
|
|
88
93
|
supportLanguages?: string[] | readonly string[];
|
|
89
94
|
}) {
|
|
90
95
|
if (Device.instance) return Device.instance;
|
|
91
|
-
if (getRenderMode() !== "csr") {
|
|
96
|
+
if (getRenderMode() !== "csr" || !isNativeTarget()) {
|
|
92
97
|
const device = createWebDevice({ lang, supportLanguages });
|
|
93
98
|
Device.instance = device;
|
|
94
99
|
return device;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "akanjs",
|
|
3
|
-
"version": "2.1.0-rc.
|
|
3
|
+
"version": "2.1.0-rc.7",
|
|
4
4
|
"sourceType": "module",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -95,6 +95,11 @@
|
|
|
95
95
|
"import": "./client/capacitor.ts",
|
|
96
96
|
"default": "./client/capacitor.ts"
|
|
97
97
|
},
|
|
98
|
+
"./capacitor.base.config": {
|
|
99
|
+
"types": "./types/capacitor.base.config.d.ts",
|
|
100
|
+
"import": "./capacitor.base.config.ts",
|
|
101
|
+
"default": "./capacitor.base.config.ts"
|
|
102
|
+
},
|
|
98
103
|
"./webkit": {
|
|
99
104
|
"types": "./types/webkit/index.d.ts",
|
|
100
105
|
"import": "./webkit/index.ts",
|
|
@@ -159,6 +164,7 @@
|
|
|
159
164
|
"@capacitor/app": "^8.1.0",
|
|
160
165
|
"@capacitor/browser": "^8.0.3",
|
|
161
166
|
"@capacitor/camera": "^8.2.0",
|
|
167
|
+
"@capacitor/cli": "^8.3.4",
|
|
162
168
|
"@capacitor/core": "^8.3.4",
|
|
163
169
|
"@capacitor/device": "^8.0.2",
|
|
164
170
|
"@capacitor/geolocation": "^8.2.0",
|
|
@@ -211,6 +217,9 @@
|
|
|
211
217
|
"@capacitor/camera": {
|
|
212
218
|
"optional": true
|
|
213
219
|
},
|
|
220
|
+
"@capacitor/cli": {
|
|
221
|
+
"optional": true
|
|
222
|
+
},
|
|
214
223
|
"@capacitor/core": {
|
|
215
224
|
"optional": true
|
|
216
225
|
},
|
|
@@ -10,11 +10,11 @@ import {
|
|
|
10
10
|
ConsoleLogger,
|
|
11
11
|
type DatabaseAdaptor,
|
|
12
12
|
DatabaseAdaptorRole,
|
|
13
|
+
JsonCompressor,
|
|
13
14
|
LibsqlDatabase,
|
|
14
15
|
type LoggingAdaptor,
|
|
15
16
|
LoggingAdaptorRole,
|
|
16
17
|
PostgresDatabase,
|
|
17
|
-
JsonCompressor,
|
|
18
18
|
type QueueAdaptor,
|
|
19
19
|
QueueAdaptorRole,
|
|
20
20
|
RedisCache,
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { CapacitorConfig } from "@capacitor/cli";
|
|
2
|
+
import type { AkanMobileTargetConfig, AppScanResult } from "akanjs";
|
|
3
|
+
export declare const withBase: (configImp?: (config: CapacitorConfig, target: AkanMobileTargetConfig) => CapacitorConfig, appData?: AppScanResult, targetName?: string) => CapacitorConfig;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { DatabaseMode } from "akanjs";
|
|
2
|
-
import { type AdaptorCls, BlobStorage, type CacheAdaptor, type CompressAdaptor, ConsoleLogger, type DatabaseAdaptor, type LoggingAdaptor,
|
|
2
|
+
import { type AdaptorCls, BlobStorage, type CacheAdaptor, type CompressAdaptor, ConsoleLogger, type DatabaseAdaptor, JsonCompressor, type LoggingAdaptor, type QueueAdaptor, type ScheduleAdaptor, Scheduler, SolidCache, SolidPubSub, SolidQueue, SqliteDatabase, type StorageAdaptor, type WebsocketAdaptor } from "akanjs/service";
|
|
3
3
|
export interface PredefinedAdaptor {
|
|
4
4
|
database: AdaptorCls<DatabaseAdaptor>;
|
|
5
5
|
cache: AdaptorCls<CacheAdaptor>;
|