@b9g/platform 0.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 +109 -0
- package/src/adapter-registry.d.ts +53 -0
- package/src/adapter-registry.js +71 -0
- package/src/base-platform.d.ts +50 -0
- package/src/base-platform.js +114 -0
- package/src/detection.d.ts +36 -0
- package/src/detection.js +126 -0
- package/src/directory-storage.d.ts +41 -0
- package/src/directory-storage.js +78 -0
- package/src/filesystem.d.ts +8 -0
- package/src/filesystem.js +10 -0
- package/src/index.d.ts +14 -0
- package/src/index.js +62 -0
- package/src/registry.d.ts +31 -0
- package/src/registry.js +74 -0
- package/src/service-worker.d.ts +149 -0
- package/src/service-worker.js +183 -0
- package/src/types.d.ts +239 -0
- package/src/types.js +36 -0
- package/src/utils.d.ts +33 -0
- package/src/utils.js +139 -0
package/package.json
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@b9g/platform",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Base Platform interface and types for Shovel deployment adapters",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"shovel",
|
|
7
|
+
"platform",
|
|
8
|
+
"deployment",
|
|
9
|
+
"adapter",
|
|
10
|
+
"interface"
|
|
11
|
+
],
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@types/wicg-file-system-access": "^2023.10.7"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"@b9g/libuild": "^0.1.10",
|
|
17
|
+
"bun-types": "latest"
|
|
18
|
+
},
|
|
19
|
+
"type": "module",
|
|
20
|
+
"types": "src/index.d.ts",
|
|
21
|
+
"module": "src/index.js",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"types": "./src/index.d.ts",
|
|
25
|
+
"import": "./src/index.js"
|
|
26
|
+
},
|
|
27
|
+
"./types": {
|
|
28
|
+
"types": "./src/types.d.ts",
|
|
29
|
+
"import": "./src/types.js"
|
|
30
|
+
},
|
|
31
|
+
"./types.js": {
|
|
32
|
+
"types": "./src/types.d.ts",
|
|
33
|
+
"import": "./src/types.js"
|
|
34
|
+
},
|
|
35
|
+
"./package.json": "./package.json",
|
|
36
|
+
"./adapter-registry": {
|
|
37
|
+
"types": "./src/adapter-registry.d.ts",
|
|
38
|
+
"import": "./src/adapter-registry.js"
|
|
39
|
+
},
|
|
40
|
+
"./adapter-registry.js": {
|
|
41
|
+
"types": "./src/adapter-registry.d.ts",
|
|
42
|
+
"import": "./src/adapter-registry.js"
|
|
43
|
+
},
|
|
44
|
+
"./base-platform": {
|
|
45
|
+
"types": "./src/base-platform.d.ts",
|
|
46
|
+
"import": "./src/base-platform.js"
|
|
47
|
+
},
|
|
48
|
+
"./base-platform.js": {
|
|
49
|
+
"types": "./src/base-platform.d.ts",
|
|
50
|
+
"import": "./src/base-platform.js"
|
|
51
|
+
},
|
|
52
|
+
"./filesystem": {
|
|
53
|
+
"types": "./src/filesystem.d.ts",
|
|
54
|
+
"import": "./src/filesystem.js"
|
|
55
|
+
},
|
|
56
|
+
"./filesystem.js": {
|
|
57
|
+
"types": "./src/filesystem.d.ts",
|
|
58
|
+
"import": "./src/filesystem.js"
|
|
59
|
+
},
|
|
60
|
+
"./index": {
|
|
61
|
+
"types": "./src/index.d.ts",
|
|
62
|
+
"import": "./src/index.js"
|
|
63
|
+
},
|
|
64
|
+
"./index.js": {
|
|
65
|
+
"types": "./src/index.d.ts",
|
|
66
|
+
"import": "./src/index.js"
|
|
67
|
+
},
|
|
68
|
+
"./registry": {
|
|
69
|
+
"types": "./src/registry.d.ts",
|
|
70
|
+
"import": "./src/registry.js"
|
|
71
|
+
},
|
|
72
|
+
"./registry.js": {
|
|
73
|
+
"types": "./src/registry.d.ts",
|
|
74
|
+
"import": "./src/registry.js"
|
|
75
|
+
},
|
|
76
|
+
"./service-worker": {
|
|
77
|
+
"types": "./src/service-worker.d.ts",
|
|
78
|
+
"import": "./src/service-worker.js"
|
|
79
|
+
},
|
|
80
|
+
"./service-worker.js": {
|
|
81
|
+
"types": "./src/service-worker.d.ts",
|
|
82
|
+
"import": "./src/service-worker.js"
|
|
83
|
+
},
|
|
84
|
+
"./utils": {
|
|
85
|
+
"types": "./src/utils.d.ts",
|
|
86
|
+
"import": "./src/utils.js"
|
|
87
|
+
},
|
|
88
|
+
"./utils.js": {
|
|
89
|
+
"types": "./src/utils.d.ts",
|
|
90
|
+
"import": "./src/utils.js"
|
|
91
|
+
},
|
|
92
|
+
"./detection": {
|
|
93
|
+
"types": "./src/detection.d.ts",
|
|
94
|
+
"import": "./src/detection.js"
|
|
95
|
+
},
|
|
96
|
+
"./detection.js": {
|
|
97
|
+
"types": "./src/detection.d.ts",
|
|
98
|
+
"import": "./src/detection.js"
|
|
99
|
+
},
|
|
100
|
+
"./directory-storage": {
|
|
101
|
+
"types": "./src/directory-storage.d.ts",
|
|
102
|
+
"import": "./src/directory-storage.js"
|
|
103
|
+
},
|
|
104
|
+
"./directory-storage.js": {
|
|
105
|
+
"types": "./src/directory-storage.d.ts",
|
|
106
|
+
"import": "./src/directory-storage.js"
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Blessed alias registry for official Shovel adapters
|
|
3
|
+
* Maps short names to full package names for CLI convenience
|
|
4
|
+
*/
|
|
5
|
+
export interface AdapterModule {
|
|
6
|
+
createCache?: (config: any) => any;
|
|
7
|
+
createFileSystem?: (config: any) => any;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Official blessed aliases for cache adapters
|
|
11
|
+
*/
|
|
12
|
+
export declare const CACHE_ALIASES: {
|
|
13
|
+
readonly memory: "@b9g/cache";
|
|
14
|
+
readonly redis: "@b9g/cache-redis";
|
|
15
|
+
readonly kv: "@b9g/cache-kv";
|
|
16
|
+
readonly cloudflare: "@b9g/cache/cloudflare";
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Official blessed aliases for filesystem adapters
|
|
20
|
+
*/
|
|
21
|
+
export declare const FILESYSTEM_ALIASES: {
|
|
22
|
+
readonly memory: "@b9g/filesystem";
|
|
23
|
+
readonly fs: "@b9g/filesystem/node";
|
|
24
|
+
readonly "bun-s3": "@b9g/filesystem/bun-s3";
|
|
25
|
+
readonly s3: "@b9g/filesystem-s3";
|
|
26
|
+
readonly r2: "@b9g/filesystem-r2";
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Resolve a cache adapter name to a package name
|
|
30
|
+
* @param name - Blessed alias (memory, redis) or full package name (@custom/cache)
|
|
31
|
+
* @returns Full package name
|
|
32
|
+
*/
|
|
33
|
+
export declare function resolveCacheAdapter(name: string): string;
|
|
34
|
+
/**
|
|
35
|
+
* Resolve a filesystem adapter name to a package name
|
|
36
|
+
* @param name - Blessed alias (memory, s3) or full package name (@custom/filesystem)
|
|
37
|
+
* @returns Full package name
|
|
38
|
+
*/
|
|
39
|
+
export declare function resolveFilesystemAdapter(name: string): string;
|
|
40
|
+
/**
|
|
41
|
+
* Dynamically load a cache adapter
|
|
42
|
+
* @param name - Adapter name (blessed alias or package name)
|
|
43
|
+
* @param config - Adapter configuration
|
|
44
|
+
* @returns Cache instance
|
|
45
|
+
*/
|
|
46
|
+
export declare function loadCacheAdapter(name: string, config?: any): Promise<any>;
|
|
47
|
+
/**
|
|
48
|
+
* Dynamically load a filesystem adapter
|
|
49
|
+
* @param name - Adapter name (blessed alias or package name)
|
|
50
|
+
* @param config - Adapter configuration
|
|
51
|
+
* @returns Filesystem adapter instance
|
|
52
|
+
*/
|
|
53
|
+
export declare function loadFilesystemAdapter(name: string, config?: any): Promise<any>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/// <reference types="./adapter-registry.d.ts" />
|
|
2
|
+
// src/adapter-registry.ts
|
|
3
|
+
var CACHE_ALIASES = {
|
|
4
|
+
memory: "@b9g/cache",
|
|
5
|
+
redis: "@b9g/cache-redis",
|
|
6
|
+
kv: "@b9g/cache-kv",
|
|
7
|
+
cloudflare: "@b9g/cache/cloudflare"
|
|
8
|
+
};
|
|
9
|
+
var FILESYSTEM_ALIASES = {
|
|
10
|
+
memory: "@b9g/filesystem",
|
|
11
|
+
fs: "@b9g/filesystem/node",
|
|
12
|
+
"bun-s3": "@b9g/filesystem/bun-s3",
|
|
13
|
+
s3: "@b9g/filesystem-s3",
|
|
14
|
+
r2: "@b9g/filesystem-r2"
|
|
15
|
+
};
|
|
16
|
+
function resolveCacheAdapter(name) {
|
|
17
|
+
if (name.startsWith("@")) {
|
|
18
|
+
return name;
|
|
19
|
+
}
|
|
20
|
+
if (name in CACHE_ALIASES) {
|
|
21
|
+
return CACHE_ALIASES[name];
|
|
22
|
+
}
|
|
23
|
+
throw new Error(`Unknown cache adapter: ${name}. Available aliases: ${Object.keys(CACHE_ALIASES).join(", ")} or use full package name like @custom/cache`);
|
|
24
|
+
}
|
|
25
|
+
function resolveFilesystemAdapter(name) {
|
|
26
|
+
if (name.startsWith("@")) {
|
|
27
|
+
return name;
|
|
28
|
+
}
|
|
29
|
+
if (name in FILESYSTEM_ALIASES) {
|
|
30
|
+
return FILESYSTEM_ALIASES[name];
|
|
31
|
+
}
|
|
32
|
+
throw new Error(`Unknown filesystem adapter: ${name}. Available aliases: ${Object.keys(FILESYSTEM_ALIASES).join(", ")} or use full package name like @custom/filesystem`);
|
|
33
|
+
}
|
|
34
|
+
async function loadCacheAdapter(name, config = {}) {
|
|
35
|
+
const packageName = resolveCacheAdapter(name);
|
|
36
|
+
try {
|
|
37
|
+
const module = await import(packageName);
|
|
38
|
+
if (!module.createCache) {
|
|
39
|
+
throw new Error(`Package ${packageName} does not export a createCache function`);
|
|
40
|
+
}
|
|
41
|
+
return module.createCache(config);
|
|
42
|
+
} catch (error) {
|
|
43
|
+
if (error instanceof Error && error.message.includes("Cannot resolve module")) {
|
|
44
|
+
throw new Error(`Cache adapter '${name}' requires: npm install ${packageName}`);
|
|
45
|
+
}
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async function loadFilesystemAdapter(name, config = {}) {
|
|
50
|
+
const packageName = resolveFilesystemAdapter(name);
|
|
51
|
+
try {
|
|
52
|
+
const module = await import(packageName);
|
|
53
|
+
if (!module.createFileSystem) {
|
|
54
|
+
throw new Error(`Package ${packageName} does not export a createFileSystem function`);
|
|
55
|
+
}
|
|
56
|
+
return module.createFileSystem(config);
|
|
57
|
+
} catch (error) {
|
|
58
|
+
if (error instanceof Error && error.message.includes("Cannot resolve module")) {
|
|
59
|
+
throw new Error(`Filesystem adapter '${name}' requires: npm install ${packageName}`);
|
|
60
|
+
}
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
export {
|
|
65
|
+
CACHE_ALIASES,
|
|
66
|
+
FILESYSTEM_ALIASES,
|
|
67
|
+
loadCacheAdapter,
|
|
68
|
+
loadFilesystemAdapter,
|
|
69
|
+
resolveCacheAdapter,
|
|
70
|
+
resolveFilesystemAdapter
|
|
71
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base platform implementation with dynamic adapter loading
|
|
3
|
+
* Provides common functionality for all platform implementations
|
|
4
|
+
*/
|
|
5
|
+
import type { Platform, PlatformConfig, CacheConfig, CacheBackendConfig, FilesystemConfig } from "./types.js";
|
|
6
|
+
import type { CacheStorage } from "@b9g/cache/cache-storage";
|
|
7
|
+
/**
|
|
8
|
+
* Base platform class with shared adapter loading logic
|
|
9
|
+
* Platform implementations extend this and provide platform-specific methods
|
|
10
|
+
*/
|
|
11
|
+
export declare abstract class BasePlatform implements Platform {
|
|
12
|
+
protected config: PlatformConfig;
|
|
13
|
+
constructor(config?: PlatformConfig);
|
|
14
|
+
abstract readonly name: string;
|
|
15
|
+
abstract readonly distDir: FileSystemDirectoryHandle;
|
|
16
|
+
abstract loadServiceWorker(entrypoint: string, options?: any): Promise<any>;
|
|
17
|
+
abstract createServer(handler: any, options?: any): any;
|
|
18
|
+
abstract getFileSystemRoot(bucketName: string): Promise<FileSystemDirectoryHandle>;
|
|
19
|
+
/**
|
|
20
|
+
* Create cache storage with dynamic adapter loading
|
|
21
|
+
* Uses platform defaults when specific cache types aren't configured
|
|
22
|
+
*/
|
|
23
|
+
createCaches(config?: CacheConfig): Promise<CacheStorage>;
|
|
24
|
+
/**
|
|
25
|
+
* Get platform-specific default cache configuration
|
|
26
|
+
* Subclasses override this to provide optimal defaults for their runtime
|
|
27
|
+
*/
|
|
28
|
+
protected getDefaultCacheConfig(): CacheConfig;
|
|
29
|
+
/**
|
|
30
|
+
* Merge user config with platform defaults
|
|
31
|
+
*/
|
|
32
|
+
protected mergeCacheConfig(userConfig?: CacheConfig): CacheConfig;
|
|
33
|
+
/**
|
|
34
|
+
* Build CacheStorage instance with dynamic adapter loading
|
|
35
|
+
*/
|
|
36
|
+
protected buildCacheStorage(config: CacheConfig): Promise<CacheStorage>;
|
|
37
|
+
/**
|
|
38
|
+
* Load a single cache instance using dynamic import
|
|
39
|
+
*/
|
|
40
|
+
protected loadCacheInstance(config: CacheBackendConfig): Promise<any>;
|
|
41
|
+
/**
|
|
42
|
+
* Load filesystem adapter using dynamic import
|
|
43
|
+
*/
|
|
44
|
+
protected loadFilesystemAdapter(config?: FilesystemConfig): Promise<any>;
|
|
45
|
+
/**
|
|
46
|
+
* Get platform-specific default filesystem configuration
|
|
47
|
+
* Subclasses override this to provide optimal defaults for their runtime
|
|
48
|
+
*/
|
|
49
|
+
protected getDefaultFilesystemConfig(): FilesystemConfig;
|
|
50
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/// <reference types="./base-platform.d.ts" />
|
|
2
|
+
// src/base-platform.ts
|
|
3
|
+
import { loadCacheAdapter, loadFilesystemAdapter } from "./adapter-registry.js";
|
|
4
|
+
var BasePlatform = class {
|
|
5
|
+
config;
|
|
6
|
+
constructor(config = {}) {
|
|
7
|
+
this.config = config;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Create cache storage with dynamic adapter loading
|
|
11
|
+
* Uses platform defaults when specific cache types aren't configured
|
|
12
|
+
*/
|
|
13
|
+
async createCaches(config) {
|
|
14
|
+
const mergedConfig = this.mergeCacheConfig(config);
|
|
15
|
+
return this.buildCacheStorage(mergedConfig);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Get platform-specific default cache configuration
|
|
19
|
+
* Subclasses override this to provide optimal defaults for their runtime
|
|
20
|
+
*/
|
|
21
|
+
getDefaultCacheConfig() {
|
|
22
|
+
return {
|
|
23
|
+
pages: { type: "memory" },
|
|
24
|
+
api: { type: "memory" },
|
|
25
|
+
static: { type: "memory" }
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Merge user config with platform defaults
|
|
30
|
+
*/
|
|
31
|
+
mergeCacheConfig(userConfig) {
|
|
32
|
+
const defaults = this.getDefaultCacheConfig();
|
|
33
|
+
const platformConfig = this.config.caches || {};
|
|
34
|
+
return {
|
|
35
|
+
...defaults,
|
|
36
|
+
...platformConfig,
|
|
37
|
+
...userConfig
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Build CacheStorage instance with dynamic adapter loading
|
|
42
|
+
*/
|
|
43
|
+
async buildCacheStorage(config) {
|
|
44
|
+
const caches = /* @__PURE__ */ new Map();
|
|
45
|
+
for (const [name, cacheConfig] of Object.entries(config)) {
|
|
46
|
+
if (cacheConfig && typeof cacheConfig === "object" && "type" in cacheConfig) {
|
|
47
|
+
const cache = await this.loadCacheInstance(cacheConfig);
|
|
48
|
+
caches.set(name, cache);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
async open(name) {
|
|
53
|
+
const cache = caches.get(name);
|
|
54
|
+
if (!cache) {
|
|
55
|
+
throw new Error(`Cache '${name}' not configured`);
|
|
56
|
+
}
|
|
57
|
+
return cache;
|
|
58
|
+
},
|
|
59
|
+
async delete(name) {
|
|
60
|
+
const deleted = caches.delete(name);
|
|
61
|
+
return deleted;
|
|
62
|
+
},
|
|
63
|
+
async has(name) {
|
|
64
|
+
return caches.has(name);
|
|
65
|
+
},
|
|
66
|
+
async keys() {
|
|
67
|
+
return Array.from(caches.keys());
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Load a single cache instance using dynamic import
|
|
73
|
+
*/
|
|
74
|
+
async loadCacheInstance(config) {
|
|
75
|
+
if (!config.type) {
|
|
76
|
+
throw new Error("Cache configuration must specify a type");
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
return await loadCacheAdapter(config.type, config);
|
|
80
|
+
} catch (error) {
|
|
81
|
+
if (error instanceof Error) {
|
|
82
|
+
throw new Error(`Failed to load cache adapter: ${error.message}`);
|
|
83
|
+
}
|
|
84
|
+
throw error;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Load filesystem adapter using dynamic import
|
|
89
|
+
*/
|
|
90
|
+
async loadFilesystemAdapter(config) {
|
|
91
|
+
const fsConfig = config || this.config.filesystem || this.getDefaultFilesystemConfig();
|
|
92
|
+
if (!fsConfig.type) {
|
|
93
|
+
throw new Error("Filesystem configuration must specify a type");
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
return await loadFilesystemAdapter(fsConfig.type, fsConfig);
|
|
97
|
+
} catch (error) {
|
|
98
|
+
if (error instanceof Error) {
|
|
99
|
+
throw new Error(`Failed to load filesystem adapter: ${error.message}`);
|
|
100
|
+
}
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Get platform-specific default filesystem configuration
|
|
106
|
+
* Subclasses override this to provide optimal defaults for their runtime
|
|
107
|
+
*/
|
|
108
|
+
getDefaultFilesystemConfig() {
|
|
109
|
+
return { type: "memory" };
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
export {
|
|
113
|
+
BasePlatform
|
|
114
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platform detection utilities
|
|
3
|
+
* Centralized logic for detecting JavaScript runtime and deployment platforms
|
|
4
|
+
*/
|
|
5
|
+
import type { PlatformDetection } from "./types.js";
|
|
6
|
+
/**
|
|
7
|
+
* Detect the current JavaScript runtime
|
|
8
|
+
*/
|
|
9
|
+
export declare function detectRuntime(): "bun" | "deno" | "node";
|
|
10
|
+
/**
|
|
11
|
+
* Detect platform for development (uses current runtime)
|
|
12
|
+
*/
|
|
13
|
+
export declare function detectDevelopmentPlatform(): string;
|
|
14
|
+
/**
|
|
15
|
+
* Comprehensive platform detection with confidence scoring
|
|
16
|
+
*/
|
|
17
|
+
export declare function detectPlatforms(): PlatformDetection[];
|
|
18
|
+
/**
|
|
19
|
+
* Get the best platform detection
|
|
20
|
+
*/
|
|
21
|
+
export declare function getBestPlatformDetection(): PlatformDetection;
|
|
22
|
+
/**
|
|
23
|
+
* Resolve platform name from options or auto-detect
|
|
24
|
+
*/
|
|
25
|
+
export declare function resolvePlatform(options: {
|
|
26
|
+
platform?: string;
|
|
27
|
+
target?: string;
|
|
28
|
+
}): string;
|
|
29
|
+
/**
|
|
30
|
+
* Create platform instance based on name
|
|
31
|
+
*/
|
|
32
|
+
export declare function createPlatform(platformName: string, options?: any): Promise<any>;
|
|
33
|
+
/**
|
|
34
|
+
* Display platform information (for CLI info command)
|
|
35
|
+
*/
|
|
36
|
+
export declare function displayPlatformInfo(platformName: string): void;
|
package/src/detection.js
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/// <reference types="./detection.d.ts" />
|
|
2
|
+
// src/detection.ts
|
|
3
|
+
function detectRuntime() {
|
|
4
|
+
if (typeof Bun !== "undefined" || process.versions?.bun) {
|
|
5
|
+
return "bun";
|
|
6
|
+
}
|
|
7
|
+
if (typeof Deno !== "undefined") {
|
|
8
|
+
return "deno";
|
|
9
|
+
}
|
|
10
|
+
return "node";
|
|
11
|
+
}
|
|
12
|
+
function detectDevelopmentPlatform() {
|
|
13
|
+
const runtime = detectRuntime();
|
|
14
|
+
switch (runtime) {
|
|
15
|
+
case "bun":
|
|
16
|
+
return "bun";
|
|
17
|
+
case "deno":
|
|
18
|
+
return "node";
|
|
19
|
+
case "node":
|
|
20
|
+
default:
|
|
21
|
+
return "node";
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function detectPlatforms() {
|
|
25
|
+
const detections = [];
|
|
26
|
+
if (typeof Bun !== "undefined") {
|
|
27
|
+
detections.push({
|
|
28
|
+
platform: "bun",
|
|
29
|
+
confidence: 0.9,
|
|
30
|
+
reasons: ["Bun global detected"]
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
if (typeof EdgeRuntime !== "undefined") {
|
|
34
|
+
detections.push({
|
|
35
|
+
platform: "vercel",
|
|
36
|
+
confidence: 0.9,
|
|
37
|
+
reasons: ["Vercel EdgeRuntime detected"]
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
if (typeof Deno !== "undefined") {
|
|
41
|
+
detections.push({
|
|
42
|
+
platform: "deno",
|
|
43
|
+
confidence: 0.9,
|
|
44
|
+
reasons: ["Deno global detected"]
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
if (typeof caches !== "undefined" && typeof Response !== "undefined" && typeof crypto !== "undefined") {
|
|
48
|
+
if (typeof addEventListener !== "undefined" && typeof fetch !== "undefined") {
|
|
49
|
+
detections.push({
|
|
50
|
+
platform: "cloudflare-workers",
|
|
51
|
+
confidence: 0.8,
|
|
52
|
+
reasons: ["Worker-like environment detected", "Web APIs available"]
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (typeof process !== "undefined" && process.versions && process.versions.node) {
|
|
57
|
+
detections.push({
|
|
58
|
+
platform: "node",
|
|
59
|
+
confidence: 0.7,
|
|
60
|
+
reasons: ["Node.js process detected"]
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
if (detections.length === 0) {
|
|
64
|
+
detections.push({
|
|
65
|
+
platform: "unknown",
|
|
66
|
+
confidence: 0,
|
|
67
|
+
reasons: ["No platform detected"]
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
return detections.sort((a, b) => b.confidence - a.confidence);
|
|
71
|
+
}
|
|
72
|
+
function getBestPlatformDetection() {
|
|
73
|
+
const detections = detectPlatforms();
|
|
74
|
+
return detections[0];
|
|
75
|
+
}
|
|
76
|
+
function resolvePlatform(options) {
|
|
77
|
+
if (options.platform) {
|
|
78
|
+
return options.platform;
|
|
79
|
+
}
|
|
80
|
+
if (options.target) {
|
|
81
|
+
return options.target;
|
|
82
|
+
}
|
|
83
|
+
return detectDevelopmentPlatform();
|
|
84
|
+
}
|
|
85
|
+
async function createPlatform(platformName, options = {}) {
|
|
86
|
+
switch (platformName) {
|
|
87
|
+
case "node": {
|
|
88
|
+
const modulePath = import.meta.resolve("@b9g/platform-node");
|
|
89
|
+
const { createNodePlatform } = await import(modulePath);
|
|
90
|
+
return createNodePlatform(options);
|
|
91
|
+
}
|
|
92
|
+
case "bun": {
|
|
93
|
+
const modulePath = import.meta.resolve("@b9g/platform-bun");
|
|
94
|
+
const { createBunPlatform } = await import(modulePath);
|
|
95
|
+
return createBunPlatform(options);
|
|
96
|
+
}
|
|
97
|
+
case "cloudflare":
|
|
98
|
+
case "cloudflare-workers":
|
|
99
|
+
case "cf": {
|
|
100
|
+
const modulePath = import.meta.resolve("@b9g/platform-cloudflare");
|
|
101
|
+
const { createCloudflarePlatform } = await import(modulePath);
|
|
102
|
+
return createCloudflarePlatform(options);
|
|
103
|
+
}
|
|
104
|
+
default:
|
|
105
|
+
throw new Error(
|
|
106
|
+
`Unknown platform: ${platformName}. Available platforms: node, bun, cloudflare`
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function displayPlatformInfo(platformName) {
|
|
111
|
+
const runtime = detectRuntime();
|
|
112
|
+
const detection = getBestPlatformDetection();
|
|
113
|
+
console.info(`\u{1F680} Platform: ${platformName}`);
|
|
114
|
+
console.info(`\u2699\uFE0F Runtime: ${runtime}`);
|
|
115
|
+
console.info(`\u{1F50D} Auto-detected: ${detection.platform} (confidence: ${detection.confidence})`);
|
|
116
|
+
console.info(`\u{1F4A1} Reasons: ${detection.reasons.join(", ")}`);
|
|
117
|
+
}
|
|
118
|
+
export {
|
|
119
|
+
createPlatform,
|
|
120
|
+
detectDevelopmentPlatform,
|
|
121
|
+
detectPlatforms,
|
|
122
|
+
detectRuntime,
|
|
123
|
+
displayPlatformInfo,
|
|
124
|
+
getBestPlatformDetection,
|
|
125
|
+
resolvePlatform
|
|
126
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Directory Storage implementation for ServiceWorker self.dirs API
|
|
3
|
+
*
|
|
4
|
+
* This implements the proposed web standard interface that parallels CacheStorage
|
|
5
|
+
* for structured filesystem access in ServiceWorkers.
|
|
6
|
+
*/
|
|
7
|
+
import type { DirectoryStorage } from "./service-worker.js";
|
|
8
|
+
/**
|
|
9
|
+
* Platform-agnostic directory storage implementation
|
|
10
|
+
* Uses a single root directory with well-known subdirectories
|
|
11
|
+
*/
|
|
12
|
+
export declare class PlatformDirectoryStorage implements DirectoryStorage {
|
|
13
|
+
private rootDir;
|
|
14
|
+
private cache;
|
|
15
|
+
constructor(rootDir: FileSystemDirectoryHandle);
|
|
16
|
+
/**
|
|
17
|
+
* Open a named directory - creates if it doesn't exist
|
|
18
|
+
* Well-known names: 'assets', 'static', 'server', 'client'
|
|
19
|
+
*/
|
|
20
|
+
open(name: string): Promise<FileSystemDirectoryHandle>;
|
|
21
|
+
/**
|
|
22
|
+
* Check if a named directory exists
|
|
23
|
+
*/
|
|
24
|
+
has(name: string): Promise<boolean>;
|
|
25
|
+
/**
|
|
26
|
+
* Delete a named directory and all its contents
|
|
27
|
+
*/
|
|
28
|
+
delete(name: string): Promise<boolean>;
|
|
29
|
+
/**
|
|
30
|
+
* List all available directory names
|
|
31
|
+
*/
|
|
32
|
+
keys(): Promise<string[]>;
|
|
33
|
+
/**
|
|
34
|
+
* Clear the cache (useful for hot reloading)
|
|
35
|
+
*/
|
|
36
|
+
clearCache(): void;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Create a DirectoryStorage instance from a root directory
|
|
40
|
+
*/
|
|
41
|
+
export declare function createDirectoryStorage(rootDir: FileSystemDirectoryHandle): DirectoryStorage;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/// <reference types="./directory-storage.d.ts" />
|
|
2
|
+
// src/directory-storage.ts
|
|
3
|
+
var PlatformDirectoryStorage = class {
|
|
4
|
+
rootDir;
|
|
5
|
+
cache = /* @__PURE__ */ new Map();
|
|
6
|
+
constructor(rootDir) {
|
|
7
|
+
this.rootDir = rootDir;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Open a named directory - creates if it doesn't exist
|
|
11
|
+
* Well-known names: 'assets', 'static', 'server', 'client'
|
|
12
|
+
*/
|
|
13
|
+
async open(name) {
|
|
14
|
+
if (this.cache.has(name)) {
|
|
15
|
+
return this.cache.get(name);
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
const dirHandle = await this.rootDir.getDirectoryHandle(name);
|
|
19
|
+
this.cache.set(name, dirHandle);
|
|
20
|
+
return dirHandle;
|
|
21
|
+
} catch (error) {
|
|
22
|
+
const dirHandle = await this.rootDir.getDirectoryHandle(name, { create: true });
|
|
23
|
+
this.cache.set(name, dirHandle);
|
|
24
|
+
return dirHandle;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Check if a named directory exists
|
|
29
|
+
*/
|
|
30
|
+
async has(name) {
|
|
31
|
+
try {
|
|
32
|
+
await this.rootDir.getDirectoryHandle(name);
|
|
33
|
+
return true;
|
|
34
|
+
} catch {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Delete a named directory and all its contents
|
|
40
|
+
*/
|
|
41
|
+
async delete(name) {
|
|
42
|
+
try {
|
|
43
|
+
await this.rootDir.removeEntry(name, { recursive: true });
|
|
44
|
+
this.cache.delete(name);
|
|
45
|
+
return true;
|
|
46
|
+
} catch {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* List all available directory names
|
|
52
|
+
*/
|
|
53
|
+
async keys() {
|
|
54
|
+
const keys = [];
|
|
55
|
+
try {
|
|
56
|
+
for await (const [name, handle] of this.rootDir.entries()) {
|
|
57
|
+
if (handle.kind === "directory") {
|
|
58
|
+
keys.push(name);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
} catch {
|
|
62
|
+
}
|
|
63
|
+
return keys.sort();
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Clear the cache (useful for hot reloading)
|
|
67
|
+
*/
|
|
68
|
+
clearCache() {
|
|
69
|
+
this.cache.clear();
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
function createDirectoryStorage(rootDir) {
|
|
73
|
+
return new PlatformDirectoryStorage(rootDir);
|
|
74
|
+
}
|
|
75
|
+
export {
|
|
76
|
+
PlatformDirectoryStorage,
|
|
77
|
+
createDirectoryStorage
|
|
78
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File System Access API implementation
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Get the file system root handle for the specified name
|
|
6
|
+
* Auto-registers Node.js platform if no platform is detected
|
|
7
|
+
*/
|
|
8
|
+
export declare function getFileSystemRoot(name?: string): Promise<FileSystemDirectoryHandle>;
|