@fgv/ts-http-storage 5.1.0-1

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.
Files changed (137) hide show
  1. package/.rush/temp/chunked-rush-logs/ts-http-storage.build.chunks.jsonl +9 -0
  2. package/.rush/temp/fbfcc9487d290993ba47f1d36e9383196e7b12ac.tar.log +61 -0
  3. package/.rush/temp/operation/build/all.log +9 -0
  4. package/.rush/temp/operation/build/log-chunks.jsonl +9 -0
  5. package/.rush/temp/operation/build/state.json +3 -0
  6. package/.rush/temp/shrinkwrap-deps.json +647 -0
  7. package/config/api-extractor.json +36 -0
  8. package/config/rig.json +10 -0
  9. package/config/typedoc.json +7 -0
  10. package/dist/ts-http-storage.d.ts +225 -0
  11. package/dist/tsdoc-metadata.json +11 -0
  12. package/docs/README.md +298 -0
  13. package/docs/classes/FsStorageProvider.createDirectory.md +20 -0
  14. package/docs/classes/FsStorageProvider.getChildren.md +20 -0
  15. package/docs/classes/FsStorageProvider.getFile.md +20 -0
  16. package/docs/classes/FsStorageProvider.getItem.md +20 -0
  17. package/docs/classes/FsStorageProvider.md +134 -0
  18. package/docs/classes/FsStorageProvider.saveFile.md +22 -0
  19. package/docs/classes/FsStorageProvider.sync.md +13 -0
  20. package/docs/classes/FsStorageProviderFactory.forNamespace.md +20 -0
  21. package/docs/classes/FsStorageProviderFactory.md +69 -0
  22. package/docs/classes/HttpStorageService.createDirectory.md +20 -0
  23. package/docs/classes/HttpStorageService.getChildren.md +20 -0
  24. package/docs/classes/HttpStorageService.getFile.md +20 -0
  25. package/docs/classes/HttpStorageService.getItem.md +20 -0
  26. package/docs/classes/HttpStorageService.md +132 -0
  27. package/docs/classes/HttpStorageService.saveFile.md +20 -0
  28. package/docs/classes/HttpStorageService.sync.md +20 -0
  29. package/docs/functions/createStorageRoutes.md +11 -0
  30. package/docs/functions/normalizeRequestPath.md +11 -0
  31. package/docs/functions/sanitizeNamespace.md +11 -0
  32. package/docs/interfaces/ICreateStorageRoutesOptions.logger.md +9 -0
  33. package/docs/interfaces/ICreateStorageRoutesOptions.md +61 -0
  34. package/docs/interfaces/ICreateStorageRoutesOptions.providers.md +9 -0
  35. package/docs/interfaces/IFsStorageProviderFactoryOptions.md +44 -0
  36. package/docs/interfaces/IFsStorageProviderFactoryOptions.rootPath.md +9 -0
  37. package/docs/interfaces/IHttpStorageProvider.createDirectory.md +20 -0
  38. package/docs/interfaces/IHttpStorageProvider.getChildren.md +20 -0
  39. package/docs/interfaces/IHttpStorageProvider.getFile.md +20 -0
  40. package/docs/interfaces/IHttpStorageProvider.getItem.md +20 -0
  41. package/docs/interfaces/IHttpStorageProvider.md +102 -0
  42. package/docs/interfaces/IHttpStorageProvider.saveFile.md +22 -0
  43. package/docs/interfaces/IHttpStorageProvider.sync.md +13 -0
  44. package/docs/interfaces/IHttpStorageProviderFactory.forNamespace.md +20 -0
  45. package/docs/interfaces/IHttpStorageProviderFactory.md +36 -0
  46. package/docs/interfaces/IStorageFileResponse.contentType.md +9 -0
  47. package/docs/interfaces/IStorageFileResponse.contents.md +9 -0
  48. package/docs/interfaces/IStorageFileResponse.md +78 -0
  49. package/docs/interfaces/IStorageFileResponse.path.md +9 -0
  50. package/docs/interfaces/IStoragePathRequest.md +61 -0
  51. package/docs/interfaces/IStoragePathRequest.namespace.md +9 -0
  52. package/docs/interfaces/IStoragePathRequest.path.md +9 -0
  53. package/docs/interfaces/IStorageSyncRequest.md +44 -0
  54. package/docs/interfaces/IStorageSyncRequest.namespace.md +9 -0
  55. package/docs/interfaces/IStorageSyncResponse.md +44 -0
  56. package/docs/interfaces/IStorageSyncResponse.synced.md +9 -0
  57. package/docs/interfaces/IStorageTreeChildrenResponse.children.md +9 -0
  58. package/docs/interfaces/IStorageTreeChildrenResponse.md +61 -0
  59. package/docs/interfaces/IStorageTreeChildrenResponse.path.md +9 -0
  60. package/docs/interfaces/IStorageTreeItem.md +78 -0
  61. package/docs/interfaces/IStorageTreeItem.name.md +9 -0
  62. package/docs/interfaces/IStorageTreeItem.path.md +9 -0
  63. package/docs/interfaces/IStorageTreeItem.type.md +9 -0
  64. package/docs/interfaces/IStorageWriteFileRequest.contentType.md +9 -0
  65. package/docs/interfaces/IStorageWriteFileRequest.contents.md +9 -0
  66. package/docs/interfaces/IStorageWriteFileRequest.md +97 -0
  67. package/docs/type-aliases/StorageItemType.md +11 -0
  68. package/docs/type-aliases/StorageNamespace.md +11 -0
  69. package/docs/variables/storageFileResponse.md +9 -0
  70. package/docs/variables/storagePathRequest.md +9 -0
  71. package/docs/variables/storageSyncRequest.md +9 -0
  72. package/docs/variables/storageTreeChildrenResponse.md +9 -0
  73. package/docs/variables/storageTreeItem.md +9 -0
  74. package/docs/variables/storageWriteFileRequest.md +9 -0
  75. package/etc/ts-http-storage.api.md +184 -0
  76. package/lib/index.d.ts +6 -0
  77. package/lib/index.d.ts.map +1 -0
  78. package/lib/index.js +43 -0
  79. package/lib/index.js.map +1 -0
  80. package/lib/packlets/storage/converters.d.ts +33 -0
  81. package/lib/packlets/storage/converters.d.ts.map +1 -0
  82. package/lib/packlets/storage/converters.js +81 -0
  83. package/lib/packlets/storage/converters.js.map +1 -0
  84. package/lib/packlets/storage/fsProvider.d.ts +47 -0
  85. package/lib/packlets/storage/fsProvider.d.ts.map +1 -0
  86. package/lib/packlets/storage/fsProvider.js +260 -0
  87. package/lib/packlets/storage/fsProvider.js.map +1 -0
  88. package/lib/packlets/storage/index.d.ts +11 -0
  89. package/lib/packlets/storage/index.d.ts.map +1 -0
  90. package/lib/packlets/storage/index.js +48 -0
  91. package/lib/packlets/storage/index.js.map +1 -0
  92. package/lib/packlets/storage/model.d.ts +82 -0
  93. package/lib/packlets/storage/model.d.ts.map +1 -0
  94. package/lib/packlets/storage/model.js +24 -0
  95. package/lib/packlets/storage/model.js.map +1 -0
  96. package/lib/packlets/storage/provider.d.ts +10 -0
  97. package/lib/packlets/storage/provider.d.ts.map +1 -0
  98. package/lib/packlets/storage/provider.js +24 -0
  99. package/lib/packlets/storage/provider.js.map +1 -0
  100. package/lib/packlets/storage/routes.d.ts +17 -0
  101. package/lib/packlets/storage/routes.d.ts.map +1 -0
  102. package/lib/packlets/storage/routes.js +170 -0
  103. package/lib/packlets/storage/routes.js.map +1 -0
  104. package/lib/packlets/storage/service.d.ts +20 -0
  105. package/lib/packlets/storage/service.d.ts.map +1 -0
  106. package/lib/packlets/storage/service.js +95 -0
  107. package/lib/packlets/storage/service.js.map +1 -0
  108. package/lib/test/unit/storage/fsProvider.test.d.ts +2 -0
  109. package/lib/test/unit/storage/fsProvider.test.d.ts.map +1 -0
  110. package/lib/test/unit/storage/fsProvider.test.js +106 -0
  111. package/lib/test/unit/storage/fsProvider.test.js.map +1 -0
  112. package/lib/test/unit/storage/routes.test.d.ts +2 -0
  113. package/lib/test/unit/storage/routes.test.d.ts.map +1 -0
  114. package/lib/test/unit/storage/routes.test.js +124 -0
  115. package/lib/test/unit/storage/routes.test.js.map +1 -0
  116. package/lib/test/unit/storage/service.test.d.ts +2 -0
  117. package/lib/test/unit/storage/service.test.d.ts.map +1 -0
  118. package/lib/test/unit/storage/service.test.js +67 -0
  119. package/lib/test/unit/storage/service.test.js.map +1 -0
  120. package/package.json +66 -0
  121. package/rush-logs/ts-http-storage.build.cache.log +3 -0
  122. package/rush-logs/ts-http-storage.build.log +9 -0
  123. package/src/index.ts +28 -0
  124. package/src/packlets/storage/converters.ts +100 -0
  125. package/src/packlets/storage/fsProvider.ts +263 -0
  126. package/src/packlets/storage/index.ts +33 -0
  127. package/src/packlets/storage/model.ts +113 -0
  128. package/src/packlets/storage/provider.ts +33 -0
  129. package/src/packlets/storage/routes.ts +215 -0
  130. package/src/packlets/storage/service.ts +114 -0
  131. package/src/test/unit/storage/fsProvider.test.ts +129 -0
  132. package/src/test/unit/storage/routes.test.ts +165 -0
  133. package/src/test/unit/storage/service.test.ts +95 -0
  134. package/temp/build/typescript/ts_l9Fw4VUO.json +1 -0
  135. package/temp/ts-http-storage.api.json +3103 -0
  136. package/temp/ts-http-storage.api.md +184 -0
  137. package/tsconfig.json +7 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"converters.js","sourceRoot":"","sources":["../../../src/packlets/storage/converters.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;AAEH,4CAA2D;AAY3D,MAAM,eAAe,GAA+B,qBAAU,CAAC,eAAe,CAAkB;IAC9F,MAAM;IACN,WAAW;CACZ,CAAC,CAAC;AAEH;;;GAGG;AACU,QAAA,eAAe,GAAgC,qBAAU,CAAC,YAAY,CAAmB;IACpG,IAAI,EAAE,qBAAU,CAAC,MAAM;IACvB,IAAI,EAAE,qBAAU,CAAC,MAAM;IACvB,IAAI,EAAE,eAAe;CACtB,CAAC,CAAC;AAEH;;;GAGG;AACU,QAAA,kBAAkB,GAC7B,qBAAU,CAAC,YAAY,CAAsB;IAC3C,IAAI,EAAE,qBAAU,CAAC,MAAM;IACvB,SAAS,EAAE,qBAAU,CAAC,MAAM,CAAC,QAAQ,EAAE;CACxC,CAAC,CAAC;AAEL;;;GAGG;AACU,QAAA,uBAAuB,GAClC,qBAAU,CAAC,YAAY,CAA2B;IAChD,IAAI,EAAE,qBAAU,CAAC,MAAM;IACvB,QAAQ,EAAE,qBAAU,CAAC,MAAM;IAC3B,WAAW,EAAE,qBAAU,CAAC,MAAM,CAAC,QAAQ,EAAE;IACzC,SAAS,EAAE,qBAAU,CAAC,MAAM,CAAC,QAAQ,EAAE;CACxC,CAAC,CAAC;AAEL;;;GAGG;AACU,QAAA,kBAAkB,GAC7B,qBAAU,CAAC,YAAY,CAAsB;IAC3C,SAAS,EAAE,qBAAU,CAAC,MAAM,CAAC,QAAQ,EAAE;CACxC,CAAC,CAAC;AAEL;;;GAGG;AACU,QAAA,mBAAmB,GAC9B,qBAAU,CAAC,YAAY,CAAuB;IAC5C,IAAI,EAAE,qBAAU,CAAC,MAAM;IACvB,QAAQ,EAAE,qBAAU,CAAC,MAAM;IAC3B,WAAW,EAAE,qBAAU,CAAC,MAAM,CAAC,QAAQ,EAAE;CAC1C,CAAC,CAAC;AAEL;;;GAGG;AACU,QAAA,2BAA2B,GACtC,qBAAU,CAAC,YAAY,CAA+B;IACpD,IAAI,EAAE,qBAAU,CAAC,MAAM;IACvB,QAAQ,EAAE,qBAAU,CAAC,OAAO,CAAC,uBAAe,CAAC;CAC9C,CAAC,CAAC","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport { type Converter, Converters } from '@fgv/ts-utils';\n\nimport type {\n IStorageFileResponse,\n IStoragePathRequest,\n IStorageSyncRequest,\n IStorageTreeChildrenResponse,\n IStorageTreeItem,\n IStorageWriteFileRequest,\n StorageItemType\n} from './model';\n\nconst storageItemType: Converter<StorageItemType> = Converters.enumeratedValue<StorageItemType>([\n 'file',\n 'directory'\n]);\n\n/**\n * Converter for {@link IStorageTreeItem}.\n * @public\n */\nexport const storageTreeItem: Converter<IStorageTreeItem> = Converters.strictObject<IStorageTreeItem>({\n path: Converters.string,\n name: Converters.string,\n type: storageItemType\n});\n\n/**\n * Converter for path-based requests.\n * @public\n */\nexport const storagePathRequest: Converter<IStoragePathRequest> =\n Converters.strictObject<IStoragePathRequest>({\n path: Converters.string,\n namespace: Converters.string.optional()\n });\n\n/**\n * Converter for write-file requests.\n * @public\n */\nexport const storageWriteFileRequest: Converter<IStorageWriteFileRequest> =\n Converters.strictObject<IStorageWriteFileRequest>({\n path: Converters.string,\n contents: Converters.string,\n contentType: Converters.string.optional(),\n namespace: Converters.string.optional()\n });\n\n/**\n * Converter for sync requests.\n * @public\n */\nexport const storageSyncRequest: Converter<IStorageSyncRequest> =\n Converters.strictObject<IStorageSyncRequest>({\n namespace: Converters.string.optional()\n });\n\n/**\n * Converter for file responses.\n * @public\n */\nexport const storageFileResponse: Converter<IStorageFileResponse> =\n Converters.strictObject<IStorageFileResponse>({\n path: Converters.string,\n contents: Converters.string,\n contentType: Converters.string.optional()\n });\n\n/**\n * Converter for children list responses.\n * @public\n */\nexport const storageTreeChildrenResponse: Converter<IStorageTreeChildrenResponse> =\n Converters.strictObject<IStorageTreeChildrenResponse>({\n path: Converters.string,\n children: Converters.arrayOf(storageTreeItem)\n });\n"]}
