@jskit-ai/uploads-runtime 0.1.134 → 0.1.136

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jskit-ai/uploads-runtime",
3
- "version": "0.1.134",
3
+ "version": "0.1.136",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "test": "node --test"
@@ -8,7 +8,7 @@
8
8
  "exports": {
9
9
  "./client": "./src/client/index.js",
10
10
  "./shared": "./src/shared/index.js",
11
- "./server/providers/UploadsRuntimeServiceProvider": "./src/server/providers/UploadsRuntimeServiceProvider.js",
11
+ "./server/providers/UploadsProvider": "./src/server/providers/UploadsProvider.js",
12
12
  "./server/multipart/registerMultipartSupport": "./src/server/multipart/registerMultipartSupport.js",
13
13
  "./server/multipart/readSingleMultipartFile": "./src/server/multipart/readSingleMultipartFile.js",
14
14
  "./server/policy/uploadPolicy": "./src/server/policy/uploadPolicy.js",
@@ -16,7 +16,7 @@
16
16
  },
17
17
  "dependencies": {
18
18
  "@fastify/multipart": "^9.4.0",
19
- "@jskit-ai/kernel": "0.1.159"
19
+ "@jskit-ai/kernel": "0.1.161"
20
20
  },
21
21
  "description": "Reusable upload runtime primitives for multipart parsing, policy validation, and blob storage.",
22
22
  "jskit": {
@@ -25,15 +25,16 @@
25
25
  "provides": [
26
26
  "runtime.uploads"
27
27
  ],
28
- "requires": []
28
+ "requires": [
29
+ "runtime.fastify"
30
+ ]
29
31
  },
30
32
  "runtime": {
31
33
  "server": {
32
- "providerEntrypoint": "src/server/providers/UploadsRuntimeServiceProvider.js",
33
34
  "providers": [
34
35
  {
35
- "entrypoint": "src/server/providers/UploadsRuntimeServiceProvider.js",
36
- "export": "UploadsRuntimeServiceProvider"
36
+ "entrypoint": "src/server/providers/UploadsProvider.js",
37
+ "export": "UploadsProvider"
37
38
  }
38
39
  ]
39
40
  },
@@ -45,8 +46,8 @@
45
46
  "apiSummary": {
46
47
  "surfaces": [
47
48
  {
48
- "subpath": "./server/providers/UploadsRuntimeServiceProvider",
49
- "summary": "Exports uploads runtime server provider."
49
+ "subpath": "./server/providers/UploadsProvider",
50
+ "summary": "Provides runtime.uploads and installs multipart support on the application Fastify instance."
50
51
  },
51
52
  {
52
53
  "subpath": "./server/multipart/registerMultipartSupport",
@@ -62,7 +63,7 @@
62
63
  },
63
64
  {
64
65
  "subpath": "./server/storage/createUploadStorageService",
65
- "summary": "Exports raw upload storage helpers backed by jskit.storage."
66
+ "summary": "Exports raw upload storage helpers backed by runtime.storage."
66
67
  },
67
68
  {
68
69
  "subpath": "./shared",
@@ -72,29 +73,8 @@
72
73
  "subpath": "./client",
73
74
  "summary": "Exports no client runtime API today (reserved client entrypoint)."
74
75
  }
75
- ],
76
- "containerTokens": {
77
- "server": [
78
- "runtime.uploads"
79
- ],
80
- "client": []
81
- }
76
+ ]
82
77
  }
83
- },
84
- "mutations": {
85
- "dependencies": {
86
- "runtime": {
87
- "@fastify/multipart": "^9.4.0",
88
- "@jskit-ai/kernel": "0.1.159"
89
- },
90
- "dev": {}
91
- },
92
- "packageJson": {
93
- "scripts": {}
94
- },
95
- "procfile": {},
96
- "files": [],
97
- "text": []
98
78
  }
99
79
  }
100
80
  }
@@ -1,17 +1,8 @@
1
1
  import fastifyMultipart from "@fastify/multipart";
2
2
 
