@ripplo/testing 0.4.8 → 0.5.0
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 +48 -18
- package/dist/assert.d.ts +1 -1
- package/dist/{builder-BMjy83Iy.d.ts → builder-DiVz3t1D.d.ts} +10 -3
- package/dist/{chunk-V6LMXKGL.js → chunk-XO36IU66.js} +32 -38
- package/dist/compiler.d.ts +2 -2
- package/dist/elysia.d.ts +3 -3
- package/dist/elysia.js +16 -23
- package/dist/{engine-DMOkJdjd.d.ts → engine-DVbF4E5A.d.ts} +20 -6
- package/dist/express.d.ts +3 -3
- package/dist/express.js +16 -45
- package/dist/fastify.d.ts +3 -3
- package/dist/fastify.js +16 -24
- package/dist/hono.d.ts +3 -3
- package/dist/hono.js +17 -24
- package/dist/index.d.ts +32 -13
- package/dist/index.js +220 -86
- package/dist/koa.d.ts +3 -3
- package/dist/koa.js +17 -20
- package/dist/lockfile.d.ts +2 -2
- package/dist/nestjs.d.ts +3 -3
- package/dist/nestjs.js +15 -20
- package/dist/nextjs.d.ts +3 -3
- package/dist/nextjs.js +16 -23
- package/dist/{types-16SB7zjP.d.ts → types-BzZrl65Z.d.ts} +9 -2
- package/package.json +1 -1
package/dist/hono.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
batchRequestSchema,
|
|
3
|
-
buildSetCookieHeader,
|
|
4
3
|
observerRequestSchema,
|
|
5
4
|
readAdapterWebhookSecret,
|
|
6
|
-
serializeCookie,
|
|
7
5
|
teardownRequestSchema,
|
|
6
|
+
toBatchRunResults,
|
|
7
|
+
toTeardownResults,
|
|
8
8
|
verifyWebhookSignature
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-XO36IU66.js";
|
|
10
10
|
import "./chunk-4MGIQFAJ.js";
|
|
11
11
|
|
|
12
12
|
// src/adapters/hono.ts
|
|
@@ -22,25 +22,17 @@ function createHonoHandler({ enabled, engine }) {
|
|
|
22
22
|
const body = tryParseJson(c.get("rawBody"));
|
|
23
23
|
const parsed = body == null ? null : batchRequestSchema.safeParse(body);
|
|
24
24
|
if (parsed == null || !parsed.success) {
|
|
25
|
-
return c.json({ error: "Invalid request body"
|
|
25
|
+
return c.json({ error: "Invalid request body" }, 400);
|
|
26
26
|
}
|
|
27
27
|
const host = c.req.header("host");
|
|
28
28
|
if (host == null || host.length === 0) {
|
|
29
|
-
return c.json({ error: "Missing host header"
|
|
29
|
+
return c.json({ error: "Missing host header" }, 400);
|
|
30
30
|
}
|
|
31
31
|
const proto = c.req.header("x-forwarded-proto") ?? "http";
|
|
32
32
|
const appUrl = `${proto}://${host}`;
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
});
|
|
37
|
-
return c.json({
|
|
38
|
-
data: result.data,
|
|
39
|
-
error: result.error,
|
|
40
|
-
executed: result.executed,
|
|
41
|
-
runId: result.runId,
|
|
42
|
-
success: result.success
|
|
43
|
-
});
|
|
33
|
+
const items = parsed.data.batch.map((b) => ({ names: b.preconditions, runId: b.runId }));
|
|
34
|
+
const results = await engine.executePreconditions(items, { appUrl });
|
|
35
|
+
return c.json({ results: toBatchRunResults(results) });
|
|
44
36
|
});
|
|
45
37
|
app.put("/execute-observer", async (c) => {
|
|
46
38
|
const body = tryParseJson(c.get("rawBody"));
|
|
@@ -49,20 +41,21 @@ function createHonoHandler({ enabled, engine }) {
|
|
|
49
41
|
return c.json({ error: "Invalid request body", success: false }, 400);
|
|
50
42
|
}
|
|
51
43
|
const result = await engine.executeObserver(parsed.data.observer, parsed.data.params);
|
|
52
|
-
return c.json({
|
|
53
|
-
error: result.error,
|
|
54
|
-
outcome: result.outcome,
|
|
55
|
-
success: result.success
|
|
56
|
-
});
|
|
44
|
+
return c.json({ error: result.error, outcome: result.outcome, success: result.success });
|
|
57
45
|
});
|
|
58
46
|
app.put("/teardown-preconditions", async (c) => {
|
|
59
47
|
const body = tryParseJson(c.get("rawBody"));
|
|
60
48
|
const parsed = body == null ? null : teardownRequestSchema.safeParse(body);
|
|
61
49
|
if (parsed == null || !parsed.success) {
|
|
62
|
-
return c.json({ error: "Invalid request body"
|
|
50
|
+
return c.json({ error: "Invalid request body" }, 400);
|
|
63
51
|
}
|
|
64
|
-
|
|
65
|
-
|
|
52
|
+
const items = parsed.data.batch.map((b) => ({
|
|
53
|
+
data: b.data,
|
|
54
|
+
names: b.preconditions,
|
|
55
|
+
runId: b.runId
|
|
56
|
+
}));
|
|
57
|
+
const results = await engine.teardown(items);
|
|
58
|
+
return c.json({ results: toTeardownResults(results) });
|
|
66
59
|
});
|
|
67
60
|
return app;
|
|
68
61
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
export { C as CoverageRegistry, O as ObserverImplFn, a as ObserverRegistry, P as PreconditionImpl, b as PreconditionRecord, c as PreconditionRegistry, R as ResolveDeps, d as RipploBuilder, e as RipploInstance, f as RipploRegistries, g as createRipplo, o as observer, p as precondition, t as test } from './builder-
|
|
1
|
+
export { C as CoverageRegistry, O as ObserverImplFn, a as ObserverRegistry, P as PreconditionImpl, b as PreconditionRecord, c as PreconditionRegistry, R as ResolveDeps, d as RipploBuilder, e as RipploInstance, f as RipploRegistries, g as createRipplo, o as observer, p as precondition, t as test } from './builder-DiVz3t1D.js';
|
|
2
2
|
import { CompileResult } from './compiler.js';
|
|
3
3
|
export { CompiledTest, compile } from './compiler.js';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
import { E as EngineRunResult, T as TeardownRunResult$1 } from './engine-DVbF4E5A.js';
|
|
5
|
+
export { a as EngineImpls, b as ExecuteBatchItem, c as ExecuteBatchOptions, N as NotImplemented, O as ObserverImplFnFor, P as PreconditionImplFor, R as RipploEngine, d as TeardownBatchItem, e as createEngine, n as notImplemented } from './engine-DVbF4E5A.js';
|
|
6
|
+
import { C as CookieEntry } from './types-BzZrl65Z.js';
|
|
7
|
+
export { c as CookieOptions, D as DEFAULT_IGNORE_PATHS, d as DEFAULT_WATCH_PATHS, e as ObserverContext, f as ObserverDefinition, O as ObserverHandle, a as ObserverInput, g as ObserverOutcome, h as Precondition, i as PreconditionDeps, P as Primitive, S as SetupContext, T as TeardownContext, j as TestDefinition, k as TestValue } from './types-BzZrl65Z.js';
|
|
7
8
|
export { D as DslNodeInput } from './step-De52hTLd.js';
|
|
8
9
|
import '@ripplo/spec';
|
|
9
10
|
|
|
@@ -18,15 +19,10 @@ interface LintResult {
|
|
|
18
19
|
}
|
|
19
20
|
declare function lint(result: CompileResult): LintResult;
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
readonly "webhook-id": string | undefined;
|
|
23
|
-
readonly "webhook-signature": string | undefined;
|
|
24
|
-
readonly "webhook-timestamp": string | undefined;
|
|
25
|
-
}
|
|
26
|
-
declare function verifyWebhookSignature(payload: string, headers: WebhookHeaders, secret: string): boolean;
|
|
22
|
+
declare function readAdapterWebhookSecret(): string;
|
|
27
23
|
interface SerializedCookie {
|
|
28
24
|
readonly domain: string | undefined;
|
|
29
|
-
readonly expires:
|
|
25
|
+
readonly expires: number | undefined;
|
|
30
26
|
readonly httpOnly: boolean | undefined;
|
|
31
27
|
readonly name: string;
|
|
32
28
|
readonly path: string | undefined;
|
|
@@ -34,7 +30,30 @@ interface SerializedCookie {
|
|
|
34
30
|
readonly secure: boolean | undefined;
|
|
35
31
|
readonly value: string;
|
|
36
32
|
}
|
|
33
|
+
type BatchRunResult = {
|
|
34
|
+
readonly cookies: ReadonlyArray<SerializedCookie>;
|
|
35
|
+
readonly data: Record<string, Record<string, string | number | boolean>>;
|
|
36
|
+
readonly executed: ReadonlyArray<string>;
|
|
37
|
+
readonly ok: true;
|
|
38
|
+
readonly runId: string;
|
|
39
|
+
} | {
|
|
40
|
+
readonly error: string;
|
|
41
|
+
readonly ok: false;
|
|
42
|
+
readonly runId: string;
|
|
43
|
+
};
|
|
44
|
+
type TeardownRunResult = {
|
|
45
|
+
readonly error: string | undefined;
|
|
46
|
+
readonly ok: boolean;
|
|
47
|
+
readonly runId: string;
|
|
48
|
+
};
|
|
49
|
+
interface WebhookHeaders {
|
|
50
|
+
readonly "webhook-id": string | undefined;
|
|
51
|
+
readonly "webhook-signature": string | undefined;
|
|
52
|
+
readonly "webhook-timestamp": string | undefined;
|
|
53
|
+
}
|
|
54
|
+
declare function verifyWebhookSignature(payload: string, headers: WebhookHeaders, secret: string): boolean;
|
|
37
55
|
declare function serializeCookie(cookie: CookieEntry): SerializedCookie;
|
|
38
|
-
declare function
|
|
56
|
+
declare function toBatchRunResults(results: ReadonlyArray<EngineRunResult>): ReadonlyArray<BatchRunResult>;
|
|
57
|
+
declare function toTeardownResults(results: ReadonlyArray<TeardownRunResult$1>): ReadonlyArray<TeardownRunResult>;
|
|
39
58
|
|
|
40
|
-
export { CompileResult, CookieEntry, type LintDiagnostic, type LintResult, type SerializedCookie,
|
|
59
|
+
export { CompileResult, CookieEntry, EngineRunResult, type LintDiagnostic, type LintResult, type SerializedCookie, TeardownRunResult$1 as TeardownRunResult, lint, readAdapterWebhookSecret, serializeCookie, toBatchRunResults, toTeardownResults, verifyWebhookSignature };
|
package/dist/index.js
CHANGED
|
@@ -17,10 +17,12 @@ import {
|
|
|
17
17
|
} from "./chunk-YFOTJIVF.js";
|
|
18
18
|
import "./chunk-MGATMMCZ.js";
|
|
19
19
|
import {
|
|
20
|
-
|
|
20
|
+
readAdapterWebhookSecret,
|
|
21
21
|
serializeCookie,
|
|
22
|
+
toBatchRunResults,
|
|
23
|
+
toTeardownResults,
|
|
22
24
|
verifyWebhookSignature
|
|
23
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-XO36IU66.js";
|
|
24
26
|
import "./chunk-4MGIQFAJ.js";
|
|
25
27
|
|
|
26
28
|
// src/chainable.ts
|
|
@@ -149,7 +151,7 @@ function stubPreconditionDef(p) {
|
|
|
149
151
|
name,
|
|
150
152
|
returns: [],
|
|
151
153
|
teardown: void 0,
|
|
152
|
-
setup: () => Promise.resolve(
|
|
154
|
+
setup: () => Promise.resolve([])
|
|
153
155
|
};
|
|
154
156
|
}
|
|
155
157
|
function stubObserverDef(o) {
|
|
@@ -860,7 +862,7 @@ function createEngine(ripplo, impls) {
|
|
|
860
862
|
const observersByName = new Map(observerDefs.map((d) => [d.name, d]));
|
|
861
863
|
return {
|
|
862
864
|
executeObserver: (name, params) => executeObserver(observersByName, name, params),
|
|
863
|
-
executePreconditions: (
|
|
865
|
+
executePreconditions: (items, options) => executePreconditions({ defsByName: preconditionsByName, items, options }),
|
|
864
866
|
getObservers: () => observerDefs,
|
|
865
867
|
getPreconditions: () => preconditionDefs,
|
|
866
868
|
getUnimplemented: () => ({
|
|
@@ -868,7 +870,7 @@ function createEngine(ripplo, impls) {
|
|
|
868
870
|
preconditions: preconditionDefs.filter((p) => !p.implemented).map((p) => p.name),
|
|
869
871
|
tests: ripplo.tests.filter((t) => !t.implemented).map((t) => t.id)
|
|
870
872
|
}),
|
|
871
|
-
teardown: (
|
|
873
|
+
teardown: (items) => teardown({ defsByName: preconditionsByName, items })
|
|
872
874
|
};
|
|
873
875
|
}
|
|
874
876
|
function wirePreconditions(registry, impls) {
|
|
@@ -913,17 +915,34 @@ function makeWiredPreconditionDef(handle, impl) {
|
|
|
913
915
|
implemented: true,
|
|
914
916
|
name,
|
|
915
917
|
returns: [],
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
}
|
|
918
|
+
setup: async (items) => {
|
|
919
|
+
const resolvedItems = items.map((item) => {
|
|
920
|
+
const resolved = {};
|
|
921
|
+
mapping.forEach(([key, depName]) => {
|
|
922
|
+
const data = item.deps[depName];
|
|
923
|
+
if (data != null) {
|
|
924
|
+
resolved[key] = data;
|
|
925
|
+
}
|
|
926
|
+
});
|
|
927
|
+
return { ctx: item.ctx, deps: resolved };
|
|
928
|
+
});
|
|
929
|
+
const results = await typedImpl.setup(resolvedItems);
|
|
930
|
+
return results.map((r) => {
|
|
931
|
+
const out = {};
|
|
932
|
+
Object.entries(r).forEach(([key, value]) => {
|
|
933
|
+
if (!isPrimitive(value)) {
|
|
934
|
+
throw new TypeError(
|
|
935
|
+
`Precondition "${name}" returned non-primitive value at key "${key}". Setup return values must be string, number, or boolean \u2014 produced via ctx.fixed/uniqueEmail/uniqueId.`
|
|
936
|
+
);
|
|
937
|
+
}
|
|
938
|
+
out[key] = value;
|
|
939
|
+
});
|
|
940
|
+
return out;
|
|
925
941
|
});
|
|
926
|
-
|
|
942
|
+
},
|
|
943
|
+
teardown: async (items) => {
|
|
944
|
+
const typed = items;
|
|
945
|
+
await typedImpl.teardown(typed);
|
|
927
946
|
}
|
|
928
947
|
};
|
|
929
948
|
}
|
|
@@ -964,88 +983,170 @@ function readBudgetOf(handle) {
|
|
|
964
983
|
}
|
|
965
984
|
async function executePreconditions({
|
|
966
985
|
defsByName,
|
|
967
|
-
|
|
986
|
+
items,
|
|
968
987
|
options
|
|
969
988
|
}) {
|
|
970
|
-
const runId = crypto.randomUUID().slice(0, 12);
|
|
971
|
-
const cookies = [];
|
|
972
989
|
const defaultDomain = deriveDefaultDomain(options?.appUrl);
|
|
973
|
-
const
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
990
|
+
const initial = items.map((item) => {
|
|
991
|
+
const cookiesRef = [];
|
|
992
|
+
return {
|
|
993
|
+
cookies: cookiesRef,
|
|
994
|
+
cookiesRef,
|
|
995
|
+
ctx: createSetupContext({ cookies: cookiesRef, defaultDomain, runId: item.runId }),
|
|
996
|
+
data: {},
|
|
997
|
+
executed: [],
|
|
998
|
+
failure: void 0,
|
|
999
|
+
names: item.names,
|
|
1000
|
+
runId: item.runId
|
|
1001
|
+
};
|
|
1002
|
+
});
|
|
1003
|
+
const order = topoOrder(defsByName, items);
|
|
1004
|
+
const orderError = order.error;
|
|
1005
|
+
if (orderError != null) {
|
|
1006
|
+
return initial.map((s) => failResult(s, orderError));
|
|
1007
|
+
}
|
|
1008
|
+
const sequence = order.names ?? [];
|
|
1009
|
+
let states = initial;
|
|
1010
|
+
let i = 0;
|
|
1011
|
+
while (i < sequence.length) {
|
|
1012
|
+
const name = sequence[i];
|
|
1013
|
+
if (name != null) {
|
|
1014
|
+
states = await executeStep({ defsByName, name, states });
|
|
1015
|
+
}
|
|
1016
|
+
i += 1;
|
|
1017
|
+
}
|
|
1018
|
+
return states.map(
|
|
1019
|
+
(s) => s.failure == null ? {
|
|
1020
|
+
cookies: s.cookiesRef,
|
|
1021
|
+
data: s.data,
|
|
1022
|
+
error: void 0,
|
|
1023
|
+
executed: s.executed,
|
|
1024
|
+
runId: s.runId,
|
|
1025
|
+
success: true
|
|
1026
|
+
} : failResult(s, s.failure)
|
|
1027
|
+
);
|
|
982
1028
|
}
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
1029
|
+
function topoOrder(defsByName, items) {
|
|
1030
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1031
|
+
const order = [];
|
|
1032
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
1033
|
+
const visitDeps = (deps) => {
|
|
1034
|
+
const found = deps.find((d) => visit(d) != null);
|
|
1035
|
+
return found == null ? void 0 : visit(found);
|
|
1036
|
+
};
|
|
1037
|
+
const visit = (name) => {
|
|
1038
|
+
if (seen.has(name)) {
|
|
1039
|
+
return void 0;
|
|
989
1040
|
}
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
return fail(state, error);
|
|
1041
|
+
if (visiting.has(name)) {
|
|
1042
|
+
return `Cycle detected at precondition "${name}"`;
|
|
993
1043
|
}
|
|
994
|
-
const
|
|
995
|
-
if (
|
|
996
|
-
return
|
|
1044
|
+
const def = defsByName.get(name);
|
|
1045
|
+
if (def == null) {
|
|
1046
|
+
return `Unknown precondition: "${name}"`;
|
|
997
1047
|
}
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1048
|
+
visiting.add(name);
|
|
1049
|
+
const deps = def.depMapping.map(([, depName]) => depName);
|
|
1050
|
+
const cycleError = visitDeps(deps);
|
|
1051
|
+
visiting.delete(name);
|
|
1052
|
+
if (cycleError != null) {
|
|
1053
|
+
return cycleError;
|
|
1054
|
+
}
|
|
1055
|
+
seen.add(name);
|
|
1056
|
+
order.push(name);
|
|
1057
|
+
return void 0;
|
|
1007
1058
|
};
|
|
1059
|
+
let err;
|
|
1060
|
+
let k = 0;
|
|
1061
|
+
const allNames = items.flatMap((item) => item.names);
|
|
1062
|
+
while (k < allNames.length && err == null) {
|
|
1063
|
+
const n = allNames[k];
|
|
1064
|
+
if (n != null) {
|
|
1065
|
+
err = visit(n);
|
|
1066
|
+
}
|
|
1067
|
+
k += 1;
|
|
1068
|
+
}
|
|
1069
|
+
if (err != null) {
|
|
1070
|
+
return { error: err, names: void 0 };
|
|
1071
|
+
}
|
|
1072
|
+
return { error: void 0, names: order };
|
|
1008
1073
|
}
|
|
1009
|
-
function
|
|
1074
|
+
async function executeStep({
|
|
1075
|
+
defsByName,
|
|
1076
|
+
name,
|
|
1077
|
+
states
|
|
1078
|
+
}) {
|
|
1079
|
+
const isActive = (s) => s.failure == null && s.names.includes(name);
|
|
1080
|
+
const active = states.filter((s) => isActive(s));
|
|
1081
|
+
if (active.length === 0) {
|
|
1082
|
+
return states;
|
|
1083
|
+
}
|
|
1010
1084
|
const def = defsByName.get(name);
|
|
1011
1085
|
if (def == null) {
|
|
1012
|
-
return
|
|
1086
|
+
return states.map(
|
|
1087
|
+
(s) => isActive(s) ? { ...s, failure: `Unknown precondition: "${name}"` } : s
|
|
1088
|
+
);
|
|
1013
1089
|
}
|
|
1014
1090
|
if (!def.implemented) {
|
|
1015
|
-
return
|
|
1091
|
+
return states.map(
|
|
1092
|
+
(s) => isActive(s) ? { ...s, failure: `Precondition "${name}" is not implemented` } : s
|
|
1093
|
+
);
|
|
1016
1094
|
}
|
|
1017
|
-
|
|
1095
|
+
const stepResult = await runSetup({ active, def, name });
|
|
1096
|
+
return states.map((s) => isActive(s) ? mergeStepResult(s, name, stepResult) : s);
|
|
1018
1097
|
}
|
|
1019
|
-
async function
|
|
1020
|
-
const
|
|
1021
|
-
if (def == null) {
|
|
1022
|
-
return `Unknown precondition: "${name}"`;
|
|
1023
|
-
}
|
|
1098
|
+
async function runSetup({ active, def, name }) {
|
|
1099
|
+
const itemsForCall = active.map((s) => ({ ctx: s.ctx, deps: s.data }));
|
|
1024
1100
|
try {
|
|
1025
|
-
const
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1101
|
+
const results = await def.setup(itemsForCall);
|
|
1102
|
+
if (results.length !== active.length) {
|
|
1103
|
+
return {
|
|
1104
|
+
batchError: `Precondition "${name}" returned ${String(results.length)} results for ${String(active.length)} items`,
|
|
1105
|
+
perItem: /* @__PURE__ */ new Map()
|
|
1106
|
+
};
|
|
1107
|
+
}
|
|
1108
|
+
const entries = active.map((s, idx) => {
|
|
1109
|
+
const r = results[idx];
|
|
1110
|
+
return r == null ? void 0 : [s.runId, r];
|
|
1034
1111
|
});
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1112
|
+
const valid = entries.filter(
|
|
1113
|
+
(e) => e != null
|
|
1114
|
+
);
|
|
1115
|
+
if (valid.length !== active.length) {
|
|
1116
|
+
return {
|
|
1117
|
+
batchError: `Precondition "${name}" returned a null result for at least one item`,
|
|
1118
|
+
perItem: /* @__PURE__ */ new Map()
|
|
1119
|
+
};
|
|
1120
|
+
}
|
|
1121
|
+
return { batchError: void 0, perItem: new Map(valid) };
|
|
1038
1122
|
} catch (error) {
|
|
1039
|
-
return
|
|
1123
|
+
return {
|
|
1124
|
+
batchError: error instanceof Error ? error.message : String(error),
|
|
1125
|
+
perItem: /* @__PURE__ */ new Map()
|
|
1126
|
+
};
|
|
1040
1127
|
}
|
|
1041
1128
|
}
|
|
1042
|
-
function
|
|
1129
|
+
function mergeStepResult(s, name, result) {
|
|
1130
|
+
if (result.batchError != null) {
|
|
1131
|
+
return { ...s, failure: result.batchError };
|
|
1132
|
+
}
|
|
1133
|
+
const data = result.perItem.get(s.runId);
|
|
1134
|
+
if (data == null) {
|
|
1135
|
+
return { ...s, failure: `Precondition "${name}" produced no result for run "${s.runId}"` };
|
|
1136
|
+
}
|
|
1043
1137
|
return {
|
|
1044
|
-
|
|
1045
|
-
data:
|
|
1138
|
+
...s,
|
|
1139
|
+
data: { ...s.data, [name]: data },
|
|
1140
|
+
executed: [...s.executed, name]
|
|
1141
|
+
};
|
|
1142
|
+
}
|
|
1143
|
+
function failResult(s, error) {
|
|
1144
|
+
return {
|
|
1145
|
+
cookies: s.cookies,
|
|
1146
|
+
data: s.data,
|
|
1046
1147
|
error,
|
|
1047
|
-
executed:
|
|
1048
|
-
runId:
|
|
1148
|
+
executed: s.executed,
|
|
1149
|
+
runId: s.runId,
|
|
1049
1150
|
success: false
|
|
1050
1151
|
};
|
|
1051
1152
|
}
|
|
@@ -1074,25 +1175,56 @@ function createObserverContext(runId) {
|
|
|
1074
1175
|
retry: (reason) => createRetryOutcome(reason)
|
|
1075
1176
|
};
|
|
1076
1177
|
}
|
|
1077
|
-
async function teardown(
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1178
|
+
async function teardown({
|
|
1179
|
+
defsByName,
|
|
1180
|
+
items
|
|
1181
|
+
}) {
|
|
1182
|
+
const errors = /* @__PURE__ */ new Map();
|
|
1183
|
+
const allNamesUnique = [...new Set(items.flatMap((i2) => i2.names))];
|
|
1184
|
+
const order = topoOrder(
|
|
1185
|
+
defsByName,
|
|
1186
|
+
allNamesUnique.map((n) => ({ names: [n], runId: "" }))
|
|
1187
|
+
);
|
|
1188
|
+
const reversed = (order.names ?? []).toReversed();
|
|
1189
|
+
let i = 0;
|
|
1190
|
+
while (i < reversed.length) {
|
|
1191
|
+
const name = reversed[i];
|
|
1082
1192
|
if (name != null) {
|
|
1083
|
-
await
|
|
1193
|
+
await teardownStep({ defsByName, errors, items, name });
|
|
1084
1194
|
}
|
|
1085
|
-
|
|
1195
|
+
i += 1;
|
|
1086
1196
|
}
|
|
1197
|
+
return items.map((it) => {
|
|
1198
|
+
const err = errors.get(it.runId);
|
|
1199
|
+
return { error: err, runId: it.runId, success: err == null };
|
|
1200
|
+
});
|
|
1087
1201
|
}
|
|
1088
|
-
async function
|
|
1202
|
+
async function teardownStep({
|
|
1203
|
+
defsByName,
|
|
1204
|
+
errors,
|
|
1205
|
+
items,
|
|
1206
|
+
name
|
|
1207
|
+
}) {
|
|
1089
1208
|
const def = defsByName.get(name);
|
|
1090
1209
|
if (def?.teardown == null) {
|
|
1091
1210
|
return;
|
|
1092
1211
|
}
|
|
1212
|
+
const active = items.filter((i) => i.names.includes(name));
|
|
1213
|
+
if (active.length === 0) {
|
|
1214
|
+
return;
|
|
1215
|
+
}
|
|
1216
|
+
const teardownItems = active.map((it) => ({
|
|
1217
|
+
ctx: { data: it.data[name] ?? {} }
|
|
1218
|
+
}));
|
|
1093
1219
|
try {
|
|
1094
|
-
await def.teardown(
|
|
1095
|
-
} catch {
|
|
1220
|
+
await def.teardown(teardownItems);
|
|
1221
|
+
} catch (error) {
|
|
1222
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1223
|
+
active.forEach((it) => {
|
|
1224
|
+
if (!errors.has(it.runId)) {
|
|
1225
|
+
errors.set(it.runId, message);
|
|
1226
|
+
}
|
|
1227
|
+
});
|
|
1096
1228
|
}
|
|
1097
1229
|
}
|
|
1098
1230
|
function createSetupContext({
|
|
@@ -1124,7 +1256,6 @@ function deriveDefaultDomain(baseUrl) {
|
|
|
1124
1256
|
export {
|
|
1125
1257
|
DEFAULT_IGNORE_PATHS,
|
|
1126
1258
|
DEFAULT_WATCH_PATHS,
|
|
1127
|
-
buildSetCookieHeader,
|
|
1128
1259
|
compile,
|
|
1129
1260
|
createEngine,
|
|
1130
1261
|
createRipplo,
|
|
@@ -1132,7 +1263,10 @@ export {
|
|
|
1132
1263
|
notImplemented,
|
|
1133
1264
|
observer,
|
|
1134
1265
|
precondition,
|
|
1266
|
+
readAdapterWebhookSecret,
|
|
1135
1267
|
serializeCookie,
|
|
1136
1268
|
test,
|
|
1269
|
+
toBatchRunResults,
|
|
1270
|
+
toTeardownResults,
|
|
1137
1271
|
verifyWebhookSignature
|
|
1138
1272
|
};
|
package/dist/koa.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Middleware } from 'koa';
|
|
2
|
-
import { R as RipploEngine } from './engine-
|
|
3
|
-
import './builder-
|
|
4
|
-
import './types-
|
|
2
|
+
import { R as RipploEngine } from './engine-DVbF4E5A.js';
|
|
3
|
+
import './builder-DiVz3t1D.js';
|
|
4
|
+
import './types-BzZrl65Z.js';
|
|
5
5
|
import './step-De52hTLd.js';
|
|
6
6
|
import '@ripplo/spec';
|
|
7
7
|
|
package/dist/koa.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
2
|
batchRequestSchema,
|
|
3
|
-
buildSetCookieHeader,
|
|
4
3
|
observerRequestSchema,
|
|
5
4
|
readAdapterWebhookSecret,
|
|
6
|
-
serializeCookie,
|
|
7
5
|
teardownRequestSchema,
|
|
6
|
+
toBatchRunResults,
|
|
7
|
+
toTeardownResults,
|
|
8
8
|
verifyWebhookSignature
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-XO36IU66.js";
|
|
10
10
|
import "./chunk-4MGIQFAJ.js";
|
|
11
11
|
|
|
12
12
|
// src/adapters/koa.ts
|
|
13
13
|
function createKoaHandler({ enabled, engine }) {
|
|
14
14
|
if (!enabled) {
|
|
15
|
-
return async (
|
|
15
|
+
return async (_ctx, next) => {
|
|
16
16
|
await next();
|
|
17
17
|
};
|
|
18
18
|
}
|
|
@@ -57,29 +57,21 @@ async function handleExecutePreconditions({ body, ctx, engine }) {
|
|
|
57
57
|
const parsed = json == null ? null : batchRequestSchema.safeParse(json);
|
|
58
58
|
if (parsed == null || !parsed.success) {
|
|
59
59
|
ctx.status = 400;
|
|
60
|
-
ctx.body = { error: "Invalid request body"
|
|
60
|
+
ctx.body = { error: "Invalid request body" };
|
|
61
61
|
return;
|
|
62
62
|
}
|
|
63
63
|
const host = ctx.get("host");
|
|
64
64
|
if (host.length === 0) {
|
|
65
65
|
ctx.status = 400;
|
|
66
|
-
ctx.body = { error: "Missing host header"
|
|
66
|
+
ctx.body = { error: "Missing host header" };
|
|
67
67
|
return;
|
|
68
68
|
}
|
|
69
69
|
const proto = ctx.get("x-forwarded-proto").length > 0 ? ctx.get("x-forwarded-proto") : "http";
|
|
70
70
|
const appUrl = `${proto}://${host}`;
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
ctx.append("Set-Cookie", buildSetCookieHeader(serializeCookie(cookie)));
|
|
74
|
-
});
|
|
71
|
+
const items = parsed.data.batch.map((b) => ({ names: b.preconditions, runId: b.runId }));
|
|
72
|
+
const results = await engine.executePreconditions(items, { appUrl });
|
|
75
73
|
ctx.status = 200;
|
|
76
|
-
ctx.body = {
|
|
77
|
-
data: result.data,
|
|
78
|
-
error: result.error,
|
|
79
|
-
executed: result.executed,
|
|
80
|
-
runId: result.runId,
|
|
81
|
-
success: result.success
|
|
82
|
-
};
|
|
74
|
+
ctx.body = { results: toBatchRunResults(results) };
|
|
83
75
|
}
|
|
84
76
|
async function handleExecuteObserver({ body, ctx, engine }) {
|
|
85
77
|
const json = tryParseJson(body);
|
|
@@ -98,12 +90,17 @@ async function handleTeardown({ body, ctx, engine }) {
|
|
|
98
90
|
const parsed = json == null ? null : teardownRequestSchema.safeParse(json);
|
|
99
91
|
if (parsed == null || !parsed.success) {
|
|
100
92
|
ctx.status = 400;
|
|
101
|
-
ctx.body = { error: "Invalid request body"
|
|
93
|
+
ctx.body = { error: "Invalid request body" };
|
|
102
94
|
return;
|
|
103
95
|
}
|
|
104
|
-
|
|
96
|
+
const items = parsed.data.batch.map((b) => ({
|
|
97
|
+
data: b.data,
|
|
98
|
+
names: b.preconditions,
|
|
99
|
+
runId: b.runId
|
|
100
|
+
}));
|
|
101
|
+
const results = await engine.teardown(items);
|
|
105
102
|
ctx.status = 200;
|
|
106
|
-
ctx.body = {
|
|
103
|
+
ctx.body = { results: toTeardownResults(results) };
|
|
107
104
|
}
|
|
108
105
|
function lastPathSegment(path) {
|
|
109
106
|
const segments = path.split("/").filter((s) => s.length > 0);
|
package/dist/lockfile.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Codec } from '@ripplo/spec';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { CompileResult } from './compiler.js';
|
|
4
|
-
import './builder-
|
|
5
|
-
import './types-
|
|
4
|
+
import './builder-DiVz3t1D.js';
|
|
5
|
+
import './types-BzZrl65Z.js';
|
|
6
6
|
import './step-De52hTLd.js';
|
|
7
7
|
|
|
8
8
|
declare const LOCKFILE_RELATIVE_PATH = ".ripplo/ripplo.lock";
|
package/dist/nestjs.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DynamicModule } from '@nestjs/common';
|
|
2
|
-
import { R as RipploEngine } from './engine-
|
|
3
|
-
import './builder-
|
|
4
|
-
import './types-
|
|
2
|
+
import { R as RipploEngine } from './engine-DVbF4E5A.js';
|
|
3
|
+
import './builder-DiVz3t1D.js';
|
|
4
|
+
import './types-BzZrl65Z.js';
|
|
5
5
|
import './step-De52hTLd.js';
|
|
6
6
|
import '@ripplo/spec';
|
|
7
7
|
|