@@ -0,0 +1,47 @@
1
+ import { type Result } from '@fgv/ts-utils';
2
+ import type { IHttpStorageProvider, IStorageFileResponse, IStorageSyncResponse, IStorageTreeItem } from './model';
3
+ import type { IHttpStorageProviderFactory } from './provider';
4
+ /**
5
+ * Options for creating filesystem-backed storage providers.
6
+ * @public
7
+ */
8
+ export interface IFsStorageProviderFactoryOptions {
9
+ readonly rootPath: string;
10
+ }
11
+ /**
12
+ * Filesystem-backed implementation of {@link IHttpStorageProvider}.
13
+ * @public
14
+ */
15
+ export declare class FsStorageProvider implements IHttpStorageProvider {
16
+ private readonly _rootPath;
17
+ constructor(rootPath: string);
18
+ getItem(itemPath: string): Promise<Result<IStorageTreeItem>>;
19
+ getChildren(itemPath: string): Promise<Result<ReadonlyArray<IStorageTreeItem>>>;
20
+ getFile(itemPath: string): Promise<Result<IStorageFileResponse>>;
21
+ saveFile(itemPath: string, contents: string, contentType?: string): Promise<Result<IStorageFileResponse>>;
22
+ deleteFile(itemPath: string): Promise<Result<boolean>>;
23
+ createDirectory(itemPath: string): Promise<Result<IStorageTreeItem>>;
24
+ sync(): Promise<Result<IStorageSyncResponse>>;
25
+ private _resolveAbsolutePath;
26
+ private _toTreeItem;
27
+ }
28
+ /**
29
+ * Normalizes a request path to a consistent POSIX format.
30
+ * @public
31
+ */
32
+ export declare function normalizeRequestPath(requestPath: string): string;
33
+ /**
34
+ * Namespace-aware provider factory backed by filesystem directories.
35
+ * @public
36
+ */
37
+ export declare class FsStorageProviderFactory implements IHttpStorageProviderFactory {
38
+ private readonly _rootPath;
39
+ constructor(options: IFsStorageProviderFactoryOptions);
40
+ forNamespace(namespace?: string): Result<IHttpStorageProvider>;
41
+ }
42
+ /**
43
+ * Sanitize namespace path segment.
44
+ * @public
45
+ */
46
+ export declare function sanitizeNamespace(namespace?: string): Result<string>;
47
+ //# sourceMappingURL=fsProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fsProvider.d.ts","sourceRoot":"","sources":["../../../src/packlets/storage/fsProvider.ts"],"names":[],"mappings":"AA0BA,OAAO,EAAuB,KAAK,MAAM,EAAW,MAAM,eAAe,CAAC;AAE1E,OAAO,KAAK,EACV,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,gBAAgB,EAEjB,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAE9D;;;GAGG;AACH,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAMD;;;GAGG;AACH,qBAAa,iBAAkB,YAAW,oBAAoB;IAC5D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEhB,QAAQ,EAAE,MAAM;IAItB,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAa5D,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAa/E,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAoBhE,QAAQ,CACnB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAmB3B,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAiBtD,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAapE,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAI1D,OAAO,CAAC,oBAAoB;IAU5B,OAAO,CAAC,WAAW;CASpB;AAuBD;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAMhE;AAED;;;GAGG;AACH,qBAAa,wBAAyB,YAAW,2BAA2B;IAC1E,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEhB,OAAO,EAAE,gCAAgC;IAIrD,YAAY,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,oBAAoB,CAAC;CAmBtE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CASpE"}
@@ -0,0 +1,260 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) 2026 Erik Fortune
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ * of this software and associated documentation files (the "Software"), to deal
7
+ * in the Software without restriction, including without limitation the rights
8
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ * copies of the Software, and to permit persons to whom the Software is
10
+ * furnished to do so, subject to the following conditions:
11
+ *
12
+ * The above copyright notice and this permission notice shall be included in all
13
+ * copies or substantial portions of the Software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ * SOFTWARE.
22
+ */
23
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
24
+ if (k2 === undefined) k2 = k;
25
+ var desc = Object.getOwnPropertyDescriptor(m, k);
26
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
27
+ desc = { enumerable: true, get: function() { return m[k]; } };
28
+ }
29
+ Object.defineProperty(o, k2, desc);
30
+ }) : (function(o, m, k, k2) {
31
+ if (k2 === undefined) k2 = k;
32
+ o[k2] = m[k];
33
+ }));
34
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
35
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
36
+ }) : function(o, v) {
37
+ o["default"] = v;
38
+ });
39
+ var __importStar = (this && this.__importStar) || (function () {
40
+ var ownKeys = function(o) {
41
+ ownKeys = Object.getOwnPropertyNames || function (o) {
42
+ var ar = [];
43
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
44
+ return ar;
45
+ };
46
+ return ownKeys(o);
47
+ };
48
+ return function (mod) {
49
+ if (mod && mod.__esModule) return mod;
50
+ var result = {};
51
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
52
+ __setModuleDefault(result, mod);
53
+ return result;
54
+ };
55
+ })();
56
+ Object.defineProperty(exports, "__esModule", { value: true });
57
+ exports.FsStorageProviderFactory = exports.FsStorageProvider = void 0;
58
+ exports.normalizeRequestPath = normalizeRequestPath;
59
+ exports.sanitizeNamespace = sanitizeNamespace;
60
+ const fs = __importStar(require("fs"));
61
+ const fsp = __importStar(require("fs/promises"));
62
+ const path = __importStar(require("path"));
63
+ const ts_utils_1 = require("@fgv/ts-utils");
64
+ function toItemType(stats) {
65
+ return stats.isDirectory() ? 'directory' : 'file';
66
+ }
67
+ /**
68
+ * Filesystem-backed implementation of {@link IHttpStorageProvider}.
69
+ * @public
70
+ */
71
+ class FsStorageProvider {
72
+ constructor(rootPath) {
73
+ this._rootPath = rootPath;
74
+ }
75
+ async getItem(itemPath) {
76
+ const resolved = this._resolveAbsolutePath(itemPath);
77
+ if (resolved.isFailure()) {
78
+ return (0, ts_utils_1.fail)(resolved.message);
79
+ }
80
+ try {
81
+ const stats = await fsp.stat(resolved.value);
82
+ return (0, ts_utils_1.succeed)(this._toTreeItem(itemPath, toItemType(stats)));
83
+ }
84
+ catch (err) {
85
+ return (0, ts_utils_1.fail)(`${itemPath}: ${_toMessage(err)}`);
86
+ }
87
+ }
88
+ async getChildren(itemPath) {
89
+ const resolved = this._resolveAbsolutePath(itemPath);
90
+ if (resolved.isFailure()) {
91
+ return (0, ts_utils_1.fail)(resolved.message);
92
+ }
93
+ try {
94
+ const entries = await fsp.readdir(resolved.value, { withFileTypes: true });
95
+ return _mapEntries(entries, itemPath);
96
+ }
97
+ catch (err) {
98
+ return (0, ts_utils_1.fail)(`${itemPath}: ${_toMessage(err)}`);
99
+ }
100
+ }
101
+ async getFile(itemPath) {
102
+ const resolved = this._resolveAbsolutePath(itemPath);
103
+ if (resolved.isFailure()) {
104
+ return (0, ts_utils_1.fail)(resolved.message);
105
+ }
106
+ try {
107
+ const stats = await fsp.stat(resolved.value);
108
+ if (!stats.isFile()) {
109
+ return (0, ts_utils_1.fail)(`${itemPath}: not a file`);
110
+ }
111
+ const contents = await fsp.readFile(resolved.value, 'utf8');
112
+ return (0, ts_utils_1.succeed)({
113
+ path: normalizeRequestPath(itemPath),
114
+ contents
115
+ });
116
+ }
117
+ catch (err) {
118
+ return (0, ts_utils_1.fail)(`${itemPath}: ${_toMessage(err)}`);
119
+ }
120
+ }
121
+ async saveFile(itemPath, contents, contentType) {
122
+ const resolved = this._resolveAbsolutePath(itemPath);
123
+ if (resolved.isFailure()) {
124
+ return (0, ts_utils_1.fail)(resolved.message);
125
+ }
126
+ try {
127
+ const parentDir = path.dirname(resolved.value);
128
+ await fsp.mkdir(parentDir, { recursive: true });
129
+ await fsp.writeFile(resolved.value, contents, 'utf8');
130
+ return (0, ts_utils_1.succeed)({
131
+ path: normalizeRequestPath(itemPath),
132
+ contents,
133
+ contentType
134
+ });
135
+ }
136
+ catch (err) {
137
+ return (0, ts_utils_1.fail)(`${itemPath}: ${_toMessage(err)}`);
138
+ }
139
+ }
140
+ async deleteFile(itemPath) {
141
+ const resolved = this._resolveAbsolutePath(itemPath);
142
+ if (resolved.isFailure()) {
143
+ return (0, ts_utils_1.fail)(resolved.message);
144
+ }
145
+ try {
146
+ const stats = await fsp.stat(resolved.value);
147
+ if (!stats.isFile()) {
148
+ return (0, ts_utils_1.fail)(`${itemPath}: not a file`);
149
+ }
150
+ await fsp.unlink(resolved.value);
151
+ return (0, ts_utils_1.succeed)(true);
152
+ }
153
+ catch (err) {
154
+ return (0, ts_utils_1.fail)(`${itemPath}: ${_toMessage(err)}`);
155
+ }
156
+ }
157
+ async createDirectory(itemPath) {
158
+ const resolved = this._resolveAbsolutePath(itemPath);
159
+ if (resolved.isFailure()) {
160
+ return (0, ts_utils_1.fail)(resolved.message);
161
+ }
162
+ try {
163
+ await fsp.mkdir(resolved.value, { recursive: true });
164
+ return (0, ts_utils_1.succeed)(this._toTreeItem(itemPath, 'directory'));
165
+ }
166
+ catch (err) {
167
+ return (0, ts_utils_1.fail)(`${itemPath}: ${_toMessage(err)}`);
168
+ }
169
+ }
170
+ async sync() {
171
+ return (0, ts_utils_1.succeed)({ synced: 0 });
172
+ }
173
+ _resolveAbsolutePath(requestPath) {
174
+ const normalized = normalizeRequestPath(requestPath);
175
+ const candidate = path.resolve(this._rootPath, `.${normalized}`);
176
+ const relative = path.relative(this._rootPath, candidate);
177
+ if (relative.startsWith('..') || path.isAbsolute(relative)) {
178
+ return (0, ts_utils_1.fail)(`${requestPath}: path is outside storage root`);
179
+ }
180
+ return (0, ts_utils_1.succeed)(candidate);
181
+ }
182
+ _toTreeItem(itemPath, type) {
183
+ const normalizedPath = normalizeRequestPath(itemPath);
184
+ const name = normalizedPath === '/' ? '/' : path.posix.basename(normalizedPath);
185
+ return {
186
+ path: normalizedPath,
187
+ name,
188
+ type
189
+ };
190
+ }
191
+ }
192
+ exports.FsStorageProvider = FsStorageProvider;
193
+ function _mapEntries(entries, parentPath) {
194
+ const normalizedParent = normalizeRequestPath(parentPath);
195
+ const items = entries.map((entry) => {
196
+ const isDirectory = entry.isDirectory();
197
+ const childPath = normalizedParent === '/' ? `/${entry.name}` : `${normalizedParent}/${entry.name}`;
198
+ return {
199
+ path: childPath,
200
+ name: entry.name,
201
+ type: isDirectory ? 'directory' : 'file'
202
+ };
203
+ });
204
+ return (0, ts_utils_1.succeed)(items);
205
+ }
206
+ function _toMessage(err) {
207
+ return err instanceof Error ? err.message : String(err);
208
+ }
209
+ /**
210
+ * Normalizes a request path to a consistent POSIX format.
211
+ * @public
212
+ */
213
+ function normalizeRequestPath(requestPath) {
214
+ if (requestPath.length === 0) {
215
+ return '/';
216
+ }
217
+ const normalized = path.posix.normalize(requestPath.startsWith('/') ? requestPath : `/${requestPath}`);
218
+ return normalized.startsWith('/') ? normalized : `/${normalized}`;
219
+ }
220
+ /**
221
+ * Namespace-aware provider factory backed by filesystem directories.
222
+ * @public
223
+ */
224
+ class FsStorageProviderFactory {
225
+ constructor(options) {
226
+ this._rootPath = path.resolve(options.rootPath);
227
+ }
228
+ forNamespace(namespace) {
229
+ const safeNamespace = sanitizeNamespace(namespace);
230
+ if (safeNamespace.isFailure()) {
231
+ return (0, ts_utils_1.fail)(safeNamespace.message);
232
+ }
233
+ const namespaceRoot = path.resolve(this._rootPath, safeNamespace.value);
234
+ const relative = path.relative(this._rootPath, namespaceRoot);
235
+ if (relative.startsWith('..') || path.isAbsolute(relative)) {
236
+ return (0, ts_utils_1.fail)(`namespace '${safeNamespace.value}' is outside root`);
237
+ }
238
+ const ensureResult = (0, ts_utils_1.captureResult)(() => fs.mkdirSync(namespaceRoot, { recursive: true }));
239
+ if (ensureResult.isFailure()) {
240
+ return (0, ts_utils_1.fail)(`namespace '${safeNamespace.value}': ${ensureResult.message}`);
241
+ }
242
+ return (0, ts_utils_1.succeed)(new FsStorageProvider(namespaceRoot));
243
+ }
244
+ }
245
+ exports.FsStorageProviderFactory = FsStorageProviderFactory;
246
+ /**
247
+ * Sanitize namespace path segment.
248
+ * @public
249
+ */
250
+ function sanitizeNamespace(namespace) {
251
+ if (!namespace || namespace.trim().length === 0) {
252
+ return (0, ts_utils_1.succeed)('default');
253
+ }
254
+ const trimmed = namespace.trim();
255
+ if (!/^[a-zA-Z0-9._-]+$/.test(trimmed)) {
256
+ return (0, ts_utils_1.fail)(`namespace '${namespace}': only [a-zA-Z0-9._-] allowed`);
257
+ }
258
+ return (0, ts_utils_1.succeed)(trimmed);
259
+ }
260
+ //# sourceMappingURL=fsProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fsProvider.js","sourceRoot":"","sources":["../../../src/packlets/storage/fsProvider.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport * as fs from 'fs';\nimport * as fsp from 'fs/promises';\nimport * as path from 'path';\n\nimport { captureResult, fail, type Result, succeed } from '@fgv/ts-utils';\n\nimport type {\n IHttpStorageProvider,\n IStorageFileResponse,\n IStorageSyncResponse,\n IStorageTreeItem,\n StorageItemType\n} from './model';\nimport type { IHttpStorageProviderFactory } from './provider';\n\n/**\n * Options for creating filesystem-backed storage providers.\n * @public\n */\nexport interface IFsStorageProviderFactoryOptions {\n readonly rootPath: string;\n}\n\nfunction toItemType(stats: fs.Stats): StorageItemType {\n return stats.isDirectory() ? 'directory' : 'file';\n}\n\n/**\n * Filesystem-backed implementation of {@link IHttpStorageProvider}.\n * @public\n */\nexport class FsStorageProvider implements IHttpStorageProvider {\n private readonly _rootPath: string;\n\n public constructor(rootPath: string) {\n this._rootPath = rootPath;\n }\n\n public async getItem(itemPath: string): Promise<Result<IStorageTreeItem>> {\n const resolved = this._resolveAbsolutePath(itemPath);\n if (resolved.isFailure()) {\n return fail(resolved.message);\n }\n try {\n const stats = await fsp.stat(resolved.value);\n return succeed(this._toTreeItem(itemPath, toItemType(stats)));\n } catch (err: unknown) {\n return fail(`${itemPath}: ${_toMessage(err)}`);\n }\n }\n\n public async getChildren(itemPath: string): Promise<Result<ReadonlyArray<IStorageTreeItem>>> {\n const resolved = this._resolveAbsolutePath(itemPath);\n if (resolved.isFailure()) {\n return fail(resolved.message);\n }\n try {\n const entries = await fsp.readdir(resolved.value, { withFileTypes: true });\n return _mapEntries(entries, itemPath);\n } catch (err: unknown) {\n return fail(`${itemPath}: ${_toMessage(err)}`);\n }\n }\n\n public async getFile(itemPath: string): Promise<Result<IStorageFileResponse>> {\n const resolved = this._resolveAbsolutePath(itemPath);\n if (resolved.isFailure()) {\n return fail(resolved.message);\n }\n try {\n const stats = await fsp.stat(resolved.value);\n if (!stats.isFile()) {\n return fail(`${itemPath}: not a file`);\n }\n const contents = await fsp.readFile(resolved.value, 'utf8');\n return succeed({\n path: normalizeRequestPath(itemPath),\n contents\n });\n } catch (err: unknown) {\n return fail(`${itemPath}: ${_toMessage(err)}`);\n }\n }\n\n public async saveFile(\n itemPath: string,\n contents: string,\n contentType?: string\n ): Promise<Result<IStorageFileResponse>> {\n const resolved = this._resolveAbsolutePath(itemPath);\n if (resolved.isFailure()) {\n return fail(resolved.message);\n }\n try {\n const parentDir = path.dirname(resolved.value);\n await fsp.mkdir(parentDir, { recursive: true });\n await fsp.writeFile(resolved.value, contents, 'utf8');\n return succeed({\n path: normalizeRequestPath(itemPath),\n contents,\n contentType\n });\n } catch (err: unknown) {\n return fail(`${itemPath}: ${_toMessage(err)}`);\n }\n }\n\n public async deleteFile(itemPath: string): Promise<Result<boolean>> {\n const resolved = this._resolveAbsolutePath(itemPath);\n if (resolved.isFailure()) {\n return fail(resolved.message);\n }\n try {\n const stats = await fsp.stat(resolved.value);\n if (!stats.isFile()) {\n return fail(`${itemPath}: not a file`);\n }\n await fsp.unlink(resolved.value);\n return succeed(true);\n } catch (err: unknown) {\n return fail(`${itemPath}: ${_toMessage(err)}`);\n }\n }\n\n public async createDirectory(itemPath: string): Promise<Result<IStorageTreeItem>> {\n const resolved = this._resolveAbsolutePath(itemPath);\n if (resolved.isFailure()) {\n return fail(resolved.message);\n }\n try {\n await fsp.mkdir(resolved.value, { recursive: true });\n return succeed(this._toTreeItem(itemPath, 'directory'));\n } catch (err: unknown) {\n return fail(`${itemPath}: ${_toMessage(err)}`);\n }\n }\n\n public async sync(): Promise<Result<IStorageSyncResponse>> {\n return succeed({ synced: 0 });\n }\n\n private _resolveAbsolutePath(requestPath: string): Result<string> {\n const normalized = normalizeRequestPath(requestPath);\n const candidate = path.resolve(this._rootPath, `.${normalized}`);\n const relative = path.relative(this._rootPath, candidate);\n if (relative.startsWith('..') || path.isAbsolute(relative)) {\n return fail(`${requestPath}: path is outside storage root`);\n }\n return succeed(candidate);\n }\n\n private _toTreeItem(itemPath: string, type: StorageItemType): IStorageTreeItem {\n const normalizedPath = normalizeRequestPath(itemPath);\n const name = normalizedPath === '/' ? '/' : path.posix.basename(normalizedPath);\n return {\n path: normalizedPath,\n name,\n type\n };\n }\n}\n\nfunction _mapEntries(\n entries: ReadonlyArray<fs.Dirent>,\n parentPath: string\n): Result<ReadonlyArray<IStorageTreeItem>> {\n const normalizedParent = normalizeRequestPath(parentPath);\n const items: IStorageTreeItem[] = entries.map((entry) => {\n const isDirectory = entry.isDirectory();\n const childPath = normalizedParent === '/' ? `/${entry.name}` : `${normalizedParent}/${entry.name}`;\n return {\n path: childPath,\n name: entry.name,\n type: isDirectory ? 'directory' : 'file'\n };\n });\n return succeed(items);\n}\n\nfunction _toMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n/**\n * Normalizes a request path to a consistent POSIX format.\n * @public\n */\nexport function normalizeRequestPath(requestPath: string): string {\n if (requestPath.length === 0) {\n return '/';\n }\n const normalized = path.posix.normalize(requestPath.startsWith('/') ? requestPath : `/${requestPath}`);\n return normalized.startsWith('/') ? normalized : `/${normalized}`;\n}\n\n/**\n * Namespace-aware provider factory backed by filesystem directories.\n * @public\n */\nexport class FsStorageProviderFactory implements IHttpStorageProviderFactory {\n private readonly _rootPath: string;\n\n public constructor(options: IFsStorageProviderFactoryOptions) {\n this._rootPath = path.resolve(options.rootPath);\n }\n\n public forNamespace(namespace?: string): Result<IHttpStorageProvider> {\n const safeNamespace = sanitizeNamespace(namespace);\n if (safeNamespace.isFailure()) {\n return fail(safeNamespace.message);\n }\n\n const namespaceRoot = path.resolve(this._rootPath, safeNamespace.value);\n const relative = path.relative(this._rootPath, namespaceRoot);\n if (relative.startsWith('..') || path.isAbsolute(relative)) {\n return fail(`namespace '${safeNamespace.value}' is outside root`);\n }\n\n const ensureResult = captureResult(() => fs.mkdirSync(namespaceRoot, { recursive: true }));\n if (ensureResult.isFailure()) {\n return fail(`namespace '${safeNamespace.value}': ${ensureResult.message}`);\n }\n\n return succeed(new FsStorageProvider(namespaceRoot));\n }\n}\n\n/**\n * Sanitize namespace path segment.\n * @public\n */\nexport function sanitizeNamespace(namespace?: string): Result<string> {\n if (!namespace || namespace.trim().length === 0) {\n return succeed('default');\n }\n const trimmed = namespace.trim();\n if (!/^[a-zA-Z0-9._-]+$/.test(trimmed)) {\n return fail(`namespace '${namespace}': only [a-zA-Z0-9._-] allowed`);\n }\n return succeed(trimmed);\n}\n"]}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Reusable HTTP storage services and route helpers.
3
+ * @packageDocumentation
4
+ */
5
+ export * from './model';
6
+ export * from './converters';
7
+ export * from './provider';
8
+ export * from './fsProvider';
9
+ export * from './service';
10
+ export * from './routes';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/packlets/storage/index.ts"],"names":[],"mappings":"AAsBA;;;GAGG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC"}
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) 2026 Erik Fortune
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ * of this software and associated documentation files (the "Software"), to deal
7
+ * in the Software without restriction, including without limitation the rights
8
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ * copies of the Software, and to permit persons to whom the Software is
10
+ * furnished to do so, subject to the following conditions:
11
+ *
12
+ * The above copyright notice and this permission notice shall be included in all
13
+ * copies or substantial portions of the Software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ * SOFTWARE.
22
+ */
23
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
24
+ if (k2 === undefined) k2 = k;
25
+ var desc = Object.getOwnPropertyDescriptor(m, k);
26
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
27
+ desc = { enumerable: true, get: function() { return m[k]; } };
28
+ }
29
+ Object.defineProperty(o, k2, desc);
30
+ }) : (function(o, m, k, k2) {
31
+ if (k2 === undefined) k2 = k;
32
+ o[k2] = m[k];
33
+ }));
34
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
35
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
36
+ };
37
+ Object.defineProperty(exports, "__esModule", { value: true });
38
+ /**
39
+ * Reusable HTTP storage services and route helpers.
40
+ * @packageDocumentation
41
+ */
42
+ __exportStar(require("./model"), exports);
43
+ __exportStar(require("./converters"), exports);
44
+ __exportStar(require("./provider"), exports);
45
+ __exportStar(require("./fsProvider"), exports);
46
+ __exportStar(require("./service"), exports);
47
+ __exportStar(require("./routes"), exports);
48
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/packlets/storage/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;;;;;;;;;;;;;;;;AAEH;;;GAGG;AAEH,0CAAwB;AACxB,+CAA6B;AAC7B,6CAA2B;AAC3B,+CAA6B;AAC7B,4CAA0B;AAC1B,2CAAyB","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/**\n * Reusable HTTP storage services and route helpers.\n * @packageDocumentation\n */\n\nexport * from './model';\nexport * from './converters';\nexport * from './provider';\nexport * from './fsProvider';\nexport * from './service';\nexport * from './routes';\n"]}
@@ -0,0 +1,82 @@
1
+ import type { Result } from '@fgv/ts-utils';
2
+ /**
3
+ * Namespace identifier for scoped storage.
4
+ * @public
5
+ */
6
+ export type StorageNamespace = string;
7
+ /**
8
+ * Storage item type.
9
+ * @public
10
+ */
11
+ export type StorageItemType = 'file' | 'directory';
12
+ /**
13
+ * Storage tree item metadata.
14
+ * @public
15
+ */
16
+ export interface IStorageTreeItem {
17
+ readonly path: string;
18
+ readonly name: string;
19
+ readonly type: StorageItemType;
20
+ }
21
+ /**
22
+ * Response for listing children.
23
+ * @public
24
+ */
25
+ export interface IStorageTreeChildrenResponse {
26
+ readonly path: string;
27
+ readonly children: ReadonlyArray<IStorageTreeItem>;
28
+ }
29
+ /**
30
+ * Response for reading a file.
31
+ * @public
32
+ */
33
+ export interface IStorageFileResponse {
34
+ readonly path: string;
35
+ readonly contents: string;
36
+ readonly contentType?: string;
37
+ }
38
+ /**
39
+ * Request for path-based operations.
40
+ * @public
41
+ */
42
+ export interface IStoragePathRequest {
43
+ readonly path: string;
44
+ readonly namespace?: StorageNamespace;
45
+ }
46
+ /**
47
+ * Request for writing file contents.
48
+ * @public
49
+ */
50
+ export interface IStorageWriteFileRequest extends IStoragePathRequest {
51
+ readonly contents: string;
52
+ readonly contentType?: string;
53
+ }
54
+ /**
55
+ * Request for sync operation.
56
+ * @public
57
+ */
58
+ export interface IStorageSyncRequest {
59
+ readonly namespace?: StorageNamespace;
60
+ }
61
+ /**
62
+ * Sync response metadata.
63
+ * @public
64
+ */
65
+ export interface IStorageSyncResponse {
66
+ readonly synced: number;
67
+ }
68
+ /**
69
+ * Provider contract for storage backends.
70
+ * All methods are async to support both filesystem and database backends.
71
+ * @public
72
+ */
73
+ export interface IHttpStorageProvider {
74
+ getItem(path: string): Promise<Result<IStorageTreeItem>>;
75
+ getChildren(path: string): Promise<Result<ReadonlyArray<IStorageTreeItem>>>;
76
+ getFile(path: string): Promise<Result<IStorageFileResponse>>;
77
+ saveFile(path: string, contents: string, contentType?: string): Promise<Result<IStorageFileResponse>>;
78
+ deleteFile(path: string): Promise<Result<boolean>>;
79
+ createDirectory(path: string): Promise<Result<IStorageTreeItem>>;
80
+ sync(): Promise<Result<IStorageSyncResponse>>;
81
+ }
82
+ //# sourceMappingURL=model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../../src/packlets/storage/model.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAE5C;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAEtC;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,WAAW,CAAC;AAEnD;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;CAChC;AAED;;;GAGG;AACH,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;CACpD;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,CAAC,EAAE,gBAAgB,CAAC;CACvC;AAED;;;GAGG;AACH,MAAM,WAAW,wBAAyB,SAAQ,mBAAmB;IACnE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,SAAS,CAAC,EAAE,gBAAgB,CAAC;CACvC;AAED;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC;IACzD,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC;IAC5E,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,CAAC;IAC7D,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,CAAC;IACtG,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IACnD,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC;IACjE,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,CAAC;CAC/C"}
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) 2026 Erik Fortune
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ * of this software and associated documentation files (the "Software"), to deal
7
+ * in the Software without restriction, including without limitation the rights
8
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ * copies of the Software, and to permit persons to whom the Software is
10
+ * furnished to do so, subject to the following conditions:
11
+ *
12
+ * The above copyright notice and this permission notice shall be included in all
13
+ * copies or substantial portions of the Software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ * SOFTWARE.
22
+ */
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ //# sourceMappingURL=model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../../../src/packlets/storage/model.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport type { Result } from '@fgv/ts-utils';\n\n/**\n * Namespace identifier for scoped storage.\n * @public\n */\nexport type StorageNamespace = string;\n\n/**\n * Storage item type.\n * @public\n */\nexport type StorageItemType = 'file' | 'directory';\n\n/**\n * Storage tree item metadata.\n * @public\n */\nexport interface IStorageTreeItem {\n readonly path: string;\n readonly name: string;\n readonly type: StorageItemType;\n}\n\n/**\n * Response for listing children.\n * @public\n */\nexport interface IStorageTreeChildrenResponse {\n readonly path: string;\n readonly children: ReadonlyArray<IStorageTreeItem>;\n}\n\n/**\n * Response for reading a file.\n * @public\n */\nexport interface IStorageFileResponse {\n readonly path: string;\n readonly contents: string;\n readonly contentType?: string;\n}\n\n/**\n * Request for path-based operations.\n * @public\n */\nexport interface IStoragePathRequest {\n readonly path: string;\n readonly namespace?: StorageNamespace;\n}\n\n/**\n * Request for writing file contents.\n * @public\n */\nexport interface IStorageWriteFileRequest extends IStoragePathRequest {\n readonly contents: string;\n readonly contentType?: string;\n}\n\n/**\n * Request for sync operation.\n * @public\n */\nexport interface IStorageSyncRequest {\n readonly namespace?: StorageNamespace;\n}\n\n/**\n * Sync response metadata.\n * @public\n */\nexport interface IStorageSyncResponse {\n readonly synced: number;\n}\n\n/**\n * Provider contract for storage backends.\n * All methods are async to support both filesystem and database backends.\n * @public\n */\nexport interface IHttpStorageProvider {\n getItem(path: string): Promise<Result<IStorageTreeItem>>;\n getChildren(path: string): Promise<Result<ReadonlyArray<IStorageTreeItem>>>;\n getFile(path: string): Promise<Result<IStorageFileResponse>>;\n saveFile(path: string, contents: string, contentType?: string): Promise<Result<IStorageFileResponse>>;\n deleteFile(path: string): Promise<Result<boolean>>;\n createDirectory(path: string): Promise<Result<IStorageTreeItem>>;\n sync(): Promise<Result<IStorageSyncResponse>>;\n}\n"]}
@@ -0,0 +1,10 @@
1
+ import type { Result } from '@fgv/ts-utils';
2
+ import type { IHttpStorageProvider, StorageNamespace } from './model';
3
+ /**
4
+ * Factory for creating namespace-scoped storage providers.
5
+ * @public
6
+ */
7
+ export interface IHttpStorageProviderFactory {
8
+ forNamespace(namespace?: StorageNamespace): Result<IHttpStorageProvider>;
9
+ }
10
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../src/packlets/storage/provider.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAE5C,OAAO,KAAK,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEtE;;;GAGG;AACH,MAAM,WAAW,2BAA2B;IAC1C,YAAY,CAAC,SAAS,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAAC,oBAAoB,CAAC,CAAC;CAC1E"}
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) 2026 Erik Fortune
4
+ *
5
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ * of this software and associated documentation files (the "Software"), to deal
7
+ * in the Software without restriction, including without limitation the rights
8
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ * copies of the Software, and to permit persons to whom the Software is
10
+ * furnished to do so, subject to the following conditions:
11
+ *
12
+ * The above copyright notice and this permission notice shall be included in all
13
+ * copies or substantial portions of the Software.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ * SOFTWARE.
22
+ */
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../../src/packlets/storage/provider.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;GAoBG","sourcesContent":["/*\n * Copyright (c) 2026 Erik Fortune\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport type { Result } from '@fgv/ts-utils';\n\nimport type { IHttpStorageProvider, StorageNamespace } from './model';\n\n/**\n * Factory for creating namespace-scoped storage providers.\n * @public\n */\nexport interface IHttpStorageProviderFactory {\n forNamespace(namespace?: StorageNamespace): Result<IHttpStorageProvider>;\n}\n"]}
@@ -0,0 +1,17 @@
1
+ import { Hono } from 'hono';
2
+ import type { Logging } from '@fgv/ts-utils';
3
+ import type { IHttpStorageProviderFactory } from './provider';
4
+ /**
5
+ * Options for creating storage routes.
6
+ * @public
7
+ */
8
+ export interface ICreateStorageRoutesOptions {
9
+ readonly providers: IHttpStorageProviderFactory;
10
+ readonly logger?: Logging.ILogger;
11
+ }
12
+ /**
13
+ * Builds storage routes for a Hono app.
14
+ * @public
15
+ */
16
+ export declare function createStorageRoutes(options: ICreateStorageRoutesOptions): Hono;
17
+ //# sourceMappingURL=routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../../src/packlets/storage/routes.ts"],"names":[],"mappings":"AAsBA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAY7C,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,YAAY,CAAC;AAE9D;;;GAGG;AACH,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,SAAS,EAAE,2BAA2B,CAAC;IAChD,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC;CACnC;AAaD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,2BAA2B,GAAG,IAAI,CAwJ9E"}