3
- async function registerMultipartSupport(app) {
4
- if (!app || typeof app.has !== "function" || typeof app.make !== "function") {
5
- throw new Error("registerMultipartSupport requires application has()/make().");
6
- }
7
-
8
- if (!app.has("jskit.fastify")) {
9
- return;
10
- }
11
-
12
- const fastify = app.make("jskit.fastify");
3
+ async function registerMultipartSupport(fastify) {
13
4
  if (!fastify || typeof fastify.register !== "function") {
14
- throw new Error("registerMultipartSupport requires Fastify register().");
5
+ throw new Error("registerMultipartSupport requires Fastify.");
15
6
  }
16
7
 
17
8
  if (fastify["jskit.uploads-runtime.multipart.support"] === true) {
@@ -1,3 +1,4 @@
1
+ import { defineProvider } from "@jskit-ai/kernel/shared/capabilities";
1
2
  import { registerMultipartSupport } from "../multipart/registerMultipartSupport.js";
2
3
  import { readSingleMultipartFile } from "../multipart/readSingleMultipartFile.js";
3
4
  import {
@@ -11,8 +12,7 @@ import {
11
12
  normalizeStorageKey
12
13
  } from "../storage/createUploadStorageService.js";
13
14
 
14
- const UPLOADS_RUNTIME_SERVER_API = Object.freeze({
15
- registerMultipartSupport,
15
+ const uploads = Object.freeze({
16
16
  readSingleMultipartFile,
17
17
  createUploadFieldError,
18
18
  readUploadBuffer,
@@ -22,20 +22,20 @@ const UPLOADS_RUNTIME_SERVER_API = Object.freeze({
22
22
  normalizeStorageKey
23
23
  });
24
24
 
25
- class UploadsRuntimeServiceProvider {
26
- static id = "runtime.uploads";
27
-
28
- register(app) {
29
- if (!app || typeof app.singleton !== "function") {
30
- throw new Error("UploadsRuntimeServiceProvider requires application singleton().");
31
- }
32
-
33
- app.singleton("runtime.uploads", () => UPLOADS_RUNTIME_SERVER_API);
25
+ const UploadsProvider = defineProvider({
26
+ id: "runtime.uploads",
27
+ requires: {
28
+ fastify: "runtime.fastify"
29
+ },
30
+ provides: {
31
+ uploads: "runtime.uploads"
32
+ },
33
+ setup() {
34
+ return { uploads };
35
+ },
36
+ async boot({ fastify }) {
37
+ await registerMultipartSupport(fastify);
34
38
  }
39
+ });
35
40
 
36
- async boot(app) {
37
- await registerMultipartSupport(app);
38
- }
39
- }
40
-
41
- export { UploadsRuntimeServiceProvider };
41
+ export { UploadsProvider };
@@ -16,7 +16,7 @@ test("uploads-runtime exports are explicit and aligned with usage", () => {
16
16
  requiredExports: [
17
17
  "./client",
18
18
  "./shared",
19
- "./server/providers/UploadsRuntimeServiceProvider",
19
+ "./server/providers/UploadsProvider",
20
20
  "./server/multipart/registerMultipartSupport",
21
21
  "./server/multipart/readSingleMultipartFile",
22
22
  "./server/policy/uploadPolicy",
@@ -1,73 +1,37 @@
1
- import test from "node:test";
2
1
  import assert from "node:assert/strict";
3
- import { UploadsRuntimeServiceProvider } from "../src/server/providers/UploadsRuntimeServiceProvider.js";
2
+ import test from "node:test";
4
3
 
5
- function createAppStub({ hasFastify = true, fastify = null } = {}) {
6
- const singletons = new Map();
7
- const singletonInstances = new Map();
8
- const resolvedFastify =
9
- fastify ||
10
- {
11
- register: async () => {},
12
- hasContentTypeParser: () => false
13
- };
4
+ import { createCapabilityRuntime, defineProvider } from "@jskit-ai/kernel/shared/capabilities";
5
+ import { UploadsProvider } from "../src/server/providers/UploadsProvider.js";
14
6
 
15
- return {
16
- has(token) {
17
- if (token === "jskit.fastify") {
18
- return hasFastify;
19
- }
20
- return singletons.has(token) || singletonInstances.has(token);
21
- },
22
- singleton(token, factory) {
23
- singletons.set(token, factory);
7
+ test("UploadsProvider provides upload operations and boots multipart support", async () => {
8
+ let registerCount = 0;
9
+ let uploads;
10
+ const fastify = {
11
+ async register() {
12
+ registerCount += 1;
24
13
  },
25
- make(token) {
26
- if (token === "jskit.fastify") {
27
- return resolvedFastify;
28
- }
29
- if (singletonInstances.has(token)) {
30
- return singletonInstances.get(token);
31
- }
32
- const factory = singletons.get(token);
33
- if (!factory) {
34
- throw new Error(`Unknown token ${String(token)}`);
35
- }
36
- const instance = factory(this);
37
- singletonInstances.set(token, instance);
38
- return instance;
14
+ hasContentTypeParser() {
15
+ return false;
39
16
  }
40
17
  };
41
- }
42
-
43
- test("UploadsRuntimeServiceProvider registers runtime uploads api", async () => {
44
- const app = createAppStub();
45
- const provider = new UploadsRuntimeServiceProvider();
46
-
47
- provider.register(app);
48
-
49
- assert.equal(app.has("runtime.uploads"), true);
50
- const runtimeUploads = app.make("runtime.uploads");
51
- assert.equal(typeof runtimeUploads.registerMultipartSupport, "function");
52
- assert.equal(typeof runtimeUploads.readSingleMultipartFile, "function");
53
- assert.equal(typeof runtimeUploads.createUploadStorageService, "function");
54
- });
55
-
56
- test("UploadsRuntimeServiceProvider boots multipart support once", async () => {
57
- let registerCount = 0;
58
- const app = createAppStub({
59
- fastify: {
60
- register: async () => {
61
- registerCount += 1;
62
- },
63
- hasContentTypeParser: () => false
18
+ const consumer = defineProvider({
19
+ id: "test.uploads.consumer",
20
+ requires: { value: "runtime.uploads" },
21
+ setup({ value }) {
22
+ uploads = value;
23
+ return {};
64
24
  }
65
25
  });
26
+ const runtime = createCapabilityRuntime({
27
+ inputs: { "runtime.fastify": fastify },
28
+ providers: [UploadsProvider, consumer]
29
+ });
66
30
 
67
- const provider = new UploadsRuntimeServiceProvider();
68
- provider.register(app);
69
- await provider.boot(app);
70
- await provider.boot(app);
71
-
31
+ await runtime.start();
72
32
  assert.equal(registerCount, 1);
33
+ assert.equal(typeof uploads.readSingleMultipartFile, "function");
34
+ assert.equal(typeof uploads.createUploadStorageService, "function");
35
+ assert.equal(Object.hasOwn(uploads, "make"), false);
36
+ await runtime.shutdown();
73
37
  });
@@ -2,33 +2,8 @@ import test from "node:test";
2
2
  import assert from "node:assert/strict";
3
3
  import { registerMultipartSupport } from "../src/server/multipart/registerMultipartSupport.js";
4
4
 
5
- function createAppStub({ hasFastify = true, fastify = null } = {}) {
6
- const resolvedFastify =
7
- fastify ||
8
- {
9
- register: async () => {},
10
- hasContentTypeParser: () => false
11
- };
12
-
13
- return {
14
- has(token) {
15
- if (token === "jskit.fastify") {
16
- return hasFastify;
17
- }
18
- return false;
19
- },
20
- make(token) {
21
- if (token === "jskit.fastify") {
22
- return resolvedFastify;
23
- }
24
- return null;
25
- }
26
- };
27
- }
28
-
29
- test("registerMultipartSupport returns early when Fastify is not available", async () => {
30
- const app = createAppStub({ hasFastify: false });
31
- await assert.doesNotReject(async () => registerMultipartSupport(app));
5
+ test("registerMultipartSupport requires the explicit Fastify dependency", async () => {
6
+ await assert.rejects(registerMultipartSupport(null), /requires Fastify/u);
32
7
  });
33
8
 
34
9
  test("registerMultipartSupport registers multipart parser only once", async () => {
@@ -39,10 +14,8 @@ test("registerMultipartSupport registers multipart parser only once", async () =
39
14
  },
40
15
  hasContentTypeParser: () => false
41
16
  };
42
- const app = createAppStub({ fastify });
43
-
44
- await registerMultipartSupport(app);
45
- await registerMultipartSupport(app);
17
+ await registerMultipartSupport(fastify);
18
+ await registerMultipartSupport(fastify);
46
19
 
47
20
  assert.equal(registerCount, 1);
48
21
  });
@@ -55,9 +28,7 @@ test("registerMultipartSupport skips registration when parser already exists", a
55
28
  },
56
29
  hasContentTypeParser: (contentType) => String(contentType || "").trim().toLowerCase() === "multipart"
57
30
  };
58
- const app = createAppStub({ fastify });
59
-
60
- await registerMultipartSupport(app);
31
+ await registerMultipartSupport(fastify);
61
32
 
62
33
  assert.equal(registerCount, 0);
63
34
  });