every-plugin 0.0.6 → 0.1.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/README.md +1 -265
- package/dist/errors.d.ts +4 -4
- package/dist/index.d.ts +2 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -3
- package/dist/plugin.d.ts +74 -34
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +100 -17
- package/dist/runtime/errors.d.ts +38 -34
- package/dist/runtime/errors.d.ts.map +1 -1
- package/dist/runtime/errors.js +2 -0
- package/dist/runtime/index.d.ts +7 -4
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +5 -10
- package/dist/runtime/services/module-federation.service.d.ts +5 -6
- package/dist/runtime/services/module-federation.service.d.ts.map +1 -1
- package/dist/runtime/services/module-federation.service.js +53 -15
- package/dist/runtime/services/plugin.service.d.ts +13 -6
- package/dist/runtime/services/plugin.service.d.ts.map +1 -1
- package/dist/runtime/services/plugin.service.js +237 -94
- package/dist/runtime/services/secrets.service.d.ts.map +1 -1
- package/dist/runtime/services.d.ts +0 -1
- package/dist/runtime/services.d.ts.map +1 -1
- package/dist/runtime/services.js +0 -1
- package/dist/runtime/streaming/index.d.ts +4 -0
- package/dist/runtime/streaming/index.d.ts.map +1 -0
- package/dist/runtime/streaming/index.js +2 -0
- package/dist/runtime/streaming/state-effects.d.ts +28 -0
- package/dist/runtime/streaming/state-effects.d.ts.map +1 -0
- package/dist/runtime/streaming/state-effects.js +30 -0
- package/dist/runtime/streaming/streaming.d.ts +8 -0
- package/dist/runtime/streaming/streaming.d.ts.map +1 -0
- package/dist/runtime/streaming/streaming.js +107 -0
- package/dist/runtime/streaming/types.d.ts +19 -0
- package/dist/runtime/streaming/types.d.ts.map +1 -0
- package/dist/runtime/streaming/types.js +1 -0
- package/dist/runtime/test-utils.d.ts +3 -0
- package/dist/runtime/test-utils.d.ts.map +1 -0
- package/dist/runtime/test-utils.js +7 -0
- package/dist/runtime/types.d.ts +1 -1
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/validation.d.ts +2 -7
- package/dist/runtime/validation.d.ts.map +1 -1
- package/dist/testing/index.d.ts +25 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +40 -0
- package/dist/testing/mocks/module-federation.service.d.ts +8 -0
- package/dist/testing/mocks/module-federation.service.d.ts.map +1 -0
- package/dist/testing/mocks/module-federation.service.js +35 -0
- package/package.json +27 -6
- package/dist/runtime/runtime.d.ts +0 -58
- package/dist/runtime/runtime.d.ts.map +0 -1
- package/dist/runtime/runtime.js +0 -75
- package/dist/runtime/runtime.test.d.ts +0 -2
- package/dist/runtime/runtime.test.d.ts.map +0 -1
- package/dist/runtime/runtime.test.js +0 -308
- package/dist/runtime/services/plugin-cache.service.d.ts +0 -18
- package/dist/runtime/services/plugin-cache.service.d.ts.map +0 -1
- package/dist/runtime/services/plugin-cache.service.js +0 -55
- package/dist/source.d.ts +0 -198
- package/dist/source.d.ts.map +0 -1
- package/dist/source.js +0 -90
|
@@ -1,308 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { Effect, Duration } from "effect";
|
|
3
|
-
import { PluginRuntime, createPluginRuntime } from "./index";
|
|
4
|
-
// Local template plugin for testing
|
|
5
|
-
const TEST_REGISTRY = {
|
|
6
|
-
"test-plugin": {
|
|
7
|
-
remoteUrl: "http://localhost:3000/remoteEntry.js",
|
|
8
|
-
type: "transformer",
|
|
9
|
-
version: "0.0.1",
|
|
10
|
-
description: "Local template plugin for testing",
|
|
11
|
-
},
|
|
12
|
-
};
|
|
13
|
-
const TEST_CONFIG = {
|
|
14
|
-
variables: {
|
|
15
|
-
baseUrl: "http://localhost:1337",
|
|
16
|
-
timeout: 5000,
|
|
17
|
-
},
|
|
18
|
-
secrets: {
|
|
19
|
-
apiKey: "{{API_KEY}}", // This will be hydrated from secrets config
|
|
20
|
-
},
|
|
21
|
-
};
|
|
22
|
-
const TEST_INPUT = {
|
|
23
|
-
query: "test query for processing",
|
|
24
|
-
options: {
|
|
25
|
-
limit: 2,
|
|
26
|
-
},
|
|
27
|
-
};
|
|
28
|
-
// Secrets configuration for hydration
|
|
29
|
-
const SECRETS_CONFIG = {
|
|
30
|
-
API_KEY: "test-api-key-value",
|
|
31
|
-
};
|
|
32
|
-
describe("Plugin Runtime Integration", () => {
|
|
33
|
-
it("should create and execute plugin end-to-end", async () => {
|
|
34
|
-
// Create the managed runtime
|
|
35
|
-
const runtime = createPluginRuntime({
|
|
36
|
-
registry: TEST_REGISTRY,
|
|
37
|
-
secrets: SECRETS_CONFIG,
|
|
38
|
-
});
|
|
39
|
-
// Execute the test within the runtime
|
|
40
|
-
const result = await runtime.runPromise(Effect.gen(function* () {
|
|
41
|
-
const pluginRuntime = yield* PluginRuntime;
|
|
42
|
-
// Create plugin (load → instantiate → initialize)
|
|
43
|
-
const initializedPlugin = yield* pluginRuntime.createPlugin("test-plugin", TEST_CONFIG);
|
|
44
|
-
// Verify plugin was initialized
|
|
45
|
-
expect(initializedPlugin).toBeDefined();
|
|
46
|
-
expect(initializedPlugin.metadata.pluginId).toBe("test-plugin");
|
|
47
|
-
expect(initializedPlugin.plugin).toBeDefined();
|
|
48
|
-
// Execute plugin
|
|
49
|
-
const output = yield* pluginRuntime.executePlugin(initializedPlugin, TEST_INPUT);
|
|
50
|
-
return output;
|
|
51
|
-
}));
|
|
52
|
-
// Validate output structure
|
|
53
|
-
expect(result).toBeDefined();
|
|
54
|
-
expect(typeof result).toBe("object");
|
|
55
|
-
const typedResult = result;
|
|
56
|
-
// Verify success wrapper structure
|
|
57
|
-
expect(typedResult).toHaveProperty("success");
|
|
58
|
-
expect(typedResult).toHaveProperty("data");
|
|
59
|
-
expect(typedResult.success).toBe(true);
|
|
60
|
-
// Verify data content
|
|
61
|
-
expect(typedResult.data).toHaveProperty("results");
|
|
62
|
-
expect(typedResult.data).toHaveProperty("count");
|
|
63
|
-
expect(Array.isArray(typedResult.data.results)).toBe(true);
|
|
64
|
-
expect(typedResult.data.count).toBe(2); // Should match the limit we set
|
|
65
|
-
expect(typedResult.data.results).toHaveLength(2);
|
|
66
|
-
// Verify results contain processed query
|
|
67
|
-
expect(typedResult.data.results[0]).toHaveProperty("id");
|
|
68
|
-
expect(typedResult.data.results[0]).toHaveProperty("content");
|
|
69
|
-
expect(typedResult.data.results[0].content).toContain("test query for processing");
|
|
70
|
-
expect(typedResult.data.results[1].content).toContain("test query for processing");
|
|
71
|
-
});
|
|
72
|
-
it("should handle plugin lifecycle correctly", async () => {
|
|
73
|
-
const runtime = createPluginRuntime({
|
|
74
|
-
registry: TEST_REGISTRY,
|
|
75
|
-
secrets: SECRETS_CONFIG,
|
|
76
|
-
});
|
|
77
|
-
await runtime.runPromise(Effect.gen(function* () {
|
|
78
|
-
const pluginRuntime = yield* PluginRuntime;
|
|
79
|
-
// Test individual lifecycle steps
|
|
80
|
-
// 1. Load plugin
|
|
81
|
-
const pluginConstructor = yield* pluginRuntime.loadPlugin("test-plugin");
|
|
82
|
-
expect(pluginConstructor).toBeDefined();
|
|
83
|
-
expect(pluginConstructor.metadata.pluginId).toBe("test-plugin");
|
|
84
|
-
// 2. Instantiate plugin
|
|
85
|
-
const pluginInstance = yield* pluginRuntime.instantiatePlugin(pluginConstructor);
|
|
86
|
-
expect(pluginInstance).toBeDefined();
|
|
87
|
-
expect(pluginInstance.plugin).toBeDefined();
|
|
88
|
-
expect(pluginInstance.metadata.pluginId).toBe("test-plugin");
|
|
89
|
-
// 3. Initialize plugin
|
|
90
|
-
const initializedPlugin = yield* pluginRuntime.initializePlugin(pluginInstance, TEST_CONFIG);
|
|
91
|
-
expect(initializedPlugin).toBeDefined();
|
|
92
|
-
expect(initializedPlugin.config).toBeDefined();
|
|
93
|
-
// 4. Execute plugin
|
|
94
|
-
const output = yield* pluginRuntime.executePlugin(initializedPlugin, TEST_INPUT);
|
|
95
|
-
expect(output).toBeDefined();
|
|
96
|
-
}));
|
|
97
|
-
});
|
|
98
|
-
it("should handle secret hydration", async () => {
|
|
99
|
-
const configWithSecrets = {
|
|
100
|
-
variables: {
|
|
101
|
-
baseUrl: "http://localhost:1337",
|
|
102
|
-
timeout: 10000,
|
|
103
|
-
},
|
|
104
|
-
secrets: {
|
|
105
|
-
apiKey: "{{API_KEY}}", // This should be hydrated
|
|
106
|
-
},
|
|
107
|
-
};
|
|
108
|
-
const secretsConfig = {
|
|
109
|
-
API_KEY: "hydrated-api-key-value",
|
|
110
|
-
};
|
|
111
|
-
const runtime = createPluginRuntime({
|
|
112
|
-
registry: TEST_REGISTRY,
|
|
113
|
-
secrets: secretsConfig,
|
|
114
|
-
});
|
|
115
|
-
await runtime.runPromise(Effect.gen(function* () {
|
|
116
|
-
const pluginRuntime = yield* PluginRuntime;
|
|
117
|
-
const initializedPlugin = yield* pluginRuntime.createPlugin("test-plugin", configWithSecrets);
|
|
118
|
-
// Verify secrets were hydrated in the config
|
|
119
|
-
expect(initializedPlugin.config).toBeDefined();
|
|
120
|
-
// Verify the config structure and that secrets were hydrated
|
|
121
|
-
const config = initializedPlugin.config;
|
|
122
|
-
expect(config).toHaveProperty("secrets");
|
|
123
|
-
expect(config.secrets).toHaveProperty("apiKey");
|
|
124
|
-
expect(config.secrets.apiKey).toBe("hydrated-api-key-value");
|
|
125
|
-
// Verify variables are also present
|
|
126
|
-
expect(config).toHaveProperty("variables");
|
|
127
|
-
expect(config.variables.baseUrl).toBe("http://localhost:1337");
|
|
128
|
-
expect(config.variables.timeout).toBe(10000);
|
|
129
|
-
// Verify the plugin was successfully initialized with hydrated secrets
|
|
130
|
-
// by executing it to ensure it works with the hydrated config
|
|
131
|
-
const output = yield* pluginRuntime.executePlugin(initializedPlugin, TEST_INPUT);
|
|
132
|
-
expect(output).toBeDefined();
|
|
133
|
-
}));
|
|
134
|
-
});
|
|
135
|
-
it("should handle validation error for missing apiKey", async () => {
|
|
136
|
-
const configWithoutApiKey = {
|
|
137
|
-
variables: {
|
|
138
|
-
baseUrl: "http://localhost:1337",
|
|
139
|
-
timeout: 5000,
|
|
140
|
-
},
|
|
141
|
-
secrets: {
|
|
142
|
-
// Missing required apiKey
|
|
143
|
-
},
|
|
144
|
-
};
|
|
145
|
-
const runtime = createPluginRuntime({
|
|
146
|
-
registry: TEST_REGISTRY,
|
|
147
|
-
secrets: SECRETS_CONFIG,
|
|
148
|
-
});
|
|
149
|
-
const result = await runtime.runPromise(Effect.gen(function* () {
|
|
150
|
-
const pluginRuntime = yield* PluginRuntime;
|
|
151
|
-
return yield* pluginRuntime.createPlugin("test-plugin", configWithoutApiKey).pipe(Effect.catchTag("PluginRuntimeError", (error) => {
|
|
152
|
-
// Should catch validation error
|
|
153
|
-
expect(error.operation).toBe("validate-config");
|
|
154
|
-
expect(error.retryable).toBe(false);
|
|
155
|
-
expect(error.pluginId).toBe("test-plugin");
|
|
156
|
-
expect(error.cause).toBeDefined();
|
|
157
|
-
// The error should mention the missing apiKey
|
|
158
|
-
const errorMessage = error.cause?.message || "";
|
|
159
|
-
// Zod validation errors might be in JSON format, so check for both formats
|
|
160
|
-
const lowerMessage = errorMessage.toLowerCase();
|
|
161
|
-
const hasApiKeyError = lowerMessage.includes("api key") ||
|
|
162
|
-
lowerMessage.includes("apikey") ||
|
|
163
|
-
lowerMessage.includes("required");
|
|
164
|
-
expect(hasApiKeyError).toBe(true);
|
|
165
|
-
console.log("Caught expected validation error:", {
|
|
166
|
-
operation: error.operation,
|
|
167
|
-
pluginId: error.pluginId,
|
|
168
|
-
retryable: error.retryable,
|
|
169
|
-
cause: error.cause?.message,
|
|
170
|
-
});
|
|
171
|
-
return Effect.succeed("validation-error-handled-properly");
|
|
172
|
-
}), Effect.catchAll((unexpectedError) => {
|
|
173
|
-
console.error("Unexpected error type:", unexpectedError);
|
|
174
|
-
expect.fail(`Expected PluginRuntimeError but got: ${unexpectedError._tag || typeof unexpectedError}`);
|
|
175
|
-
return Effect.succeed("should-not-reach-here");
|
|
176
|
-
}));
|
|
177
|
-
}));
|
|
178
|
-
expect(result).toBe("validation-error-handled-properly");
|
|
179
|
-
});
|
|
180
|
-
it("should handle runtime shutdown gracefully", async () => {
|
|
181
|
-
const runtime = createPluginRuntime({
|
|
182
|
-
registry: TEST_REGISTRY,
|
|
183
|
-
secrets: SECRETS_CONFIG,
|
|
184
|
-
});
|
|
185
|
-
await runtime.runPromise(Effect.gen(function* () {
|
|
186
|
-
const pluginRuntime = yield* PluginRuntime;
|
|
187
|
-
// Test shutdown
|
|
188
|
-
yield* pluginRuntime.shutdown();
|
|
189
|
-
// Shutdown should complete without errors
|
|
190
|
-
expect(true).toBe(true); // If we reach here, shutdown was successful
|
|
191
|
-
}));
|
|
192
|
-
});
|
|
193
|
-
it("should handle invalid remoteUrl with proper error handling", async () => {
|
|
194
|
-
const INVALID_REGISTRY = {
|
|
195
|
-
"invalid-plugin": {
|
|
196
|
-
remoteUrl: "https://invalid-plugin-url-that-does-not-exist.com/plugin.js",
|
|
197
|
-
type: "transformer",
|
|
198
|
-
version: "1.0.0",
|
|
199
|
-
description: "Invalid plugin for testing error handling",
|
|
200
|
-
},
|
|
201
|
-
};
|
|
202
|
-
const runtime = createPluginRuntime({
|
|
203
|
-
registry: INVALID_REGISTRY,
|
|
204
|
-
secrets: {},
|
|
205
|
-
});
|
|
206
|
-
const result = await runtime.runPromise(Effect.gen(function* () {
|
|
207
|
-
const pluginRuntime = yield* PluginRuntime;
|
|
208
|
-
return yield* pluginRuntime.createPlugin("invalid-plugin", {}).pipe(Effect.catchTag("PluginRuntimeError", (error) => {
|
|
209
|
-
expect(error.operation).toBe("register-remote");
|
|
210
|
-
expect(error.retryable).toBe(true);
|
|
211
|
-
expect(error.pluginId).toBe("invalid-plugin");
|
|
212
|
-
expect(error.cause).toBeDefined();
|
|
213
|
-
console.debug("Caught expected PluginRuntimeError:", {
|
|
214
|
-
operation: error.operation,
|
|
215
|
-
pluginId: error.pluginId,
|
|
216
|
-
retryable: error.retryable,
|
|
217
|
-
cause: error.cause?.message,
|
|
218
|
-
});
|
|
219
|
-
return Effect.succeed("error-handled-properly");
|
|
220
|
-
}), Effect.catchAll((unexpectedError) => {
|
|
221
|
-
// If any other error type is thrown, fail the test
|
|
222
|
-
console.error("Unexpected error type:", unexpectedError);
|
|
223
|
-
expect.fail(`Expected PluginRuntimeError but got: ${unexpectedError._tag || typeof unexpectedError}`);
|
|
224
|
-
return Effect.succeed("should-not-reach-here");
|
|
225
|
-
}));
|
|
226
|
-
}));
|
|
227
|
-
expect(result).toBe("error-handled-properly");
|
|
228
|
-
});
|
|
229
|
-
it("should handle plugin not found in registry", async () => {
|
|
230
|
-
// Empty registry to test missing plugin
|
|
231
|
-
const EMPTY_REGISTRY = {};
|
|
232
|
-
const runtime = createPluginRuntime({
|
|
233
|
-
registry: EMPTY_REGISTRY,
|
|
234
|
-
secrets: {},
|
|
235
|
-
});
|
|
236
|
-
const result = await runtime.runPromise(Effect.gen(function* () {
|
|
237
|
-
const pluginRuntime = yield* PluginRuntime;
|
|
238
|
-
return yield* pluginRuntime.loadPlugin("non-existent-plugin").pipe(Effect.catchTag("PluginRuntimeError", (error) => {
|
|
239
|
-
// Validate error properties
|
|
240
|
-
expect(error.operation).toBe("load-plugin");
|
|
241
|
-
expect(error.retryable).toBe(false);
|
|
242
|
-
expect(error.pluginId).toBe("non-existent-plugin");
|
|
243
|
-
expect(error.cause).toBeDefined();
|
|
244
|
-
expect(error.cause?.message).toContain("not found in registry");
|
|
245
|
-
// Log error details for debugging
|
|
246
|
-
console.log("Caught expected PluginRuntimeError for missing plugin:", {
|
|
247
|
-
operation: error.operation,
|
|
248
|
-
pluginId: error.pluginId,
|
|
249
|
-
retryable: error.retryable,
|
|
250
|
-
cause: error.cause?.message,
|
|
251
|
-
});
|
|
252
|
-
// Return success to make test pass
|
|
253
|
-
return Effect.succeed("plugin-not-found-handled-properly");
|
|
254
|
-
}), Effect.catchAll((unexpectedError) => {
|
|
255
|
-
// If any other error type is thrown, fail the test
|
|
256
|
-
console.error("Unexpected error type:", unexpectedError);
|
|
257
|
-
expect.fail(`Expected PluginRuntimeError but got: ${unexpectedError._tag || typeof unexpectedError}`);
|
|
258
|
-
return Effect.succeed("should-not-reach-here");
|
|
259
|
-
}));
|
|
260
|
-
}));
|
|
261
|
-
expect(result).toBe("plugin-not-found-handled-properly");
|
|
262
|
-
});
|
|
263
|
-
it("should handle constructor instantiation failure", async () => {
|
|
264
|
-
// Registry with real remote that should fail during instantiation/initialization
|
|
265
|
-
const REAL_REMOTE_REGISTRY = {
|
|
266
|
-
"simple-transform": {
|
|
267
|
-
remoteUrl: "https://unpkg.com/@curatedotfun/simple-transform@latest/dist/remoteEntry.js",
|
|
268
|
-
type: "transformer",
|
|
269
|
-
version: "latest",
|
|
270
|
-
description: "Real remote plugin for testing constructor failure",
|
|
271
|
-
},
|
|
272
|
-
};
|
|
273
|
-
const runtime = createPluginRuntime({
|
|
274
|
-
registry: REAL_REMOTE_REGISTRY,
|
|
275
|
-
secrets: {},
|
|
276
|
-
});
|
|
277
|
-
const result = await runtime.runPromise(Effect.gen(function* () {
|
|
278
|
-
const pluginRuntime = yield* PluginRuntime;
|
|
279
|
-
return yield* pluginRuntime.createPlugin("simple-transform", {}).pipe(Effect.timeout(Duration.seconds(1)), // Timeout after 3 seconds
|
|
280
|
-
Effect.catchTag("PluginRuntimeError", (error) => {
|
|
281
|
-
// Validate error properties
|
|
282
|
-
expect(["load-remote"]).toContain(error.operation);
|
|
283
|
-
expect(error.retryable).toBe(true);
|
|
284
|
-
expect(error.pluginId).toBe("simple-transform");
|
|
285
|
-
expect(error.cause).toBeDefined();
|
|
286
|
-
// Log error details for debugging
|
|
287
|
-
console.log("Caught expected PluginRuntimeError for constructor failure:", {
|
|
288
|
-
operation: error.operation,
|
|
289
|
-
pluginId: error.pluginId,
|
|
290
|
-
retryable: error.retryable,
|
|
291
|
-
cause: error.cause?.message,
|
|
292
|
-
});
|
|
293
|
-
// Return success to make test pass
|
|
294
|
-
return Effect.succeed("constructor-failure-handled-properly");
|
|
295
|
-
}), Effect.catchTag("TimeoutException", () => {
|
|
296
|
-
// Handle timeout as expected failure - remote is too slow
|
|
297
|
-
console.log("Plugin creation timed out - treating as expected failure");
|
|
298
|
-
return Effect.succeed("timeout-handled-properly");
|
|
299
|
-
}), Effect.catchAll((unexpectedError) => {
|
|
300
|
-
// If any other error type is thrown, fail the test
|
|
301
|
-
console.error("Unexpected error type:", unexpectedError);
|
|
302
|
-
expect.fail(`Expected PluginRuntimeError or TimeoutException but got: ${unexpectedError._tag || typeof unexpectedError}`);
|
|
303
|
-
return Effect.succeed("should-not-reach-here");
|
|
304
|
-
}));
|
|
305
|
-
}));
|
|
306
|
-
expect(["constructor-failure-handled-properly", "timeout-handled-properly"]).toContain(result);
|
|
307
|
-
});
|
|
308
|
-
});
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { Effect, Layer } from "effect";
|
|
2
|
-
import { PluginRuntimeError } from "../errors";
|
|
3
|
-
import type { PluginConstructor } from "../types";
|
|
4
|
-
import { ModuleFederationService } from "./module-federation.service";
|
|
5
|
-
export interface IPluginCacheService {
|
|
6
|
-
readonly getCachedConstructor: (cacheKey: string) => Effect.Effect<PluginConstructor, PluginRuntimeError>;
|
|
7
|
-
readonly invalidate: (cacheKey: string) => Effect.Effect<void>;
|
|
8
|
-
}
|
|
9
|
-
declare const PluginCacheService_base: import("effect/Context").TagClass<PluginCacheService, "PluginCacheService", IPluginCacheService> & Effect.Tag.Proxy<PluginCacheService, IPluginCacheService> & {
|
|
10
|
-
use: <X>(body: (_: IPluginCacheService) => X) => [X] extends [Effect.Effect<infer A, infer E, infer R>] ? Effect.Effect<A, E, R | PluginCacheService> : [X] extends [PromiseLike<infer A_1>] ? Effect.Effect<A_1, import("effect/Cause").UnknownException, PluginCacheService> : Effect.Effect<X, never, PluginCacheService>;
|
|
11
|
-
};
|
|
12
|
-
export declare class PluginCacheService extends PluginCacheService_base {
|
|
13
|
-
static Live: Layer.Layer<PluginCacheService, never, ModuleFederationService>;
|
|
14
|
-
}
|
|
15
|
-
export declare const PluginCacheServiceTag: typeof PluginCacheService;
|
|
16
|
-
export declare const PluginCacheServiceLive: Layer.Layer<PluginCacheService, never, ModuleFederationService>;
|
|
17
|
-
export {};
|
|
18
|
-
//# sourceMappingURL=plugin-cache.service.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-cache.service.d.ts","sourceRoot":"","sources":["../../../src/runtime/services/plugin-cache.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,MAAM,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAEtE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,oBAAoB,EAAE,CAC7B,QAAQ,EAAE,MAAM,KACb,MAAM,CAAC,MAAM,CAAC,iBAAiB,EAAE,kBAAkB,CAAC,CAAC;IAC1D,QAAQ,CAAC,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;CAChE;;;;AAED,qBAAa,kBAAmB,SAAQ,uBAGrC;IACD,MAAM,CAAC,IAAI,kEAoET;CACH;AAED,eAAO,MAAM,qBAAqB,2BAAqB,CAAC;AACxD,eAAO,MAAM,sBAAsB,iEAA0B,CAAC"}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { Cache, Duration, Effect, Layer } from "effect";
|
|
2
|
-
import { PluginRuntimeError } from "../errors";
|
|
3
|
-
import { ModuleFederationService } from "./module-federation.service";
|
|
4
|
-
export class PluginCacheService extends Effect.Tag("PluginCacheService")() {
|
|
5
|
-
static Live = Layer.effect(PluginCacheService, Effect.gen(function* () {
|
|
6
|
-
const mfService = yield* ModuleFederationService;
|
|
7
|
-
const cache = yield* Cache.make({
|
|
8
|
-
capacity: 50,
|
|
9
|
-
timeToLive: Duration.minutes(30),
|
|
10
|
-
lookup: (cacheKey) => {
|
|
11
|
-
// Parse cache key: "pluginId:url"
|
|
12
|
-
const colonIndex = cacheKey.indexOf(":");
|
|
13
|
-
if (colonIndex === -1) {
|
|
14
|
-
return Effect.fail(new PluginRuntimeError({
|
|
15
|
-
pluginId: cacheKey,
|
|
16
|
-
operation: "cache-lookup",
|
|
17
|
-
cause: new Error(`Invalid cache key format: ${cacheKey}`),
|
|
18
|
-
retryable: false,
|
|
19
|
-
}));
|
|
20
|
-
}
|
|
21
|
-
const pluginId = cacheKey.substring(0, colonIndex);
|
|
22
|
-
const url = cacheKey.substring(colonIndex + 1);
|
|
23
|
-
return Effect.gen(function* () {
|
|
24
|
-
yield* mfService.registerRemote(pluginId, url).pipe(Effect.mapError((mfError) => new PluginRuntimeError({
|
|
25
|
-
pluginId,
|
|
26
|
-
operation: "register-remote",
|
|
27
|
-
cause: mfError.cause,
|
|
28
|
-
retryable: true,
|
|
29
|
-
})));
|
|
30
|
-
const ctor = yield* mfService.loadRemoteConstructor(pluginId, url).pipe(Effect.mapError((mfError) => new PluginRuntimeError({
|
|
31
|
-
pluginId,
|
|
32
|
-
operation: "load-remote",
|
|
33
|
-
cause: mfError.cause,
|
|
34
|
-
retryable: true,
|
|
35
|
-
})));
|
|
36
|
-
return {
|
|
37
|
-
ctor,
|
|
38
|
-
metadata: {
|
|
39
|
-
pluginId,
|
|
40
|
-
version: "unknown", // Will be resolved from registry
|
|
41
|
-
description: "Loaded from remote",
|
|
42
|
-
type: "unknown",
|
|
43
|
-
},
|
|
44
|
-
};
|
|
45
|
-
});
|
|
46
|
-
},
|
|
47
|
-
});
|
|
48
|
-
return {
|
|
49
|
-
getCachedConstructor: (cacheKey) => cache.get(cacheKey),
|
|
50
|
-
invalidate: (cacheKey) => cache.invalidate(cacheKey),
|
|
51
|
-
};
|
|
52
|
-
}));
|
|
53
|
-
}
|
|
54
|
-
export const PluginCacheServiceTag = PluginCacheService;
|
|
55
|
-
export const PluginCacheServiceLive = PluginCacheService.Live;
|
package/dist/source.d.ts
DELETED
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
import { z } from "zod";
|
|
2
|
-
import type { Config, Input, Output, Plugin } from "./plugin";
|
|
3
|
-
/**
|
|
4
|
-
* Zod schema for the Author interface
|
|
5
|
-
*/
|
|
6
|
-
export declare const authorSchema: z.ZodObject<{
|
|
7
|
-
id: z.ZodOptional<z.ZodString>;
|
|
8
|
-
username: z.ZodOptional<z.ZodString>;
|
|
9
|
-
displayName: z.ZodOptional<z.ZodString>;
|
|
10
|
-
url: z.ZodOptional<z.ZodString>;
|
|
11
|
-
}, z.core.$strip>;
|
|
12
|
-
/**
|
|
13
|
-
* Zod schema for PluginSourceItem - defines the structure that plugins must return
|
|
14
|
-
*/
|
|
15
|
-
export declare const pluginSourceItemSchema: z.ZodObject<{
|
|
16
|
-
externalId: z.ZodString;
|
|
17
|
-
content: z.ZodString;
|
|
18
|
-
contentType: z.ZodOptional<z.ZodString>;
|
|
19
|
-
createdAt: z.ZodOptional<z.ZodString>;
|
|
20
|
-
url: z.ZodOptional<z.ZodString>;
|
|
21
|
-
authors: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
22
|
-
id: z.ZodOptional<z.ZodString>;
|
|
23
|
-
username: z.ZodOptional<z.ZodString>;
|
|
24
|
-
displayName: z.ZodOptional<z.ZodString>;
|
|
25
|
-
url: z.ZodOptional<z.ZodString>;
|
|
26
|
-
}, z.core.$strip>>>;
|
|
27
|
-
raw: z.ZodUnknown;
|
|
28
|
-
}, z.core.$strip>;
|
|
29
|
-
/**
|
|
30
|
-
* Standard content types supported by the system.
|
|
31
|
-
* Plugins can extend this with custom types.
|
|
32
|
-
*/
|
|
33
|
-
export declare const ContentType: {
|
|
34
|
-
readonly POST: "post";
|
|
35
|
-
readonly ARTICLE: "article";
|
|
36
|
-
readonly VIDEO: "video";
|
|
37
|
-
readonly PODCAST: "podcast";
|
|
38
|
-
readonly WEBSITE: "website";
|
|
39
|
-
readonly FEED: "feed";
|
|
40
|
-
readonly DATABASE_ENTRY: "database-entry";
|
|
41
|
-
readonly UNKNOWN: "unknown";
|
|
42
|
-
};
|
|
43
|
-
export type ContentType = (typeof ContentType)[keyof typeof ContentType];
|
|
44
|
-
/**
|
|
45
|
-
* Represents a single author - derived from the authorSchema
|
|
46
|
-
*/
|
|
47
|
-
export type Author = z.infer<typeof authorSchema>;
|
|
48
|
-
/**
|
|
49
|
-
* Base PluginSourceItem type derived from schema (with unknown raw type)
|
|
50
|
-
*/
|
|
51
|
-
export type BasePluginSourceItem = z.infer<typeof pluginSourceItemSchema>;
|
|
52
|
-
/**
|
|
53
|
-
* This is the data structure a plugin is responsible for creating.
|
|
54
|
-
* It's generic over the raw data type.
|
|
55
|
-
*/
|
|
56
|
-
export interface PluginSourceItem<TRaw = Record<string, any>> extends Omit<BasePluginSourceItem, "raw"> {
|
|
57
|
-
raw: TRaw;
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* This is the final, canonical data structure used within the system.
|
|
61
|
-
* It extends PluginSourceItem with system-generated fields.
|
|
62
|
-
*/
|
|
63
|
-
export interface SourceItem<TRaw = Record<string, any>> extends PluginSourceItem<TRaw> {
|
|
64
|
-
id: string;
|
|
65
|
-
createdAt: string;
|
|
66
|
-
metadata: {
|
|
67
|
-
sourcePlugin: string;
|
|
68
|
-
workflowId: string;
|
|
69
|
-
runId: string;
|
|
70
|
-
[key: string]: any;
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Defines the progress of a job submitted to an external asynchronous service (e.g., Masa).
|
|
75
|
-
*/
|
|
76
|
-
export interface AsyncJobProgress {
|
|
77
|
-
workflowId: string;
|
|
78
|
-
status: "submitted" | "pending" | "processing" | "done" | "error" | "timeout";
|
|
79
|
-
submittedAt: string;
|
|
80
|
-
lastCheckedAt?: string;
|
|
81
|
-
errorMessage?: string;
|
|
82
|
-
}
|
|
83
|
-
export declare const AsyncJobProgressSchema: z.ZodObject<{
|
|
84
|
-
workflowId: z.ZodString;
|
|
85
|
-
status: z.ZodEnum<{
|
|
86
|
-
error: "error";
|
|
87
|
-
timeout: "timeout";
|
|
88
|
-
submitted: "submitted";
|
|
89
|
-
pending: "pending";
|
|
90
|
-
processing: "processing";
|
|
91
|
-
done: "done";
|
|
92
|
-
}>;
|
|
93
|
-
submittedAt: z.ZodString;
|
|
94
|
-
lastCheckedAt: z.ZodOptional<z.ZodString>;
|
|
95
|
-
errorMessage: z.ZodOptional<z.ZodString>;
|
|
96
|
-
}, z.core.$strip>;
|
|
97
|
-
/**
|
|
98
|
-
* Generic platform-specific state for managing resumable searches and long-running jobs.
|
|
99
|
-
*/
|
|
100
|
-
export interface PlatformState {
|
|
101
|
-
latestProcessedId?: string | number | Record<string, any>;
|
|
102
|
-
currentAsyncJob?: AsyncJobProgress | null;
|
|
103
|
-
[key: string]: any;
|
|
104
|
-
}
|
|
105
|
-
export declare const PlatformStateSchema: z.ZodObject<{
|
|
106
|
-
latestProcessedId: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodRecord<z.ZodString, z.ZodAny>]>>;
|
|
107
|
-
currentAsyncJob: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
108
|
-
workflowId: z.ZodString;
|
|
109
|
-
status: z.ZodEnum<{
|
|
110
|
-
error: "error";
|
|
111
|
-
timeout: "timeout";
|
|
112
|
-
submitted: "submitted";
|
|
113
|
-
pending: "pending";
|
|
114
|
-
processing: "processing";
|
|
115
|
-
done: "done";
|
|
116
|
-
}>;
|
|
117
|
-
submittedAt: z.ZodString;
|
|
118
|
-
lastCheckedAt: z.ZodOptional<z.ZodString>;
|
|
119
|
-
errorMessage: z.ZodOptional<z.ZodString>;
|
|
120
|
-
}, z.core.$strip>>>;
|
|
121
|
-
}, z.core.$catchall<z.ZodAny>>;
|
|
122
|
-
/**
|
|
123
|
-
* State passed between search calls to enable resumption.
|
|
124
|
-
* TData is expected to be an object conforming to PlatformState or a derivative.
|
|
125
|
-
*/
|
|
126
|
-
export interface LastProcessedState<TData extends PlatformState = PlatformState> {
|
|
127
|
-
data: TData;
|
|
128
|
-
}
|
|
129
|
-
export type SourceConfig<V extends z.ZodTypeAny = z.ZodRecord<z.ZodString, z.ZodUnknown>, S extends z.ZodTypeAny = z.ZodRecord<z.ZodString, z.ZodUnknown>> = Config<V, S>;
|
|
130
|
-
export interface SourceInput<TSearchOptions extends z.ZodTypeAny = z.ZodTypeAny> extends Input<z.ZodAny> {
|
|
131
|
-
searchOptions: TSearchOptions;
|
|
132
|
-
lastProcessedState?: LastProcessedState<PlatformState> | null;
|
|
133
|
-
}
|
|
134
|
-
export interface PluginSourceInput<TSearchOptions = Record<string, unknown>> extends Input<z.ZodAny> {
|
|
135
|
-
searchOptions: TSearchOptions;
|
|
136
|
-
lastProcessedState?: LastProcessedState<PlatformState> | null;
|
|
137
|
-
}
|
|
138
|
-
export interface PluginSourceOutputData<TItem extends PluginSourceItem = PluginSourceItem> {
|
|
139
|
-
items: TItem[];
|
|
140
|
-
nextLastProcessedState?: PlatformState | null;
|
|
141
|
-
}
|
|
142
|
-
export interface PluginSourceOutput<TItem extends PluginSourceItem = PluginSourceItem> extends Output<z.ZodAny> {
|
|
143
|
-
success: boolean;
|
|
144
|
-
data?: PluginSourceOutputData<TItem>;
|
|
145
|
-
errors?: Array<{
|
|
146
|
-
message: string;
|
|
147
|
-
details?: Record<string, unknown>;
|
|
148
|
-
stack?: string;
|
|
149
|
-
}>;
|
|
150
|
-
}
|
|
151
|
-
export interface SourceOutputData {
|
|
152
|
-
items: SourceItem[];
|
|
153
|
-
nextLastProcessedState?: PlatformState | null;
|
|
154
|
-
}
|
|
155
|
-
export interface SourceOutput extends Output<z.ZodAny> {
|
|
156
|
-
success: boolean;
|
|
157
|
-
data?: SourceOutputData;
|
|
158
|
-
errors?: Array<{
|
|
159
|
-
message: string;
|
|
160
|
-
details?: Record<string, unknown>;
|
|
161
|
-
stack?: string;
|
|
162
|
-
}>;
|
|
163
|
-
}
|
|
164
|
-
export interface SourcePlugin<TInputSchema extends z.ZodTypeAny = z.ZodTypeAny, TOutputSchema extends z.ZodTypeAny = z.ZodTypeAny, TConfigSchema extends z.ZodTypeAny = z.ZodTypeAny> extends Plugin<TInputSchema, TOutputSchema, TConfigSchema> {
|
|
165
|
-
readonly type: "source";
|
|
166
|
-
}
|
|
167
|
-
export declare const createSourceInputSchema: <TSearchOptions extends z.ZodTypeAny, TState extends z.ZodTypeAny>(searchOptionsSchema: TSearchOptions, stateSchema: TState) => z.ZodObject<{
|
|
168
|
-
searchOptions: TSearchOptions;
|
|
169
|
-
lastProcessedState: z.ZodNullable<z.ZodOptional<z.ZodObject<{
|
|
170
|
-
data: z.ZodNullable<z.ZodOptional<TState>>;
|
|
171
|
-
}, z.core.$strip>>>;
|
|
172
|
-
}, z.core.$strip>;
|
|
173
|
-
export declare const createSourceOutputSchema: <TItem extends z.ZodTypeAny, TState extends z.ZodTypeAny>(itemData: TItem, stateSchema: TState) => z.ZodObject<{
|
|
174
|
-
success: z.ZodBoolean;
|
|
175
|
-
data: z.ZodOptional<z.ZodObject<{
|
|
176
|
-
items: z.ZodArray<z.ZodObject<{
|
|
177
|
-
externalId: z.ZodString;
|
|
178
|
-
content: z.ZodString;
|
|
179
|
-
contentType: z.ZodOptional<z.ZodString>;
|
|
180
|
-
createdAt: z.ZodOptional<z.ZodString>;
|
|
181
|
-
url: z.ZodOptional<z.ZodString>;
|
|
182
|
-
authors: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
183
|
-
id: z.ZodOptional<z.ZodString>;
|
|
184
|
-
username: z.ZodOptional<z.ZodString>;
|
|
185
|
-
displayName: z.ZodOptional<z.ZodString>;
|
|
186
|
-
url: z.ZodOptional<z.ZodString>;
|
|
187
|
-
}, z.core.$strip>>>;
|
|
188
|
-
raw: TItem;
|
|
189
|
-
}, z.core.$strip>>;
|
|
190
|
-
nextLastProcessedState: z.ZodNullable<z.ZodOptional<TState>>;
|
|
191
|
-
}, z.core.$strip>>;
|
|
192
|
-
errors: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
193
|
-
message: z.ZodString;
|
|
194
|
-
details: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
195
|
-
stack: z.ZodOptional<z.ZodString>;
|
|
196
|
-
}, z.core.$strip>>>;
|
|
197
|
-
}, z.core.$strip>;
|
|
198
|
-
//# sourceMappingURL=source.d.ts.map
|
package/dist/source.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../src/source.ts"],"names":[],"mappings":"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"}
|