@lunora/platform-node 0.0.0 → 1.0.0-alpha.2
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/LICENSE.md +111 -0
- package/README.md +11 -37
- package/dist/conformance/index.d.mts +9 -0
- package/dist/conformance/index.d.ts +9 -0
- package/dist/conformance/index.mjs +1 -0
- package/dist/index.d.mts +517 -0
- package/dist/index.d.ts +517 -0
- package/dist/index.mjs +1 -0
- package/dist/packem_shared/createNodeGlobalStore-BvteXWRK.mjs +1 -0
- package/dist/packem_shared/createNodePlatform-BQimmgT9.mjs +1 -0
- package/dist/packem_shared/createNodeQueueHost-CLQ5hOBf.mjs +17 -0
- package/dist/packem_shared/createNodeR2Bucket-Wb8pyi2X.mjs +1 -0
- package/dist/packem_shared/createNodeSchedulerHost-DRjZhuxe.mjs +15 -0
- package/dist/packem_shared/createNodeShardHost-DEHe5Vcm.mjs +1 -0
- package/dist/packem_shared/createNodeShardKvStore-BfKCQTjE.mjs +1 -0
- package/dist/packem_shared/createNodeShardRegistry-0iSMdi9-.mjs +1 -0
- package/dist/packem_shared/createNodeShardState-DdOj9FzJ.mjs +1 -0
- package/dist/packem_shared/createNodeSocketHost-CytowrYN.mjs +2 -0
- package/dist/packem_shared/createNodeWorkflowHost-Dht_jgSv.mjs +1 -0
- package/dist/packem_shared/createNodeWorkflowStore-jlNR6Y3h.mjs +21 -0
- package/dist/packem_shared/to-array-buffer-CP4NlF-y.mjs +1 -0
- package/package.json +59 -7
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LunoraError as d}from"@lunora/errors";import{isWorkflowDefinition as k,workflowDefaultName as N,createWorkflowRunContext as E,workflowBindingName as A}from"@lunora/workflow";import{defineWorkflow as D,createRuntime as O}from"@visulima/workflow";const c="@lunora/platform-node:terminated",T={d:864e5,day:864e5,days:864e5,h:36e5,hour:36e5,hours:36e5,m:6e4,millisecond:1,milliseconds:1,minute:6e4,minutes:6e4,ms:1,s:1e3,second:1e3,seconds:1e3,w:6048e5,week:6048e5,weeks:6048e5,month:2592e6,months:2592e6},b=/^(\d+(?:\.\d+)?)\s*([a-z]+)$/i,I=n=>{if(typeof n=="number"){if(!Number.isFinite(n))throw new d("VALIDATION_ERROR",`@lunora/platform-node: workflow duration must be finite, got ${String(n)}`);return Math.max(0,n)}const r=b.exec(n.trim());if(r===null)throw new d("VALIDATION_ERROR",`@lunora/platform-node: unsupported workflow duration "${n}"`);const a=Number(r[1]),i=(r[2]??"").toLowerCase(),u=T[i];if(u===void 0)throw new d("VALIDATION_ERROR",`@lunora/platform-node: unsupported workflow duration "${n}"`);const l=a*u;if(!Number.isFinite(l))throw new d("VALIDATION_ERROR",`@lunora/platform-node: workflow duration "${n}" overflows`);return Math.max(0,l)},p="@lunora/platform-node:alias",$=n=>({attempt:1,config:{retries:{limit:1}},step:{count:1,name:n}}),_=n=>{switch(n){case"completed":return"complete";case"failed":return"errored";default:return"waiting"}},x=n=>({do:(async(r,a,i,u)=>{const l=typeof a=="function"?a:i;if(typeof l!="function")throw new d("VALIDATION_ERROR",`@lunora/platform-node: step.do("${r}") requires a callback`);return n.step(r,async()=>l($(r)))}),sleep:async(r,a)=>{const i=I(a);i!==0&&await n.sleep(r,i)},sleepUntil:async(r,a)=>{const i=typeof a=="number"?a:a.getTime();if(!Number.isFinite(i))throw new d("VALIDATION_ERROR",`@lunora/platform-node: step.sleepUntil("${r}") needs a valid timestamp`);const u=Math.max(0,i-Date.now());u!==0&&await n.sleep(r,u)},waitForEvent:(async(r,a)=>({payload:await n.waitForEvent(r,a.type,{timeout:a.timeout===void 0?void 0:I(a.timeout)}),type:a.type}))}),q=n=>{const r=Object.entries(n.workflows).map(([e,t])=>{if(!k(t))throw new d("VALIDATION_ERROR",`@lunora/platform-node: "${e}" is not a defineWorkflow result`);return{definition:t,exportName:e,id:t.name??N(e)}}),{store:a}=n,i={...n.env},u=r.map(({definition:e,exportName:t,id:o})=>D({id:o,tags:[t],run:async s=>{const f=x(s),v=E({env:i,event:{instanceId:s.runId,payload:s.payload,timestamp:new Date,workflowName:o},exportName:t,step:f});return await e.handler(v)}})),l=new Set,R={acquire:a.acquire===void 0?void 0:async(e,t,o)=>a.acquire?.(e,t,o)??!1,delete:async e=>a.delete(e),due:async(e,t)=>a.due(e,t),load:async e=>{const t=await a.load(e);return t===void 0||t.definitionId===c||t.definitionId===p?void 0:t},release:a.release===void 0?void 0:async(e,t)=>a.release?.(e,t),save:async e=>{l.has(e.runId)||await a.save(e)}},w=O({leaseTtlMs:n.leaseTtlMs,store:R,workflows:u}),m=e=>({id:e,pause:()=>Promise.reject(new d("NOT_IMPLEMENTED",`@lunora/platform-node: workflow instance "${e}" cannot be paused — the visulima engine has no pause equivalent`)),restart:()=>Promise.reject(new d("NOT_IMPLEMENTED",`@lunora/platform-node: workflow instance "${e}" cannot be restarted — the visulima engine has no restart equivalent`)),resume:async()=>{if((await a.load(e))?.definitionId===c)throw new d("BAD_REQUEST",`@lunora/platform-node: workflow instance "${e}" was terminated and cannot be resumed`);await w.resume(e)},sendEvent:async t=>{const o=await w.getRun(e);if(o?.status!=="waiting"||o.pending?.kind!=="event"||o.pending.eventName!==t.type)throw new d("BAD_REQUEST",`@lunora/platform-node: workflow instance "${e}" is not waiting for event "${t.type}"`);await w.signal(e,t.type,t.payload)},status:async()=>{const t=await a.load(e);if(t===void 0)return{status:"unknown"};if(t.definitionId===c)return{status:"terminated"};const o=await w.getRun(e);return o===void 0?{status:"unknown"}:{error:o.error===void 0?void 0:{message:o.error.message,name:o.error.name},output:o.output,status:_(o.status)}},terminate:async()=>{await a.load(e)!==void 0&&(l.add(e),await a.delete(e),await a.save({definitionId:c,runId:e,snapshot:void 0,status:"failed",updatedAt:Date.now()}))}}),g=async e=>{const t=await a.load(e);return t?.definitionId===p?t.snapshot:e},y=async(e,t)=>{if(t?.id===void 0){const f=await w.trigger(e,t?.params);return m(f.runId)}const o=await a.load(t.id);if(o?.definitionId===p)return m(o.snapshot);if(o!==void 0)throw new d("BAD_REQUEST",`@lunora/platform-node: workflow create({ id: "${t.id}" }) names an existing run — pass the id a previous create returned, or a fresh one`);const s=await w.trigger(e,t.params);return await a.save({definitionId:p,runId:t.id,snapshot:s.runId,status:"failed",updatedAt:Date.now()}),m(s.runId)},h={};for(const{exportName:e,id:t}of r){const o={create:async s=>y(t,s),createBatch:async s=>{const f=[];for(const v of s)f.push(await y(t,v));return f},get:async s=>m(await g(s))};h[e]=o,i[A(e)]=o}return{bindings:h,env:i,runtime:w}};export{q as createNodeWorkflowHost};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const i=n=>{n.pragma("journal_mode = WAL"),n.exec(`CREATE TABLE IF NOT EXISTS _lunora_workflow_runs (
|
|
2
|
+
run_id TEXT PRIMARY KEY,
|
|
3
|
+
definition_id TEXT NOT NULL,
|
|
4
|
+
status TEXT NOT NULL,
|
|
5
|
+
event_name TEXT,
|
|
6
|
+
wake_at INTEGER,
|
|
7
|
+
updated_at INTEGER NOT NULL,
|
|
8
|
+
snapshot TEXT NOT NULL
|
|
9
|
+
)`),n.exec("CREATE INDEX IF NOT EXISTS _lunora_workflow_runs_due ON _lunora_workflow_runs (wake_at)"),n.exec("CREATE TABLE IF NOT EXISTS _lunora_workflow_leases (run_id TEXT PRIMARY KEY, token TEXT NOT NULL, expires_at INTEGER NOT NULL)");const t=n.prepare(`INSERT INTO _lunora_workflow_runs (run_id, definition_id, status, event_name, wake_at, updated_at, snapshot)
|
|
10
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
11
|
+
ON CONFLICT (run_id) DO UPDATE SET
|
|
12
|
+
definition_id = excluded.definition_id,
|
|
13
|
+
status = excluded.status,
|
|
14
|
+
event_name = excluded.event_name,
|
|
15
|
+
wake_at = excluded.wake_at,
|
|
16
|
+
updated_at = excluded.updated_at,
|
|
17
|
+
snapshot = excluded.snapshot`),o=n.prepare("SELECT * FROM _lunora_workflow_runs WHERE run_id = ?"),u=n.prepare("DELETE FROM _lunora_workflow_runs WHERE run_id = ?"),d=n.prepare("DELETE FROM _lunora_workflow_leases WHERE run_id = ?"),s=n.prepare(`SELECT run_id FROM _lunora_workflow_runs
|
|
18
|
+
WHERE status IN ('suspended', 'waiting') AND wake_at IS NOT NULL AND wake_at <= ?
|
|
19
|
+
ORDER BY wake_at LIMIT ?`),E=n.prepare(`INSERT INTO _lunora_workflow_leases (run_id, token, expires_at) VALUES (?, ?, ?)
|
|
20
|
+
ON CONFLICT (run_id) DO UPDATE SET token = excluded.token, expires_at = excluded.expires_at
|
|
21
|
+
WHERE _lunora_workflow_leases.expires_at <= ? OR _lunora_workflow_leases.token = excluded.token`),l=n.prepare("DELETE FROM _lunora_workflow_leases WHERE run_id = ? AND token = ?");return{acquire:async(e,a,r)=>{const _=Date.now();return E.run(e,a,_+r,_).changes>0},delete:async e=>{u.run(e),d.run(e)},due:async(e,a)=>s.all(e,a).map(r=>r.run_id),load:async e=>{const a=o.get(e);if(a!==void 0)return{definitionId:a.definition_id,eventName:a.event_name??void 0,runId:a.run_id,snapshot:JSON.parse(a.snapshot),status:a.status,updatedAt:a.updated_at,wakeAt:a.wake_at??void 0}},release:async(e,a)=>{l.run(e,a)},save:async e=>{t.run(e.runId,e.definitionId,e.status,e.eventName??null,e.wakeAt??null,e.updatedAt,JSON.stringify(e.snapshot??null))}}};export{i as createNodeWorkflowStore};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const f=e=>typeof e=="string"?new TextEncoder().encode(e).buffer:e instanceof ArrayBuffer?e:ArrayBuffer.isView(e)?e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength):new ArrayBuffer(0);export{f as t};
|
package/package.json
CHANGED
|
@@ -1,10 +1,62 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/platform-node",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.0.0-alpha.2",
|
|
4
|
+
"description": "Node implementation of the Lunora platform contracts: ShardHost, SocketHost, ShardDirectory, ShardKvStore, SchedulerHost over better-sqlite3 and an in-process socket registry (dev/test target)",
|
|
5
5
|
"keywords": [
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
"better-sqlite3",
|
|
7
|
+
"lunora",
|
|
8
|
+
"node",
|
|
9
|
+
"platform",
|
|
10
|
+
"portability"
|
|
11
|
+
],
|
|
12
|
+
"homepage": "https://lunora.sh",
|
|
13
|
+
"bugs": "https://github.com/anolilab/lunora/issues",
|
|
14
|
+
"license": "FSL-1.1-Apache-2.0",
|
|
15
|
+
"author": {
|
|
16
|
+
"name": "Daniel Bannert",
|
|
17
|
+
"email": "d.bannert@anolilab.de"
|
|
18
|
+
},
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "git+https://github.com/anolilab/lunora.git",
|
|
22
|
+
"directory": "packages/platform-node"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"./dist",
|
|
26
|
+
"README.md",
|
|
27
|
+
"LICENSE.md"
|
|
28
|
+
],
|
|
29
|
+
"type": "module",
|
|
30
|
+
"sideEffects": false,
|
|
31
|
+
"main": "./dist/index.mjs",
|
|
32
|
+
"module": "./dist/index.mjs",
|
|
33
|
+
"types": "./dist/index.d.ts",
|
|
34
|
+
"exports": {
|
|
35
|
+
".": {
|
|
36
|
+
"types": "./dist/index.d.ts",
|
|
37
|
+
"import": "./dist/index.mjs"
|
|
38
|
+
},
|
|
39
|
+
"./conformance": {
|
|
40
|
+
"types": "./dist/conformance/index.d.ts",
|
|
41
|
+
"import": "./dist/conformance/index.mjs"
|
|
42
|
+
},
|
|
43
|
+
"./package.json": "./package.json"
|
|
44
|
+
},
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public"
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"@lunora/d1": "1.0.0-alpha.69",
|
|
50
|
+
"@lunora/errors": "1.0.0-alpha.16",
|
|
51
|
+
"@lunora/platform": "1.0.0-alpha.7",
|
|
52
|
+
"@lunora/queue": "1.0.0-alpha.21",
|
|
53
|
+
"@lunora/sql-store": "1.0.0-alpha.71",
|
|
54
|
+
"@lunora/workflow": "1.0.0-alpha.23",
|
|
55
|
+
"@visulima/workflow": "2.0.0",
|
|
56
|
+
"better-sqlite3": "^12.11.1",
|
|
57
|
+
"cron-parser": "5.6.2"
|
|
58
|
+
},
|
|
59
|
+
"engines": {
|
|
60
|
+
"node": "^22.15.0 || >=24.11.0"
|
|
61
|
+
}
|
|
62
|
+
}
|