@jskit-ai/storage-runtime 0.1.4
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.
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export default Object.freeze({
|
|
2
|
+
packageVersion: 1,
|
|
3
|
+
packageId: "@jskit-ai/storage-runtime",
|
|
4
|
+
version: "0.1.4",
|
|
5
|
+
dependsOn: [
|
|
6
|
+
"@jskit-ai/kernel"
|
|
7
|
+
],
|
|
8
|
+
capabilities: {
|
|
9
|
+
provides: [
|
|
10
|
+
"runtime.storage"
|
|
11
|
+
],
|
|
12
|
+
requires: []
|
|
13
|
+
},
|
|
14
|
+
runtime: {
|
|
15
|
+
server: {
|
|
16
|
+
providerEntrypoint: "src/server/providers/StorageRuntimeServiceProvider.js",
|
|
17
|
+
providers: [
|
|
18
|
+
{
|
|
19
|
+
entrypoint: "src/server/providers/StorageRuntimeServiceProvider.js",
|
|
20
|
+
export: "StorageRuntimeServiceProvider"
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
},
|
|
24
|
+
client: {
|
|
25
|
+
providers: []
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
metadata: {
|
|
29
|
+
apiSummary: {
|
|
30
|
+
surfaces: [
|
|
31
|
+
{
|
|
32
|
+
subpath: "./server/providers/StorageRuntimeServiceProvider",
|
|
33
|
+
summary: "Exports storage runtime server provider."
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
subpath: "./client",
|
|
37
|
+
summary: "Exports no client runtime API today (reserved client entrypoint)."
|
|
38
|
+
}
|
|
39
|
+
],
|
|
40
|
+
containerTokens: {
|
|
41
|
+
server: [
|
|
42
|
+
"runtime.storage",
|
|
43
|
+
"KERNEL_TOKENS.Storage"
|
|
44
|
+
],
|
|
45
|
+
client: []
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
mutations: {
|
|
50
|
+
dependencies: {
|
|
51
|
+
runtime: {
|
|
52
|
+
"@jskit-ai/kernel": "0.1.4",
|
|
53
|
+
"unstorage": "^1.17.3"
|
|
54
|
+
},
|
|
55
|
+
dev: {}
|
|
56
|
+
},
|
|
57
|
+
packageJson: {
|
|
58
|
+
scripts: {}
|
|
59
|
+
},
|
|
60
|
+
procfile: {},
|
|
61
|
+
files: [],
|
|
62
|
+
text: []
|
|
63
|
+
}
|
|
64
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jskit-ai/storage-runtime",
|
|
3
|
+
"version": "0.1.4",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"test": "node --test"
|
|
7
|
+
},
|
|
8
|
+
"exports": {
|
|
9
|
+
"./client": "./src/client/index.js",
|
|
10
|
+
"./server/providers/StorageRuntimeServiceProvider": "./src/server/providers/StorageRuntimeServiceProvider.js"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@jskit-ai/kernel": "0.1.4",
|
|
14
|
+
"unstorage": "^1.17.3"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { KERNEL_TOKENS } from "@jskit-ai/kernel/shared/support/tokens";
|
|
2
|
+
import * as storageBinding from "../storageBinding.js";
|
|
3
|
+
|
|
4
|
+
const STORAGE_RUNTIME_SERVER_TOKEN = "runtime.storage";
|
|
5
|
+
const STORAGE_RUNTIME_SERVER_API = Object.freeze({
|
|
6
|
+
...storageBinding
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
class StorageRuntimeServiceProvider {
|
|
10
|
+
static id = STORAGE_RUNTIME_SERVER_TOKEN;
|
|
11
|
+
|
|
12
|
+
static dependsOn = ["runtime.server"];
|
|
13
|
+
|
|
14
|
+
register(app) {
|
|
15
|
+
if (!app || typeof app.singleton !== "function") {
|
|
16
|
+
throw new Error("StorageRuntimeServiceProvider requires application singleton().");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
app.singleton(STORAGE_RUNTIME_SERVER_TOKEN, () => STORAGE_RUNTIME_SERVER_API);
|
|
20
|
+
app.singleton(KERNEL_TOKENS.Storage, (scope) => storageBinding.createStorageBinding(scope));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
boot() {}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export { STORAGE_RUNTIME_SERVER_TOKEN, StorageRuntimeServiceProvider };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { mkdirSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { createStorage } from "unstorage";
|
|
4
|
+
import fsDriver from "unstorage/drivers/fs";
|
|
5
|
+
import memoryDriver from "unstorage/drivers/memory";
|
|
6
|
+
import { KERNEL_TOKENS } from "@jskit-ai/kernel/shared/support/tokens";
|
|
7
|
+
|
|
8
|
+
const STORAGE_DRIVER_ENV_KEY = "JSKIT_STORAGE_DRIVER";
|
|
9
|
+
const STORAGE_FS_BASE_PATH_ENV_KEY = "JSKIT_STORAGE_FS_BASE_PATH";
|
|
10
|
+
const DEFAULT_STORAGE_DRIVER = "fs";
|
|
11
|
+
|
|
12
|
+
function normalizeStorageDriver(value) {
|
|
13
|
+
const normalized = String(value || "").trim().toLowerCase();
|
|
14
|
+
return normalized || DEFAULT_STORAGE_DRIVER;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function resolveFsBasePath(fsBasePath, { rootDir } = {}) {
|
|
18
|
+
const normalized = String(fsBasePath || "").trim();
|
|
19
|
+
if (normalized) {
|
|
20
|
+
return path.resolve(normalized);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const resolvedRootDir = rootDir || process.cwd();
|
|
24
|
+
return path.resolve(resolvedRootDir, "data", "storage");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function createStorageBinding(scope, { rootDir = process.cwd() } = {}) {
|
|
28
|
+
const env = scope && typeof scope.has === "function" && scope.has(KERNEL_TOKENS.Env) ? scope.make(KERNEL_TOKENS.Env) : {};
|
|
29
|
+
const driver = normalizeStorageDriver(env?.[STORAGE_DRIVER_ENV_KEY]);
|
|
30
|
+
|
|
31
|
+
if (driver === "memory") {
|
|
32
|
+
return createStorage({
|
|
33
|
+
driver: memoryDriver()
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (driver !== "fs") {
|
|
38
|
+
throw new Error(`Unsupported ${STORAGE_DRIVER_ENV_KEY} "${driver}". Supported: fs, memory.`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const fsBasePath = resolveFsBasePath(env?.[STORAGE_FS_BASE_PATH_ENV_KEY], { rootDir });
|
|
42
|
+
mkdirSync(fsBasePath, { recursive: true });
|
|
43
|
+
|
|
44
|
+
return createStorage({
|
|
45
|
+
driver: fsDriver({
|
|
46
|
+
base: fsBasePath
|
|
47
|
+
})
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export {
|
|
52
|
+
STORAGE_DRIVER_ENV_KEY,
|
|
53
|
+
STORAGE_FS_BASE_PATH_ENV_KEY,
|
|
54
|
+
DEFAULT_STORAGE_DRIVER,
|
|
55
|
+
normalizeStorageDriver,
|
|
56
|
+
createStorageBinding
|
|
57
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { KERNEL_TOKENS } from "@jskit-ai/kernel/shared/support/tokens";
|
|
4
|
+
import { StorageRuntimeServiceProvider } from "../src/server/providers/StorageRuntimeServiceProvider.js";
|
|
5
|
+
|
|
6
|
+
function createSingletonApp() {
|
|
7
|
+
const singletons = new Map();
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
has(token) {
|
|
11
|
+
return singletons.has(token);
|
|
12
|
+
},
|
|
13
|
+
singleton(token, factory) {
|
|
14
|
+
singletons.set(token, factory(this));
|
|
15
|
+
},
|
|
16
|
+
make(token) {
|
|
17
|
+
if (!singletons.has(token)) {
|
|
18
|
+
throw new Error(`Token ${String(token)} is not registered.`);
|
|
19
|
+
}
|
|
20
|
+
return singletons.get(token);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
test("StorageRuntimeServiceProvider registers runtime storage api and storage binding", async () => {
|
|
26
|
+
const app = createSingletonApp();
|
|
27
|
+
app.singleton(KERNEL_TOKENS.Env, () => ({
|
|
28
|
+
JSKIT_STORAGE_DRIVER: "memory"
|
|
29
|
+
}));
|
|
30
|
+
|
|
31
|
+
const provider = new StorageRuntimeServiceProvider();
|
|
32
|
+
provider.register(app);
|
|
33
|
+
|
|
34
|
+
assert.equal(app.has("runtime.storage"), true);
|
|
35
|
+
assert.equal(app.has(KERNEL_TOKENS.Storage), true);
|
|
36
|
+
|
|
37
|
+
const runtimeStorageApi = app.make("runtime.storage");
|
|
38
|
+
assert.equal(typeof runtimeStorageApi.createStorageBinding, "function");
|
|
39
|
+
|
|
40
|
+
const storage = app.make(KERNEL_TOKENS.Storage);
|
|
41
|
+
assert.equal(typeof storage.setItemRaw, "function");
|
|
42
|
+
assert.equal(typeof storage.getItemRaw, "function");
|
|
43
|
+
|
|
44
|
+
await storage.setItemRaw("tests/storage-runtime", Buffer.from("ok"));
|
|
45
|
+
const value = await storage.getItemRaw("tests/storage-runtime");
|
|
46
|
+
assert.equal(Buffer.from(value).toString(), "ok");
|
|
47
|
+
});
|