@lunora/testing 1.0.0-alpha.219 → 1.0.0-alpha.220
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 +7 -1
- package/dist/index.d.mts +34 -21
- package/dist/index.d.ts +34 -21
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/lunoraTest-ZriKevr9.mjs +1 -0
- package/package.json +1 -1
- package/dist/packem_shared/lunoraTest-Jxj4GpVd.mjs +0 -1
package/README.md
CHANGED
|
@@ -109,13 +109,19 @@ Each `lunoraTest(...)` opens an in-memory SQLite database; call `t.close()`
|
|
|
109
109
|
Pass a `fetch` option to replace the throwing stub in action contexts:
|
|
110
110
|
|
|
111
111
|
```ts
|
|
112
|
-
const fakeFetch = vi.fn<typeof globalThis.fetch>()
|
|
112
|
+
const fakeFetch = vi.fn<typeof globalThis.fetch>(async () => Response.json({ ok: true }));
|
|
113
113
|
const t = lunoraTest(schema, { fetch: fakeFetch });
|
|
114
114
|
// ctx.fetch inside any action now calls fakeFetch
|
|
115
115
|
```
|
|
116
116
|
|
|
117
117
|
Without the option, `ctx.fetch` still throws the v1 error on first access.
|
|
118
118
|
|
|
119
|
+
#### Injectable `ctx.services`
|
|
120
|
+
|
|
121
|
+
Pass a `services` option with a fake per `lunora.config` service an action calls
|
|
122
|
+
(`{ documentParser: { fetch } }`). See the [package docs](https://lunora.sh/docs/packages/testing#injectable-ctxservices)
|
|
123
|
+
for an example.
|
|
124
|
+
|
|
119
125
|
#### Fixed `ctx.now`
|
|
120
126
|
|
|
121
127
|
Pass a `now` option (epoch ms) to pin `ctx.now` across every context, so
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AgentMessageRow, AgentRunInput, AgentGenerateResult, AgentRunResult, AgentDefinition } from '@lunora/agent';
|
|
2
|
-
import { ScheduledJob, RegisteredAction, RegisteredMutation, RegisteredQuery, ArgsValidator, InferArgs, ActionCtx, MutationCtx, QueryCtx,
|
|
2
|
+
import { ScheduledJob, LogFields, RegisteredAction, RegisteredMutation, RegisteredQuery, ArgsValidator, InferArgs, ActionCtx, MutationCtx, QueryCtx, TableDefinition, Schema } from '@lunora/server';
|
|
3
3
|
export {
|
|
4
4
|
/**
|
|
5
5
|
* `@lunora/testing` — the user-facing toolkit for end-to-end testing a Lunora app.
|
|
@@ -326,6 +326,25 @@ interface SweepOptions {
|
|
|
326
326
|
*/
|
|
327
327
|
throwOnError?: boolean;
|
|
328
328
|
}
|
|
329
|
+
/** What a handler attached to the dispatch's span (`ctx.span`) during a harness run. */
|
|
330
|
+
interface RecordedWideEvent {
|
|
331
|
+
/**
|
|
332
|
+
* Attributes accumulated across the run, merged in call order. Values are
|
|
333
|
+
* recorded AS PASSED (not coerced the way the real pipeline normalizes them),
|
|
334
|
+
* so a test asserts on what the handler meant rather than on the wire form.
|
|
335
|
+
*/
|
|
336
|
+
attributes: LogFields;
|
|
337
|
+
/** Span events recorded via `ctx.span.addEvent` / `recordException`, in order. */
|
|
338
|
+
events: {
|
|
339
|
+
attributes?: LogFields;
|
|
340
|
+
name: string;
|
|
341
|
+
}[];
|
|
342
|
+
/** Links recorded via `ctx.span.addLink`, in order. */
|
|
343
|
+
links: {
|
|
344
|
+
spanId: string;
|
|
345
|
+
traceId: string;
|
|
346
|
+
}[];
|
|
347
|
+
}
|
|
329
348
|
/**
|
|
330
349
|
* The schema value produced by `@lunora/server`'s `defineSchema`. Accepted
|
|
331
350
|
* structurally; internally it is handed to `@lunora/do`'s `runShardMigrations` /
|
|
@@ -428,7 +447,7 @@ interface LunoraTestOptions {
|
|
|
428
447
|
* Pass `vi.fn()` or any `typeof globalThis.fetch` compatible implementation.
|
|
429
448
|
* @example
|
|
430
449
|
* ```ts
|
|
431
|
-
* const fakeFetch = vi.fn()
|
|
450
|
+
* const fakeFetch = vi.fn(async () => Response.json({ ok: true }));
|
|
432
451
|
* const t = lunoraTest(schema, { fetch: fakeFetch });
|
|
433
452
|
* ```
|
|
434
453
|
*/
|
|
@@ -460,6 +479,19 @@ interface LunoraTestOptions {
|
|
|
460
479
|
* ```
|
|
461
480
|
*/
|
|
462
481
|
now?: number;
|
|
482
|
+
/**
|
|
483
|
+
* Fakes for `ctx.services` (the `lunora.config` `services` an app calls),
|
|
484
|
+
* keyed like `ctx.services`. Set on action contexts only — queries and
|
|
485
|
+
* mutations have no `ctx.services` at runtime either. A key with no fake
|
|
486
|
+
* throws on use, naming the option to add it to.
|
|
487
|
+
* @example
|
|
488
|
+
* ```ts
|
|
489
|
+
* const t = lunoraTest(schema, {
|
|
490
|
+
* services: { documentParser: { fetch: vi.fn(async () => Response.json({ text: "…" })) } },
|
|
491
|
+
* });
|
|
492
|
+
* ```
|
|
493
|
+
*/
|
|
494
|
+
services?: Record<string, object>;
|
|
463
495
|
}
|
|
464
496
|
/**
|
|
465
497
|
* The in-memory test harness returned by {@link lunoraTest}. Mirrors the first
|
|
@@ -553,25 +585,6 @@ interface TestHarness {
|
|
|
553
585
|
/** Return a harness view that shares this harness's db but reports the given identity on `ctx.auth`. */
|
|
554
586
|
withIdentity: (identity: TestIdentity) => TestHarness;
|
|
555
587
|
}
|
|
556
|
-
/** What a handler attached to the dispatch's span (`ctx.span`) during a harness run. */
|
|
557
|
-
interface RecordedWideEvent {
|
|
558
|
-
/**
|
|
559
|
-
* Attributes accumulated across the run, merged in call order. Values are
|
|
560
|
-
* recorded AS PASSED (not coerced the way the real pipeline normalizes them),
|
|
561
|
-
* so a test asserts on what the handler meant rather than on the wire form.
|
|
562
|
-
*/
|
|
563
|
-
attributes: LogFields;
|
|
564
|
-
/** Span events recorded via `ctx.span.addEvent` / `recordException`, in order. */
|
|
565
|
-
events: {
|
|
566
|
-
attributes?: LogFields;
|
|
567
|
-
name: string;
|
|
568
|
-
}[];
|
|
569
|
-
/** Links recorded via `ctx.span.addLink`, in order. */
|
|
570
|
-
links: {
|
|
571
|
-
spanId: string;
|
|
572
|
-
traceId: string;
|
|
573
|
-
}[];
|
|
574
|
-
}
|
|
575
588
|
/**
|
|
576
589
|
* Spin up an in-memory Lunora function harness for `schema`.
|
|
577
590
|
*
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AgentMessageRow, AgentRunInput, AgentGenerateResult, AgentRunResult, AgentDefinition } from '@lunora/agent';
|
|
2
|
-
import { ScheduledJob, RegisteredAction, RegisteredMutation, RegisteredQuery, ArgsValidator, InferArgs, ActionCtx, MutationCtx, QueryCtx,
|
|
2
|
+
import { ScheduledJob, LogFields, RegisteredAction, RegisteredMutation, RegisteredQuery, ArgsValidator, InferArgs, ActionCtx, MutationCtx, QueryCtx, TableDefinition, Schema } from '@lunora/server';
|
|
3
3
|
export {
|
|
4
4
|
/**
|
|
5
5
|
* `@lunora/testing` — the user-facing toolkit for end-to-end testing a Lunora app.
|
|
@@ -326,6 +326,25 @@ interface SweepOptions {
|
|
|
326
326
|
*/
|
|
327
327
|
throwOnError?: boolean;
|
|
328
328
|
}
|
|
329
|
+
/** What a handler attached to the dispatch's span (`ctx.span`) during a harness run. */
|
|
330
|
+
interface RecordedWideEvent {
|
|
331
|
+
/**
|
|
332
|
+
* Attributes accumulated across the run, merged in call order. Values are
|
|
333
|
+
* recorded AS PASSED (not coerced the way the real pipeline normalizes them),
|
|
334
|
+
* so a test asserts on what the handler meant rather than on the wire form.
|
|
335
|
+
*/
|
|
336
|
+
attributes: LogFields;
|
|
337
|
+
/** Span events recorded via `ctx.span.addEvent` / `recordException`, in order. */
|
|
338
|
+
events: {
|
|
339
|
+
attributes?: LogFields;
|
|
340
|
+
name: string;
|
|
341
|
+
}[];
|
|
342
|
+
/** Links recorded via `ctx.span.addLink`, in order. */
|
|
343
|
+
links: {
|
|
344
|
+
spanId: string;
|
|
345
|
+
traceId: string;
|
|
346
|
+
}[];
|
|
347
|
+
}
|
|
329
348
|
/**
|
|
330
349
|
* The schema value produced by `@lunora/server`'s `defineSchema`. Accepted
|
|
331
350
|
* structurally; internally it is handed to `@lunora/do`'s `runShardMigrations` /
|
|
@@ -428,7 +447,7 @@ interface LunoraTestOptions {
|
|
|
428
447
|
* Pass `vi.fn()` or any `typeof globalThis.fetch` compatible implementation.
|
|
429
448
|
* @example
|
|
430
449
|
* ```ts
|
|
431
|
-
* const fakeFetch = vi.fn()
|
|
450
|
+
* const fakeFetch = vi.fn(async () => Response.json({ ok: true }));
|
|
432
451
|
* const t = lunoraTest(schema, { fetch: fakeFetch });
|
|
433
452
|
* ```
|
|
434
453
|
*/
|
|
@@ -460,6 +479,19 @@ interface LunoraTestOptions {
|
|
|
460
479
|
* ```
|
|
461
480
|
*/
|
|
462
481
|
now?: number;
|
|
482
|
+
/**
|
|
483
|
+
* Fakes for `ctx.services` (the `lunora.config` `services` an app calls),
|
|
484
|
+
* keyed like `ctx.services`. Set on action contexts only — queries and
|
|
485
|
+
* mutations have no `ctx.services` at runtime either. A key with no fake
|
|
486
|
+
* throws on use, naming the option to add it to.
|
|
487
|
+
* @example
|
|
488
|
+
* ```ts
|
|
489
|
+
* const t = lunoraTest(schema, {
|
|
490
|
+
* services: { documentParser: { fetch: vi.fn(async () => Response.json({ text: "…" })) } },
|
|
491
|
+
* });
|
|
492
|
+
* ```
|
|
493
|
+
*/
|
|
494
|
+
services?: Record<string, object>;
|
|
463
495
|
}
|
|
464
496
|
/**
|
|
465
497
|
* The in-memory test harness returned by {@link lunoraTest}. Mirrors the first
|
|
@@ -553,25 +585,6 @@ interface TestHarness {
|
|
|
553
585
|
/** Return a harness view that shares this harness's db but reports the given identity on `ctx.auth`. */
|
|
554
586
|
withIdentity: (identity: TestIdentity) => TestHarness;
|
|
555
587
|
}
|
|
556
|
-
/** What a handler attached to the dispatch's span (`ctx.span`) during a harness run. */
|
|
557
|
-
interface RecordedWideEvent {
|
|
558
|
-
/**
|
|
559
|
-
* Attributes accumulated across the run, merged in call order. Values are
|
|
560
|
-
* recorded AS PASSED (not coerced the way the real pipeline normalizes them),
|
|
561
|
-
* so a test asserts on what the handler meant rather than on the wire form.
|
|
562
|
-
*/
|
|
563
|
-
attributes: LogFields;
|
|
564
|
-
/** Span events recorded via `ctx.span.addEvent` / `recordException`, in order. */
|
|
565
|
-
events: {
|
|
566
|
-
attributes?: LogFields;
|
|
567
|
-
name: string;
|
|
568
|
-
}[];
|
|
569
|
-
/** Links recorded via `ctx.span.addLink`, in order. */
|
|
570
|
-
links: {
|
|
571
|
-
spanId: string;
|
|
572
|
-
traceId: string;
|
|
573
|
-
}[];
|
|
574
|
-
}
|
|
575
588
|
/**
|
|
576
589
|
* Spin up an in-memory Lunora function harness for `schema`.
|
|
577
590
|
*
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{agentHarness as o,finalTurn as t,toolCallTurn as a}from"./packem_shared/agentHarness-DA9onGVO.mjs";import{evaluationAttributes as l,recordEvaluation as n}from"./packem_shared/evaluationAttributes-CYLgTP1P.mjs";import{lunoraTest as s}from"./packem_shared/lunoraTest-
|
|
1
|
+
import{agentHarness as o,finalTurn as t,toolCallTurn as a}from"./packem_shared/agentHarness-DA9onGVO.mjs";import{evaluationAttributes as l,recordEvaluation as n}from"./packem_shared/evaluationAttributes-CYLgTP1P.mjs";import{lunoraTest as s}from"./packem_shared/lunoraTest-ZriKevr9.mjs";import{groundednessScorer as p,mrrScorer as u,ndcgAtK as x,precisionAtK as S,recallAtK as f}from"./packem_shared/groundednessScorer-kgXJCZDg.mjs";import{containsScorer as g,evaluate as A,exactMatchScorer as v,keywordScorer as K,llmScorer as M,regexScorer as T,scoreSample as k}from"./packem_shared/containsScorer-DoLfFOs6.mjs";import{extractLink as C,listCapturedMail as b,waitForMail as h}from"@lunora/mail/testing";export{o as agentHarness,g as containsScorer,A as evaluate,l as evaluationAttributes,v as exactMatchScorer,C as extractLink,t as finalTurn,p as groundednessScorer,K as keywordScorer,b as listCapturedMail,M as llmScorer,s as lunoraTest,u as mrrScorer,x as ndcgAtK,S as precisionAtK,f as recallAtK,n as recordEvaluation,T as regexScorer,k as scoreSample,a as toolCallTurn,h as waitForMail};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LunoraError as k}from"@lunora/errors";import{withDeferredSchedules as le,bindTableFacade as me,beginDeferredSchedules as he}from"@lunora/server";import{runShardMigrations as ye,TransactionHeadroomTracker as J,createShardCtxDb as be,RLS_UNWRAP_SYMBOL as we}from"@lunora/shard-engine";import{evaluationAttributes as ge}from"./evaluationAttributes-CYLgTP1P.mjs";import{assertScheduleDelay as pe,MAX_RETRY_ATTEMPTS as ve,RETRY_BASE_DELAY_MS as Ae}from"@lunora/scheduler";import{DatabaseSync as Ee}from"node:sqlite";const V=e=>{throw new k("INTERNAL",`ctx.${e} is not available in the in-memory @lunora/testing harness (v1)`)},Se=new Set(["$$typeof","asymmetricMatch","then","toJSON"]),Re=e=>new Proxy({...e},{get(r,n){if(!(Se.has(n)&&!Object.hasOwn(r,n))){if(typeof n=="symbol"||Object.hasOwn(r,n)||n in Object.prototype)return Reflect.get(r,n);throw new k("INTERNAL",`ctx.services.${n} has no fake in the @lunora/testing harness — pass lunoraTest(schema, { services: { ${n}: … } })`)}}}),S=e=>new Proxy((...r)=>V(e),{apply:()=>V(e),get:()=>V(e)}),oe={spanId:"0000000000000001",traceId:"00000000000000000000000000000001"},Te={addEvent:()=>{},addLink:()=>{},recordEvaluation:()=>{},recordException:()=>{},setAttribute:()=>{},setAttributes:()=>{},spanContext:()=>oe},Pe=()=>{const e={attributes:{},events:[],links:[]},r={addEvent:(n,a)=>{e.events.push({...a===void 0?{}:{attributes:{...a}},name:n})},addLink:n=>{e.links.push({spanId:n.spanId,traceId:n.traceId})},recordEvaluation:n=>{Object.assign(e.attributes,ge(n))},recordException:n=>{const a={"exception.message":n instanceof Error?n.message:String(n),"exception.type":n instanceof Error?n.constructor.name:"Error"};n instanceof Error&&n.stack!==void 0&&(a["exception.stacktrace"]=n.stack),r.addEvent("exception",a)},setAttribute:(n,a)=>{e.attributes[n]=a},setAttributes:n=>{Object.assign(e.attributes,n)},spanContext:()=>oe};return{handle:r,recorded:e}},W=async(e,r)=>await r(W,Te),z={count:()=>{},gauge:()=>{},record:()=>{}},H={debug:()=>{},error:()=>{},event:()=>{},fatal:()=>{},info:()=>{},log:()=>{},trace:()=>{},warn:()=>{},with:()=>H},Q=e=>{let r="";for(let a=0;a<e.length;a+=32768)r+=String.fromCharCode(...e.subarray(a,a+32768));return btoa(r)},xe=e=>{const r=atob(e),n=new Uint8Array(r.length);for(let a=0;a<r.length;a+=1)n[a]=r.codePointAt(a)??0;return n},A="$lunora.wire$",G=64,te=1024,K="__proto__",re={BigInt64Array,BigUint64Array,Float32Array,Float64Array,Int8Array,Int16Array,Int32Array,Uint8Array,Uint8ClampedArray,Uint16Array,Uint32Array},ne={Error,EvalError,RangeError,ReferenceError,SyntaxError,TypeError,URIError},Ne=e=>{if(e===null||typeof e!="object")return!1;const r=Object.getPrototypeOf(e);return r===null||r===Object.prototype},x=(e,r=0)=>{if(r>G)throw new RangeError(`wire-codec: value nesting exceeds the ${G}-level limit`);if(e===void 0)return[A,"undefined"];if(e===null)return null;const n=typeof e;if(n==="bigint")return[A,"bigint",e.toString()];if(n==="number"){const t=e;return Number.isNaN(t)?[A,"nan"]:t===1/0?[A,"inf"]:t===-1/0?[A,"-inf"]:t}if(n!=="object")return e;if(e instanceof Date)return[A,"date",x(e.getTime(),r+1)];if(e instanceof Error){const t=e,i={};for(const f of Object.keys(t)){if(t[f]===void 0)continue;const l=x(t[f],r+1);f===K?Object.defineProperty(i,f,{configurable:!0,enumerable:!0,value:l,writable:!0}):i[f]=l}const d=[A,"error",String(t.name),String(t.message),i];return t.cause!==void 0&&d.push(x(t.cause,r+1)),d}if(e instanceof URL)return[A,"url",e.href];if(e instanceof Map)return[A,"map",[...e.entries()].map(([t,i])=>[x(t,r+1),x(i,r+1)])];if(e instanceof Set)return[A,"set",[...e].map(t=>x(t,r+1))];if(e instanceof ArrayBuffer)return[A,"bytes",Q(new Uint8Array(e)),"ArrayBuffer"];if(ArrayBuffer.isView(e)){const t=e,i=t.constructor.name,d=new Uint8Array(t.buffer,t.byteOffset,t.byteLength);return i==="Uint8Array"?[A,"bytes",Q(d)]:[A,"bytes",Q(d),i]}if(Array.isArray(e)){const t=e.map(i=>x(i,r+1));return t.length>0&&t[0]===A?[A,"arr",t]:t}if(!Ne(e)){const t=e.constructor?.name??"value";throw new TypeError(`wire-codec: cannot encode a ${t} over the Lunora wire — only plain objects, arrays, and the supported built-ins (Date, Error, URL, Map, Set, ArrayBuffer/typed arrays, bigint) round-trip`)}const a=e,h={};for(const t of Object.keys(a)){const i=a[t];if(i===void 0)continue;const d=x(i,r+1);t===K?Object.defineProperty(h,t,{configurable:!0,enumerable:!0,value:d,writable:!0}):h[t]=d}return h},P=(e,r=0)=>{if(r>G)throw new RangeError(`wire-codec: value nesting exceeds the ${G}-level limit`);if(e===null||typeof e!="object")return e;if(Array.isArray(e)){if(e[0]===A)switch(e[1]){case"-inf":return-1/0;case"arr":return e[2].map(t=>P(t,r+1));case"bigint":{const t=e[2];if(typeof t!="string"||t.length>te||!/^-?\d+$/.test(t))throw new RangeError(`wire-codec: invalid or over-long bigint (max ${te} digits)`);return BigInt(t)}case"date":{const t=P(e[2],r+1);if(typeof t!="number")throw new TypeError("wire-codec: malformed date — epoch must be a number");return new Date(t)}case"map":{const t=e[2];return new Map(t.map(i=>{if(!Array.isArray(i)||i.length!==2)throw new TypeError("wire-codec: malformed map entry — expected a [key, value] pair");return[P(i[0],r+1),P(i[1],r+1)]}))}case"set":return new Set(e[2].map(t=>P(t,r+1)));case"url":{const t=e[2];if(typeof t!="string")throw new TypeError("wire-codec: malformed url — href must be a string");return new URL(t)}case"error":{const t=e[2],i=e[3];if(typeof t!="string"||typeof i!="string")throw new TypeError("wire-codec: malformed error — name and message must be strings");const d=(Object.hasOwn(ne,t)?ne[t]:void 0)??Error,f=new d(i);f.name!==t&&Object.defineProperty(f,"name",{configurable:!0,value:t,writable:!0});const l=P(e[4],r+1);if(l===null||typeof l!="object"||Array.isArray(l))throw new TypeError("wire-codec: malformed error — props must be an object");for(const p of Object.keys(l))p===K?Object.defineProperty(f,p,{configurable:!0,enumerable:!0,value:l[p],writable:!0}):f[p]=l[p];return e.length>5&&Object.defineProperty(f,"cause",{configurable:!0,value:P(e[5],r+1),writable:!0}),f}case"bytes":{const t=e[2];if(typeof t!="string")throw new TypeError("wire-codec: malformed bytes — payload must be a base64 string");const i=xe(t);if(Q(i)!==t)throw new TypeError("wire-codec: malformed bytes — payload must be canonical padded base64");const d=e[3]??"Uint8Array";if(d==="ArrayBuffer")return i.buffer.byteLength===i.byteLength?i.buffer:i.slice().buffer;const f=Object.hasOwn(re,d)?re[d]:void 0;return f?new f(i.slice().buffer):i}case"inf":return 1/0;case"nan":return Number.NaN;case"undefined":return;default:return e.map(t=>P(t,r+1))}return e.map(h=>P(h,r+1))}const n=e,a={};for(const h of Object.keys(n)){const t=P(n[h],r+1);h===K?Object.defineProperty(a,h,{configurable:!0,enumerable:!0,value:t,writable:!0}):a[h]=t}return a},ke=(e,r,n,a,h)=>{let t=h,i=1;const d=new Map,f=[],l=(c,b,y={},s)=>{const o=x(y);JSON.stringify(o);const g=P(o),E=s??`fake-job-${String(i)}`;return i+=1,d.set(E,{args:g,enqueuedAt:t,functionPath:b,id:E,scheduledFor:c}),E},p=c=>typeof c=="string"?c:"__lunoraRef"in c?c.__lunoraRef:c.name??c.className??"",R={cancel:c=>{const b=d.has(c);return d.delete(c),Promise.resolve({cancelled:b})},get:c=>Promise.resolve(d.get(c)??null),list:()=>Promise.resolve([...d.values()]),runAfter:(c,b,y,s)=>{pe(c,"ctx.scheduler.runAfter");const o=l(t+c,p(b),y,s?.id);return Promise.resolve(o)},runAt:(c,b,y,s)=>{const o=l(c,p(b),y,s?.id);return Promise.resolve(o)}},I=async c=>{d.delete(c.id);const b=a(),y=c.functionPath===void 0?void 0:b.get(c.functionPath);if(y===void 0)throw new k("FUNCTION_NOT_FOUND",`unknown functionPath "${c.functionPath??"(workflow-targeted)"}"`,{status:404});if(y.kind!=="mutation"&&y.kind!=="action")throw new k("FUNCTION_NOT_FOUND",`functionPath "${c.functionPath??"(workflow-targeted)"}" is a ${y.kind} — only mutations and actions can be scheduled`,{status:404});const s=e(),o=y.kind==="action"?n():r();await s(y.kind,y,{...o,now:t},c.args)},U=async c=>{const b=[...d.values()].filter(o=>o.scheduledFor<=c).toSorted((o,g)=>o.scheduledFor-g.scheduledFor),y=[];let s=0;for(const o of b)if(d.has(o.id)){s+=1;try{await I(o)}catch(g){const E=(o.attempts??0)+1;if(E>ve){const _={args:o.args,error:g,functionPath:o.functionPath??"",id:o.id};y.push(_),f.push(_)}else{const _=Ae*2**(E-1);d.set(o.id,{...o,attempts:E,scheduledFor:t+_})}}}return{executed:s,failed:y}},O=async(c,b)=>{const{executed:y,failed:s}=await U(c);if(s.length>0&&(b?.throwOnError??!0)){const[o]=s;throw s.length===1&&o!==void 0?o.error:new AggregateError(s.map(g=>g.error),`${String(s.length)} scheduled jobs failed: ${s.map(g=>g.functionPath).join(", ")}`)}return y};return{controls:{advance:(c,b)=>(t+=c,O(t,b)),failures:()=>[...f],list:()=>[...d.values()],runPending:c=>O(Number.POSITIVE_INFINITY,c)},scheduler:R}},Ie=()=>{const e=new Ee(":memory:"),r=a=>({one(){if(a.length!==1)throw new k("INTERNAL",`expected exactly one row, received ${String(a.length)}`);const[h]=a;return h},[Symbol.iterator](){return a[Symbol.iterator]()},toArray(){return a}});return{close:()=>{e.close()},sql:{exec:(a,...h)=>{const i=e.prepare(a).all(...h);return r(i)}}}},Oe=e=>{if(e===null||typeof e.userId!="string"||e.userId.length===0)return{claims:null,userId:null};const{userId:r,...n}=e;return{claims:Object.keys(n).length>0?n:null,userId:r}};class je extends J{current=new J;reset(){this.current=new J}headroom(){return this.current.headroom()}recordRead(r){this.current.recordRead(r)}recordWrite(r){this.current.recordWrite(r)}}const q=e=>{if(typeof e!="object"||e===null)return;const{kind:r}=e;if(r==="query"||r==="mutation"||r==="action")return r},_e=e=>typeof e=="object"&&e!==null&&e.visibility==="internal"?"internal":"public",Ce=(e,r,n)=>(h,t)=>{let i=!1;const d=[];let f,l,p=0,R=0;const I=()=>q(h)?e("query",h,r,t,!1):Promise.resolve(h(r)),U=(s,o)=>{if(s<R)return;R=s;const g={done:!1,value:o};if(d.length===0)f=g,l=void 0;else{f=void 0,l=void 0;for(const E of d.splice(0))E.resolve(g)}},O=(s,o)=>{if(!(s<R))if(R=s,d.length===0)l={error:o},f=void 0;else{f=void 0,l=void 0;for(const g of d.splice(0))g.reject(o)}},F=s=>o=>{U(s,o)},c=s=>o=>{O(s,o)},b=()=>{if(i)return;p+=1;const s=p;I().then(F(s)).catch(c(s))};n.add(b);const y={[Symbol.asyncIterator](){return y},next:()=>{if(i)return Promise.resolve({done:!0,value:void 0});if(R===p){if(l!==void 0){const{error:s}=l;return l=void 0,Promise.reject(s)}if(f!==void 0){const s=f;return f=void 0,Promise.resolve(s)}}return R<p?new Promise((s,o)=>{d.push({reject:o,resolve:s})}):I().then(s=>{if(l!==void 0){const{error:o}=l;throw l=void 0,o}if(f!==void 0){const o=f;return f=void 0,o}return{done:!1,value:s}})},return:()=>{i=!0,n.delete(b);for(const s of d.splice(0))s.resolve({done:!0,value:void 0});return Promise.resolve({done:!0,value:void 0})}};return I().then(F(0)).catch(c(0)),y},qe=(e,r)=>{const{close:n,sql:a}=Ie(),h=e;ye(a,h);const t=new je,i=w=>{const v=w;for(const T of Object.keys(h.tables))v[T]=me(w,T);return w},d=w=>{const v=be({auth:{identity:w.claims,userId:w.userId},enforceRls:r?.enforceRls??!0,headroom:t,schema:h,sql:a}),T=v[we]??v;return{database:i(v),rawDatabase:i(T)}},f=w=>{a.exec.call(a,w)};let l=Promise.resolve();const p=w=>{const v=async()=>{const C=he({scheduler:X});t.reset(),f("BEGIN");try{const B=await w();return f("COMMIT"),await C(!0),B}catch(B){try{f("ROLLBACK")}catch{}throw await C(!1),B}},T=l.then(v);return l=T.then(()=>{},()=>{}),T};let R=!1;const I=()=>{R||(R=!0,n())},U=new Map(Object.entries(r?.functions??{}).map(([w,v])=>[w,v])),O=new Set,F=()=>{for(const w of O)w()},c=w=>(F(),w);let b,y,s;const o=r?.now??Date.now(),g=Pe(),E=(w,v)=>{if(w===void 0)throw new k("INTERNAL",`[fake-scheduler] ${v} not yet available — scheduler.advance called before harness construction completed`);return w},{controls:_,scheduler:se}=ke(()=>E(b,"dispatch"),()=>E(y,"mutationContext"),()=>E(s,"actionContext"),()=>U,o),X=le(se),Z=w=>{const v=Oe(w),T={getIdentity:()=>Promise.resolve(v.claims),userId:v.userId},{database:C,rawDatabase:B}=d(v),$={auth:T,db:C,env:r?.env,log:H,metrics:z,now:o,span:g.handle,trace:W,runQuery:((u,m)=>j("query",u,$,m)),secrets:S("secrets"),storage:S("storage"),vectors:S("vectors")},D={auth:T,db:C,env:r?.env,log:H,metrics:z,now:o,span:g.handle,trace:W,runMutation:((u,m)=>j("mutation",u,D,m)),runQuery:((u,m)=>j("query",u,$,m)),scheduler:X,secrets:S("secrets"),storage:S("storage"),vectors:S("vectors"),workflows:S("workflows")};y??=D;const ie={...D,db:B},Y={auth:T,db:C,env:r?.env,fetch:r?.fetch??S("fetch"),log:H,metrics:z,now:o,span:g.handle,trace:W,runAction:((u,m)=>j("action",u,Y,m)),runMutation:((u,m)=>p(()=>j("mutation",u,D,m)).then(c)),runQuery:((u,m)=>j("query",u,$,m)),scheduler:X,secrets:S("secrets"),services:Re(r?.services),storage:S("storage"),vectors:S("vectors"),workflows:S("workflows")};s??=Y;const L=(u,m,N,M,fe)=>{const ee=q(m);if(ee!==u)throw new k("INTERNAL",`expected a registered ${u}, received a ${ee??"non-function"} reference`);if(!fe&&_e(m)==="internal")throw new k("INTERNAL",`This ${u} is an internal function — it is unreachable from the external RPC boundary in production. Call it through ctx.run${u.charAt(0).toUpperCase()}${u.slice(1)} from another function instead.`);return Promise.resolve(m.handler(N,M??{}))},j=(u,m,N,M)=>L(u,m,N,M,!0);b??=(u,m,N,M)=>u==="mutation"?p(()=>L("mutation",m,N,M,!0)).then(c):(t.reset(),j("action",m,N,M));const ce=((u,m)=>(t.reset(),q(u)?L("query",u,$,m,!1):Promise.resolve(u($)))),ae=((u,m)=>{const N=q(u)?()=>L("mutation",u,D,m,!1):()=>u(D);return p(N).then(c)}),ue=((u,m)=>(t.reset(),q(u)?L("action",u,Y,m,!1):Promise.resolve(u(Y)))),de=Ce((...u)=>(t.reset(),L(...u)),$,O);return{action:ue,close:I,mutation:ae,query:ce,run:u=>p(()=>u(ie)).then(c),scheduler:_,subscribe:de,wideEvent:()=>g.recorded,withIdentity:u=>Z(u)}};return Z(null)};export{qe as lunoraTest};
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{LunoraError as _}from"@lunora/errors";import{withDeferredSchedules as le,bindTableFacade as me,beginDeferredSchedules as ye}from"@lunora/server";import{runShardMigrations as he,TransactionHeadroomTracker as V,createShardCtxDb as be,RLS_UNWRAP_SYMBOL as we}from"@lunora/shard-engine";import{evaluationAttributes as ge}from"./evaluationAttributes-CYLgTP1P.mjs";import{assertScheduleDelay as pe,MAX_RETRY_ATTEMPTS as ve,RETRY_BASE_DELAY_MS as Ae}from"@lunora/scheduler";import{DatabaseSync as Ee}from"node:sqlite";const W=e=>{let r="";for(let a=0;a<e.length;a+=32768)r+=String.fromCharCode(...e.subarray(a,a+32768));return btoa(r)},Se=e=>{const r=atob(e),s=new Uint8Array(r.length);for(let a=0;a<r.length;a+=1)s[a]=r.codePointAt(a)??0;return s},A="$lunora.wire$",G=64,te=1024,X="__proto__",re={BigInt64Array,BigUint64Array,Float32Array,Float64Array,Int8Array,Int16Array,Int32Array,Uint8Array,Uint8ClampedArray,Uint16Array,Uint32Array},ne={Error,EvalError,RangeError,ReferenceError,SyntaxError,TypeError,URIError},Te=e=>{if(e===null||typeof e!="object")return!1;const r=Object.getPrototypeOf(e);return r===null||r===Object.prototype},k=(e,r=0)=>{if(r>G)throw new RangeError(`wire-codec: value nesting exceeds the ${G}-level limit`);if(e===void 0)return[A,"undefined"];if(e===null)return null;const s=typeof e;if(s==="bigint")return[A,"bigint",e.toString()];if(s==="number"){const t=e;return Number.isNaN(t)?[A,"nan"]:t===1/0?[A,"inf"]:t===-1/0?[A,"-inf"]:t}if(s!=="object")return e;if(e instanceof Date)return[A,"date",k(e.getTime(),r+1)];if(e instanceof Error){const t=e,i={};for(const f of Object.keys(t)){if(t[f]===void 0)continue;const l=k(t[f],r+1);f===X?Object.defineProperty(i,f,{configurable:!0,enumerable:!0,value:l,writable:!0}):i[f]=l}const d=[A,"error",String(t.name),String(t.message),i];return t.cause!==void 0&&d.push(k(t.cause,r+1)),d}if(e instanceof URL)return[A,"url",e.href];if(e instanceof Map)return[A,"map",[...e.entries()].map(([t,i])=>[k(t,r+1),k(i,r+1)])];if(e instanceof Set)return[A,"set",[...e].map(t=>k(t,r+1))];if(e instanceof ArrayBuffer)return[A,"bytes",W(new Uint8Array(e)),"ArrayBuffer"];if(ArrayBuffer.isView(e)){const t=e,i=t.constructor.name,d=new Uint8Array(t.buffer,t.byteOffset,t.byteLength);return i==="Uint8Array"?[A,"bytes",W(d)]:[A,"bytes",W(d),i]}if(Array.isArray(e)){const t=e.map(i=>k(i,r+1));return t.length>0&&t[0]===A?[A,"arr",t]:t}if(!Te(e)){const t=e.constructor?.name??"value";throw new TypeError(`wire-codec: cannot encode a ${t} over the Lunora wire — only plain objects, arrays, and the supported built-ins (Date, Error, URL, Map, Set, ArrayBuffer/typed arrays, bigint) round-trip`)}const a=e,y={};for(const t of Object.keys(a)){const i=a[t];if(i===void 0)continue;const d=k(i,r+1);t===X?Object.defineProperty(y,t,{configurable:!0,enumerable:!0,value:d,writable:!0}):y[t]=d}return y},R=(e,r=0)=>{if(r>G)throw new RangeError(`wire-codec: value nesting exceeds the ${G}-level limit`);if(e===null||typeof e!="object")return e;if(Array.isArray(e)){if(e[0]===A)switch(e[1]){case"-inf":return-1/0;case"arr":return e[2].map(t=>R(t,r+1));case"bigint":{const t=e[2];if(typeof t!="string"||t.length>te||!/^-?\d+$/.test(t))throw new RangeError(`wire-codec: invalid or over-long bigint (max ${te} digits)`);return BigInt(t)}case"date":{const t=R(e[2],r+1);if(typeof t!="number")throw new TypeError("wire-codec: malformed date — epoch must be a number");return new Date(t)}case"map":{const t=e[2];return new Map(t.map(i=>{if(!Array.isArray(i)||i.length!==2)throw new TypeError("wire-codec: malformed map entry — expected a [key, value] pair");return[R(i[0],r+1),R(i[1],r+1)]}))}case"set":return new Set(e[2].map(t=>R(t,r+1)));case"url":{const t=e[2];if(typeof t!="string")throw new TypeError("wire-codec: malformed url — href must be a string");return new URL(t)}case"error":{const t=e[2],i=e[3];if(typeof t!="string"||typeof i!="string")throw new TypeError("wire-codec: malformed error — name and message must be strings");const d=(Object.hasOwn(ne,t)?ne[t]:void 0)??Error,f=new d(i);f.name!==t&&Object.defineProperty(f,"name",{configurable:!0,value:t,writable:!0});const l=R(e[4],r+1);if(l===null||typeof l!="object"||Array.isArray(l))throw new TypeError("wire-codec: malformed error — props must be an object");for(const p of Object.keys(l))p===X?Object.defineProperty(f,p,{configurable:!0,enumerable:!0,value:l[p],writable:!0}):f[p]=l[p];return e.length>5&&Object.defineProperty(f,"cause",{configurable:!0,value:R(e[5],r+1),writable:!0}),f}case"bytes":{const t=e[2];if(typeof t!="string")throw new TypeError("wire-codec: malformed bytes — payload must be a base64 string");const i=Se(t);if(W(i)!==t)throw new TypeError("wire-codec: malformed bytes — payload must be canonical padded base64");const d=e[3]??"Uint8Array";if(d==="ArrayBuffer")return i.buffer.byteLength===i.byteLength?i.buffer:i.slice().buffer;const f=Object.hasOwn(re,d)?re[d]:void 0;return f?new f(i.slice().buffer):i}case"inf":return 1/0;case"nan":return Number.NaN;case"undefined":return;default:return e.map(t=>R(t,r+1))}return e.map(y=>R(y,r+1))}const s=e,a={};for(const y of Object.keys(s)){const t=R(s[y],r+1);y===X?Object.defineProperty(a,y,{configurable:!0,enumerable:!0,value:t,writable:!0}):a[y]=t}return a},Pe=(e,r,s,a,y)=>{let t=y,i=1;const d=new Map,f=[],l=(c,b,h={},o)=>{const n=k(h);JSON.stringify(n);const g=R(n),E=o??`fake-job-${String(i)}`;return i+=1,d.set(E,{args:g,enqueuedAt:t,functionPath:b,id:E,scheduledFor:c}),E},p=c=>typeof c=="string"?c:"__lunoraRef"in c?c.__lunoraRef:c.name??c.className??"",T={cancel:c=>{const b=d.has(c);return d.delete(c),Promise.resolve({cancelled:b})},get:c=>Promise.resolve(d.get(c)??null),list:()=>Promise.resolve([...d.values()]),runAfter:(c,b,h,o)=>{pe(c,"ctx.scheduler.runAfter");const n=l(t+c,p(b),h,o?.id);return Promise.resolve(n)},runAt:(c,b,h,o)=>{const n=l(c,p(b),h,o?.id);return Promise.resolve(n)}},I=async c=>{d.delete(c.id);const b=a(),h=c.functionPath===void 0?void 0:b.get(c.functionPath);if(h===void 0)throw new _("FUNCTION_NOT_FOUND",`unknown functionPath "${c.functionPath??"(workflow-targeted)"}"`,{status:404});if(h.kind!=="mutation"&&h.kind!=="action")throw new _("FUNCTION_NOT_FOUND",`functionPath "${c.functionPath??"(workflow-targeted)"}" is a ${h.kind} — only mutations and actions can be scheduled`,{status:404});const o=e(),n=h.kind==="action"?s():r();await o(h.kind,h,{...n,now:t},c.args)},$=async c=>{const b=[...d.values()].filter(n=>n.scheduledFor<=c).toSorted((n,g)=>n.scheduledFor-g.scheduledFor),h=[];let o=0;for(const n of b)if(d.has(n.id)){o+=1;try{await I(n)}catch(g){const E=(n.attempts??0)+1;if(E>ve){const j={args:n.args,error:g,functionPath:n.functionPath??"",id:n.id};h.push(j),f.push(j)}else{const j=Ae*2**(E-1);d.set(n.id,{...n,attempts:E,scheduledFor:t+j})}}}return{executed:o,failed:h}},N=async(c,b)=>{const{executed:h,failed:o}=await $(c);if(o.length>0&&(b?.throwOnError??!0)){const[n]=o;throw o.length===1&&n!==void 0?n.error:new AggregateError(o.map(g=>g.error),`${String(o.length)} scheduled jobs failed: ${o.map(g=>g.functionPath).join(", ")}`)}return h};return{controls:{advance:(c,b)=>(t+=c,N(t,b)),failures:()=>[...f],list:()=>[...d.values()],runPending:c=>N(Number.POSITIVE_INFINITY,c)},scheduler:T}},Re=()=>{const e=new Ee(":memory:"),r=a=>({one(){if(a.length!==1)throw new _("INTERNAL",`expected exactly one row, received ${String(a.length)}`);const[y]=a;return y},[Symbol.iterator](){return a[Symbol.iterator]()},toArray(){return a}});return{close:()=>{e.close()},sql:{exec:(a,...y)=>{const i=e.prepare(a).all(...y);return r(i)}}}},ke=e=>{if(e===null||typeof e.userId!="string"||e.userId.length===0)return{claims:null,userId:null};const{userId:r,...s}=e;return{claims:Object.keys(s).length>0?s:null,userId:r}};class xe extends V{current=new V;reset(){this.current=new V}headroom(){return this.current.headroom()}recordRead(r){this.current.recordRead(r)}recordWrite(r){this.current.recordWrite(r)}}const q=e=>{if(typeof e!="object"||e===null)return;const{kind:r}=e;if(r==="query"||r==="mutation"||r==="action")return r},Ie=e=>typeof e=="object"&&e!==null&&e.visibility==="internal"?"internal":"public",J=e=>{throw new _("INTERNAL",`ctx.${e} is not available in the in-memory @lunora/testing harness (v1)`)},S=e=>new Proxy((...r)=>J(e),{apply:()=>J(e),get:()=>J(e)}),oe={spanId:"0000000000000001",traceId:"00000000000000000000000000000001"},Ne={addEvent:()=>{},addLink:()=>{},recordEvaluation:()=>{},recordException:()=>{},setAttribute:()=>{},setAttributes:()=>{},spanContext:()=>oe},Oe=()=>{const e={attributes:{},events:[],links:[]},r={addEvent:(s,a)=>{e.events.push({...a===void 0?{}:{attributes:{...a}},name:s})},addLink:s=>{e.links.push({spanId:s.spanId,traceId:s.traceId})},recordEvaluation:s=>{Object.assign(e.attributes,ge(s))},recordException:s=>{const a={"exception.message":s instanceof Error?s.message:String(s),"exception.type":s instanceof Error?s.constructor.name:"Error"};s instanceof Error&&s.stack!==void 0&&(a["exception.stacktrace"]=s.stack),r.addEvent("exception",a)},setAttribute:(s,a)=>{e.attributes[s]=a},setAttributes:s=>{Object.assign(e.attributes,s)},spanContext:()=>oe};return{handle:r,recorded:e}},H=async(e,r)=>await r(H,Ne),z={count:()=>{},gauge:()=>{},record:()=>{}},Q={debug:()=>{},error:()=>{},event:()=>{},fatal:()=>{},info:()=>{},log:()=>{},trace:()=>{},warn:()=>{},with:()=>Q},_e=(e,r,s)=>(y,t)=>{let i=!1;const d=[];let f,l,p=0,T=0;const I=()=>q(y)?e("query",y,r,t,!1):Promise.resolve(y(r)),$=(o,n)=>{if(o<T)return;T=o;const g={done:!1,value:n};if(d.length===0)f=g,l=void 0;else{f=void 0,l=void 0;for(const E of d.splice(0))E.resolve(g)}},N=(o,n)=>{if(!(o<T))if(T=o,d.length===0)l={error:n},f=void 0;else{f=void 0,l=void 0;for(const g of d.splice(0))g.reject(n)}},F=o=>n=>{$(o,n)},c=o=>n=>{N(o,n)},b=()=>{if(i)return;p+=1;const o=p;I().then(F(o)).catch(c(o))};s.add(b);const h={[Symbol.asyncIterator](){return h},next:()=>{if(i)return Promise.resolve({done:!0,value:void 0});if(T===p){if(l!==void 0){const{error:o}=l;return l=void 0,Promise.reject(o)}if(f!==void 0){const o=f;return f=void 0,Promise.resolve(o)}}return T<p?new Promise((o,n)=>{d.push({reject:n,resolve:o})}):I().then(o=>{if(l!==void 0){const{error:n}=l;throw l=void 0,n}if(f!==void 0){const n=f;return f=void 0,n}return{done:!1,value:o}})},return:()=>{i=!0,s.delete(b);for(const o of d.splice(0))o.resolve({done:!0,value:void 0});return Promise.resolve({done:!0,value:void 0})}};return I().then(F(0)).catch(c(0)),h},Fe=(e,r)=>{const{close:s,sql:a}=Re(),y=e;he(a,y);const t=new xe,i=w=>{const v=w;for(const P of Object.keys(y.tables))v[P]=me(w,P);return w},d=w=>{const v=be({auth:{identity:w.claims,userId:w.userId},enforceRls:r?.enforceRls??!0,headroom:t,schema:y,sql:a}),P=v[we]??v;return{database:i(v),rawDatabase:i(P)}},f=w=>{a.exec.call(a,w)};let l=Promise.resolve();const p=w=>{const v=async()=>{const C=ye({scheduler:K});t.reset(),f("BEGIN");try{const B=await w();return f("COMMIT"),await C(!0),B}catch(B){try{f("ROLLBACK")}catch{}throw await C(!1),B}},P=l.then(v);return l=P.then(()=>{},()=>{}),P};let T=!1;const I=()=>{T||(T=!0,s())},$=new Map(Object.entries(r?.functions??{}).map(([w,v])=>[w,v])),N=new Set,F=()=>{for(const w of N)w()},c=w=>(F(),w);let b,h,o;const n=r?.now??Date.now(),g=Oe(),E=(w,v)=>{if(w===void 0)throw new _("INTERNAL",`[fake-scheduler] ${v} not yet available — scheduler.advance called before harness construction completed`);return w},{controls:j,scheduler:se}=Pe(()=>E(b,"dispatch"),()=>E(h,"mutationContext"),()=>E(o,"actionContext"),()=>$,n),K=le(se),Z=w=>{const v=ke(w),P={getIdentity:()=>Promise.resolve(v.claims),userId:v.userId},{database:C,rawDatabase:B}=d(v),D={auth:P,db:C,env:r?.env,log:Q,metrics:z,now:n,span:g.handle,trace:H,runQuery:((u,m)=>O("query",u,D,m)),secrets:S("secrets"),storage:S("storage"),vectors:S("vectors")},L={auth:P,db:C,env:r?.env,log:Q,metrics:z,now:n,span:g.handle,trace:H,runMutation:((u,m)=>O("mutation",u,L,m)),runQuery:((u,m)=>O("query",u,D,m)),scheduler:K,secrets:S("secrets"),storage:S("storage"),vectors:S("vectors"),workflows:S("workflows")};h??=L;const ie={...L,db:B},Y={auth:P,db:C,env:r?.env,fetch:r?.fetch??S("fetch"),log:Q,metrics:z,now:n,span:g.handle,trace:H,runAction:((u,m)=>O("action",u,Y,m)),runMutation:((u,m)=>p(()=>O("mutation",u,L,m)).then(c)),runQuery:((u,m)=>O("query",u,D,m)),scheduler:K,secrets:S("secrets"),storage:S("storage"),vectors:S("vectors"),workflows:S("workflows")};o??=Y;const M=(u,m,x,U,fe)=>{const ee=q(m);if(ee!==u)throw new _("INTERNAL",`expected a registered ${u}, received a ${ee??"non-function"} reference`);if(!fe&&Ie(m)==="internal")throw new _("INTERNAL",`This ${u} is an internal function — it is unreachable from the external RPC boundary in production. Call it through ctx.run${u.charAt(0).toUpperCase()}${u.slice(1)} from another function instead.`);return Promise.resolve(m.handler(x,U??{}))},O=(u,m,x,U)=>M(u,m,x,U,!0);b??=(u,m,x,U)=>u==="mutation"?p(()=>M("mutation",m,x,U,!0)).then(c):(t.reset(),O("action",m,x,U));const ce=((u,m)=>(t.reset(),q(u)?M("query",u,D,m,!1):Promise.resolve(u(D)))),ae=((u,m)=>{const x=q(u)?()=>M("mutation",u,L,m,!1):()=>u(L);return p(x).then(c)}),ue=((u,m)=>(t.reset(),q(u)?M("action",u,Y,m,!1):Promise.resolve(u(Y)))),de=_e((...u)=>(t.reset(),M(...u)),D,N);return{action:ue,close:I,mutation:ae,query:ce,run:u=>p(()=>u(ie)).then(c),scheduler:j,subscribe:de,wideEvent:()=>g.recorded,withIdentity:u=>Z(u)}};return Z(null)};export{Fe as lunoraTest};
|