@couch-kit/host 1.0.0 → 1.1.0
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/package.json +1 -1
- package/src/assets.ts +114 -0
- package/src/index.tsx +5 -4
package/package.json
CHANGED
package/src/assets.ts
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
import {
|
|
3
|
+
documentDirectory,
|
|
4
|
+
getInfoAsync,
|
|
5
|
+
deleteAsync,
|
|
6
|
+
makeDirectoryAsync,
|
|
7
|
+
copyAsync,
|
|
8
|
+
} from "expo-file-system/legacy";
|
|
9
|
+
import { Platform } from "react-native";
|
|
10
|
+
import { toErrorMessage } from "@couch-kit/core";
|
|
11
|
+
|
|
12
|
+
export interface AssetManifest {
|
|
13
|
+
files: string[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface ExtractAssetsResult {
|
|
17
|
+
/** The filesystem path to the extracted www directory, or undefined if not ready */
|
|
18
|
+
staticDir: string | undefined;
|
|
19
|
+
/** Whether extraction is in progress */
|
|
20
|
+
loading: boolean;
|
|
21
|
+
/** Error message if extraction failed */
|
|
22
|
+
error: string | null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Extracts bundled web assets from the APK to the filesystem so the native
|
|
27
|
+
* HTTP server can serve them.
|
|
28
|
+
*
|
|
29
|
+
* On Android, assets live inside the APK and cannot be served directly by
|
|
30
|
+
* a native HTTP server. This hook copies each file listed in the manifest
|
|
31
|
+
* from `asset:///www/<file>` to `${documentDirectory}www/<file>`.
|
|
32
|
+
*
|
|
33
|
+
* On iOS, assets are accessible from the bundle directory, so extraction
|
|
34
|
+
* is skipped and `staticDir` is returned as `undefined` (the server falls
|
|
35
|
+
* back to the bundle path).
|
|
36
|
+
*
|
|
37
|
+
* @param manifest - The asset manifest generated by `couch-kit bundle`.
|
|
38
|
+
* Contains a `files` array listing all relative paths.
|
|
39
|
+
*/
|
|
40
|
+
export function useExtractAssets(manifest: AssetManifest): ExtractAssetsResult {
|
|
41
|
+
const [staticDir, setStaticDir] = useState<string | undefined>(undefined);
|
|
42
|
+
const [loading, setLoading] = useState(true);
|
|
43
|
+
const [error, setError] = useState<string | null>(null);
|
|
44
|
+
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
// iOS: skip extraction, server uses bundle path fallback
|
|
47
|
+
if (Platform.OS !== "android") {
|
|
48
|
+
setLoading(false);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
let cancelled = false;
|
|
53
|
+
|
|
54
|
+
const extractAssets = async () => {
|
|
55
|
+
try {
|
|
56
|
+
if (!documentDirectory) {
|
|
57
|
+
throw new Error("Document directory is not available");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const targetDir = `${documentDirectory}www/`;
|
|
61
|
+
|
|
62
|
+
// Clean previous extraction to ensure fresh assets after app updates
|
|
63
|
+
const dirInfo = await getInfoAsync(targetDir);
|
|
64
|
+
if (dirInfo.exists) {
|
|
65
|
+
await deleteAsync(targetDir, { idempotent: true });
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Create the root target directory
|
|
69
|
+
await makeDirectoryAsync(targetDir, { intermediates: true });
|
|
70
|
+
|
|
71
|
+
// Copy each file from APK assets to filesystem
|
|
72
|
+
for (const file of manifest.files) {
|
|
73
|
+
if (cancelled) return;
|
|
74
|
+
|
|
75
|
+
const sourceUri = `asset:///www/${file}`;
|
|
76
|
+
const destUri = `${targetDir}${file}`;
|
|
77
|
+
|
|
78
|
+
// Ensure subdirectory exists (e.g., "assets/" in "assets/index.js")
|
|
79
|
+
const lastSlash = file.lastIndexOf("/");
|
|
80
|
+
if (lastSlash > 0) {
|
|
81
|
+
const subDir = `${targetDir}${file.substring(0, lastSlash)}`;
|
|
82
|
+
await makeDirectoryAsync(subDir, { intermediates: true });
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
await copyAsync({ from: sourceUri, to: destUri });
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (cancelled) return;
|
|
89
|
+
|
|
90
|
+
// Strip file:// prefix for the native HTTP server
|
|
91
|
+
const rawPath = targetDir.replace(/^file:\/\//, "");
|
|
92
|
+
setStaticDir(rawPath);
|
|
93
|
+
} catch (e) {
|
|
94
|
+
if (!cancelled) {
|
|
95
|
+
const message = toErrorMessage(e);
|
|
96
|
+
console.warn("[CouchKit] Asset extraction failed:", message);
|
|
97
|
+
setError(message);
|
|
98
|
+
}
|
|
99
|
+
} finally {
|
|
100
|
+
if (!cancelled) {
|
|
101
|
+
setLoading(false);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
extractAssets();
|
|
107
|
+
|
|
108
|
+
return () => {
|
|
109
|
+
cancelled = true;
|
|
110
|
+
};
|
|
111
|
+
}, [manifest]);
|
|
112
|
+
|
|
113
|
+
return { staticDir, loading, error };
|
|
114
|
+
}
|
package/src/index.tsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
4
|
-
export * from
|
|
1
|
+
export * from "./provider";
|
|
2
|
+
export * from "./server";
|
|
3
|
+
export * from "./websocket";
|
|
4
|
+
export * from "./network";
|
|
5
|
+
export * from "./assets";
|