@ultrst-armada/kloks 1.4.3 → 1.4.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.
- package/package.json +8 -20
- package/packages/audio-midi/dist/index.d.ts +23 -14
- package/packages/audio-midi/dist/index.js +170 -45
- package/packages/audio-midi/kloks.manifest.json +8 -8
- package/packages/audio-midi/package.json +1 -1
- package/packages/backend/dist/{WebSocketTransport-CxUzUfwl.d.ts → WebSocketTransport-CHmkJ0tj.d.ts} +109 -2
- package/packages/backend/dist/auth/index.js +6 -6
- package/packages/backend/dist/chunk-5336MTXD.js +597 -0
- package/packages/backend/dist/{chunk-T3NYNBDC.js → chunk-5E6JRFUH.js} +201 -3
- package/packages/backend/dist/{chunk-XTWHEZWS.js → chunk-7B24ZWB3.js} +16 -1
- package/packages/backend/dist/{chunk-DZ4ZGIZM.js → chunk-JXUSBKJ2.js} +91 -654
- package/packages/backend/dist/{chunk-FO6WYLW4.js → chunk-KI3LHMUN.js} +133 -46
- package/packages/backend/dist/{chunk-4ZFXEFOE.js → chunk-MPYASJ5A.js} +2 -87
- package/packages/backend/dist/{chunk-KX3OTBQ3.js → chunk-OZDYAEH4.js} +0 -114
- package/packages/backend/dist/chunk-TY32TUNI.js +376 -0
- package/packages/backend/dist/chunk-VDROUXFT.js +116 -0
- package/packages/backend/dist/chunk-ZDH4XI7W.js +140 -0
- package/packages/backend/dist/client/index.d.ts +2 -3
- package/packages/backend/dist/connectivity/index.d.ts +18 -6
- package/packages/backend/dist/connectivity/index.js +3 -7
- package/packages/backend/dist/index.d.ts +3 -6
- package/packages/backend/dist/index.js +101 -91
- package/packages/backend/dist/krnl-services.d.ts +84 -7
- package/packages/backend/dist/krnl-services.js +40 -12
- package/packages/backend/dist/services/index.d.ts +4 -6
- package/packages/backend/dist/services/index.js +2 -2
- package/packages/backend/dist/srkl/index.js +6 -4
- package/packages/backend/dist/storage/index.js +7 -7
- package/packages/backend/dist/workspace/index.js +2 -2
- package/packages/backend/kloks.manifest.json +47 -45
- package/packages/backend/package.json +3 -8
- package/packages/client/package.json +1 -1
- package/packages/contracts/dist/index.js +5 -10
- package/packages/contracts/package.json +1 -1
- package/packages/functions/dist/index.d.ts +12 -1
- package/packages/functions/dist/index.js +132 -24
- package/packages/functions/package.json +1 -1
- package/packages/orchestrations/dist/index.d.ts +33 -31
- package/packages/orchestrations/dist/index.js +81 -203
- package/packages/orchestrations/kloks.manifest.json +10 -2
- package/packages/orchestrations/package.json +2 -2
- package/packages/services/dist/index.d.ts +51 -1
- package/packages/services/dist/index.js +234 -36
- package/packages/services/kloks.manifest.json +69 -33
- package/packages/services/package.json +1 -1
- package/packages/state-graph/dist/{BaseGraph-BvkSYOTw.d.ts → BaseGraph-Bd5F1NMP.d.ts} +1 -1
- package/packages/state-graph/dist/{BaseNode-DTcd3K1B.d.ts → BaseNode-DKpGXMy8.d.ts} +6 -0
- package/packages/state-graph/dist/{CompatibilityMatrix-Dj-tCWUA.d.ts → CompatibilityMatrix-TiEJ3j3_.d.ts} +1 -1
- package/packages/state-graph/dist/domain/index.d.ts +3 -3
- package/packages/state-graph/dist/domain/index.js +0 -1
- package/packages/state-graph/dist/index.d.ts +40 -8
- package/packages/state-graph/dist/index.js +214 -65
- package/packages/state-graph/dist/rules/index.d.ts +3 -3
- package/packages/state-graph/dist/rules/index.js +0 -1
- package/packages/state-graph/dist/spatial/index.d.ts +4 -4
- package/packages/state-graph/dist/spatial/index.js +0 -1
- package/packages/state-graph/dist/state/index.js +1 -3
- package/packages/state-graph/dist/store/index.d.ts +4 -4
- package/packages/state-graph/dist/store/index.js +0 -1
- package/packages/state-graph/dist/{types-VDoc4FIc.d.ts → types-D5kQSa65.d.ts} +2 -2
- package/packages/state-graph/kloks.manifest.json +26 -10
- package/packages/state-graph/package.json +2 -8
- package/packages/backend/dist/IdempotencyManager-B5MjK871.d.ts +0 -16
- package/packages/backend/dist/chunk-25Y7AVTP.js +0 -55
- package/packages/backend/dist/chunk-3EPY34R6.js +0 -67
- package/packages/backend/dist/chunk-7KNGX522.js +0 -220
- package/packages/backend/dist/chunk-FZKBTF34.js +0 -15
- package/packages/backend/dist/chunk-QGHDJGYS.js +0 -92
- package/packages/backend/dist/chunk-UPFKBBQI.js +0 -138
- package/packages/backend/dist/chunk-VQEFULWT.js +0 -88
- package/packages/backend/dist/execution/index.d.ts +0 -124
- package/packages/backend/dist/execution/index.js +0 -20
- package/packages/backend/dist/types-BERZJ93O.d.ts +0 -110
- package/packages/state-graph/dist/chunk-3RG5ZIWI.js +0 -10
- package/packages/state-graph/dist/chunk-Q5I42UX7.js +0 -0
- package/packages/state-graph/dist/chunk-ZTHBPV24.js +0 -267
- package/packages/state-graph/dist/execution/index.d.ts +0 -152
- package/packages/state-graph/dist/execution/index.js +0 -16
- /package/packages/state-graph/dist/{chunk-SHIBCPGQ.js → chunk-EW4ACSZB.js} +0 -0
|
@@ -13,8 +13,14 @@
|
|
|
13
13
|
"export": "StateLifecycleServiceFacade",
|
|
14
14
|
"facade": "StateLifecycleServiceFacade"
|
|
15
15
|
},
|
|
16
|
-
"modes": [
|
|
17
|
-
|
|
16
|
+
"modes": [
|
|
17
|
+
"backend"
|
|
18
|
+
],
|
|
19
|
+
"targets": {
|
|
20
|
+
"backend": [
|
|
21
|
+
"BackendFacade.services"
|
|
22
|
+
]
|
|
23
|
+
}
|
|
18
24
|
},
|
|
19
25
|
{
|
|
20
26
|
"id": "node-graph",
|
|
@@ -26,15 +32,25 @@
|
|
|
26
32
|
"export": "NodeGraphEngineServiceFacade",
|
|
27
33
|
"facade": "NodeGraphEngineServiceFacade"
|
|
28
34
|
},
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
"modes": ["backend", "fullstack"],
|
|
35
|
+
"modes": [
|
|
36
|
+
"backend",
|
|
37
|
+
"fullstack"
|
|
38
|
+
],
|
|
34
39
|
"targets": {
|
|
35
|
-
"backend": [
|
|
36
|
-
|
|
37
|
-
|
|
40
|
+
"backend": [
|
|
41
|
+
"BackendFacade.services"
|
|
42
|
+
],
|
|
43
|
+
"frontend": [
|
|
44
|
+
"App.main-content"
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
"defaultFrontend": {
|
|
48
|
+
"component": "FrnlEditableNodeGraph",
|
|
49
|
+
"package": "@ultrst-armada/floks/canvas-ui",
|
|
50
|
+
"export": "FrnlEditableNodeGraph",
|
|
51
|
+
"relationship": "recommended"
|
|
52
|
+
},
|
|
53
|
+
"dependencies": []
|
|
38
54
|
}
|
|
39
55
|
]
|
|
40
56
|
}
|
|
@@ -23,11 +23,6 @@
|
|
|
23
23
|
"types": "./dist/state/index.d.ts",
|
|
24
24
|
"default": "./dist/state/index.js"
|
|
25
25
|
},
|
|
26
|
-
"./execution": {
|
|
27
|
-
"import": "./dist/execution/index.js",
|
|
28
|
-
"types": "./dist/execution/index.d.ts",
|
|
29
|
-
"default": "./dist/execution/index.js"
|
|
30
|
-
},
|
|
31
26
|
"./domain": {
|
|
32
27
|
"import": "./dist/domain/index.js",
|
|
33
28
|
"types": "./dist/domain/index.d.ts",
|
|
@@ -50,13 +45,12 @@
|
|
|
50
45
|
}
|
|
51
46
|
},
|
|
52
47
|
"scripts": {
|
|
53
|
-
"build": "tsup src/index.ts src/state/index.ts src/
|
|
48
|
+
"build": "tsup src/index.ts src/state/index.ts src/domain/index.ts src/rules/index.ts src/spatial/index.ts src/store/index.ts --format esm --dts --clean --external zustand --external react --external ws",
|
|
54
49
|
"typecheck": "tsc --noEmit",
|
|
55
50
|
"clean": "rm -rf dist"
|
|
56
51
|
},
|
|
57
52
|
"dependencies": {
|
|
58
53
|
"@kloks/functions": "workspace:*",
|
|
59
|
-
"bullmq": "^6.3.8",
|
|
60
54
|
"zustand": "^5.0.15"
|
|
61
55
|
},
|
|
62
56
|
"peerDependencies": {
|
|
@@ -68,6 +62,6 @@
|
|
|
68
62
|
}
|
|
69
63
|
},
|
|
70
64
|
"devDependencies": {
|
|
71
|
-
"@ultrst-armada/krnl": "^1.0.
|
|
65
|
+
"@ultrst-armada/krnl": "^1.0.3"
|
|
72
66
|
}
|
|
73
67
|
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file IdempotencyManager.ts
|
|
3
|
-
* @description In-flight mutation deduplication, concurrent attachment, and completed result caching.
|
|
4
|
-
*/
|
|
5
|
-
declare class IdempotencyManager {
|
|
6
|
-
private inFlight;
|
|
7
|
-
private completedCache;
|
|
8
|
-
private ttlMs;
|
|
9
|
-
constructor(ttlMs?: number);
|
|
10
|
-
executeIdempotent<T>(idempotencyKey: string, operation: () => Promise<T>): Promise<T>;
|
|
11
|
-
has(idempotencyKey: string): boolean;
|
|
12
|
-
prune(): void;
|
|
13
|
-
clear(): void;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export { IdempotencyManager as I };
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
// src/auth/SessionManager.ts
|
|
2
|
-
var SessionManager = class {
|
|
3
|
-
ttl;
|
|
4
|
-
constructor(ttlMs = 864e5) {
|
|
5
|
-
this.ttl = ttlMs;
|
|
6
|
-
}
|
|
7
|
-
generateToken(userId) {
|
|
8
|
-
return `sess::${userId}::${Date.now()}::${Math.random().toString(36).substring(2, 9)}`;
|
|
9
|
-
}
|
|
10
|
-
createSession(userId, role) {
|
|
11
|
-
return {
|
|
12
|
-
token: this.generateToken(userId),
|
|
13
|
-
userId,
|
|
14
|
-
role,
|
|
15
|
-
expiresAt: Date.now() + this.ttl
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
isValid(session) {
|
|
19
|
-
return Date.now() < session.expiresAt;
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
// src/auth/RateLimiter.ts
|
|
24
|
-
var RateLimiter = class {
|
|
25
|
-
attempts = /* @__PURE__ */ new Map();
|
|
26
|
-
windowMs;
|
|
27
|
-
maxUser;
|
|
28
|
-
maxAdmin;
|
|
29
|
-
constructor(windowMs = 9e5, maxUser = 5, maxAdmin = 3) {
|
|
30
|
-
this.windowMs = windowMs;
|
|
31
|
-
this.maxUser = maxUser;
|
|
32
|
-
this.maxAdmin = maxAdmin;
|
|
33
|
-
}
|
|
34
|
-
check(identifier, isAdminAttempt = false) {
|
|
35
|
-
const now = Date.now();
|
|
36
|
-
let record = this.attempts.get(identifier);
|
|
37
|
-
if (!record || now - record.windowStart > this.windowMs) {
|
|
38
|
-
record = { count: 0, windowStart: now };
|
|
39
|
-
this.attempts.set(identifier, record);
|
|
40
|
-
}
|
|
41
|
-
record.count++;
|
|
42
|
-
const limit = isAdminAttempt ? this.maxAdmin : this.maxUser;
|
|
43
|
-
if (record.count > limit) {
|
|
44
|
-
throw new Error("Too many requests. Please try again later.");
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
reset(identifier) {
|
|
48
|
-
this.attempts.delete(identifier);
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
export {
|
|
53
|
-
SessionManager,
|
|
54
|
-
RateLimiter
|
|
55
|
-
};
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
// src/connectivity/IdempotencyManager.ts
|
|
2
|
-
var IdempotencyManager = class {
|
|
3
|
-
inFlight = /* @__PURE__ */ new Map();
|
|
4
|
-
completedCache = /* @__PURE__ */ new Map();
|
|
5
|
-
ttlMs;
|
|
6
|
-
constructor(ttlMs = 6e4) {
|
|
7
|
-
this.ttlMs = ttlMs;
|
|
8
|
-
}
|
|
9
|
-
async executeIdempotent(idempotencyKey, operation) {
|
|
10
|
-
const cached = this.completedCache.get(idempotencyKey);
|
|
11
|
-
if (cached) {
|
|
12
|
-
if (Date.now() - cached.timestamp < this.ttlMs) {
|
|
13
|
-
if (cached.status === "completed") {
|
|
14
|
-
return cached.result;
|
|
15
|
-
}
|
|
16
|
-
throw new Error(cached.error || "[IdempotencyManager] Previous execution failed.");
|
|
17
|
-
} else {
|
|
18
|
-
this.completedCache.delete(idempotencyKey);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
const existingFlight = this.inFlight.get(idempotencyKey);
|
|
22
|
-
if (existingFlight) {
|
|
23
|
-
return await existingFlight;
|
|
24
|
-
}
|
|
25
|
-
const executionPromise = (async () => {
|
|
26
|
-
try {
|
|
27
|
-
const result = await operation();
|
|
28
|
-
this.completedCache.set(idempotencyKey, {
|
|
29
|
-
status: "completed",
|
|
30
|
-
result,
|
|
31
|
-
timestamp: Date.now()
|
|
32
|
-
});
|
|
33
|
-
return result;
|
|
34
|
-
} catch (err) {
|
|
35
|
-
this.completedCache.set(idempotencyKey, {
|
|
36
|
-
status: "failed",
|
|
37
|
-
error: err?.message || String(err),
|
|
38
|
-
timestamp: Date.now()
|
|
39
|
-
});
|
|
40
|
-
throw err;
|
|
41
|
-
} finally {
|
|
42
|
-
this.inFlight.delete(idempotencyKey);
|
|
43
|
-
}
|
|
44
|
-
})();
|
|
45
|
-
this.inFlight.set(idempotencyKey, executionPromise);
|
|
46
|
-
return await executionPromise;
|
|
47
|
-
}
|
|
48
|
-
has(idempotencyKey) {
|
|
49
|
-
return this.inFlight.has(idempotencyKey) || this.completedCache.has(idempotencyKey);
|
|
50
|
-
}
|
|
51
|
-
prune() {
|
|
52
|
-
const now = Date.now();
|
|
53
|
-
for (const [key, entry] of this.completedCache.entries()) {
|
|
54
|
-
if (now - entry.timestamp > this.ttlMs) {
|
|
55
|
-
this.completedCache.delete(key);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
clear() {
|
|
60
|
-
this.inFlight.clear();
|
|
61
|
-
this.completedCache.clear();
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
export {
|
|
66
|
-
IdempotencyManager
|
|
67
|
-
};
|
|
@@ -1,220 +0,0 @@
|
|
|
1
|
-
// ../../node_modules/.pnpm/@ultrst-armada+krnl@1.0.2/node_modules/@ultrst-armada/krnl/packages/core/dist/index.js
|
|
2
|
-
var ServiceStateStore = class {
|
|
3
|
-
state;
|
|
4
|
-
listeners = /* @__PURE__ */ new Set();
|
|
5
|
-
constructor(initialState) {
|
|
6
|
-
this.state = { ...initialState };
|
|
7
|
-
}
|
|
8
|
-
getState() {
|
|
9
|
-
return Object.freeze({ ...this.state });
|
|
10
|
-
}
|
|
11
|
-
setState(mutation) {
|
|
12
|
-
this.state = { ...this.state, ...mutation };
|
|
13
|
-
const snapshot = this.getState();
|
|
14
|
-
for (const listener of this.listeners) {
|
|
15
|
-
listener(snapshot, mutation);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
subscribe(listener) {
|
|
19
|
-
this.listeners.add(listener);
|
|
20
|
-
return () => {
|
|
21
|
-
this.listeners.delete(listener);
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
reset(newState) {
|
|
25
|
-
this.state = { ...newState || {} };
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
var ServiceEventBus = class {
|
|
29
|
-
handlers = /* @__PURE__ */ new Map();
|
|
30
|
-
on(event, handler) {
|
|
31
|
-
if (!this.handlers.has(event)) {
|
|
32
|
-
this.handlers.set(event, /* @__PURE__ */ new Set());
|
|
33
|
-
}
|
|
34
|
-
const set = this.handlers.get(event);
|
|
35
|
-
set.add(handler);
|
|
36
|
-
return () => {
|
|
37
|
-
set.delete(handler);
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
emit(event, payload) {
|
|
41
|
-
const set = this.handlers.get(event);
|
|
42
|
-
if (!set) return;
|
|
43
|
-
for (const handler of Array.from(set)) {
|
|
44
|
-
try {
|
|
45
|
-
handler(payload);
|
|
46
|
-
} catch (err) {
|
|
47
|
-
console.error(`[ServiceEventBus] Handler error for '${event}':`, err);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
clear() {
|
|
52
|
-
this.handlers.clear();
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
var LifecycleManager = class {
|
|
56
|
-
status = "uninitialized";
|
|
57
|
-
getStatus() {
|
|
58
|
-
return this.status;
|
|
59
|
-
}
|
|
60
|
-
setStatus(next) {
|
|
61
|
-
this.status = next;
|
|
62
|
-
}
|
|
63
|
-
assertRunning(serviceName) {
|
|
64
|
-
if (this.status !== "running") {
|
|
65
|
-
throw new Error(`[Service:${serviceName}] Cannot invoke operation while status is '${this.status}' (expected 'running').`);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
var ServiceInstance = class {
|
|
70
|
-
constructor(definition) {
|
|
71
|
-
this.definition = definition;
|
|
72
|
-
this.id = definition.id;
|
|
73
|
-
this.name = definition.name;
|
|
74
|
-
this.version = definition.version;
|
|
75
|
-
this.lifecycle = new LifecycleManager();
|
|
76
|
-
this.eventBus = new ServiceEventBus();
|
|
77
|
-
if (definition.state?.initial) {
|
|
78
|
-
this.stateStore = new ServiceStateStore(definition.state.initial);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
definition;
|
|
82
|
-
id;
|
|
83
|
-
name;
|
|
84
|
-
version;
|
|
85
|
-
stateStore;
|
|
86
|
-
eventBus;
|
|
87
|
-
lifecycle;
|
|
88
|
-
getDefinition() {
|
|
89
|
-
return this.definition;
|
|
90
|
-
}
|
|
91
|
-
async start() {
|
|
92
|
-
this.lifecycle.setStatus("starting");
|
|
93
|
-
if (this.definition.lifecycle?.onInit) {
|
|
94
|
-
await this.definition.lifecycle.onInit();
|
|
95
|
-
}
|
|
96
|
-
if (this.definition.lifecycle?.onStart) {
|
|
97
|
-
await this.definition.lifecycle.onStart();
|
|
98
|
-
}
|
|
99
|
-
this.lifecycle.setStatus("running");
|
|
100
|
-
}
|
|
101
|
-
async stop() {
|
|
102
|
-
this.lifecycle.setStatus("stopping");
|
|
103
|
-
if (this.definition.lifecycle?.onStop) {
|
|
104
|
-
await this.definition.lifecycle.onStop();
|
|
105
|
-
}
|
|
106
|
-
if (this.definition.lifecycle?.onDispose) {
|
|
107
|
-
await this.definition.lifecycle.onDispose();
|
|
108
|
-
}
|
|
109
|
-
this.lifecycle.setStatus("stopped");
|
|
110
|
-
}
|
|
111
|
-
async call(op, input, ctx = {}) {
|
|
112
|
-
this.lifecycle.assertRunning(this.name);
|
|
113
|
-
const operation = this.definition.operations[op];
|
|
114
|
-
if (!operation) {
|
|
115
|
-
throw new Error(`[Service:${this.name}] Operation '${op}' not found.`);
|
|
116
|
-
}
|
|
117
|
-
return await operation.handler(input, ctx);
|
|
118
|
-
}
|
|
119
|
-
getState() {
|
|
120
|
-
if (!this.stateStore) {
|
|
121
|
-
return Object.freeze({});
|
|
122
|
-
}
|
|
123
|
-
return this.stateStore.getState();
|
|
124
|
-
}
|
|
125
|
-
setState(mutation) {
|
|
126
|
-
if (!this.stateStore) {
|
|
127
|
-
this.stateStore = new ServiceStateStore(mutation);
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
this.stateStore.setState(mutation);
|
|
131
|
-
}
|
|
132
|
-
on(event, handler) {
|
|
133
|
-
return this.eventBus.on(event, handler);
|
|
134
|
-
}
|
|
135
|
-
emit(event, payload) {
|
|
136
|
-
this.eventBus.emit(event, payload);
|
|
137
|
-
}
|
|
138
|
-
};
|
|
139
|
-
var ServiceProxy = class {
|
|
140
|
-
constructor(definition, adapter, endpoint) {
|
|
141
|
-
this.definition = definition;
|
|
142
|
-
this.adapter = adapter;
|
|
143
|
-
this.endpoint = endpoint;
|
|
144
|
-
this.id = definition.id;
|
|
145
|
-
this.name = definition.name;
|
|
146
|
-
this.version = definition.version;
|
|
147
|
-
this.stateCache = definition.state?.initial || {};
|
|
148
|
-
}
|
|
149
|
-
definition;
|
|
150
|
-
adapter;
|
|
151
|
-
endpoint;
|
|
152
|
-
id;
|
|
153
|
-
name;
|
|
154
|
-
version;
|
|
155
|
-
stateCache;
|
|
156
|
-
eventHandlers = /* @__PURE__ */ new Map();
|
|
157
|
-
getDefinition() {
|
|
158
|
-
return this.definition;
|
|
159
|
-
}
|
|
160
|
-
async start() {
|
|
161
|
-
}
|
|
162
|
-
async stop() {
|
|
163
|
-
}
|
|
164
|
-
async call(op, input, ctx = {}) {
|
|
165
|
-
if (!this.adapter.send) {
|
|
166
|
-
throw new Error(`[ServiceProxy:${this.name}] Adapter does not support send().`);
|
|
167
|
-
}
|
|
168
|
-
const envelope = {
|
|
169
|
-
id: `req-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`,
|
|
170
|
-
type: "request",
|
|
171
|
-
operation: op,
|
|
172
|
-
payload: input,
|
|
173
|
-
timestamp: Date.now()
|
|
174
|
-
};
|
|
175
|
-
const response = await this.adapter.send(this.endpoint, envelope);
|
|
176
|
-
if (response.error) {
|
|
177
|
-
throw new Error(`[ServiceProxy:${this.name}] Remote error: ${response.error}`);
|
|
178
|
-
}
|
|
179
|
-
return response.payload;
|
|
180
|
-
}
|
|
181
|
-
getState() {
|
|
182
|
-
return Object.freeze({ ...this.stateCache });
|
|
183
|
-
}
|
|
184
|
-
setState(mutation) {
|
|
185
|
-
this.stateCache = { ...this.stateCache, ...mutation };
|
|
186
|
-
}
|
|
187
|
-
on(event, handler) {
|
|
188
|
-
if (!this.eventHandlers.has(event)) {
|
|
189
|
-
this.eventHandlers.set(event, /* @__PURE__ */ new Set());
|
|
190
|
-
}
|
|
191
|
-
const handlers = this.eventHandlers.get(event);
|
|
192
|
-
handlers.add(handler);
|
|
193
|
-
return () => {
|
|
194
|
-
handlers.delete(handler);
|
|
195
|
-
};
|
|
196
|
-
}
|
|
197
|
-
emit(event, payload) {
|
|
198
|
-
const handlers = this.eventHandlers.get(event);
|
|
199
|
-
if (handlers) {
|
|
200
|
-
for (const handler of Array.from(handlers)) {
|
|
201
|
-
handler(payload);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
};
|
|
206
|
-
function createServiceDefinition(definition) {
|
|
207
|
-
return definition;
|
|
208
|
-
}
|
|
209
|
-
function createService(definition) {
|
|
210
|
-
return new ServiceInstance(definition);
|
|
211
|
-
}
|
|
212
|
-
function createServiceProxy(definition, adapter, endpoint) {
|
|
213
|
-
return new ServiceProxy(definition, adapter, endpoint);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
export {
|
|
217
|
-
createServiceDefinition,
|
|
218
|
-
createService,
|
|
219
|
-
createServiceProxy
|
|
220
|
-
};
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
// src/workspace/WorkspaceCanonical.ts
|
|
2
|
-
function formatCanonicalWorkspaceFolderName(appName, userName, workspaceName) {
|
|
3
|
-
const safeApp = appName.replace(/[^a-zA-Z0-9]/g, "_").toLowerCase();
|
|
4
|
-
const safeUser = userName.replace(/[^a-zA-Z0-9]/g, "_").toLowerCase();
|
|
5
|
-
const safeWs = workspaceName.replace(/[^a-zA-Z0-9]/g, "_").toLowerCase();
|
|
6
|
-
return `ultrst_${safeApp}_${safeUser}_${safeWs}`;
|
|
7
|
-
}
|
|
8
|
-
function sanitizeWorkspaceName(name) {
|
|
9
|
-
return name.replace(/[^a-zA-Z0-9-_\s]/g, "").trim();
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export {
|
|
13
|
-
formatCanonicalWorkspaceFolderName,
|
|
14
|
-
sanitizeWorkspaceName
|
|
15
|
-
};
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
IdempotencyManager
|
|
3
|
-
} from "./chunk-3EPY34R6.js";
|
|
4
|
-
|
|
5
|
-
// src/execution/BackendFacade.ts
|
|
6
|
-
var ExecutableBackendFacade = class {
|
|
7
|
-
constructor(name, idempotency) {
|
|
8
|
-
this.name = name;
|
|
9
|
-
this.idempotency = idempotency || new IdempotencyManager();
|
|
10
|
-
}
|
|
11
|
-
name;
|
|
12
|
-
services = /* @__PURE__ */ new Map();
|
|
13
|
-
idempotency;
|
|
14
|
-
registerService(service) {
|
|
15
|
-
this.services.set(service.name, service);
|
|
16
|
-
return this;
|
|
17
|
-
}
|
|
18
|
-
async executeCommand(command, context) {
|
|
19
|
-
const startTime = Date.now();
|
|
20
|
-
if (!context || !context.isWorkerContext) {
|
|
21
|
-
return {
|
|
22
|
-
correlationId: command.correlationId,
|
|
23
|
-
status: "FAILED",
|
|
24
|
-
error: "[BackendFacade] DIRECT_COMPONENT -> BACKEND_FACADE is strictly FORBIDDEN. Access allowed for WORKER_ONLY.",
|
|
25
|
-
executionTimestamp: startTime
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
const runCore = async () => {
|
|
29
|
-
try {
|
|
30
|
-
const parts = command.type.split(".");
|
|
31
|
-
if (parts.length < 2) {
|
|
32
|
-
throw new Error(
|
|
33
|
-
`[BackendFacade] Invalid command type "${command.type}". Expected "service.operation".`
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
const [serviceName, operationName] = parts;
|
|
37
|
-
const service = this.services.get(serviceName);
|
|
38
|
-
if (!service) {
|
|
39
|
-
throw new Error(`[BackendFacade] Service "${serviceName}" not registered.`);
|
|
40
|
-
}
|
|
41
|
-
const data = await service.execute(operationName, command.payload);
|
|
42
|
-
return {
|
|
43
|
-
correlationId: command.correlationId,
|
|
44
|
-
status: "COMPLETED",
|
|
45
|
-
data,
|
|
46
|
-
executionTimestamp: Date.now()
|
|
47
|
-
};
|
|
48
|
-
} catch (err) {
|
|
49
|
-
return {
|
|
50
|
-
correlationId: command.correlationId,
|
|
51
|
-
status: "FAILED",
|
|
52
|
-
error: err?.message || String(err),
|
|
53
|
-
executionTimestamp: Date.now()
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
if (command.idempotencyKey) {
|
|
58
|
-
return await this.idempotency.executeIdempotent(command.idempotencyKey, runCore);
|
|
59
|
-
}
|
|
60
|
-
return await runCore();
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
// src/execution/WorkerExecutionBoundary.ts
|
|
65
|
-
var WorkerExecutionBoundary = class {
|
|
66
|
-
constructor(workerId, facade) {
|
|
67
|
-
this.workerId = workerId;
|
|
68
|
-
this.facade = facade;
|
|
69
|
-
}
|
|
70
|
-
workerId;
|
|
71
|
-
facade;
|
|
72
|
-
async processJob(command) {
|
|
73
|
-
const context = {
|
|
74
|
-
isWorkerContext: true,
|
|
75
|
-
workerId: this.workerId,
|
|
76
|
-
timestamp: Date.now()
|
|
77
|
-
};
|
|
78
|
-
return await this.facade.executeCommand(command, context);
|
|
79
|
-
}
|
|
80
|
-
static assertWorkerContext(context) {
|
|
81
|
-
if (!context || !context.isWorkerContext) {
|
|
82
|
-
throw new Error(
|
|
83
|
-
"[WorkerExecutionBoundary] Violation: DIRECT_COMPONENT -> BACKEND_FACADE is forbidden. Only BullMQ Workers may execute backend commands."
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
export {
|
|
90
|
-
ExecutableBackendFacade,
|
|
91
|
-
WorkerExecutionBoundary
|
|
92
|
-
};
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
// src/connectivity/JobScheduler.ts
|
|
2
|
-
var JobScheduler = class {
|
|
3
|
-
jobs = /* @__PURE__ */ new Map();
|
|
4
|
-
handlers = /* @__PURE__ */ new Map();
|
|
5
|
-
sequenceCounters = /* @__PURE__ */ new Map();
|
|
6
|
-
activeCount = 0;
|
|
7
|
-
maxConcurrency;
|
|
8
|
-
paused = false;
|
|
9
|
-
constructor(maxConcurrency = 5) {
|
|
10
|
-
this.maxConcurrency = maxConcurrency;
|
|
11
|
-
}
|
|
12
|
-
registerHandler(type, handler) {
|
|
13
|
-
this.handlers.set(type, handler);
|
|
14
|
-
return this;
|
|
15
|
-
}
|
|
16
|
-
submit(input) {
|
|
17
|
-
const id = input.id || `job-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
|
|
18
|
-
const streamKey = input.sequenceKey || "default";
|
|
19
|
-
const seq = (this.sequenceCounters.get(streamKey) ?? 0) + 1;
|
|
20
|
-
this.sequenceCounters.set(streamKey, seq);
|
|
21
|
-
const job = {
|
|
22
|
-
id,
|
|
23
|
-
type: input.type,
|
|
24
|
-
payload: input.payload,
|
|
25
|
-
priority: input.priority || "NORMAL",
|
|
26
|
-
sequence: seq,
|
|
27
|
-
sequenceKey: streamKey,
|
|
28
|
-
dependencies: input.dependencies || [],
|
|
29
|
-
sessionId: input.sessionId,
|
|
30
|
-
correlationId: input.correlationId,
|
|
31
|
-
state: "PENDING",
|
|
32
|
-
progress: 0,
|
|
33
|
-
createdAt: Date.now(),
|
|
34
|
-
updatedAt: Date.now()
|
|
35
|
-
};
|
|
36
|
-
this.jobs.set(id, job);
|
|
37
|
-
this.checkAndQueue(job);
|
|
38
|
-
this.drainQueue();
|
|
39
|
-
return job;
|
|
40
|
-
}
|
|
41
|
-
checkAndQueue(job) {
|
|
42
|
-
if (job.state !== "PENDING") return false;
|
|
43
|
-
const depsResolved = (job.dependencies || []).every((depId) => {
|
|
44
|
-
const dep = this.jobs.get(depId);
|
|
45
|
-
return dep && dep.state === "COMPLETED";
|
|
46
|
-
});
|
|
47
|
-
if (depsResolved) {
|
|
48
|
-
job.state = "QUEUED";
|
|
49
|
-
job.updatedAt = Date.now();
|
|
50
|
-
return true;
|
|
51
|
-
}
|
|
52
|
-
return false;
|
|
53
|
-
}
|
|
54
|
-
priorityWeight(priority) {
|
|
55
|
-
switch (priority) {
|
|
56
|
-
case "CRITICAL":
|
|
57
|
-
return 4;
|
|
58
|
-
case "HIGH":
|
|
59
|
-
return 3;
|
|
60
|
-
case "NORMAL":
|
|
61
|
-
return 2;
|
|
62
|
-
case "LOW":
|
|
63
|
-
return 1;
|
|
64
|
-
default:
|
|
65
|
-
return 2;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
async drainQueue() {
|
|
69
|
-
if (this.paused || this.activeCount >= this.maxConcurrency) return;
|
|
70
|
-
const queuedJobs = Array.from(this.jobs.values()).filter((j) => j.state === "QUEUED").sort((a, b) => this.priorityWeight(b.priority) - this.priorityWeight(a.priority) || (a.sequence || 0) - (b.sequence || 0));
|
|
71
|
-
for (const job of queuedJobs) {
|
|
72
|
-
if (this.activeCount >= this.maxConcurrency) break;
|
|
73
|
-
this.executeJob(job);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
async executeJob(job) {
|
|
77
|
-
const handler = this.handlers.get(job.type);
|
|
78
|
-
if (!handler) {
|
|
79
|
-
job.state = "FAILED";
|
|
80
|
-
job.error = `[JobScheduler] No registered handler for job type "${job.type}".`;
|
|
81
|
-
job.updatedAt = Date.now();
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
this.activeCount++;
|
|
85
|
-
job.state = "RUNNING";
|
|
86
|
-
job.updatedAt = Date.now();
|
|
87
|
-
const progressCallback = (progress) => {
|
|
88
|
-
job.progress = Math.min(100, Math.max(0, progress));
|
|
89
|
-
job.updatedAt = Date.now();
|
|
90
|
-
};
|
|
91
|
-
try {
|
|
92
|
-
job.result = await handler(job, progressCallback);
|
|
93
|
-
job.state = "COMPLETED";
|
|
94
|
-
job.progress = 100;
|
|
95
|
-
} catch (err) {
|
|
96
|
-
job.state = "FAILED";
|
|
97
|
-
job.error = err?.message || String(err);
|
|
98
|
-
} finally {
|
|
99
|
-
job.updatedAt = Date.now();
|
|
100
|
-
this.activeCount--;
|
|
101
|
-
for (const pendingJob of this.jobs.values()) {
|
|
102
|
-
if (pendingJob.dependencies?.includes(job.id)) {
|
|
103
|
-
this.checkAndQueue(pendingJob);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
this.drainQueue();
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
cancel(jobId) {
|
|
110
|
-
const job = this.jobs.get(jobId);
|
|
111
|
-
if (!job || job.state === "COMPLETED" || job.state === "FAILED") return false;
|
|
112
|
-
job.state = "CANCELLED";
|
|
113
|
-
job.updatedAt = Date.now();
|
|
114
|
-
return true;
|
|
115
|
-
}
|
|
116
|
-
pause() {
|
|
117
|
-
this.paused = true;
|
|
118
|
-
}
|
|
119
|
-
resume() {
|
|
120
|
-
this.paused = false;
|
|
121
|
-
this.drainQueue();
|
|
122
|
-
}
|
|
123
|
-
status(jobId) {
|
|
124
|
-
return this.jobs.get(jobId);
|
|
125
|
-
}
|
|
126
|
-
getAllJobs() {
|
|
127
|
-
return Array.from(this.jobs.values());
|
|
128
|
-
}
|
|
129
|
-
clear() {
|
|
130
|
-
this.jobs.clear();
|
|
131
|
-
this.sequenceCounters.clear();
|
|
132
|
-
this.activeCount = 0;
|
|
133
|
-
}
|
|
134
|
-
};
|
|
135
|
-
|
|
136
|
-
export {
|
|
137
|
-
JobScheduler
|
|
138
|
-
};
|