@b9g/platform 0.1.5 → 0.1.6

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@b9g/platform",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "ServiceWorker-first universal deployment platform. Write ServiceWorker apps once, deploy anywhere (Node/Bun/Cloudflare). Registry-based multi-app orchestration.",
5
5
  "keywords": [
6
6
  "serviceworker",
@@ -16,6 +16,8 @@
16
16
  ],
17
17
  "dependencies": {
18
18
  "@b9g/async-context": "^0.1.1",
19
+ "@b9g/cache": "^0.1.4",
20
+ "@b9g/filesystem": "^0.1.5",
19
21
  "@logtape/logtape": "^1.2.0"
20
22
  },
21
23
  "devDependencies": {
package/src/config.d.ts CHANGED
@@ -16,6 +16,7 @@
16
16
  * "S3_BUCKET || my-bucket-name"
17
17
  * "BASE_PATH || ./uploads"
18
18
  */
19
+ import { Cache } from "@b9g/cache";
19
20
  /**
20
21
  * Parse a configuration expression with the DSL
21
22
  */
@@ -92,6 +93,16 @@ export interface BucketFactoryOptions {
92
93
  /**
93
94
  * Creates a bucket factory function for CustomBucketStorage.
94
95
  * Lazily imports bucket implementations.
96
+ *
97
+ * Provider resolution:
98
+ * 1. "node" -> built-in NodeBucket (default)
99
+ * 2. "memory" -> built-in MemoryBucket
100
+ * 3. "s3" -> @b9g/filesystem-s3 (blessed module)
101
+ * 4. Any other string -> treated as a module name (e.g., "my-custom-bucket")
102
+ *
103
+ * Custom bucket modules must export a class that:
104
+ * - Implements FileSystemDirectoryHandle
105
+ * - Has constructor(name: string, options?: object)
95
106
  */
96
107
  export declare function createBucketFactory(options: BucketFactoryOptions): (name: string) => Promise<FileSystemDirectoryHandle>;
97
108
  export interface CacheFactoryOptions {
@@ -101,5 +112,14 @@ export interface CacheFactoryOptions {
101
112
  /**
102
113
  * Creates a cache factory function for CustomCacheStorage.
103
114
  * Lazily imports cache implementations.
115
+ *
116
+ * Provider resolution:
117
+ * 1. "memory" -> built-in MemoryCache
118
+ * 2. "redis" -> @b9g/cache-redis (blessed module)
119
+ * 3. Any other string -> treated as a module name (e.g., "my-custom-cache")
120
+ *
121
+ * Custom cache modules must export a class that:
122
+ * - Extends Cache (from @b9g/cache)
123
+ * - Has constructor(name: string, options?: object)
104
124
  */
105
125
  export declare function createCacheFactory(options?: CacheFactoryOptions): (name: string) => Promise<Cache>;
package/src/config.js CHANGED
@@ -2,6 +2,7 @@
2
2
  // src/config.ts
3
3
  import { readFileSync } from "fs";
4
4
  import { resolve } from "path";
5
+ import { Cache } from "@b9g/cache";
5
6
  function getEnv() {
6
7
  if (typeof import.meta !== "undefined" && import.meta.env) {
7
8
  return import.meta.env;
@@ -409,6 +410,11 @@ var WELL_KNOWN_BUCKET_PATHS = {
409
410
  static: (baseDir) => resolve(baseDir, "../static"),
410
411
  server: (baseDir) => baseDir
411
412
  };
413
+ var BUILTIN_BUCKET_PROVIDERS = {
414
+ node: "@b9g/filesystem/node.js",
415
+ memory: "@b9g/filesystem/memory.js",
416
+ s3: "@b9g/filesystem-s3"
417
+ };
412
418
  function createBucketFactory(options) {
413
419
  const { baseDir, config } = options;
414
420
  return async (name) => {
@@ -422,32 +428,80 @@ function createBucketFactory(options) {
422
428
  bucketPath = resolve(baseDir, `../${name}`);
423
429
  }
424
430
  const provider = String(bucketConfig.provider || "node");
425
- switch (provider) {
426
- case "memory": {
427
- const { MemoryBucket } = await import("@b9g/filesystem/memory.js");
428
- return new MemoryBucket(name);
431
+ const modulePath = BUILTIN_BUCKET_PROVIDERS[provider] || provider;
432
+ if (modulePath === "@b9g/filesystem/node.js") {
433
+ const { NodeBucket } = await import("@b9g/filesystem/node.js");
434
+ return new NodeBucket(bucketPath);
435
+ }
436
+ if (modulePath === "@b9g/filesystem/memory.js") {
437
+ const { MemoryBucket } = await import("@b9g/filesystem/memory.js");
438
+ return new MemoryBucket(name);
439
+ }
440
+ try {
441
+ const module = await import(modulePath);
442
+ const BucketClass = module.default || // Default export
443
+ module.S3Bucket || // Named export for s3
444
+ module.Bucket || // Generic Bucket export
445
+ Object.values(module).find(
446
+ (v) => typeof v === "function" && v.name?.includes("Bucket")
447
+ );
448
+ if (!BucketClass) {
449
+ throw new Error(
450
+ `Bucket module "${modulePath}" does not export a valid bucket class. Expected a default export or named export (S3Bucket, Bucket).`
451
+ );
429
452
  }
430
- case "node":
431
- default: {
432
- const { NodeBucket } = await import("@b9g/filesystem/node.js");
433
- return new NodeBucket(bucketPath);
453
+ const { provider: _, path: __, ...bucketOptions } = bucketConfig;
454
+ return new BucketClass(name, { path: bucketPath, ...bucketOptions });
455
+ } catch (error) {
456
+ if (error.code === "ERR_MODULE_NOT_FOUND" || error.code === "MODULE_NOT_FOUND") {
457
+ throw new Error(
458
+ `Bucket provider "${provider}" not found. Make sure the module "${modulePath}" is installed.
459
+ For S3: npm install @b9g/filesystem-s3`
460
+ );
434
461
  }
462
+ throw error;
435
463
  }
436
464
  };
437
465
  }
466
+ var BUILTIN_CACHE_PROVIDERS = {
467
+ memory: "@b9g/cache/memory.js",
468
+ redis: "@b9g/cache-redis"
469
+ };
438
470
  function createCacheFactory(options = {}) {
439
471
  const { config } = options;
440
472
  return async (name) => {
441
473
  const cacheConfig = config ? getCacheConfig(config, name) : {};
442
474
  const provider = String(cacheConfig.provider || "memory");
443
- switch (provider) {
444
- case "memory":
445
- default: {
446
- const { MemoryCache } = await import("@b9g/cache/memory.js");
447
- return new MemoryCache(name, {
448
- maxEntries: typeof cacheConfig.maxEntries === "number" ? cacheConfig.maxEntries : 1e3
449
- });
475
+ const modulePath = BUILTIN_CACHE_PROVIDERS[provider] || provider;
476
+ if (modulePath === "@b9g/cache/memory.js") {
477
+ const { MemoryCache } = await import("@b9g/cache/memory.js");
478
+ return new MemoryCache(name, {
479
+ maxEntries: typeof cacheConfig.maxEntries === "number" ? cacheConfig.maxEntries : 1e3
480
+ });
481
+ }
482
+ try {
483
+ const module = await import(modulePath);
484
+ const CacheClass = module.default || // Default export
485
+ module.RedisCache || // Named export for redis
486
+ module.Cache || // Generic Cache export
487
+ Object.values(module).find(
488
+ (v) => typeof v === "function" && v.prototype instanceof Cache
489
+ );
490
+ if (!CacheClass) {
491
+ throw new Error(
492
+ `Cache module "${modulePath}" does not export a valid cache class. Expected a default export or named export (RedisCache, Cache) that extends Cache.`
493
+ );
494
+ }
495
+ const { provider: _, ...cacheOptions } = cacheConfig;
496
+ return new CacheClass(name, cacheOptions);
497
+ } catch (error) {
498
+ if (error.code === "ERR_MODULE_NOT_FOUND" || error.code === "MODULE_NOT_FOUND") {
499
+ throw new Error(
500
+ `Cache provider "${provider}" not found. Make sure the module "${modulePath}" is installed.
501
+ For redis: npm install @b9g/cache-redis`
502
+ );
450
503
  }
504
+ throw error;
451
505
  }
452
506
  };
453
507
  }