@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.
- package/.rush/temp/chunked-rush-logs/ts-http-storage.build.chunks.jsonl +9 -0
- package/.rush/temp/fbfcc9487d290993ba47f1d36e9383196e7b12ac.tar.log +61 -0
- package/.rush/temp/operation/build/all.log +9 -0
- package/.rush/temp/operation/build/log-chunks.jsonl +9 -0
- package/.rush/temp/operation/build/state.json +3 -0
- package/.rush/temp/shrinkwrap-deps.json +647 -0
- package/config/api-extractor.json +36 -0
- package/config/rig.json +10 -0
- package/config/typedoc.json +7 -0
- package/dist/ts-http-storage.d.ts +225 -0
- package/dist/tsdoc-metadata.json +11 -0
- package/docs/README.md +298 -0
- package/docs/classes/FsStorageProvider.createDirectory.md +20 -0
- package/docs/classes/FsStorageProvider.getChildren.md +20 -0
- package/docs/classes/FsStorageProvider.getFile.md +20 -0
- package/docs/classes/FsStorageProvider.getItem.md +20 -0
- package/docs/classes/FsStorageProvider.md +134 -0
- package/docs/classes/FsStorageProvider.saveFile.md +22 -0
- package/docs/classes/FsStorageProvider.sync.md +13 -0
- package/docs/classes/FsStorageProviderFactory.forNamespace.md +20 -0
- package/docs/classes/FsStorageProviderFactory.md +69 -0
- package/docs/classes/HttpStorageService.createDirectory.md +20 -0
- package/docs/classes/HttpStorageService.getChildren.md +20 -0
- package/docs/classes/HttpStorageService.getFile.md +20 -0
- package/docs/classes/HttpStorageService.getItem.md +20 -0
- package/docs/classes/HttpStorageService.md +132 -0
- package/docs/classes/HttpStorageService.saveFile.md +20 -0
- package/docs/classes/HttpStorageService.sync.md +20 -0
- package/docs/functions/createStorageRoutes.md +11 -0
- package/docs/functions/normalizeRequestPath.md +11 -0
- package/docs/functions/sanitizeNamespace.md +11 -0
- package/docs/interfaces/ICreateStorageRoutesOptions.logger.md +9 -0
- package/docs/interfaces/ICreateStorageRoutesOptions.md +61 -0
- package/docs/interfaces/ICreateStorageRoutesOptions.providers.md +9 -0
- package/docs/interfaces/IFsStorageProviderFactoryOptions.md +44 -0
- package/docs/interfaces/IFsStorageProviderFactoryOptions.rootPath.md +9 -0
- package/docs/interfaces/IHttpStorageProvider.createDirectory.md +20 -0
- package/docs/interfaces/IHttpStorageProvider.getChildren.md +20 -0
- package/docs/interfaces/IHttpStorageProvider.getFile.md +20 -0
- package/docs/interfaces/IHttpStorageProvider.getItem.md +20 -0
- package/docs/interfaces/IHttpStorageProvider.md +102 -0
- package/docs/interfaces/IHttpStorageProvider.saveFile.md +22 -0
- package/docs/interfaces/IHttpStorageProvider.sync.md +13 -0
- package/docs/interfaces/IHttpStorageProviderFactory.forNamespace.md +20 -0
- package/docs/interfaces/IHttpStorageProviderFactory.md +36 -0
- package/docs/interfaces/IStorageFileResponse.contentType.md +9 -0
- package/docs/interfaces/IStorageFileResponse.contents.md +9 -0
- package/docs/interfaces/IStorageFileResponse.md +78 -0
- package/docs/interfaces/IStorageFileResponse.path.md +9 -0
- package/docs/interfaces/IStoragePathRequest.md +61 -0
- package/docs/interfaces/IStoragePathRequest.namespace.md +9 -0
- package/docs/interfaces/IStoragePathRequest.path.md +9 -0
- package/docs/interfaces/IStorageSyncRequest.md +44 -0
- package/docs/interfaces/IStorageSyncRequest.namespace.md +9 -0
- package/docs/interfaces/IStorageSyncResponse.md +44 -0
- package/docs/interfaces/IStorageSyncResponse.synced.md +9 -0
- package/docs/interfaces/IStorageTreeChildrenResponse.children.md +9 -0
- package/docs/interfaces/IStorageTreeChildrenResponse.md +61 -0
- package/docs/interfaces/IStorageTreeChildrenResponse.path.md +9 -0
- package/docs/interfaces/IStorageTreeItem.md +78 -0
- package/docs/interfaces/IStorageTreeItem.name.md +9 -0
- package/docs/interfaces/IStorageTreeItem.path.md +9 -0
- package/docs/interfaces/IStorageTreeItem.type.md +9 -0
- package/docs/interfaces/IStorageWriteFileRequest.contentType.md +9 -0
- package/docs/interfaces/IStorageWriteFileRequest.contents.md +9 -0
- package/docs/interfaces/IStorageWriteFileRequest.md +97 -0
- package/docs/type-aliases/StorageItemType.md +11 -0
- package/docs/type-aliases/StorageNamespace.md +11 -0
- package/docs/variables/storageFileResponse.md +9 -0
- package/docs/variables/storagePathRequest.md +9 -0
- package/docs/variables/storageSyncRequest.md +9 -0
- package/docs/variables/storageTreeChildrenResponse.md +9 -0
- package/docs/variables/storageTreeItem.md +9 -0
- package/docs/variables/storageWriteFileRequest.md +9 -0
- package/etc/ts-http-storage.api.md +184 -0
- package/lib/index.d.ts +6 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +43 -0
- package/lib/index.js.map +1 -0
- package/lib/packlets/storage/converters.d.ts +33 -0
- package/lib/packlets/storage/converters.d.ts.map +1 -0
- package/lib/packlets/storage/converters.js +81 -0
- package/lib/packlets/storage/converters.js.map +1 -0
- package/lib/packlets/storage/fsProvider.d.ts +47 -0
- package/lib/packlets/storage/fsProvider.d.ts.map +1 -0
- package/lib/packlets/storage/fsProvider.js +260 -0
- package/lib/packlets/storage/fsProvider.js.map +1 -0
- package/lib/packlets/storage/index.d.ts +11 -0
- package/lib/packlets/storage/index.d.ts.map +1 -0
- package/lib/packlets/storage/index.js +48 -0
- package/lib/packlets/storage/index.js.map +1 -0
- package/lib/packlets/storage/model.d.ts +82 -0
- package/lib/packlets/storage/model.d.ts.map +1 -0
- package/lib/packlets/storage/model.js +24 -0
- package/lib/packlets/storage/model.js.map +1 -0
- package/lib/packlets/storage/provider.d.ts +10 -0
- package/lib/packlets/storage/provider.d.ts.map +1 -0
- package/lib/packlets/storage/provider.js +24 -0
- package/lib/packlets/storage/provider.js.map +1 -0
- package/lib/packlets/storage/routes.d.ts +17 -0
- package/lib/packlets/storage/routes.d.ts.map +1 -0
- package/lib/packlets/storage/routes.js +170 -0
- package/lib/packlets/storage/routes.js.map +1 -0
- package/lib/packlets/storage/service.d.ts +20 -0
- package/lib/packlets/storage/service.d.ts.map +1 -0
- package/lib/packlets/storage/service.js +95 -0
- package/lib/packlets/storage/service.js.map +1 -0
- package/lib/test/unit/storage/fsProvider.test.d.ts +2 -0
- package/lib/test/unit/storage/fsProvider.test.d.ts.map +1 -0
- package/lib/test/unit/storage/fsProvider.test.js +106 -0
- package/lib/test/unit/storage/fsProvider.test.js.map +1 -0
- package/lib/test/unit/storage/routes.test.d.ts +2 -0
- package/lib/test/unit/storage/routes.test.d.ts.map +1 -0
- package/lib/test/unit/storage/routes.test.js +124 -0
- package/lib/test/unit/storage/routes.test.js.map +1 -0
- package/lib/test/unit/storage/service.test.d.ts +2 -0
- package/lib/test/unit/storage/service.test.d.ts.map +1 -0
- package/lib/test/unit/storage/service.test.js +67 -0
- package/lib/test/unit/storage/service.test.js.map +1 -0
- package/package.json +66 -0
- package/rush-logs/ts-http-storage.build.cache.log +3 -0
- package/rush-logs/ts-http-storage.build.log +9 -0
- package/src/index.ts +28 -0
- package/src/packlets/storage/converters.ts +100 -0
- package/src/packlets/storage/fsProvider.ts +263 -0
- package/src/packlets/storage/index.ts +33 -0
- package/src/packlets/storage/model.ts +113 -0
- package/src/packlets/storage/provider.ts +33 -0
- package/src/packlets/storage/routes.ts +215 -0
- package/src/packlets/storage/service.ts +114 -0
- package/src/test/unit/storage/fsProvider.test.ts +129 -0
- package/src/test/unit/storage/routes.test.ts +165 -0
- package/src/test/unit/storage/service.test.ts +95 -0
- package/temp/build/typescript/ts_l9Fw4VUO.json +1 -0
- package/temp/ts-http-storage.api.json +3103 -0
- package/temp/ts-http-storage.api.md +184 -0
- 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"}
|