rivetkit 2.3.30 → 3.0.0-preview.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/dist/browser/client.d.ts +58 -9
- package/dist/browser/client.js +193 -20
- package/dist/browser/client.js.map +1 -1
- package/dist/browser/inspector/client.js +1 -2
- package/dist/browser/inspector/client.js.map +1 -1
- package/dist/tsup/{chunk-P2PHHJMH.cjs → chunk-25MUHNWE.cjs} +326 -166
- package/dist/tsup/chunk-25MUHNWE.cjs.map +1 -0
- package/dist/tsup/{chunk-5SN6GAYX.cjs → chunk-3SPYZMME.cjs} +3 -3
- package/dist/tsup/{chunk-5SN6GAYX.cjs.map → chunk-3SPYZMME.cjs.map} +1 -1
- package/dist/tsup/{chunk-4SNS3PYZ.js → chunk-3URL73AV.js} +2 -2
- package/dist/tsup/{chunk-EKAQ7HG2.js → chunk-442XBCAF.js} +3 -3
- package/dist/tsup/{chunk-CORYIKDC.js → chunk-5F7FWAJI.js} +10 -11
- package/dist/tsup/chunk-5F7FWAJI.js.map +1 -0
- package/dist/tsup/{chunk-I472KTIC.js → chunk-6IGGYL2C.js} +185 -25
- package/dist/tsup/chunk-6IGGYL2C.js.map +1 -0
- package/dist/tsup/{chunk-JI6GZ2C2.js → chunk-A2CF6PFH.js} +18 -1
- package/dist/tsup/chunk-A2CF6PFH.js.map +1 -0
- package/dist/tsup/{chunk-OUB7SGSA.js → chunk-ANNVZW6B.js} +2 -2
- package/dist/tsup/{chunk-ZIIQQHC3.cjs → chunk-BCG7PTBS.cjs} +4 -4
- package/dist/tsup/{chunk-ZIIQQHC3.cjs.map → chunk-BCG7PTBS.cjs.map} +1 -1
- package/dist/tsup/{chunk-OJFVABRH.cjs → chunk-CJ3MX5MI.cjs} +7 -7
- package/dist/tsup/{chunk-OJFVABRH.cjs.map → chunk-CJ3MX5MI.cjs.map} +1 -1
- package/dist/tsup/{chunk-GEUBEODU.cjs → chunk-EPPV7WB2.cjs} +3 -3
- package/dist/tsup/{chunk-GEUBEODU.cjs.map → chunk-EPPV7WB2.cjs.map} +1 -1
- package/dist/tsup/{chunk-MXV26ZBB.js → chunk-OLZ4KAFL.js} +4 -4
- package/dist/tsup/{chunk-5UUOECX2.cjs → chunk-QDRZMCX5.cjs} +10 -10
- package/dist/tsup/{chunk-5UUOECX2.cjs.map → chunk-QDRZMCX5.cjs.map} +1 -1
- package/dist/tsup/{chunk-MYWZCDML.cjs → chunk-RTWH3AX3.cjs} +19 -2
- package/dist/tsup/chunk-RTWH3AX3.cjs.map +1 -0
- package/dist/tsup/{chunk-H3SGQEHZ.js → chunk-WGKL7HMH.js} +2 -2
- package/dist/tsup/{chunk-6LOYTFPZ.js → chunk-WGQHG26S.js} +2 -2
- package/dist/tsup/{chunk-2BIRGEIU.cjs → chunk-XSOHGU4G.cjs} +10 -11
- package/dist/tsup/chunk-XSOHGU4G.cjs.map +1 -0
- package/dist/tsup/{chunk-ABPZG7QV.cjs → chunk-YZVVID47.cjs} +3 -3
- package/dist/tsup/{chunk-ABPZG7QV.cjs.map → chunk-YZVVID47.cjs.map} +1 -1
- package/dist/tsup/client/mod.cjs +6 -6
- package/dist/tsup/client/mod.d.cts +15 -3
- package/dist/tsup/client/mod.d.ts +15 -3
- package/dist/tsup/client/mod.js +5 -5
- package/dist/tsup/common/log.cjs +2 -2
- package/dist/tsup/common/log.js +1 -1
- package/dist/tsup/common/websocket.cjs +3 -3
- package/dist/tsup/common/websocket.js +2 -2
- package/dist/tsup/{config-osdJqQwX.d.cts → config-8NgsxIcT.d.cts} +43 -12
- package/dist/tsup/{config-ey2I2zz5.d.ts → config-B2wlj9wx.d.cts} +7 -1
- package/dist/tsup/{config-ey2I2zz5.d.cts → config-B2wlj9wx.d.ts} +7 -1
- package/dist/tsup/{config-Cv6pjCt-.d.ts → config-DJ3KW-fe.d.ts} +43 -12
- package/dist/tsup/{context-CoVbKBuk.d.ts → context-BL8kUGjq.d.ts} +2 -2
- package/dist/tsup/{context-DpjrM7n7.d.cts → context-_RoE_YHL.d.cts} +2 -2
- package/dist/tsup/db/drizzle.cjs +2 -2
- package/dist/tsup/db/drizzle.d.cts +1 -1
- package/dist/tsup/db/drizzle.d.ts +1 -1
- package/dist/tsup/db/drizzle.js +1 -1
- package/dist/tsup/db/mod.cjs +3 -3
- package/dist/tsup/db/mod.d.cts +2 -2
- package/dist/tsup/db/mod.d.ts +2 -2
- package/dist/tsup/db/mod.js +2 -2
- package/dist/tsup/dynamic/mod.d.cts +2 -2
- package/dist/tsup/dynamic/mod.d.ts +2 -2
- package/dist/tsup/inspector/mod.cjs +5 -5
- package/dist/tsup/inspector/mod.js +4 -4
- package/dist/tsup/inspector/workflow.cjs +4 -4
- package/dist/tsup/inspector/workflow.js +3 -3
- package/dist/tsup/inspector-tab/mod.d.cts +3 -3
- package/dist/tsup/inspector-tab/mod.d.ts +3 -3
- package/dist/tsup/mod.cjs +254 -166
- package/dist/tsup/mod.cjs.map +1 -1
- package/dist/tsup/mod.d.cts +4 -4
- package/dist/tsup/mod.d.ts +4 -4
- package/dist/tsup/mod.js +168 -80
- package/dist/tsup/mod.js.map +1 -1
- package/dist/tsup/test/mod.cjs +7 -7
- package/dist/tsup/test/mod.d.cts +2 -2
- package/dist/tsup/test/mod.d.ts +2 -2
- package/dist/tsup/test/mod.js +5 -5
- package/dist/tsup/unstable/migrations.d.cts +1 -1
- package/dist/tsup/unstable/migrations.d.ts +1 -1
- package/dist/tsup/utils.cjs +2 -2
- package/dist/tsup/utils.js +1 -1
- package/dist/tsup/workflow/mod.cjs +17 -17
- package/dist/tsup/workflow/mod.d.cts +4 -4
- package/dist/tsup/workflow/mod.d.ts +4 -4
- package/dist/tsup/workflow/mod.js +5 -5
- package/package.json +9 -10
- package/src/actor/keys.ts +86 -0
- package/src/client/actor-conn.ts +92 -6
- package/src/client/actor-handle.ts +21 -3
- package/src/client/client.ts +6 -0
- package/src/client/config.ts +12 -1
- package/src/client/lifecycle-errors.ts +16 -1
- package/src/client/retry-budget.ts +78 -0
- package/src/client/utils.ts +13 -2
- package/src/common/database/config.ts +7 -1
- package/src/common/database/native-database.ts +17 -6
- package/src/common/router.ts +1 -1
- package/src/engine-api/actors.ts +3 -3
- package/src/engine-client/actor-websocket-client.ts +4 -2
- package/src/engine-client/api-endpoints.ts +44 -14
- package/src/engine-client/mod.ts +2 -2
- package/src/registry/config/envoy.ts +1 -1
- package/src/registry/config/index.ts +28 -31
- package/src/registry/index.ts +51 -19
- package/src/registry/napi-runtime.ts +3 -2
- package/src/registry/native.ts +126 -34
- package/src/registry/runtime.ts +27 -10
- package/src/registry/wasm-runtime.ts +6 -3
- package/src/utils/env-vars.ts +15 -10
- package/dist/tsup/chunk-2BIRGEIU.cjs.map +0 -1
- package/dist/tsup/chunk-CORYIKDC.js.map +0 -1
- package/dist/tsup/chunk-I472KTIC.js.map +0 -1
- package/dist/tsup/chunk-JI6GZ2C2.js.map +0 -1
- package/dist/tsup/chunk-MYWZCDML.cjs.map +0 -1
- package/dist/tsup/chunk-P2PHHJMH.cjs.map +0 -1
- package/src/actor/config.test.ts +0 -78
- package/src/actor/keys.test.ts +0 -275
- package/src/actor/utils.test.ts +0 -48
- package/src/client/test.ts +0 -44
- package/src/client/token-provider.test.ts +0 -86
- package/src/common/database/mod.test.ts +0 -364
- package/src/common/database/native-database.test.ts +0 -220
- package/src/common/inline-websocket-adapter.test.ts +0 -51
- package/src/db/drizzle.test.ts +0 -164
- package/src/registry/config/index.test.ts +0 -25
- package/src/registry/run-handler-coordinator.test.ts +0 -252
- package/src/registry/runtime.test.ts +0 -124
- package/src/unstable/migrations.test.ts +0 -170
- package/src/utils/endpoint-parser.test.ts +0 -206
- package/src/utils.test.ts +0 -34
- package/src/workflow/driver.test.ts +0 -62
- /package/dist/tsup/{chunk-4SNS3PYZ.js.map → chunk-3URL73AV.js.map} +0 -0
- /package/dist/tsup/{chunk-EKAQ7HG2.js.map → chunk-442XBCAF.js.map} +0 -0
- /package/dist/tsup/{chunk-OUB7SGSA.js.map → chunk-ANNVZW6B.js.map} +0 -0
- /package/dist/tsup/{chunk-MXV26ZBB.js.map → chunk-OLZ4KAFL.js.map} +0 -0
- /package/dist/tsup/{chunk-H3SGQEHZ.js.map → chunk-WGKL7HMH.js.map} +0 -0
- /package/dist/tsup/{chunk-6LOYTFPZ.js.map → chunk-WGQHG26S.js.map} +0 -0
package/src/actor/config.test.ts
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "vitest";
|
|
2
|
-
import {
|
|
3
|
-
ActorOptionsSchema,
|
|
4
|
-
type DefineRunHandlerOptions,
|
|
5
|
-
defineRunHandler,
|
|
6
|
-
getRunFunction,
|
|
7
|
-
getRunInspectorKind,
|
|
8
|
-
getRunMetadata,
|
|
9
|
-
} from "./config";
|
|
10
|
-
|
|
11
|
-
describe("ActorOptionsSchema", () => {
|
|
12
|
-
test("keeps the Actor Runtime Socket opt-in", () => {
|
|
13
|
-
expect(ActorOptionsSchema.parse({}).enableActorRuntimeSocket).toBe(
|
|
14
|
-
false,
|
|
15
|
-
);
|
|
16
|
-
expect(
|
|
17
|
-
ActorOptionsSchema.parse({ enableActorRuntimeSocket: true })
|
|
18
|
-
.enableActorRuntimeSocket,
|
|
19
|
-
).toBe(true);
|
|
20
|
-
});
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
describe("defineRunHandler", () => {
|
|
24
|
-
test("preserves the callable and exposes static metadata without creating an inspector", () => {
|
|
25
|
-
let inspectorCreates = 0;
|
|
26
|
-
const run = async (value: number): Promise<string> => String(value);
|
|
27
|
-
const defined = defineRunHandler(run, {
|
|
28
|
-
name: "Durable import",
|
|
29
|
-
icon: "diagram-project",
|
|
30
|
-
inspectorKind: "workflow",
|
|
31
|
-
createInspector: () => {
|
|
32
|
-
inspectorCreates += 1;
|
|
33
|
-
return {
|
|
34
|
-
inspector: {
|
|
35
|
-
workflow: {
|
|
36
|
-
getHistory: () => null,
|
|
37
|
-
getState: async () => null,
|
|
38
|
-
onHistoryUpdated: () => () => {},
|
|
39
|
-
replayFromStep: async () => null,
|
|
40
|
-
},
|
|
41
|
-
},
|
|
42
|
-
};
|
|
43
|
-
},
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
const exactType: (value: number) => Promise<string> = defined;
|
|
47
|
-
expect(exactType).toBe(run);
|
|
48
|
-
expect(getRunFunction(defined)).toBe(run);
|
|
49
|
-
expect(getRunMetadata(defined)).toEqual({
|
|
50
|
-
name: "Durable import",
|
|
51
|
-
icon: "diagram-project",
|
|
52
|
-
});
|
|
53
|
-
expect(getRunInspectorKind(defined)).toBe("workflow");
|
|
54
|
-
expect(inspectorCreates).toBe(0);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
test("requires static inspector metadata and its factory together", () => {
|
|
58
|
-
expect(() =>
|
|
59
|
-
defineRunHandler(async () => {}, {
|
|
60
|
-
inspectorKind: "workflow",
|
|
61
|
-
} as unknown as DefineRunHandlerOptions),
|
|
62
|
-
).toThrow("requires inspectorKind and createInspector together");
|
|
63
|
-
expect(() =>
|
|
64
|
-
defineRunHandler(async () => {}, {
|
|
65
|
-
createInspector: () => ({
|
|
66
|
-
inspector: {
|
|
67
|
-
workflow: {
|
|
68
|
-
getHistory: () => null,
|
|
69
|
-
getState: async () => null,
|
|
70
|
-
onHistoryUpdated: () => () => {},
|
|
71
|
-
replayFromStep: async () => null,
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
|
-
}),
|
|
75
|
-
} as unknown as DefineRunHandlerOptions),
|
|
76
|
-
).toThrow("requires inspectorKind and createInspector together");
|
|
77
|
-
});
|
|
78
|
-
});
|
package/src/actor/keys.test.ts
DELETED
|
@@ -1,275 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "vitest";
|
|
2
|
-
import {
|
|
3
|
-
deserializeActorKey,
|
|
4
|
-
EMPTY_KEY,
|
|
5
|
-
KEY_SEPARATOR,
|
|
6
|
-
serializeActorKey,
|
|
7
|
-
} from "./keys";
|
|
8
|
-
|
|
9
|
-
describe("Key serialization and deserialization", () => {
|
|
10
|
-
// Test serialization
|
|
11
|
-
describe("serializeActorKey", () => {
|
|
12
|
-
test("serializes empty key array", () => {
|
|
13
|
-
expect(serializeActorKey([])).toBe(EMPTY_KEY);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
test("serializes single key", () => {
|
|
17
|
-
expect(serializeActorKey(["test"])).toBe("test");
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
test("serializes multiple keys", () => {
|
|
21
|
-
expect(serializeActorKey(["a", "b", "c"])).toBe(
|
|
22
|
-
`a${KEY_SEPARATOR}b${KEY_SEPARATOR}c`,
|
|
23
|
-
);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
test("escapes forward slashes in keys", () => {
|
|
27
|
-
expect(serializeActorKey(["a/b"])).toBe("a\\/b");
|
|
28
|
-
expect(serializeActorKey(["a/b", "c"])).toBe(
|
|
29
|
-
`a\\/b${KEY_SEPARATOR}c`,
|
|
30
|
-
);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
test("escapes empty key marker in keys", () => {
|
|
34
|
-
expect(serializeActorKey([EMPTY_KEY])).toBe(`\\${EMPTY_KEY}`);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
test("handles complex keys", () => {
|
|
38
|
-
expect(serializeActorKey(["a/b", EMPTY_KEY, "c/d"])).toBe(
|
|
39
|
-
`a\\/b${KEY_SEPARATOR}\\${EMPTY_KEY}${KEY_SEPARATOR}c\\/d`,
|
|
40
|
-
);
|
|
41
|
-
});
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
// Test deserialization
|
|
45
|
-
describe("deserializeActorKey", () => {
|
|
46
|
-
test("deserializes empty string", () => {
|
|
47
|
-
expect(deserializeActorKey("")).toEqual([]);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
test("deserializes undefined/null", () => {
|
|
51
|
-
expect(deserializeActorKey(undefined as unknown as string)).toEqual(
|
|
52
|
-
[],
|
|
53
|
-
);
|
|
54
|
-
expect(deserializeActorKey(null as unknown as string)).toEqual([]);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
test("deserializes empty key marker", () => {
|
|
58
|
-
expect(deserializeActorKey(EMPTY_KEY)).toEqual([]);
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
test("deserializes single key", () => {
|
|
62
|
-
expect(deserializeActorKey("test")).toEqual(["test"]);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
test("deserializes multiple keys", () => {
|
|
66
|
-
expect(
|
|
67
|
-
deserializeActorKey(`a${KEY_SEPARATOR}b${KEY_SEPARATOR}c`),
|
|
68
|
-
).toEqual(["a", "b", "c"]);
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
test("deserializes keys with escaped forward slashes", () => {
|
|
72
|
-
expect(deserializeActorKey("a\\/b")).toEqual(["a/b"]);
|
|
73
|
-
expect(deserializeActorKey(`a\\/b${KEY_SEPARATOR}c`)).toEqual([
|
|
74
|
-
"a/b",
|
|
75
|
-
"c",
|
|
76
|
-
]);
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
test("deserializes keys with escaped empty key marker", () => {
|
|
80
|
-
expect(deserializeActorKey(`\\${EMPTY_KEY}`)).toEqual([EMPTY_KEY]);
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
test("deserializes complex keys", () => {
|
|
84
|
-
expect(
|
|
85
|
-
deserializeActorKey(
|
|
86
|
-
`a\\/b${KEY_SEPARATOR}\\${EMPTY_KEY}${KEY_SEPARATOR}c\\/d`,
|
|
87
|
-
),
|
|
88
|
-
).toEqual(["a/b", EMPTY_KEY, "c/d"]);
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
// Test edge cases
|
|
93
|
-
describe("edge cases", () => {
|
|
94
|
-
test("handles empty string parts", () => {
|
|
95
|
-
const testCases: Array<[string[], string]> = [
|
|
96
|
-
[[""], "\\0"],
|
|
97
|
-
[["a", "", "b"], "a/\\0/b"],
|
|
98
|
-
[["", "a"], "\\0/a"],
|
|
99
|
-
[["a", ""], "a/\\0"],
|
|
100
|
-
[["", "", ""], "\\0/\\0/\\0"],
|
|
101
|
-
[["", "a", "", "b", ""], "\\0/a/\\0/b/\\0"],
|
|
102
|
-
[[], "/"],
|
|
103
|
-
[["test"], "test"],
|
|
104
|
-
[["a", "b", "c"], "a/b/c"],
|
|
105
|
-
[["a/b", "c"], "a\\/b/c"],
|
|
106
|
-
[[EMPTY_KEY], "\\/"],
|
|
107
|
-
[["a/b", EMPTY_KEY, "c/d"], "a\\/b/\\//c\\/d"],
|
|
108
|
-
[
|
|
109
|
-
["special\\chars", "more:complex,keys", "final key"],
|
|
110
|
-
"special\\\\chars/more:complex,keys/final key",
|
|
111
|
-
],
|
|
112
|
-
];
|
|
113
|
-
|
|
114
|
-
for (const [key, expectedSerialized] of testCases) {
|
|
115
|
-
const serialized = serializeActorKey(key);
|
|
116
|
-
expect(serialized).toBe(expectedSerialized);
|
|
117
|
-
const deserialized = deserializeActorKey(serialized);
|
|
118
|
-
expect(deserialized).toEqual(key);
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
test("differentiates empty array from array with empty string", () => {
|
|
123
|
-
const emptyArray: string[] = [];
|
|
124
|
-
const arrayWithEmptyString = [""];
|
|
125
|
-
|
|
126
|
-
const serialized1 = serializeActorKey(emptyArray);
|
|
127
|
-
const serialized2 = serializeActorKey(arrayWithEmptyString);
|
|
128
|
-
|
|
129
|
-
expect(serialized1).toBe(EMPTY_KEY); // Should be "/"
|
|
130
|
-
expect(serialized2).not.toBe(EMPTY_KEY); // Should NOT be "/"
|
|
131
|
-
expect(serialized2).toBe("\\0"); // Empty string becomes \0 marker
|
|
132
|
-
|
|
133
|
-
expect(deserializeActorKey(serialized1)).toEqual(emptyArray);
|
|
134
|
-
expect(deserializeActorKey(serialized2)).toEqual(
|
|
135
|
-
arrayWithEmptyString,
|
|
136
|
-
);
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
test("handles mix of empty strings and forward slash (EMPTY_KEY)", () => {
|
|
140
|
-
const testCases: Array<[string[], string]> = [
|
|
141
|
-
[["", EMPTY_KEY, ""], "\\0/\\//\\0"],
|
|
142
|
-
[[EMPTY_KEY, ""], "\\//\\0"],
|
|
143
|
-
[["", EMPTY_KEY], "\\0/\\/"],
|
|
144
|
-
[["a", "", EMPTY_KEY, "", "b"], "a/\\0/\\//\\0/b"],
|
|
145
|
-
];
|
|
146
|
-
|
|
147
|
-
for (const [key, expectedSerialized] of testCases) {
|
|
148
|
-
const serialized = serializeActorKey(key);
|
|
149
|
-
expect(serialized).toBe(expectedSerialized);
|
|
150
|
-
const deserialized = deserializeActorKey(serialized);
|
|
151
|
-
expect(deserialized).toEqual(key);
|
|
152
|
-
}
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
test("handles literal backslash-zero string", () => {
|
|
156
|
-
const testCases: Array<[string[], string]> = [
|
|
157
|
-
[["\\0"], "\\\\0"], // Literal \0 string
|
|
158
|
-
[["a\\0b"], "a\\\\0b"], // Literal \0 in middle
|
|
159
|
-
[["\\0", ""], "\\\\0/\\0"], // Literal \0 with empty string
|
|
160
|
-
[["", "\\0"], "\\0/\\\\0"], // Empty string with literal \0
|
|
161
|
-
];
|
|
162
|
-
|
|
163
|
-
for (const [key, expectedSerialized] of testCases) {
|
|
164
|
-
const serialized = serializeActorKey(key);
|
|
165
|
-
expect(serialized).toBe(expectedSerialized);
|
|
166
|
-
const deserialized = deserializeActorKey(serialized);
|
|
167
|
-
expect(deserialized).toEqual(key);
|
|
168
|
-
}
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
test("handles backslash at the end", () => {
|
|
172
|
-
const key = ["abc\\"];
|
|
173
|
-
const serialized = serializeActorKey(key);
|
|
174
|
-
expect(serialized).toBe("abc\\\\");
|
|
175
|
-
const deserialized = deserializeActorKey(serialized);
|
|
176
|
-
expect(deserialized).toEqual(key);
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
test("handles backslashes in middle of string", () => {
|
|
180
|
-
const testCases: Array<[string[], string]> = [
|
|
181
|
-
[["abc\\def"], "abc\\\\def"],
|
|
182
|
-
[["abc\\\\def"], "abc\\\\\\\\def"],
|
|
183
|
-
[["path\\to\\file"], "path\\\\to\\\\file"],
|
|
184
|
-
];
|
|
185
|
-
|
|
186
|
-
for (const [key, expectedSerialized] of testCases) {
|
|
187
|
-
const serialized = serializeActorKey(key);
|
|
188
|
-
expect(serialized).toBe(expectedSerialized);
|
|
189
|
-
const deserialized = deserializeActorKey(serialized);
|
|
190
|
-
expect(deserialized).toEqual(key);
|
|
191
|
-
}
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
test("handles forward slashes at the end of strings", () => {
|
|
195
|
-
const serialized = serializeActorKey(["abc\\/"]);
|
|
196
|
-
expect(deserializeActorKey(serialized)).toEqual(["abc\\/"]);
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
test("handles mixed backslashes and forward slashes", () => {
|
|
200
|
-
const testCases: Array<[string[], string]> = [
|
|
201
|
-
[["path\\to\\file/dir"], "path\\\\to\\\\file\\/dir"],
|
|
202
|
-
[["file\\with/slash"], "file\\\\with\\/slash"],
|
|
203
|
-
[
|
|
204
|
-
["path\\to\\file", "with/slash"],
|
|
205
|
-
"path\\\\to\\\\file/with\\/slash",
|
|
206
|
-
],
|
|
207
|
-
];
|
|
208
|
-
|
|
209
|
-
for (const [key, expectedSerialized] of testCases) {
|
|
210
|
-
const serialized = serializeActorKey(key);
|
|
211
|
-
expect(serialized).toBe(expectedSerialized);
|
|
212
|
-
const deserialized = deserializeActorKey(serialized);
|
|
213
|
-
expect(deserialized).toEqual(key);
|
|
214
|
-
}
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
test("handles multiple consecutive forward slashes", () => {
|
|
218
|
-
const key = ["a//b"];
|
|
219
|
-
const serialized = serializeActorKey(key);
|
|
220
|
-
expect(serialized).toBe("a\\/\\/b");
|
|
221
|
-
const deserialized = deserializeActorKey(serialized);
|
|
222
|
-
expect(deserialized).toEqual(key);
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
test("handles special characters", () => {
|
|
226
|
-
const key = ["a💻b", "c🔑d"];
|
|
227
|
-
const serialized = serializeActorKey(key);
|
|
228
|
-
expect(serialized).toBe("a💻b/c🔑d");
|
|
229
|
-
const deserialized = deserializeActorKey(serialized);
|
|
230
|
-
expect(deserialized).toEqual(key);
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
test("handles escaped forward slashes immediately after separator", () => {
|
|
234
|
-
const key = ["abc", "/def"];
|
|
235
|
-
const serialized = serializeActorKey(key);
|
|
236
|
-
expect(serialized).toBe(`abc${KEY_SEPARATOR}\\/def`);
|
|
237
|
-
expect(deserializeActorKey(serialized)).toEqual(key);
|
|
238
|
-
});
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
// Test exact key matching
|
|
242
|
-
describe("exact key matching", () => {
|
|
243
|
-
test("differentiates [a,b] from [a,b,c]", () => {
|
|
244
|
-
const key1 = ["a", "b"];
|
|
245
|
-
const key2 = ["a", "b", "c"];
|
|
246
|
-
|
|
247
|
-
const serialized1 = serializeActorKey(key1);
|
|
248
|
-
const serialized2 = serializeActorKey(key2);
|
|
249
|
-
|
|
250
|
-
expect(serialized1).not.toBe(serialized2);
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
test("differentiates [a,b] from [a]", () => {
|
|
254
|
-
const key1 = ["a", "b"];
|
|
255
|
-
const key2 = ["a"];
|
|
256
|
-
|
|
257
|
-
const serialized1 = serializeActorKey(key1);
|
|
258
|
-
const serialized2 = serializeActorKey(key2);
|
|
259
|
-
|
|
260
|
-
expect(serialized1).not.toBe(serialized2);
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
test("differentiates [a/b] from [a,b]", () => {
|
|
264
|
-
const key1 = ["a/b"];
|
|
265
|
-
const key2 = ["a", "b"];
|
|
266
|
-
|
|
267
|
-
const serialized1 = serializeActorKey(key1);
|
|
268
|
-
const serialized2 = serializeActorKey(key2);
|
|
269
|
-
|
|
270
|
-
expect(serialized1).not.toBe(serialized2);
|
|
271
|
-
expect(deserializeActorKey(serialized1)).toEqual(key1);
|
|
272
|
-
expect(deserializeActorKey(serialized2)).toEqual(key2);
|
|
273
|
-
});
|
|
274
|
-
});
|
|
275
|
-
});
|
package/src/actor/utils.test.ts
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from "vitest";
|
|
2
|
-
import { isConnStatePath, isStatePath } from "./utils";
|
|
3
|
-
|
|
4
|
-
describe("isStatePath", () => {
|
|
5
|
-
test("matches exact state", () => {
|
|
6
|
-
expect(isStatePath("state")).toBe(true);
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
test("matches nested state paths", () => {
|
|
10
|
-
expect(isStatePath("state.foo")).toBe(true);
|
|
11
|
-
expect(isStatePath("state.foo.bar")).toBe(true);
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
test("does not match other paths", () => {
|
|
15
|
-
expect(isStatePath("connections")).toBe(false);
|
|
16
|
-
expect(isStatePath("stateX")).toBe(false);
|
|
17
|
-
expect(isStatePath("mystate")).toBe(false);
|
|
18
|
-
});
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
describe("isConnStatePath", () => {
|
|
22
|
-
test("matches connection state paths", () => {
|
|
23
|
-
expect(isConnStatePath("connections.0.state")).toBe(true);
|
|
24
|
-
expect(isConnStatePath("connections.123.state")).toBe(true);
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
test("matches nested connection state paths", () => {
|
|
28
|
-
expect(isConnStatePath("connections.0.state.foo")).toBe(true);
|
|
29
|
-
expect(isConnStatePath("connections.5.state.bar.baz")).toBe(true);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
test("does not match non-state connection paths", () => {
|
|
33
|
-
expect(isConnStatePath("connections.0.params")).toBe(false);
|
|
34
|
-
expect(isConnStatePath("connections.0.token")).toBe(false);
|
|
35
|
-
expect(isConnStatePath("connections.0")).toBe(false);
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
test("does not match other paths", () => {
|
|
39
|
-
expect(isConnStatePath("state")).toBe(false);
|
|
40
|
-
expect(isConnStatePath("connections")).toBe(false);
|
|
41
|
-
expect(isConnStatePath("other.0.state")).toBe(false);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
test("does not match malformed paths", () => {
|
|
45
|
-
expect(isConnStatePath("connections.state")).toBe(false);
|
|
46
|
-
expect(isConnStatePath("connections.0.stateX")).toBe(false);
|
|
47
|
-
});
|
|
48
|
-
});
|
package/src/client/test.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
//import { exec as execCallback } from "node:child_process";
|
|
2
|
-
//import { setupLogging } from "@/common//log";
|
|
3
|
-
//import type { ClientOptions } from "./client";
|
|
4
|
-
//import { InternalError } from "./errors";
|
|
5
|
-
//import { Client } from "./mod.ts";
|
|
6
|
-
//
|
|
7
|
-
///**
|
|
8
|
-
// * Uses the Rivet CLI to read the manager endpoint to connect to. This allows
|
|
9
|
-
// * for writing tests that run locally without hardcoding the manager endpoint.
|
|
10
|
-
// */
|
|
11
|
-
//export async function readEndpointFromCli(): Promise<string> {
|
|
12
|
-
// // Read endpoint
|
|
13
|
-
// const cliPath = process.env.RIVET_CLI_PATH ?? "rivet";
|
|
14
|
-
//
|
|
15
|
-
// try {
|
|
16
|
-
// const { stdout, stderr } = await new Promise<{
|
|
17
|
-
// stdout: string;
|
|
18
|
-
// stderr: string;
|
|
19
|
-
// }>((resolve, reject) => {
|
|
20
|
-
// execCallback(`${cliPath} manager endpoint`, (error, stdout, stderr) => {
|
|
21
|
-
// if (error) reject(error);
|
|
22
|
-
// else resolve({ stdout, stderr });
|
|
23
|
-
// });
|
|
24
|
-
// });
|
|
25
|
-
//
|
|
26
|
-
// if (stderr) {
|
|
27
|
-
// throw new Error(stderr);
|
|
28
|
-
// }
|
|
29
|
-
//
|
|
30
|
-
// // Decode output
|
|
31
|
-
// return stdout.trim();
|
|
32
|
-
// } catch (error) {
|
|
33
|
-
// throw new InternalError(`Read endpoint failed: ${error}`);
|
|
34
|
-
// }
|
|
35
|
-
//}
|
|
36
|
-
//
|
|
37
|
-
//export class TestClient extends Client {
|
|
38
|
-
// public constructor(opts?: ClientOptions) {
|
|
39
|
-
// // Setup logging automatically
|
|
40
|
-
// setupLogging();
|
|
41
|
-
//
|
|
42
|
-
// super(readEndpointFromCli(), opts);
|
|
43
|
-
// }
|
|
44
|
-
//}
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test, vi } from "vitest";
|
|
2
|
-
import {
|
|
3
|
-
isInvalidToken,
|
|
4
|
-
isInvalidTokenResponse,
|
|
5
|
-
TokenProvider,
|
|
6
|
-
} from "./token-provider";
|
|
7
|
-
|
|
8
|
-
describe("renewable client tokens", () => {
|
|
9
|
-
test("single-flights initial issuance and concurrent rejection refreshes", async () => {
|
|
10
|
-
const getToken = vi.fn(
|
|
11
|
-
async ({ forceRefresh }: { forceRefresh: boolean }) =>
|
|
12
|
-
forceRefresh ? "renewed" : "initial",
|
|
13
|
-
);
|
|
14
|
-
const provider = new TokenProvider(getToken);
|
|
15
|
-
expect(
|
|
16
|
-
await Promise.all([provider.current(), provider.current()]),
|
|
17
|
-
).toEqual(["initial", "initial"]);
|
|
18
|
-
expect(getToken).toHaveBeenCalledTimes(1);
|
|
19
|
-
expect(
|
|
20
|
-
await Promise.all([
|
|
21
|
-
provider.refreshIfCurrent("initial"),
|
|
22
|
-
provider.refreshIfCurrent("initial"),
|
|
23
|
-
]),
|
|
24
|
-
).toEqual(["renewed", "renewed"]);
|
|
25
|
-
expect(getToken).toHaveBeenCalledTimes(2);
|
|
26
|
-
expect(await provider.refreshIfCurrent("initial")).toBe("renewed");
|
|
27
|
-
expect(getToken).toHaveBeenCalledTimes(2);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
test("retries failed issuance and refuses empty credentials", async () => {
|
|
31
|
-
const getToken = vi
|
|
32
|
-
.fn()
|
|
33
|
-
.mockRejectedValueOnce(new Error("issuer down"))
|
|
34
|
-
.mockResolvedValueOnce("ok");
|
|
35
|
-
const provider = new TokenProvider(getToken);
|
|
36
|
-
await expect(provider.current()).rejects.toThrow("issuer down");
|
|
37
|
-
expect(await provider.current()).toBe("ok");
|
|
38
|
-
await expect(
|
|
39
|
-
new TokenProvider(async () => "").current(),
|
|
40
|
-
).rejects.toThrow("nonempty");
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
test("refreshes before a known JWT expiry and treats opaque tokens as unexpiring hints", async () => {
|
|
44
|
-
const payload = btoa(
|
|
45
|
-
JSON.stringify({ exp: Math.floor(Date.now() / 1_000) + 1 }),
|
|
46
|
-
).replaceAll("=", "");
|
|
47
|
-
const getToken = vi.fn(async () => `header.${payload}.signature`);
|
|
48
|
-
const provider = new TokenProvider(getToken);
|
|
49
|
-
await provider.current();
|
|
50
|
-
await provider.current();
|
|
51
|
-
expect(getToken).toHaveBeenCalledTimes(2);
|
|
52
|
-
const opaque = vi.fn(async () => "opaque");
|
|
53
|
-
const opaqueProvider = new TokenProvider(opaque);
|
|
54
|
-
await opaqueProvider.current();
|
|
55
|
-
await opaqueProvider.current();
|
|
56
|
-
expect(opaque).toHaveBeenCalledTimes(1);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
test("only confirmed 401 invalid/expired errors permit renewal", () => {
|
|
60
|
-
expect(isInvalidToken("auth", "invalid_token")).toBe(true);
|
|
61
|
-
expect(isInvalidToken("auth", "token_expired")).toBe(true);
|
|
62
|
-
for (const code of [
|
|
63
|
-
"insufficient_permissions",
|
|
64
|
-
"verification_unavailable",
|
|
65
|
-
"issuance_unavailable",
|
|
66
|
-
]) {
|
|
67
|
-
expect(isInvalidToken("auth", code)).toBe(false);
|
|
68
|
-
}
|
|
69
|
-
expect(
|
|
70
|
-
isInvalidTokenResponse(
|
|
71
|
-
new Response(null, {
|
|
72
|
-
status: 401,
|
|
73
|
-
headers: { "x-rivet-error": "auth.token_expired" },
|
|
74
|
-
}),
|
|
75
|
-
),
|
|
76
|
-
).toBe(true);
|
|
77
|
-
expect(
|
|
78
|
-
isInvalidTokenResponse(
|
|
79
|
-
new Response(null, {
|
|
80
|
-
status: 503,
|
|
81
|
-
headers: { "x-rivet-error": "auth.token_expired" },
|
|
82
|
-
}),
|
|
83
|
-
),
|
|
84
|
-
).toBe(false);
|
|
85
|
-
});
|
|
86
|
-
});
|