@runnee/sdk 0.0.0-stage → 0.1.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/CHANGELOG.md +9 -0
- package/CONTRIBUTING.md +29 -0
- package/LICENSE +21 -0
- package/README.md +76 -2
- package/RELEASING.md +32 -0
- package/SECURITY.md +11 -0
- package/lib/cjs/contracts.d.ts +1279 -0
- package/lib/cjs/contracts.js +1391 -0
- package/lib/cjs/errors.d.ts +34 -0
- package/lib/cjs/errors.js +49 -0
- package/lib/cjs/http.d.ts +25 -0
- package/lib/cjs/http.js +260 -0
- package/lib/cjs/index.d.ts +57 -0
- package/lib/cjs/index.js +86 -0
- package/lib/cjs/package.json +2 -0
- package/lib/cjs/types.d.ts +304 -0
- package/lib/cjs/types.js +2 -0
- package/lib/cjs/validation.d.ts +3 -0
- package/lib/cjs/validation.js +102 -0
- package/lib/esm/contracts.d.ts +1279 -0
- package/lib/esm/contracts.js +1388 -0
- package/lib/esm/errors.d.ts +34 -0
- package/lib/esm/errors.js +34 -0
- package/lib/esm/http.d.ts +25 -0
- package/lib/esm/http.js +256 -0
- package/lib/esm/index.d.ts +57 -0
- package/lib/esm/index.js +68 -0
- package/lib/esm/types.d.ts +304 -0
- package/lib/esm/types.js +1 -0
- package/lib/esm/validation.d.ts +3 -0
- package/lib/esm/validation.js +98 -0
- package/openapi.json +7932 -0
- package/package.json +64 -4
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
export type Error = {
|
|
2
|
+
statusCode?: number;
|
|
3
|
+
message?: string | string[];
|
|
4
|
+
error?: string;
|
|
5
|
+
code?: string;
|
|
6
|
+
[key: string]: unknown;
|
|
7
|
+
};
|
|
8
|
+
export type ExecuteRequest = {
|
|
9
|
+
code: string;
|
|
10
|
+
mode?: 'dry-run' | 'live';
|
|
11
|
+
event?: {
|
|
12
|
+
[key: string]: unknown;
|
|
13
|
+
};
|
|
14
|
+
retainSource?: boolean;
|
|
15
|
+
scriptName?: string;
|
|
16
|
+
secretNames?: string[];
|
|
17
|
+
scriptId?: string;
|
|
18
|
+
};
|
|
19
|
+
export type Diagnostic = {
|
|
20
|
+
code?: string;
|
|
21
|
+
message: string;
|
|
22
|
+
line?: number;
|
|
23
|
+
column?: number;
|
|
24
|
+
filename?: string;
|
|
25
|
+
snippet?: string;
|
|
26
|
+
[key: string]: unknown;
|
|
27
|
+
};
|
|
28
|
+
export type Timings = {
|
|
29
|
+
[key: string]: number;
|
|
30
|
+
};
|
|
31
|
+
export type ExecutionResult = {
|
|
32
|
+
durationMs: number;
|
|
33
|
+
instructions: number;
|
|
34
|
+
returnValue?: unknown;
|
|
35
|
+
replies: {
|
|
36
|
+
count: number;
|
|
37
|
+
lastPayload?: unknown;
|
|
38
|
+
};
|
|
39
|
+
counters?: {
|
|
40
|
+
dbOps: number;
|
|
41
|
+
httpCalls: number;
|
|
42
|
+
};
|
|
43
|
+
explain?: {
|
|
44
|
+
[key: string]: unknown;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
export type ExecuteResponse = {
|
|
48
|
+
success: boolean;
|
|
49
|
+
mocked?: boolean;
|
|
50
|
+
error?: Diagnostic;
|
|
51
|
+
executionResult?: ExecutionResult;
|
|
52
|
+
replies?: unknown[];
|
|
53
|
+
metrics?: {
|
|
54
|
+
[key: string]: unknown;
|
|
55
|
+
};
|
|
56
|
+
telemetryRecorded?: boolean;
|
|
57
|
+
executionId?: string | null;
|
|
58
|
+
replayed?: boolean;
|
|
59
|
+
originalResultOmitted?: boolean;
|
|
60
|
+
[key: string]: unknown;
|
|
61
|
+
};
|
|
62
|
+
export type Policy = {
|
|
63
|
+
[key: string]: unknown;
|
|
64
|
+
};
|
|
65
|
+
export type Execution = {
|
|
66
|
+
id: string;
|
|
67
|
+
scriptName?: string | null;
|
|
68
|
+
mode: string;
|
|
69
|
+
status: string;
|
|
70
|
+
durationMs: number;
|
|
71
|
+
instructionsUsed: number;
|
|
72
|
+
errorCode?: string | null;
|
|
73
|
+
httpCalls?: number;
|
|
74
|
+
dbOps?: number;
|
|
75
|
+
errorMessage?: string | null;
|
|
76
|
+
hasSource?: boolean;
|
|
77
|
+
timings?: Timings;
|
|
78
|
+
createdAt: string;
|
|
79
|
+
expiresAt?: string;
|
|
80
|
+
[key: string]: unknown;
|
|
81
|
+
};
|
|
82
|
+
export type ExecutionDetail = {
|
|
83
|
+
id: string;
|
|
84
|
+
scriptName?: string | null;
|
|
85
|
+
mode: string;
|
|
86
|
+
status: string;
|
|
87
|
+
durationMs: number;
|
|
88
|
+
instructionsUsed: number;
|
|
89
|
+
errorCode?: string | null;
|
|
90
|
+
httpCalls?: number;
|
|
91
|
+
dbOps?: number;
|
|
92
|
+
errorMessage?: string | null;
|
|
93
|
+
hasSource?: boolean;
|
|
94
|
+
timings?: Timings;
|
|
95
|
+
createdAt: string;
|
|
96
|
+
expiresAt?: string;
|
|
97
|
+
sourceCode?: string | null;
|
|
98
|
+
outputPreview?: string | null;
|
|
99
|
+
[key: string]: unknown;
|
|
100
|
+
};
|
|
101
|
+
export type ExecutionPage = {
|
|
102
|
+
items: Execution[];
|
|
103
|
+
nextCursor: string | null;
|
|
104
|
+
policy: Policy;
|
|
105
|
+
};
|
|
106
|
+
export type Script = {
|
|
107
|
+
id: string;
|
|
108
|
+
name: string;
|
|
109
|
+
currentVersion: number;
|
|
110
|
+
createdAt: string;
|
|
111
|
+
updatedAt: string;
|
|
112
|
+
};
|
|
113
|
+
export type ScriptDetail = {
|
|
114
|
+
id: string;
|
|
115
|
+
name: string;
|
|
116
|
+
currentVersion: number;
|
|
117
|
+
createdAt: string;
|
|
118
|
+
updatedAt: string;
|
|
119
|
+
code: string;
|
|
120
|
+
versions: {
|
|
121
|
+
version: number;
|
|
122
|
+
createdAt: string;
|
|
123
|
+
bytes: number;
|
|
124
|
+
}[];
|
|
125
|
+
[key: string]: unknown;
|
|
126
|
+
};
|
|
127
|
+
export type ScriptList = {
|
|
128
|
+
items: Script[];
|
|
129
|
+
policy: Policy;
|
|
130
|
+
};
|
|
131
|
+
export type ScriptCreate = {
|
|
132
|
+
name: string;
|
|
133
|
+
code: string;
|
|
134
|
+
};
|
|
135
|
+
export type ScriptUpdate = {
|
|
136
|
+
name: string;
|
|
137
|
+
code: string;
|
|
138
|
+
expectedVersion: number;
|
|
139
|
+
};
|
|
140
|
+
export type ScriptRestore = {
|
|
141
|
+
version: number;
|
|
142
|
+
expectedVersion: number;
|
|
143
|
+
};
|
|
144
|
+
export type ScriptVersion = {
|
|
145
|
+
version: number;
|
|
146
|
+
code: string;
|
|
147
|
+
createdAt: string;
|
|
148
|
+
};
|
|
149
|
+
export type Deleted = {
|
|
150
|
+
deleted: boolean;
|
|
151
|
+
};
|
|
152
|
+
export type Storage = {
|
|
153
|
+
policy: Policy;
|
|
154
|
+
history: {
|
|
155
|
+
count: number;
|
|
156
|
+
bytes: number;
|
|
157
|
+
};
|
|
158
|
+
scripts: {
|
|
159
|
+
count: number;
|
|
160
|
+
versions: number;
|
|
161
|
+
bytes: number;
|
|
162
|
+
};
|
|
163
|
+
};
|
|
164
|
+
export type Secret = {
|
|
165
|
+
name: string;
|
|
166
|
+
allowInline: boolean;
|
|
167
|
+
scriptIds: string[];
|
|
168
|
+
version: number;
|
|
169
|
+
createdAt: string;
|
|
170
|
+
updatedAt: string;
|
|
171
|
+
};
|
|
172
|
+
export type SecretList = {
|
|
173
|
+
items: Secret[];
|
|
174
|
+
};
|
|
175
|
+
export type SecretCreate = {
|
|
176
|
+
name: string;
|
|
177
|
+
value: string;
|
|
178
|
+
allowInline?: boolean;
|
|
179
|
+
scriptIds?: string[];
|
|
180
|
+
};
|
|
181
|
+
export type SecretUpdate = {
|
|
182
|
+
value?: string;
|
|
183
|
+
allowInline?: boolean;
|
|
184
|
+
scriptIds?: string[];
|
|
185
|
+
};
|
|
186
|
+
export type SandboxLimits = {
|
|
187
|
+
timeoutMs: number;
|
|
188
|
+
maxInstructions: number;
|
|
189
|
+
maxMemoryMb: number;
|
|
190
|
+
};
|
|
191
|
+
export type Sandbox = {
|
|
192
|
+
plan: string;
|
|
193
|
+
configurable: boolean;
|
|
194
|
+
limits: SandboxLimits;
|
|
195
|
+
defaults: SandboxLimits;
|
|
196
|
+
maxLimits: SandboxLimits;
|
|
197
|
+
};
|
|
198
|
+
export type Plan = {
|
|
199
|
+
id: string;
|
|
200
|
+
configurable?: boolean;
|
|
201
|
+
limits: SandboxLimits;
|
|
202
|
+
maxLimits?: SandboxLimits;
|
|
203
|
+
name: string;
|
|
204
|
+
monthlyUsd?: number | null;
|
|
205
|
+
yearlyMonthlyUsd?: number | null;
|
|
206
|
+
usageUsdPer1k?: number;
|
|
207
|
+
executionsPerMonth: number | null;
|
|
208
|
+
timeoutMs?: number;
|
|
209
|
+
features?: string[];
|
|
210
|
+
[key: string]: unknown;
|
|
211
|
+
};
|
|
212
|
+
export type Plans = {
|
|
213
|
+
configured: boolean;
|
|
214
|
+
plans: Plan[];
|
|
215
|
+
};
|
|
216
|
+
export type BillingStatus = {
|
|
217
|
+
configured: boolean;
|
|
218
|
+
plan: Plan;
|
|
219
|
+
subscription: {
|
|
220
|
+
status?: string;
|
|
221
|
+
interval?: string | null;
|
|
222
|
+
currentPeriodEnd?: string | null;
|
|
223
|
+
cancelAtPeriodEnd?: boolean;
|
|
224
|
+
hasCustomer?: boolean;
|
|
225
|
+
[key: string]: unknown;
|
|
226
|
+
} | null;
|
|
227
|
+
usage: {
|
|
228
|
+
executions: number;
|
|
229
|
+
limit: number | null;
|
|
230
|
+
resetsAt: string;
|
|
231
|
+
};
|
|
232
|
+
};
|
|
233
|
+
export type UsageSummary = {
|
|
234
|
+
windowDays: number;
|
|
235
|
+
totalExecutions: number;
|
|
236
|
+
successfulExecutions: number;
|
|
237
|
+
failedExecutions: number;
|
|
238
|
+
averageDurationMs: number;
|
|
239
|
+
latest: {
|
|
240
|
+
[key: string]: unknown;
|
|
241
|
+
}[];
|
|
242
|
+
};
|
|
243
|
+
export type UsageHistory = {
|
|
244
|
+
days: number;
|
|
245
|
+
total: number;
|
|
246
|
+
success: number;
|
|
247
|
+
failed: number;
|
|
248
|
+
successRate: number;
|
|
249
|
+
daily: {
|
|
250
|
+
date: string;
|
|
251
|
+
total: number;
|
|
252
|
+
success: number;
|
|
253
|
+
failed: number;
|
|
254
|
+
avgDurationMs: number;
|
|
255
|
+
}[];
|
|
256
|
+
topScripts: {
|
|
257
|
+
name: string;
|
|
258
|
+
count: number;
|
|
259
|
+
}[];
|
|
260
|
+
topScriptsSample: {
|
|
261
|
+
days: number;
|
|
262
|
+
limit: number;
|
|
263
|
+
};
|
|
264
|
+
apiKeys: {
|
|
265
|
+
active: number;
|
|
266
|
+
lastUsedAt: string | null;
|
|
267
|
+
};
|
|
268
|
+
};
|
|
269
|
+
export type TelemetryExecution = {
|
|
270
|
+
scriptName?: string;
|
|
271
|
+
mode?: string;
|
|
272
|
+
status: string;
|
|
273
|
+
durationMs: number;
|
|
274
|
+
instructionsUsed: number;
|
|
275
|
+
memoryUsageKb?: number;
|
|
276
|
+
errorCode?: string;
|
|
277
|
+
metadata?: {
|
|
278
|
+
[key: string]: unknown;
|
|
279
|
+
};
|
|
280
|
+
};
|
|
281
|
+
export type TelemetryEvent = {
|
|
282
|
+
eventName: string;
|
|
283
|
+
pagePath?: string;
|
|
284
|
+
sessionId?: string;
|
|
285
|
+
fingerprintHash?: string;
|
|
286
|
+
properties?: {
|
|
287
|
+
[key: string]: string | number | boolean | null;
|
|
288
|
+
};
|
|
289
|
+
};
|
|
290
|
+
export type TelemetryRecorded = {
|
|
291
|
+
[key: string]: unknown;
|
|
292
|
+
} | string | null;
|
|
293
|
+
export type Accepted = {
|
|
294
|
+
accepted: boolean;
|
|
295
|
+
};
|
|
296
|
+
export type Health = {
|
|
297
|
+
status: 'operational' | 'degraded';
|
|
298
|
+
timestamp: string;
|
|
299
|
+
services: {
|
|
300
|
+
id: string;
|
|
301
|
+
name: string;
|
|
302
|
+
status: 'operational' | 'degraded';
|
|
303
|
+
}[];
|
|
304
|
+
};
|
package/lib/cjs/types.js
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validate = validate;
|
|
4
|
+
exports.encodeRequest = encodeRequest;
|
|
5
|
+
const contracts_js_1 = require("./contracts.js");
|
|
6
|
+
const errors_js_1 = require("./errors.js");
|
|
7
|
+
const schemas = contracts_js_1.contracts.schemas;
|
|
8
|
+
function valid(value, s, depth = 0) {
|
|
9
|
+
if (depth > 40)
|
|
10
|
+
return false;
|
|
11
|
+
if (s.$ref)
|
|
12
|
+
return valid(value, schemas[s.$ref.split('/').pop()], depth + 1);
|
|
13
|
+
if (s.anyOf)
|
|
14
|
+
return s.anyOf.some((sub) => valid(value, sub, depth + 1));
|
|
15
|
+
if (s.enum && !s.enum.includes(value))
|
|
16
|
+
return false;
|
|
17
|
+
if (s.type === 'null')
|
|
18
|
+
return value === null;
|
|
19
|
+
if (s.type === 'boolean')
|
|
20
|
+
return typeof value === 'boolean';
|
|
21
|
+
if (s.type === 'number' || s.type === 'integer')
|
|
22
|
+
return (typeof value === 'number' &&
|
|
23
|
+
Number.isFinite(value) &&
|
|
24
|
+
(s.type !== 'integer' || Number.isSafeInteger(value)) &&
|
|
25
|
+
(s.minimum === undefined || value >= s.minimum) &&
|
|
26
|
+
(s.maximum === undefined || value <= s.maximum));
|
|
27
|
+
if (s.type === 'string')
|
|
28
|
+
return (typeof value === 'string' &&
|
|
29
|
+
(s.minLength === undefined || value.length >= s.minLength) &&
|
|
30
|
+
(s.maxLength === undefined || value.length <= s.maxLength) &&
|
|
31
|
+
(!s.pattern || new RegExp(s.pattern).test(value)) &&
|
|
32
|
+
(s.format !== 'uuid' || /^[a-f\d]{8}-(?:[a-f\d]{4}-){3}[a-f\d]{12}$/i.test(value)));
|
|
33
|
+
if (s.type === 'array')
|
|
34
|
+
return (Array.isArray(value) &&
|
|
35
|
+
(s.minItems === undefined || value.length >= s.minItems) &&
|
|
36
|
+
(s.maxItems === undefined || value.length <= s.maxItems) &&
|
|
37
|
+
(!s.uniqueItems || new Set(value.map((v) => JSON.stringify(v))).size === value.length) &&
|
|
38
|
+
value.every((v) => valid(v, s.items ?? {}, depth + 1)));
|
|
39
|
+
if (s.type === 'object') {
|
|
40
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
41
|
+
return false;
|
|
42
|
+
const record = value;
|
|
43
|
+
return ((!s.minProperties || Object.keys(record).length >= s.minProperties) &&
|
|
44
|
+
(s.required ?? []).every((k) => Object.hasOwn(record, k)) &&
|
|
45
|
+
Object.entries(record).every(([k, v]) => Object.hasOwn(s.properties ?? {}, k)
|
|
46
|
+
? valid(v, s.properties[k], depth + 1)
|
|
47
|
+
: s.additionalProperties === false
|
|
48
|
+
? false
|
|
49
|
+
: typeof s.additionalProperties === 'object'
|
|
50
|
+
? valid(v, s.additionalProperties, depth + 1)
|
|
51
|
+
: true));
|
|
52
|
+
}
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
function validate(value, name, response, requestId) {
|
|
56
|
+
if (!schemas[name] || !valid(value, schemas[name])) {
|
|
57
|
+
const ErrorClass = response ? errors_js_1.RunneeResponseError : errors_js_1.RunneeValidationError;
|
|
58
|
+
throw new ErrorClass(response
|
|
59
|
+
? 'Runnee returned an unexpected response.'
|
|
60
|
+
: 'Request does not match the Runnee API contract.', { requestId });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/** Reject non-JSON inputs before I/O; serialization failures must never look retryable. */
|
|
64
|
+
function encodeRequest(value) {
|
|
65
|
+
const ancestors = new Set();
|
|
66
|
+
let count = 0, characters = 0;
|
|
67
|
+
const walk = (v, depth = 0) => {
|
|
68
|
+
if (++count > 10000 || depth > 20)
|
|
69
|
+
throw new errors_js_1.RunneeValidationError('Request JSON exceeds the nesting or value limit.');
|
|
70
|
+
if (v === null || typeof v === 'boolean')
|
|
71
|
+
return;
|
|
72
|
+
if (typeof v === 'string') {
|
|
73
|
+
characters += v.length;
|
|
74
|
+
if (characters > 102400)
|
|
75
|
+
throw new errors_js_1.RunneeValidationError('Request JSON is too large.');
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
if (typeof v === 'number' && Number.isFinite(v))
|
|
79
|
+
return;
|
|
80
|
+
if (v &&
|
|
81
|
+
typeof v === 'object' &&
|
|
82
|
+
(Array.isArray(v) ||
|
|
83
|
+
Object.getPrototypeOf(v) === Object.prototype ||
|
|
84
|
+
Object.getPrototypeOf(v) === null)) {
|
|
85
|
+
if (ancestors.has(v))
|
|
86
|
+
throw new errors_js_1.RunneeValidationError('Request JSON contains a cycle.');
|
|
87
|
+
ancestors.add(v);
|
|
88
|
+
for (const [key, entry] of Object.entries(v)) {
|
|
89
|
+
characters += key.length;
|
|
90
|
+
walk(entry, depth + 1);
|
|
91
|
+
}
|
|
92
|
+
ancestors.delete(v);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
throw new errors_js_1.RunneeValidationError('Request data must contain only JSON values.');
|
|
96
|
+
};
|
|
97
|
+
walk(value);
|
|
98
|
+
const encoded = JSON.stringify(value);
|
|
99
|
+
if (new TextEncoder().encode(encoded).byteLength > 102400)
|
|
100
|
+
throw new errors_js_1.RunneeValidationError('Request JSON exceeds 100 KiB.');
|
|
101
|
+
return encoded;
|
|
102
|
+
}
|