@sponson/sim 0.0.0-stage → 0.4.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/LICENSE +202 -0
- package/README.md +4 -2
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +21 -0
- package/dist/bin.js.map +1 -0
- package/dist/chaos.d.ts +70 -0
- package/dist/chaos.js +78 -0
- package/dist/chaos.js.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.js +42 -0
- package/dist/index.js.map +1 -0
- package/dist/provider.d.ts +99 -0
- package/dist/provider.js +62 -0
- package/dist/provider.js.map +1 -0
- package/dist/routes/clerk.d.ts +33 -0
- package/dist/routes/clerk.js +85 -0
- package/dist/routes/clerk.js.map +1 -0
- package/dist/routes/neon.d.ts +73 -0
- package/dist/routes/neon.js +184 -0
- package/dist/routes/neon.js.map +1 -0
- package/dist/routes/vercel.d.ts +114 -0
- package/dist/routes/vercel.js +370 -0
- package/dist/routes/vercel.js.map +1 -0
- package/dist/server.d.ts +4 -0
- package/dist/server.js +130 -0
- package/dist/server.js.map +1 -0
- package/dist/state.d.ts +90 -0
- package/dist/state.js +109 -0
- package/dist/state.js.map +1 -0
- package/package.json +47 -3
package/dist/state.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory state for the fake cloud: the core (chaos, write log, ids) plus one state object per registered
|
|
3
|
+
* provider, reachable as `state.<provider>` (e.g. `state.vercel.projects`).
|
|
4
|
+
*/
|
|
5
|
+
import { CHAOS_KEYS, chaosFor, defaultChaos } from "./chaos.js";
|
|
6
|
+
import { clerkSim } from "./routes/clerk.js";
|
|
7
|
+
import { neonSim } from "./routes/neon.js";
|
|
8
|
+
import { vercelSim } from "./routes/vercel.js";
|
|
9
|
+
/**
|
|
10
|
+
* Every simulated provider, by URL prefix (`/<name>/…`), drift prefix (`<name>.…`), seed key and state key.
|
|
11
|
+
* Order matters only for determinism: resets seed providers (and so allocate ids) in this order.
|
|
12
|
+
*/
|
|
13
|
+
export const PROVIDERS = { vercel: vercelSim, neon: neonSim, clerk: clerkSim };
|
|
14
|
+
/** The demo projects every provider starts with when a seed does not name it. */
|
|
15
|
+
export const DEFAULT_SEED = Object.fromEntries(Object.entries(PROVIDERS).map(([name, p]) => [name, p.defaultSeed]));
|
|
16
|
+
/** The registry as the core sees it: names and type-erased providers. */
|
|
17
|
+
export function providerEntries() {
|
|
18
|
+
return Object.entries(PROVIDERS);
|
|
19
|
+
}
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging
|
|
21
|
+
export class SimState {
|
|
22
|
+
chaos = defaultChaos();
|
|
23
|
+
writes = [];
|
|
24
|
+
seq = 0;
|
|
25
|
+
held = [];
|
|
26
|
+
constructor(seed) {
|
|
27
|
+
this.reset(seed);
|
|
28
|
+
}
|
|
29
|
+
nextId(prefix) {
|
|
30
|
+
this.seq += 1;
|
|
31
|
+
return `${prefix}${this.seq}`;
|
|
32
|
+
}
|
|
33
|
+
/** The state object of one provider. */
|
|
34
|
+
provider(name) {
|
|
35
|
+
return this[name];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Clear everything (state, chaos, writes) and apply a seed. A partial seed replaces only the providers it names;
|
|
39
|
+
* the others keep their defaults, so `{ clerk: {...} }` still has the demo Vercel and Neon projects.
|
|
40
|
+
*/
|
|
41
|
+
reset(seed) {
|
|
42
|
+
const s = seed ?? {};
|
|
43
|
+
this.release();
|
|
44
|
+
this.chaos = defaultChaos();
|
|
45
|
+
this.writes = [];
|
|
46
|
+
this.seq = 0;
|
|
47
|
+
const states = this;
|
|
48
|
+
for (const [name, p] of providerEntries())
|
|
49
|
+
states[name] = p.reset(this, name in s ? s[name] : p.defaultSeed);
|
|
50
|
+
if (s.chaos)
|
|
51
|
+
this.applyChaos(s.chaos);
|
|
52
|
+
}
|
|
53
|
+
/** Merge a chaos request; drift is applied to state right away and not kept. */
|
|
54
|
+
applyChaos(req) {
|
|
55
|
+
const { drift, ...rest } = req;
|
|
56
|
+
// The request arrives as JSON over HTTP: its keys are checked here, not by the type.
|
|
57
|
+
const entries = Object.entries(rest);
|
|
58
|
+
for (const [k, v] of entries) {
|
|
59
|
+
// A misspelt key would silently leave the test running without its chaos.
|
|
60
|
+
if (!CHAOS_KEYS.has(k))
|
|
61
|
+
throw new Error(`unknown chaos key: ${k} (known: ${[...CHAOS_KEYS].join(", ")}, drift)`);
|
|
62
|
+
if (v !== undefined)
|
|
63
|
+
Object.assign(this.chaos, { [k]: v });
|
|
64
|
+
}
|
|
65
|
+
if (drift)
|
|
66
|
+
for (const [key, value] of Object.entries(drift))
|
|
67
|
+
this.applyDrift(key, value);
|
|
68
|
+
return this.chaos;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Drift: change provider state behind the client's back, like a human in a console. The key is
|
|
72
|
+
* `<provider>.<rest>`, or `<provider>:<project>.<rest>` to limit it to one project; each provider documents
|
|
73
|
+
* the `<rest>` forms it accepts in its `drift`. Values are a new value, "delete", or "recreate" (delete and
|
|
74
|
+
* re-create with the same name and a new id).
|
|
75
|
+
*/
|
|
76
|
+
applyDrift(key, value) {
|
|
77
|
+
const m = key.match(/^([a-z][a-z0-9_-]*)(?::([^.]+))?\.(.+)$/);
|
|
78
|
+
const entry = m ? providerEntries().find(([name]) => name === m[1]) : undefined;
|
|
79
|
+
if (!m || !entry)
|
|
80
|
+
throw new Error(`unknown drift key: ${key}`);
|
|
81
|
+
const [name, p] = entry;
|
|
82
|
+
if (!p.drift(this, this.provider(name), { key, rest: m[3], value, ...(m[2] !== undefined ? { only: m[2] } : {}) }))
|
|
83
|
+
throw new Error(`unknown drift key: ${key}`);
|
|
84
|
+
}
|
|
85
|
+
/** Requests currently held by chaos `hold_next`. */
|
|
86
|
+
get heldCount() {
|
|
87
|
+
return this.held.length;
|
|
88
|
+
}
|
|
89
|
+
/** Park the calling request until `release()`. */
|
|
90
|
+
hold() {
|
|
91
|
+
return new Promise((resolve) => this.held.push(resolve));
|
|
92
|
+
}
|
|
93
|
+
/** Let every held request proceed; returns how many there were. */
|
|
94
|
+
release() {
|
|
95
|
+
const held = this.held;
|
|
96
|
+
this.held = [];
|
|
97
|
+
for (const go of held)
|
|
98
|
+
go();
|
|
99
|
+
return held.length;
|
|
100
|
+
}
|
|
101
|
+
/** Decide what chaos does to this request, consuming one count when it does something. */
|
|
102
|
+
chaosFor(method, path) {
|
|
103
|
+
return chaosFor(this.chaos, method, path);
|
|
104
|
+
}
|
|
105
|
+
snapshot() {
|
|
106
|
+
return { ...Object.fromEntries(providerEntries().map(([name]) => [name, this.provider(name)])), chaos: this.chaos };
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,50 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sponson/sim",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "Local fake cloud for Sponson: Vercel, Neon and Clerk API subsets with chaos injection.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"sponson",
|
|
7
|
+
"fake-cloud",
|
|
8
|
+
"api-simulator",
|
|
9
|
+
"chaos-testing",
|
|
10
|
+
"vercel",
|
|
11
|
+
"neon",
|
|
12
|
+
"clerk",
|
|
13
|
+
"testing"
|
|
14
|
+
],
|
|
15
|
+
"license": "Apache-2.0",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/MishaBear94/Sponson.git",
|
|
19
|
+
"directory": "packages/sim"
|
|
20
|
+
},
|
|
21
|
+
"engines": {
|
|
22
|
+
"node": ">=22"
|
|
23
|
+
},
|
|
24
|
+
"type": "module",
|
|
25
|
+
"main": "./dist/index.js",
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"default": "./dist/index.js"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"bin": {
|
|
34
|
+
"sponson-sim": "./dist/bin.js"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {},
|
|
37
|
+
"files": [
|
|
38
|
+
"dist",
|
|
39
|
+
"!dist/.tsbuildinfo",
|
|
40
|
+
"README.md",
|
|
41
|
+
"LICENSE"
|
|
42
|
+
],
|
|
43
|
+
"homepage": "https://sponson.mintlify.site",
|
|
44
|
+
"bugs": {
|
|
45
|
+
"url": "https://github.com/MishaBear94/Sponson/issues"
|
|
46
|
+
},
|
|
47
|
+
"scripts": {
|
|
48
|
+
"build": "tsc -b"
|
|
49
|
+
}
|
|
6
50
|
}
|