@b9g/platform 0.1.1 → 0.1.3

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/README.md ADDED
@@ -0,0 +1,215 @@
1
+ # @b9g/platform
2
+
3
+ Universal platform abstraction for ServiceWorker-style applications with automatic platform detection and worker thread architecture.
4
+
5
+ ## Features
6
+
7
+ - **ServiceWorker Pattern**: Load applications as ServiceWorker entrypoints
8
+ - **Multi-Platform**: Node.js, Bun, Cloudflare Workers support
9
+ - **Auto-Detection**: Automatic runtime detection with explicit override
10
+ - **Worker Architecture**: Multi-worker concurrency with coordinated caching
11
+ - **Hot Reloading**: VM module isolation for clean development reloads
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install @b9g/platform
17
+ ```
18
+
19
+ ## Platform Packages
20
+
21
+ Install platform-specific implementations:
22
+
23
+ ```bash
24
+ # For Node.js
25
+ npm install @b9g/platform-node
26
+
27
+ # For Bun
28
+ npm install @b9g/platform-bun
29
+
30
+ # For Cloudflare Workers
31
+ npm install @b9g/platform-cloudflare
32
+ ```
33
+
34
+ ## Quick Start
35
+
36
+ ```javascript
37
+ import { createPlatform } from '@b9g/platform';
38
+
39
+ // Auto-detect platform
40
+ const platform = await createPlatform('auto');
41
+
42
+ // Load ServiceWorker app
43
+ const serviceWorker = await platform.loadServiceWorker('./app.js', {
44
+ workerCount: 2,
45
+ hotReload: true
46
+ });
47
+
48
+ // Create server
49
+ const server = platform.createServer(serviceWorker.handleRequest, {
50
+ port: 3000,
51
+ host: 'localhost'
52
+ });
53
+
54
+ await server.listen();
55
+ ```
56
+
57
+ ## ServiceWorker Pattern
58
+
59
+ Write your app as a ServiceWorker entrypoint:
60
+
61
+ ```javascript
62
+ // app.js - ServiceWorker-style entrypoint
63
+ import { Router } from '@b9g/router';
64
+
65
+ const router = new Router();
66
+ router.get('/', () => new Response('Hello World!'));
67
+
68
+ // ServiceWorker lifecycle events
69
+ addEventListener('install', event => {
70
+ console.log('App installing...');
71
+ });
72
+
73
+ addEventListener('activate', event => {
74
+ console.log('App activated!');
75
+ });
76
+
77
+ // Handle fetch events
78
+ addEventListener('fetch', event => {
79
+ event.respondWith(router.handler(event.request));
80
+ });
81
+ ```
82
+
83
+ ## Platform Detection
84
+
85
+ ```javascript
86
+ import {
87
+ detectPlatform,
88
+ createPlatform,
89
+ displayPlatformInfo
90
+ } from '@b9g/platform';
91
+
92
+ // Detect current runtime
93
+ const detected = detectPlatform();
94
+ console.log(detected); // { runtime: 'bun', platforms: ['bun', 'node'] }
95
+
96
+ // Create platform instance
97
+ const platform = await createPlatform('bun', {
98
+ // Platform-specific options
99
+ });
100
+
101
+ // Display platform information
102
+ displayPlatformInfo(detected);
103
+ ```
104
+
105
+ ## Worker Architecture
106
+
107
+ ```javascript
108
+ const platform = await createPlatform('node');
109
+
110
+ const serviceWorker = await platform.loadServiceWorker('./app.js', {
111
+ workerCount: 4, // Number of worker threads
112
+ hotReload: true, // Enable hot reloading
113
+ caches: {
114
+ pages: { type: 'memory', maxEntries: 1000 },
115
+ api: { type: 'memory', ttl: 300 }
116
+ }
117
+ });
118
+
119
+ // Workers coordinate through PostMessage
120
+ // Each worker loads your ServiceWorker app
121
+ // Cache operations are coordinated across workers
122
+ ```
123
+
124
+ ## Platform-Specific Features
125
+
126
+ ### Node.js Platform
127
+
128
+ ```javascript
129
+ import { createNodePlatform } from '@b9g/platform-node';
130
+
131
+ const platform = await createNodePlatform({
132
+ // Node.js specific options
133
+ });
134
+ ```
135
+
136
+ ### Bun Platform
137
+
138
+ ```javascript
139
+ import { createBunPlatform } from '@b9g/platform-bun';
140
+
141
+ const platform = await createBunPlatform({
142
+ // Bun specific options
143
+ });
144
+ ```
145
+
146
+ ### Cloudflare Workers Platform
147
+
148
+ ```javascript
149
+ import { createCloudflarePlatform } from '@b9g/platform-cloudflare';
150
+
151
+ const platform = await createCloudflarePlatform({
152
+ // Cloudflare specific options
153
+ });
154
+ ```
155
+
156
+ ## API Reference
157
+
158
+ ### Platform Interface
159
+
160
+ ```typescript
161
+ interface Platform {
162
+ loadServiceWorker(entrypoint: string, options: ServiceWorkerOptions): Promise<ServiceWorkerInstance>;
163
+ createServer(handler: Handler, options: ServerOptions): Server;
164
+ dispose(): Promise<void>;
165
+ }
166
+ ```
167
+
168
+ ### ServiceWorker Options
169
+
170
+ ```typescript
171
+ interface ServiceWorkerOptions {
172
+ workerCount?: number;
173
+ hotReload?: boolean;
174
+ caches?: CacheConfig;
175
+ }
176
+ ```
177
+
178
+ ### Platform Detection
179
+
180
+ ```typescript
181
+ function detectPlatform(): PlatformDetection;
182
+ function createPlatform(platformName: string, options?: any): Promise<Platform>;
183
+ function displayPlatformInfo(detection: PlatformDetection): void;
184
+ ```
185
+
186
+ ## Development vs Production
187
+
188
+ ### Development (2 workers default)
189
+ - Encourages concurrency thinking from the start
190
+ - Hot reloading with VM module isolation
191
+ - Verbose logging and error reporting
192
+
193
+ ### Production (CPU count workers)
194
+ - Maximum throughput with worker-per-core
195
+ - Optimized cache coordination
196
+ - Minimal logging overhead
197
+
198
+ ## Integration with CLI
199
+
200
+ The platform abstraction powers the Shovel CLI:
201
+
202
+ ```bash
203
+ # Auto-detect and run
204
+ shovel develop app.js
205
+
206
+ # Explicit platform targeting
207
+ shovel develop app.js --platform=bun --workers=4
208
+
209
+ # Platform-specific builds
210
+ shovel build app.js --platform=cloudflare
211
+ ```
212
+
213
+ ## License
214
+
215
+ MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@b9g/platform",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Base Platform interface and types for Shovel deployment adapters",
5
5
  "keywords": [
6
6
  "shovel",
@@ -104,6 +104,22 @@
104
104
  "./directory-storage.js": {
105
105
  "types": "./src/directory-storage.d.ts",
106
106
  "import": "./src/directory-storage.js"
107
+ },
108
+ "./worker-pool": {
109
+ "types": "./src/worker-pool.d.ts",
110
+ "import": "./src/worker-pool.js"
111
+ },
112
+ "./worker-pool.js": {
113
+ "types": "./src/worker-pool.d.ts",
114
+ "import": "./src/worker-pool.js"
115
+ },
116
+ "./worker-web": {
117
+ "types": "./src/worker-web.d.ts",
118
+ "import": "./src/worker-web.js"
119
+ },
120
+ "./worker-web.js": {
121
+ "types": "./src/worker-web.d.ts",
122
+ "import": "./src/worker-web.js"
107
123
  }
108
124
  }
109
125
  }
@@ -12,10 +12,9 @@ export declare abstract class BasePlatform implements Platform {
12
12
  protected config: PlatformConfig;
13
13
  constructor(config?: PlatformConfig);
14
14
  abstract readonly name: string;
15
- abstract readonly distDir: FileSystemDirectoryHandle;
16
15
  abstract loadServiceWorker(entrypoint: string, options?: any): Promise<any>;
17
16
  abstract createServer(handler: any, options?: any): any;
18
- abstract getFileSystemRoot(bucketName: string): Promise<FileSystemDirectoryHandle>;
17
+ abstract getDirectoryHandle(name: string): Promise<FileSystemDirectoryHandle>;
19
18
  /**
20
19
  * Create cache storage with dynamic adapter loading
21
20
  * Uses platform defaults when specific cache types aren't configured
@@ -1,41 +1,41 @@
1
1
  /**
2
- * Directory Storage implementation for ServiceWorker self.dirs API
2
+ * Bucket Storage implementation for ServiceWorker self.buckets API
3
3
  *
4
4
  * This implements the proposed web standard interface that parallels CacheStorage
5
5
  * for structured filesystem access in ServiceWorkers.
6
6
  */
7
- import type { DirectoryStorage } from "./service-worker.js";
7
+ import type { BucketStorage as BucketStorageInterface } from "./service-worker.js";
8
8
  /**
9
- * Platform-agnostic directory storage implementation
10
- * Uses a single root directory with well-known subdirectories
9
+ * Platform-agnostic bucket storage implementation
10
+ * Uses bucket pattern where each bucket name maps to a separate filesystem root
11
11
  */
12
- export declare class PlatformDirectoryStorage implements DirectoryStorage {
13
- private rootDir;
14
- private cache;
15
- constructor(rootDir: FileSystemDirectoryHandle);
12
+ export declare class PlatformBucketStorage implements BucketStorageInterface {
13
+ private buckets;
14
+ constructor(rootPath?: string);
16
15
  /**
17
- * Open a named directory - creates if it doesn't exist
18
- * Well-known names: 'assets', 'static', 'server', 'client'
16
+ * Open a named bucket - creates if it doesn't exist
17
+ * Well-known names: 'assets', 'static', 'uploads', 'temp'
18
+ * Special values: '', '/', '.' return the root bucket
19
19
  */
20
20
  open(name: string): Promise<FileSystemDirectoryHandle>;
21
21
  /**
22
- * Check if a named directory exists
22
+ * Check if a named bucket exists
23
23
  */
24
24
  has(name: string): Promise<boolean>;
25
25
  /**
26
- * Delete a named directory and all its contents
26
+ * Delete a named bucket and all its contents
27
27
  */
28
28
  delete(name: string): Promise<boolean>;
29
29
  /**
30
- * List all available directory names
30
+ * List all available bucket names
31
31
  */
32
32
  keys(): Promise<string[]>;
33
33
  /**
34
- * Clear the cache (useful for hot reloading)
34
+ * Alias for open() - for compatibility with File System Access API naming
35
35
  */
36
- clearCache(): void;
36
+ getDirectoryHandle(name: string): Promise<FileSystemDirectoryHandle>;
37
37
  }
38
38
  /**
39
- * Create a DirectoryStorage instance from a root directory
39
+ * Create a BucketStorage instance from a root path
40
40
  */
41
- export declare function createDirectoryStorage(rootDir: FileSystemDirectoryHandle): DirectoryStorage;
41
+ export declare function createBucketStorage(rootPath?: string): BucketStorageInterface;
@@ -1,78 +1,53 @@
1
1
  /// <reference types="./directory-storage.d.ts" />
2
2
  // src/directory-storage.ts
3
- var PlatformDirectoryStorage = class {
4
- rootDir;
5
- cache = /* @__PURE__ */ new Map();
6
- constructor(rootDir) {
7
- this.rootDir = rootDir;
3
+ import { BucketStorage, LocalBucket } from "@b9g/filesystem";
4
+ var PlatformBucketStorage = class {
5
+ buckets;
6
+ constructor(rootPath = "./dist") {
7
+ this.buckets = new BucketStorage((name) => {
8
+ if (name === "" || name === "/" || name === ".") {
9
+ return new LocalBucket(rootPath);
10
+ }
11
+ return new LocalBucket(`${rootPath}/${name}`);
12
+ });
8
13
  }
9
14
  /**
10
- * Open a named directory - creates if it doesn't exist
11
- * Well-known names: 'assets', 'static', 'server', 'client'
15
+ * Open a named bucket - creates if it doesn't exist
16
+ * Well-known names: 'assets', 'static', 'uploads', 'temp'
17
+ * Special values: '', '/', '.' return the root bucket
12
18
  */
13
19
  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
- }
20
+ return await this.buckets.open(name);
26
21
  }
27
22
  /**
28
- * Check if a named directory exists
23
+ * Check if a named bucket exists
29
24
  */
30
25
  async has(name) {
31
- try {
32
- await this.rootDir.getDirectoryHandle(name);
33
- return true;
34
- } catch {
35
- return false;
36
- }
26
+ return await this.buckets.has(name);
37
27
  }
38
28
  /**
39
- * Delete a named directory and all its contents
29
+ * Delete a named bucket and all its contents
40
30
  */
41
31
  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
- }
32
+ return await this.buckets.delete(name);
49
33
  }
50
34
  /**
51
- * List all available directory names
35
+ * List all available bucket names
52
36
  */
53
37
  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();
38
+ return await this.buckets.keys();
64
39
  }
65
40
  /**
66
- * Clear the cache (useful for hot reloading)
41
+ * Alias for open() - for compatibility with File System Access API naming
67
42
  */
68
- clearCache() {
69
- this.cache.clear();
43
+ async getDirectoryHandle(name) {
44
+ return await this.open(name);
70
45
  }
71
46
  };
72
- function createDirectoryStorage(rootDir) {
73
- return new PlatformDirectoryStorage(rootDir);
47
+ function createBucketStorage(rootPath = "./dist") {
48
+ return new PlatformBucketStorage(rootPath);
74
49
  }
75
50
  export {
76
- PlatformDirectoryStorage,
77
- createDirectoryStorage
51
+ PlatformBucketStorage,
52
+ createBucketStorage
78
53
  };
@@ -2,7 +2,15 @@
2
2
  * File System Access API implementation
3
3
  */
4
4
  /**
5
- * Get the file system root handle for the specified name
5
+ * Get the file system directory handle for the specified name
6
6
  * Auto-registers Node.js platform if no platform is detected
7
7
  */
8
+ export declare function getDirectoryHandle(name: string): Promise<FileSystemDirectoryHandle>;
9
+ /**
10
+ * @deprecated Use getDirectoryHandle() instead
11
+ */
12
+ export declare function getBucket(name?: string): Promise<FileSystemDirectoryHandle>;
13
+ /**
14
+ * @deprecated Use getDirectoryHandle() instead
15
+ */
8
16
  export declare function getFileSystemRoot(name?: string): Promise<FileSystemDirectoryHandle>;
package/src/filesystem.js CHANGED
@@ -1,10 +1,20 @@
1
1
  /// <reference types="./filesystem.d.ts" />
2
2
  // src/filesystem.ts
3
3
  import { getPlatformAsync } from "./registry.js";
4
+ async function getDirectoryHandle(name) {
5
+ const platform = await getPlatformAsync();
6
+ return await platform.getDirectoryHandle(name);
7
+ }
8
+ async function getBucket(name) {
9
+ const platform = await getPlatformAsync();
10
+ return await platform.getDirectoryHandle(name || "");
11
+ }
4
12
  async function getFileSystemRoot(name) {
5
13
  const platform = await getPlatformAsync();
6
- return await platform.getFileSystemRoot(name);
14
+ return await platform.getDirectoryHandle(name || "");
7
15
  }
8
16
  export {
17
+ getBucket,
18
+ getDirectoryHandle,
9
19
  getFileSystemRoot
10
20
  };
package/src/index.d.ts CHANGED
@@ -6,9 +6,10 @@
6
6
  */
7
7
  export type { Platform, CacheConfig, CacheBackendConfig, ServerOptions, CorsConfig, Handler, Server, ServiceWorkerOptions, ServiceWorkerInstance, PlatformDetection, PlatformRegistry, } from "./types.js";
8
8
  export { BasePlatform } from "./types.js";
9
- export { ServiceWorkerRuntime, createServiceWorkerGlobals, type ShovelFetchEvent, type ShovelInstallEvent, type ShovelActivateEvent, type ShovelStaticEvent, type DirectoryStorage, } from "./service-worker.js";
10
- export { PlatformDirectoryStorage, createDirectoryStorage, } from "./directory-storage.js";
9
+ export { ServiceWorkerRuntime, createServiceWorkerGlobals, type ShovelFetchEvent, type ShovelInstallEvent, type ShovelActivateEvent, type ShovelStaticEvent, type BucketStorage as BucketStorageInterface, } from "./service-worker.js";
10
+ export { PlatformBucketStorage, createBucketStorage, } from "./directory-storage.js";
11
11
  export { platformRegistry, detectPlatform, getPlatform, getPlatformAsync, } from "./registry.js";
12
12
  export { detectRuntime, detectDevelopmentPlatform, detectPlatforms, getBestPlatformDetection, resolvePlatform, createPlatform, displayPlatformInfo, } from "./detection.js";
13
13
  export { parseTTL, mergeCacheConfig, validateCacheConfig, createCorsHeaders, mergeHeaders, isPreflightRequest, createPreflightResponse, } from "./utils.js";
14
- export { getFileSystemRoot } from "./filesystem.js";
14
+ export { getDirectoryHandle, getBucket, getFileSystemRoot } from "./filesystem.js";
15
+ export { WorkerPool, type WorkerFactory, type PlatformWorker, type WorkerPoolOptions } from "./worker-pool.js";
package/src/index.js CHANGED
@@ -6,8 +6,8 @@ import {
6
6
  createServiceWorkerGlobals
7
7
  } from "./service-worker.js";
8
8
  import {
9
- PlatformDirectoryStorage,
10
- createDirectoryStorage
9
+ PlatformBucketStorage,
10
+ createBucketStorage
11
11
  } from "./directory-storage.js";
12
12
  import {
13
13
  platformRegistry,
@@ -33,13 +33,15 @@ import {
33
33
  isPreflightRequest,
34
34
  createPreflightResponse
35
35
  } from "./utils.js";
36
- import { getFileSystemRoot } from "./filesystem.js";
36
+ import { getDirectoryHandle, getBucket, getFileSystemRoot } from "./filesystem.js";
37
+ import { WorkerPool } from "./worker-pool.js";
37
38
  export {
38
39
  BasePlatform,
39
- PlatformDirectoryStorage,
40
+ PlatformBucketStorage,
40
41
  ServiceWorkerRuntime,
42
+ WorkerPool,
43
+ createBucketStorage,
41
44
  createCorsHeaders,
42
- createDirectoryStorage,
43
45
  createPlatform,
44
46
  createPreflightResponse,
45
47
  createServiceWorkerGlobals,
@@ -49,6 +51,8 @@ export {
49
51
  detectRuntime,
50
52
  displayPlatformInfo,
51
53
  getBestPlatformDetection,
54
+ getBucket,
55
+ getDirectoryHandle,
52
56
  getFileSystemRoot,
53
57
  getPlatform,
54
58
  getPlatformAsync,