@selfchecks/selfchecks 0.1.25 → 0.1.26

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 CHANGED
@@ -27,7 +27,6 @@ export default defineConfig({
27
27
  checks: {
28
28
  activated: true,
29
29
  frequency: Frequency.EVERY_15M,
30
- checkMatch: "**/*.check.ts",
31
30
  },
32
31
  });
33
32
  ```
@@ -51,6 +50,29 @@ new BrowserCheck("homepage", {
51
50
 
52
51
  The entrypoint is a regular Playwright Test file.
53
52
 
53
+ Define an API check with request assertions:
54
+
55
+ ```ts
56
+ import { ApiCheck, AssertionBuilder } from "@selfchecks/selfchecks/constructs";
57
+
58
+ new ApiCheck("health", {
59
+ maxResponseTime: 2_000,
60
+ request: {
61
+ method: "GET",
62
+ url: "{{API_URL}}/health",
63
+ queryParameters: { probe: "selfchecks" },
64
+ assertions: [
65
+ AssertionBuilder.statusCode().equals(200),
66
+ AssertionBuilder.jsonBody("$.data.ok").equals(true),
67
+ ],
68
+ },
69
+ });
70
+ ```
71
+
72
+ The Selfchecks CLI executes TypeScript manifests locally and compiles them into
73
+ `DeploymentManifest v1`. Imported helpers, loops, and computed construct definitions
74
+ are supported as long as their final properties belong to the compatibility profile.
75
+
54
76
  ## Checkly-compatible imports
55
77
 
56
78
  Existing projects can keep supported imports from `checkly` by installing this
@@ -82,9 +104,11 @@ import {
82
104
  ```
83
105
 
84
106
  Compatibility is intentionally limited to these constructs and their exported
85
- TypeScript types. Other Checkly constructs, CLI commands, cloud APIs, and runtime
86
- features are not supported. Assertion and alert objects are accepted for source
87
- compatibility, but Selfchecks does not currently deploy their Checkly configuration.
107
+ TypeScript types. API request assertions and webhook alert channels attached through
108
+ groups are deployed. Unsupported properties produce a compiler error instead of being
109
+ silently ignored. Checkly locations, runtimes, secrets, status pages, maintenance
110
+ windows, alert escalation policies, REST APIs, CLI commands, and cloud runtime
111
+ behavior are not supported.
88
112
 
89
113
  See the complete [migration guide](https://selfchecks.github.io/getting-started.html#migration)
90
114
  and [Selfchecks documentation](https://selfchecks.github.io/getting-started.html).
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=compiler-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compiler-runtime.d.ts","sourceRoot":"","sources":["../src/compiler-runtime.ts"],"names":[],"mappings":""}
@@ -0,0 +1,473 @@
1
+ import { readdir } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { pathToFileURL } from "node:url";
4
+ const constructCollectorSymbol = Symbol.for("@selfchecks/selfchecks/construct-collector");
5
+ const ignoredDirectories = new Set([
6
+ ".git",
7
+ ".next",
8
+ ".selfchecks",
9
+ "coverage",
10
+ "dist",
11
+ "node_modules",
12
+ "playwright-report",
13
+ "test-results",
14
+ ]);
15
+ const configFileNames = [
16
+ "selfchecks.config.ts",
17
+ "selfchecks.config.mts",
18
+ "selfchecks.config.js",
19
+ "selfchecks.config.mjs",
20
+ "checkly.config.ts",
21
+ "checkly.config.mts",
22
+ "checkly.config.js",
23
+ "checkly.config.mjs",
24
+ ];
25
+ const commonCheckKeys = new Set([
26
+ "activated",
27
+ "alertChannels",
28
+ "frequency",
29
+ "group",
30
+ "muted",
31
+ "name",
32
+ "retryStrategy",
33
+ "shouldFail",
34
+ "tags",
35
+ ]);
36
+ const groupKeys = new Set([
37
+ "activated",
38
+ "alertChannels",
39
+ "frequency",
40
+ "muted",
41
+ "name",
42
+ "retryStrategy",
43
+ "shouldFail",
44
+ "tags",
45
+ ]);
46
+ const webhookKeys = new Set([
47
+ "method",
48
+ "name",
49
+ "sendDegraded",
50
+ "sendFailure",
51
+ "sendRecovery",
52
+ "sslExpiry",
53
+ "template",
54
+ "url",
55
+ ]);
56
+ process.once("message", (message) => {
57
+ void run(message)
58
+ .then((manifest) => process.send?.({ manifest, success: true }))
59
+ .catch((error) => process.send?.({
60
+ error: error instanceof Error ? error.message : String(error),
61
+ success: false,
62
+ }));
63
+ });
64
+ async function run(options) {
65
+ const configPath = options.configPath
66
+ ? path.resolve(options.rootDir, options.configPath)
67
+ : await findConfigPath(options.rootDir);
68
+ const configModule = configPath
69
+ ? (await import(pathToFileURL(configPath).href))
70
+ : undefined;
71
+ const config = configModule?.default ?? {};
72
+ const projectName = readRequiredString(config.projectName, "projectName");
73
+ const logicalId = readRequiredString(config.logicalId, "logicalId");
74
+ const collector = [];
75
+ globalThis[constructCollectorSymbol] = collector;
76
+ try {
77
+ for (const filePath of await findCheckFiles(options.rootDir)) {
78
+ await import(pathToFileURL(filePath).href);
79
+ }
80
+ }
81
+ finally {
82
+ delete globalThis[constructCollectorSymbol];
83
+ }
84
+ const groups = new Map(collector
85
+ .filter((item) => item.kind === "CheckGroup" || item.kind === "CheckGroupV2")
86
+ .map((item) => [item.logicalId, item]));
87
+ const channels = new Map(collector
88
+ .filter((item) => item.kind === "WebhookAlertChannel")
89
+ .map((item) => [item.logicalId, item]));
90
+ assertUniqueLogicalIds(collector.filter((item) => item.kind === "ApiCheck" || item.kind === "BrowserCheck"), "check");
91
+ assertUniqueLogicalIds(collector.filter((item) => item.kind === "CheckGroup" || item.kind === "CheckGroupV2"), "group");
92
+ assertUniqueLogicalIds(collector.filter((item) => item.kind === "WebhookAlertChannel"), "alert channel");
93
+ for (const group of groups.values()) {
94
+ assertSupportedProperties(group, asRecord(group.props), groupKeys);
95
+ }
96
+ for (const channel of channels.values()) {
97
+ assertSupportedProperties(channel, asRecord(channel.props), webhookKeys);
98
+ }
99
+ assertSupportedConfigDefaults(config);
100
+ const checks = collector
101
+ .filter((item) => item.kind === "ApiCheck" || item.kind === "BrowserCheck")
102
+ .map((item) => compileCheck(item, config, groups, channels));
103
+ if (checks.length === 0) {
104
+ throw new Error(`No Selfchecks definitions were found in ${options.rootDir}.`);
105
+ }
106
+ return {
107
+ alertChannels: [...channels.values()].map(compileWebhookAlertChannel),
108
+ checks,
109
+ project: { logicalId, name: projectName },
110
+ version: 1,
111
+ warnings: [],
112
+ };
113
+ }
114
+ async function findConfigPath(rootDir) {
115
+ const entries = new Set(await readdir(rootDir));
116
+ const configName = configFileNames.find((name) => entries.has(name));
117
+ return configName ? path.join(rootDir, configName) : undefined;
118
+ }
119
+ async function findCheckFiles(rootDir) {
120
+ const files = [];
121
+ async function visit(directory) {
122
+ for (const entry of await readdir(directory, { withFileTypes: true })) {
123
+ if (entry.isDirectory()) {
124
+ if (!ignoredDirectories.has(entry.name)) {
125
+ await visit(path.join(directory, entry.name));
126
+ }
127
+ }
128
+ else if (entry.isFile() && /\.check\.(?:[cm]?[jt]s)$/.test(entry.name)) {
129
+ files.push(path.join(directory, entry.name));
130
+ }
131
+ }
132
+ }
133
+ await visit(rootDir);
134
+ return files.sort();
135
+ }
136
+ function compileCheck(construct, config, groups, channels) {
137
+ const type = construct.kind === "ApiCheck" ? "api" : "browser";
138
+ const ownProps = asRecord(construct.props);
139
+ const groupLogicalId = getLogicalId(ownProps.group);
140
+ const group = groupLogicalId ? groups.get(groupLogicalId) : undefined;
141
+ if (groupLogicalId && !group) {
142
+ throw new Error(`${construct.kind} ${construct.logicalId} references unknown group: ${groupLogicalId}`);
143
+ }
144
+ const groupProps = group ? asRecord(group.props) : {};
145
+ const groupCheckDefaults = pickGroupCheckDefaults(groupProps);
146
+ const checkDefaults = asRecord(config.checks);
147
+ const typeDefaults = type === "browser" ? asRecord(config.checks?.browserChecks) : {};
148
+ const props = {
149
+ ...checkDefaults,
150
+ ...typeDefaults,
151
+ ...groupCheckDefaults,
152
+ ...ownProps,
153
+ };
154
+ const allowedKeys = new Set(commonCheckKeys);
155
+ if (type === "browser") {
156
+ allowedKeys.add("code");
157
+ }
158
+ else {
159
+ allowedKeys.add("degradedResponseTime");
160
+ allowedKeys.add("maxResponseTime");
161
+ allowedKeys.add("request");
162
+ }
163
+ assertSupportedProperties(construct, ownProps, allowedKeys);
164
+ const frequency = normalizeFrequency(props.frequency, construct.logicalId);
165
+ const tags = normalizeStrings(props.tags);
166
+ const retryStrategy = normalizeRetryStrategy(props.retryStrategy, construct.logicalId);
167
+ const alertChannelLogicalIds = normalizeReferences(ownProps.alertChannels ?? groupProps.alertChannels ?? checkDefaults.alertChannels);
168
+ const unknownAlertChannel = alertChannelLogicalIds.find((logicalId) => !channels.has(logicalId));
169
+ if (unknownAlertChannel) {
170
+ throw new Error(`${construct.kind} ${construct.logicalId} references unknown alert channel: ${unknownAlertChannel}`);
171
+ }
172
+ const base = {
173
+ alertChannelLogicalIds,
174
+ enabled: props.activated !== false,
175
+ key: construct.logicalId,
176
+ muted: props.muted === true,
177
+ name: typeof props.name === "string" ? props.name : construct.logicalId,
178
+ shouldFail: props.shouldFail === true,
179
+ tags,
180
+ type,
181
+ ...(frequency ? { frequency } : {}),
182
+ ...(group
183
+ ? {
184
+ groupKey: group.logicalId,
185
+ groupName: typeof groupProps.name === "string" ? groupProps.name : group.logicalId,
186
+ }
187
+ : {}),
188
+ ...(retryStrategy ? { retryStrategy } : {}),
189
+ };
190
+ if (type === "api") {
191
+ base.request = compileRequest(props.request, construct.logicalId);
192
+ base.degradedResponseTime = optionalNonNegativeNumber(props.degradedResponseTime, "degradedResponseTime", construct.logicalId);
193
+ base.maxResponseTime = optionalNonNegativeNumber(props.maxResponseTime, "maxResponseTime", construct.logicalId);
194
+ }
195
+ else {
196
+ const code = asRecord(props.code);
197
+ const entrypoint = code.entrypoint;
198
+ if (typeof entrypoint !== "string" || !entrypoint.trim()) {
199
+ throw new Error(`BrowserCheck ${construct.logicalId} requires code.entrypoint.`);
200
+ }
201
+ base.entrypoint = entrypoint;
202
+ }
203
+ return base;
204
+ }
205
+ function pickGroupCheckDefaults(props) {
206
+ return Object.fromEntries(["activated", "frequency", "muted", "retryStrategy", "shouldFail", "tags"].flatMap((key) => (key in props ? [[key, props[key]]] : [])));
207
+ }
208
+ function assertSupportedConfigDefaults(config) {
209
+ const defaults = asRecord(config.checks);
210
+ const browserDefaults = asRecord(config.checks?.browserChecks);
211
+ const defaultKeys = new Set(commonCheckKeys);
212
+ defaultKeys.delete("group");
213
+ defaultKeys.add("browserChecks");
214
+ defaultKeys.add("degradedResponseTime");
215
+ defaultKeys.add("maxResponseTime");
216
+ for (const key of Object.keys(defaults)) {
217
+ if (!defaultKeys.has(key)) {
218
+ throw new Error(`Selfchecks configuration uses unsupported checks.${key}.`);
219
+ }
220
+ }
221
+ const browserKeys = new Set(commonCheckKeys);
222
+ browserKeys.delete("alertChannels");
223
+ browserKeys.delete("group");
224
+ for (const key of Object.keys(browserDefaults)) {
225
+ if (!browserKeys.has(key)) {
226
+ throw new Error(`Selfchecks configuration uses unsupported checks.browserChecks.${key}.`);
227
+ }
228
+ }
229
+ }
230
+ function compileRequest(value, logicalId) {
231
+ const request = asRecord(value);
232
+ const allowedKeys = new Set([
233
+ "assertions",
234
+ "basicAuth",
235
+ "body",
236
+ "bodyType",
237
+ "followRedirects",
238
+ "headers",
239
+ "method",
240
+ "queryParameters",
241
+ "url",
242
+ ]);
243
+ for (const key of Object.keys(request)) {
244
+ if (!allowedKeys.has(key)) {
245
+ throw new Error(`ApiCheck ${logicalId} request uses unsupported property: ${key}`);
246
+ }
247
+ }
248
+ if (typeof request.method !== "string" || typeof request.url !== "string") {
249
+ throw new Error(`ApiCheck ${logicalId} requires request.method and request.url.`);
250
+ }
251
+ const assertions = compileAssertions(request.assertions, logicalId);
252
+ const bodyType = request.bodyType;
253
+ if (bodyType !== undefined &&
254
+ !["FORM", "GRAPHQL", "JSON", "NONE", "RAW"].includes(String(bodyType))) {
255
+ throw new Error(`ApiCheck ${logicalId} has unsupported request.bodyType.`);
256
+ }
257
+ return {
258
+ assertions,
259
+ headers: normalizeKeyValuePairs(request.headers),
260
+ method: request.method.toUpperCase(),
261
+ queryParameters: normalizeKeyValuePairs(request.queryParameters),
262
+ url: request.url,
263
+ ...(typeof request.body === "string" ? { body: request.body } : {}),
264
+ ...(typeof bodyType === "string" ? { bodyType: bodyType } : {}),
265
+ ...(typeof request.followRedirects === "boolean"
266
+ ? { followRedirects: request.followRedirects }
267
+ : {}),
268
+ ...(isBasicAuth(request.basicAuth) ? { basicAuth: request.basicAuth } : {}),
269
+ };
270
+ }
271
+ function compileWebhookAlertChannel(construct) {
272
+ const props = asRecord(construct.props);
273
+ const url = props.url instanceof URL ? props.url.toString() : props.url;
274
+ if (typeof url !== "string") {
275
+ throw new Error(`WebhookAlertChannel ${construct.logicalId} requires a URL.`);
276
+ }
277
+ const method = typeof props.method === "string" ? props.method.toUpperCase() : "POST";
278
+ if (!["DELETE", "GET", "PATCH", "POST", "PUT"].includes(method)) {
279
+ throw new Error(`WebhookAlertChannel ${construct.logicalId} uses unsupported method: ${method}`);
280
+ }
281
+ return {
282
+ adapter: "generic",
283
+ logicalId: construct.logicalId,
284
+ method: method,
285
+ name: typeof props.name === "string" ? props.name : construct.logicalId,
286
+ sendDegraded: props.sendDegraded === true,
287
+ sendFailure: props.sendFailure !== false,
288
+ sendRecovery: props.sendRecovery !== false,
289
+ sslExpiry: props.sslExpiry === true,
290
+ ...(typeof props.template === "string" ? { template: props.template } : {}),
291
+ url,
292
+ };
293
+ }
294
+ function assertSupportedProperties(construct, props, allowedKeys) {
295
+ for (const key of Object.keys(props)) {
296
+ if (!allowedKeys.has(key)) {
297
+ throw new Error(`${construct.kind} ${construct.logicalId} uses unsupported property: ${key}`);
298
+ }
299
+ }
300
+ }
301
+ function assertUniqueLogicalIds(constructs, label) {
302
+ const seen = new Set();
303
+ for (const construct of constructs) {
304
+ if (seen.has(construct.logicalId)) {
305
+ throw new Error(`Duplicate ${label} logicalId: ${construct.logicalId}`);
306
+ }
307
+ seen.add(construct.logicalId);
308
+ }
309
+ }
310
+ function compileAssertions(value, logicalId) {
311
+ if (value === undefined) {
312
+ return [];
313
+ }
314
+ if (!Array.isArray(value)) {
315
+ throw new Error(`ApiCheck ${logicalId} request.assertions must be an array.`);
316
+ }
317
+ const sources = new Set([
318
+ "HEADERS",
319
+ "JSON_BODY",
320
+ "RESPONSE_TIME",
321
+ "STATUS_CODE",
322
+ "TEXT_BODY",
323
+ ]);
324
+ const comparisons = new Set([
325
+ "CONTAINS",
326
+ "EQUALS",
327
+ "GREATER_THAN",
328
+ "HAS_KEY",
329
+ "HAS_VALUE",
330
+ "IS_EMPTY",
331
+ "IS_NOT_NULL",
332
+ "IS_NULL",
333
+ "LESS_THAN",
334
+ "NOT_CONTAINS",
335
+ "NOT_EMPTY",
336
+ "NOT_EQUALS",
337
+ "NOT_HAS_KEY",
338
+ "NOT_HAS_VALUE",
339
+ ]);
340
+ return value.map((item, index) => {
341
+ const assertion = asRecord(item);
342
+ for (const key of Object.keys(assertion)) {
343
+ if (!["comparison", "property", "source", "target"].includes(key)) {
344
+ throw new Error(`ApiCheck ${logicalId} assertion ${index} uses unsupported property: ${key}`);
345
+ }
346
+ }
347
+ if (!sources.has(String(assertion.source))) {
348
+ throw new Error(`ApiCheck ${logicalId} assertion ${index} uses unsupported source: ${String(assertion.source)}`);
349
+ }
350
+ if (!comparisons.has(String(assertion.comparison))) {
351
+ throw new Error(`ApiCheck ${logicalId} assertion ${index} uses unsupported comparison: ${String(assertion.comparison)}`);
352
+ }
353
+ if (assertion.property !== undefined && typeof assertion.property !== "string") {
354
+ throw new Error(`ApiCheck ${logicalId} assertion ${index} property must be a string.`);
355
+ }
356
+ return { ...assertion };
357
+ });
358
+ }
359
+ function normalizeFrequency(value, logicalId) {
360
+ if (value === undefined) {
361
+ return undefined;
362
+ }
363
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value <= 0) {
364
+ throw new Error(`Check ${logicalId} requires a positive minute frequency.`);
365
+ }
366
+ return { intervalMinutes: value };
367
+ }
368
+ function normalizeRetryStrategy(value, logicalId) {
369
+ if (value === undefined) {
370
+ return undefined;
371
+ }
372
+ const strategy = asRecord(value);
373
+ const supportedTypes = new Set([
374
+ "EXPONENTIAL",
375
+ "FIXED",
376
+ "LINEAR",
377
+ "NO_RETRIES",
378
+ "SINGLE_RETRY",
379
+ ]);
380
+ if (!supportedTypes.has(String(strategy.type))) {
381
+ throw new Error(`Check ${logicalId} uses unsupported retry strategy type.`);
382
+ }
383
+ for (const key of Object.keys(strategy)) {
384
+ if (![
385
+ "baseBackoffSeconds",
386
+ "maxDurationSeconds",
387
+ "maxRetries",
388
+ "onlyOn",
389
+ "sameRegion",
390
+ "type",
391
+ ].includes(key)) {
392
+ throw new Error(`Check ${logicalId} retry strategy uses unsupported property: ${key}`);
393
+ }
394
+ }
395
+ for (const key of [
396
+ "baseBackoffSeconds",
397
+ "maxDurationSeconds",
398
+ "maxRetries",
399
+ ]) {
400
+ const item = strategy[key];
401
+ if (item !== undefined && (!Number.isSafeInteger(item) || Number(item) < 0)) {
402
+ throw new Error(`Check ${logicalId} retry strategy ${key} must be non-negative.`);
403
+ }
404
+ }
405
+ if (typeof strategy.maxRetries === "number" && strategy.maxRetries > 10) {
406
+ throw new Error(`Check ${logicalId} retry strategy maxRetries cannot exceed 10.`);
407
+ }
408
+ if (strategy.maxDurationSeconds === 0) {
409
+ throw new Error(`Check ${logicalId} retry strategy maxDurationSeconds must be positive.`);
410
+ }
411
+ if (strategy.onlyOn !== undefined &&
412
+ strategy.onlyOn !== "NETWORK_ERROR" &&
413
+ (!Array.isArray(strategy.onlyOn) ||
414
+ !strategy.onlyOn.every((item) => typeof item === "string" && item.length > 0))) {
415
+ throw new Error(`Check ${logicalId} retry strategy onlyOn is invalid.`);
416
+ }
417
+ if (strategy.sameRegion !== undefined && typeof strategy.sameRegion !== "boolean") {
418
+ throw new Error(`Check ${logicalId} retry strategy sameRegion must be boolean.`);
419
+ }
420
+ return { ...strategy };
421
+ }
422
+ function normalizeKeyValuePairs(value) {
423
+ if (Array.isArray(value)) {
424
+ return Object.fromEntries(value.flatMap((item) => {
425
+ const pair = asRecord(item);
426
+ return typeof pair.key === "string" && typeof pair.value === "string"
427
+ ? [[pair.key, pair.value]]
428
+ : [];
429
+ }));
430
+ }
431
+ return Object.fromEntries(Object.entries(asRecord(value)).flatMap(([key, item]) => typeof item === "string" ? [[key, item]] : []));
432
+ }
433
+ function normalizeReferences(value) {
434
+ if (!Array.isArray(value)) {
435
+ return [];
436
+ }
437
+ return value.flatMap((item) => {
438
+ const logicalId = getLogicalId(item);
439
+ return logicalId ? [logicalId] : [];
440
+ });
441
+ }
442
+ function normalizeStrings(value) {
443
+ if (!Array.isArray(value)) {
444
+ return [];
445
+ }
446
+ return [...new Set(value.filter((item) => typeof item === "string"))];
447
+ }
448
+ function getLogicalId(value) {
449
+ const record = asRecord(value);
450
+ return typeof record.logicalId === "string" ? record.logicalId : undefined;
451
+ }
452
+ function readRequiredString(value, name) {
453
+ if (typeof value !== "string" || !value.trim()) {
454
+ throw new Error(`Selfchecks configuration requires ${name}.`);
455
+ }
456
+ return value.trim();
457
+ }
458
+ function optionalNonNegativeNumber(value, property, logicalId) {
459
+ if (value === undefined) {
460
+ return undefined;
461
+ }
462
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
463
+ throw new Error(`ApiCheck ${logicalId} ${property} must be non-negative.`);
464
+ }
465
+ return value;
466
+ }
467
+ function isBasicAuth(value) {
468
+ const auth = asRecord(value);
469
+ return typeof auth.username === "string" && typeof auth.password === "string";
470
+ }
471
+ function asRecord(value) {
472
+ return value && typeof value === "object" ? value : {};
473
+ }
@@ -0,0 +1,53 @@
1
+ import type { Assertion, Request, RetryStrategy, WebhookAlertChannelProps } from "./constructs.js";
2
+ export type CompiledApiRequest = Omit<Request, "assertions" | "headers" | "queryParameters"> & {
3
+ assertions: Assertion[];
4
+ headers: Record<string, string>;
5
+ queryParameters: Record<string, string>;
6
+ };
7
+ export type CompiledCheck = {
8
+ alertChannelLogicalIds: string[];
9
+ degradedResponseTime?: number;
10
+ enabled: boolean;
11
+ entrypoint?: string;
12
+ frequency?: {
13
+ intervalMinutes: number;
14
+ };
15
+ groupKey?: string;
16
+ groupName?: string;
17
+ key: string;
18
+ maxResponseTime?: number;
19
+ muted: boolean;
20
+ name: string;
21
+ request?: CompiledApiRequest;
22
+ retryStrategy?: RetryStrategy;
23
+ shouldFail: boolean;
24
+ tags: string[];
25
+ type: "api" | "browser";
26
+ };
27
+ export type CompiledWebhookAlertChannel = Omit<WebhookAlertChannelProps, "method" | "name" | "sendDegraded" | "sendFailure" | "sendRecovery" | "sslExpiry" | "url"> & {
28
+ adapter: "generic";
29
+ logicalId: string;
30
+ method: "DELETE" | "GET" | "PATCH" | "POST" | "PUT";
31
+ name: string;
32
+ sendDegraded: boolean;
33
+ sendFailure: boolean;
34
+ sendRecovery: boolean;
35
+ sslExpiry: boolean;
36
+ url: string;
37
+ };
38
+ export type DeploymentManifest = {
39
+ alertChannels: CompiledWebhookAlertChannel[];
40
+ checks: CompiledCheck[];
41
+ project: {
42
+ logicalId: string;
43
+ name: string;
44
+ };
45
+ version: 1;
46
+ warnings: string[];
47
+ };
48
+ export type CompileProjectOptions = {
49
+ configPath?: string;
50
+ rootDir: string;
51
+ };
52
+ export declare function compileProject(options: CompileProjectOptions): Promise<DeploymentManifest>;
53
+ //# sourceMappingURL=compiler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../src/compiler.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,SAAS,EACT,OAAO,EACP,aAAa,EACb,wBAAwB,EACzB,MAAM,iBAAiB,CAAC;AAEzB,MAAM,MAAM,kBAAkB,GAAG,IAAI,CACnC,OAAO,EACP,YAAY,GAAG,SAAS,GAAG,iBAAiB,CAC7C,GAAG;IACF,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,sBAAsB,EAAE,MAAM,EAAE,CAAC;IACjC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE;QAAE,eAAe,EAAE,MAAM,CAAA;KAAE,CAAC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,UAAU,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,IAAI,EAAE,KAAK,GAAG,SAAS,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG,IAAI,CAC5C,wBAAwB,EACtB,QAAQ,GACR,MAAM,GACN,cAAc,GACd,aAAa,GACb,cAAc,GACd,WAAW,GACX,KAAK,CACR,GAAG;IACF,OAAO,EAAE,SAAS,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,QAAQ,GAAG,KAAK,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,EAAE,OAAO,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,aAAa,EAAE,2BAA2B,EAAE,CAAC;IAC7C,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,OAAO,EAAE;QACP,SAAS,EAAE,MAAM,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,OAAO,EAAE,CAAC,CAAC;IACX,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAMF,wBAAsB,cAAc,CAClC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,kBAAkB,CAAC,CAiD7B"}
@@ -0,0 +1,43 @@
1
+ import { fork } from "node:child_process";
2
+ import path from "node:path";
3
+ import { createRequire } from "node:module";
4
+ import { fileURLToPath, pathToFileURL } from "node:url";
5
+ export async function compileProject(options) {
6
+ const moduleUrl = import.meta.url.startsWith("file:")
7
+ ? import.meta.url
8
+ : pathToFileURL(path.join(process.cwd(), "packages/checkly-compat/src/compiler.ts"))
9
+ .href;
10
+ const runtimePath = fileURLToPath(new URL(moduleUrl.endsWith(".ts") ? "./compiler-runtime.ts" : "./compiler-runtime.js", moduleUrl));
11
+ const tsxLoader = pathToFileURL(createRequire(moduleUrl).resolve("tsx")).href;
12
+ return new Promise((resolve, reject) => {
13
+ const child = fork(runtimePath, [], {
14
+ cwd: options.rootDir,
15
+ env: process.env,
16
+ execArgv: ["--import", tsxLoader],
17
+ silent: true,
18
+ });
19
+ let stderr = "";
20
+ let settled = false;
21
+ child.stderr?.setEncoding("utf8");
22
+ child.stderr?.on("data", (chunk) => {
23
+ stderr += chunk;
24
+ });
25
+ child.on("message", (message) => {
26
+ settled = true;
27
+ child.disconnect();
28
+ if (message.success) {
29
+ resolve(message.manifest);
30
+ }
31
+ else {
32
+ reject(new Error(message.error));
33
+ }
34
+ });
35
+ child.once("error", reject);
36
+ child.once("exit", (code) => {
37
+ if (!settled) {
38
+ reject(new Error(stderr.trim() || `Selfchecks project compiler exited with status ${code}.`));
39
+ }
40
+ });
41
+ child.send(options);
42
+ });
43
+ }
@@ -1,39 +1,65 @@
1
1
  export type FrequencyValue = number;
2
2
  export declare const Frequency: {
3
+ readonly EVERY_1H: 60;
4
+ readonly EVERY_1M: 1;
3
5
  readonly EVERY_10M: 10;
4
6
  readonly EVERY_12H: number;
5
7
  readonly EVERY_15M: 15;
6
8
  readonly EVERY_24H: number;
7
9
  readonly EVERY_2H: number;
10
+ readonly EVERY_2M: 2;
8
11
  readonly EVERY_30M: 30;
9
12
  readonly EVERY_3H: number;
13
+ readonly EVERY_5M: 5;
10
14
  readonly EVERY_6H: number;
11
15
  };
12
16
  export type Assertion = {
13
- operator: "contains" | "equals" | "isEmpty" | "isNotNull";
14
- source: string;
17
+ comparison: "CONTAINS" | "EQUALS" | "GREATER_THAN" | "HAS_KEY" | "HAS_VALUE" | "IS_EMPTY" | "IS_NOT_NULL" | "IS_NULL" | "LESS_THAN" | "NOT_CONTAINS" | "NOT_EMPTY" | "NOT_EQUALS" | "NOT_HAS_KEY" | "NOT_HAS_VALUE";
18
+ property?: string;
19
+ source: "HEADERS" | "JSON_BODY" | "RESPONSE_TIME" | "STATUS_CODE" | "TEXT_BODY";
15
20
  target?: unknown;
16
21
  };
17
22
  type AssertionChain = {
18
23
  contains(value: unknown): Assertion;
19
24
  equals(value: unknown): Assertion;
25
+ greaterThan(value: number): Assertion;
26
+ hasKey(value: string): Assertion;
27
+ hasValue(value: unknown): Assertion;
20
28
  isEmpty(): Assertion;
21
29
  isNotNull(): Assertion;
30
+ isNull(): Assertion;
31
+ lessThan(value: number): Assertion;
32
+ notContains(value: unknown): Assertion;
33
+ notEmpty(): Assertion;
34
+ notEquals(value: unknown): Assertion;
35
+ notHasKey(value: string): Assertion;
36
+ notHasValue(value: unknown): Assertion;
22
37
  };
23
38
  export declare const AssertionBuilder: {
24
- jsonBody: (path: string) => AssertionChain;
39
+ headers: (property?: string) => AssertionChain;
40
+ jsonBody: (property?: string) => AssertionChain;
41
+ responseTime: () => AssertionChain;
25
42
  statusCode: () => AssertionChain;
26
- textBody: () => AssertionChain;
43
+ textBody: (property?: string) => AssertionChain;
44
+ };
45
+ export type KeyValuePair = {
46
+ key: string;
47
+ locked?: boolean;
48
+ secret?: boolean;
49
+ value: string;
27
50
  };
28
51
  export type Request = {
29
52
  assertions?: Assertion[];
53
+ basicAuth?: {
54
+ password: string;
55
+ username: string;
56
+ };
30
57
  body?: string;
58
+ bodyType?: "FORM" | "GRAPHQL" | "JSON" | "NONE" | "RAW";
31
59
  followRedirects?: boolean;
32
- headers?: Array<{
33
- key: string;
34
- value: string;
35
- }> | Record<string, string>;
60
+ headers?: KeyValuePair[] | Record<string, string>;
36
61
  method: string;
62
+ queryParameters?: KeyValuePair[] | Record<string, string>;
37
63
  skipSSL?: boolean;
38
64
  url: string;
39
65
  };
@@ -41,19 +67,21 @@ export type RetryStrategy = {
41
67
  baseBackoffSeconds?: number;
42
68
  maxDurationSeconds?: number;
43
69
  maxRetries?: number;
44
- onlyOn?: string[];
70
+ onlyOn?: "NETWORK_ERROR" | string[];
45
71
  sameRegion?: boolean;
46
- type: "EXPONENTIAL" | "FIXED" | "LINEAR" | "NO_RETRIES";
72
+ type: "EXPONENTIAL" | "FIXED" | "LINEAR" | "NO_RETRIES" | "SINGLE_RETRY";
47
73
  };
48
74
  type RetryStrategyOptions = Omit<RetryStrategy, "type">;
49
75
  export declare const RetryStrategyBuilder: {
50
- exponentialStrategy: (options: RetryStrategyOptions) => RetryStrategy;
51
- fixedStrategy: (options: RetryStrategyOptions) => RetryStrategy;
52
- linearStrategy: (options: RetryStrategyOptions) => RetryStrategy;
76
+ exponentialStrategy: (options?: RetryStrategyOptions) => RetryStrategy;
77
+ fixedStrategy: (options?: RetryStrategyOptions) => RetryStrategy;
78
+ linearStrategy: (options?: RetryStrategyOptions) => RetryStrategy;
53
79
  noRetries: () => RetryStrategy;
80
+ singleRetry: (options?: Pick<RetryStrategyOptions, "baseBackoffSeconds" | "onlyOn" | "sameRegion">) => RetryStrategy;
54
81
  };
55
82
  type SharedCheckProps = {
56
83
  activated?: boolean;
84
+ alertChannels?: WebhookAlertChannel[];
57
85
  environmentVariables?: Array<{
58
86
  key: string;
59
87
  value: string;
@@ -64,6 +92,7 @@ type SharedCheckProps = {
64
92
  name?: string;
65
93
  retryStrategy?: RetryStrategy;
66
94
  runParallel?: boolean;
95
+ shouldFail?: boolean;
67
96
  tags?: string[];
68
97
  };
69
98
  export type ApiCheckProps = SharedCheckProps & {
@@ -75,7 +104,6 @@ export type BrowserCheckProps = SharedCheckProps & {
75
104
  code: {
76
105
  entrypoint: string;
77
106
  };
78
- shouldFail?: boolean;
79
107
  };
80
108
  export type CheckGroupV2Props = SharedCheckProps & {
81
109
  alertChannels?: WebhookAlertChannel[];
@@ -83,6 +111,11 @@ export type CheckGroupV2Props = SharedCheckProps & {
83
111
  locations?: string[];
84
112
  privateLocations?: string[];
85
113
  };
114
+ export type CollectedConstruct = {
115
+ kind: string;
116
+ logicalId: string;
117
+ props: unknown;
118
+ };
86
119
  declare class Construct<Props> {
87
120
  readonly logicalId: string;
88
121
  readonly props: Props;
@@ -1 +1 @@
1
- {"version":3,"file":"constructs.d.ts","sourceRoot":"","sources":["../src/constructs.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"constructs.d.ts","sourceRoot":"","sources":["../src/constructs.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC;AAEpC,eAAO,MAAM,SAAS;;;;;;;;;;;;;CAa6B,CAAC;AAEpD,MAAM,MAAM,SAAS,GAAG;IACtB,UAAU,EACN,UAAU,GACV,QAAQ,GACR,cAAc,GACd,SAAS,GACT,WAAW,GACX,UAAU,GACV,aAAa,GACb,SAAS,GACT,WAAW,GACX,cAAc,GACd,WAAW,GACX,YAAY,GACZ,aAAa,GACb,eAAe,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,eAAe,GAAG,aAAa,GAAG,WAAW,CAAC;IAChF,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,KAAK,cAAc,GAAG;IACpB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,CAAC;IAClC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,CAAC;IACpC,OAAO,IAAI,SAAS,CAAC;IACrB,SAAS,IAAI,SAAS,CAAC;IACvB,MAAM,IAAI,SAAS,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,QAAQ,IAAI,SAAS,CAAC;IACtB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,CAAC;IACrC,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,CAAC;CACxC,CAAC;AAkCF,eAAO,MAAM,gBAAgB;yBACN,MAAM;0BACL,MAAM;;;0BAGN,MAAM;CAC7B,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;IACzB,SAAS,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACnD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;IACxD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,OAAO,CAAC,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1D,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,eAAe,GAAG,MAAM,EAAE,CAAC;IACpC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,IAAI,EAAE,aAAa,GAAG,OAAO,GAAG,QAAQ,GAAG,YAAY,GAAG,cAAc,CAAC;CAC1E,CAAC;AAEF,KAAK,oBAAoB,GAAG,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;AAExD,eAAO,MAAM,oBAAoB;oCACA,oBAAoB,KAAQ,aAAa;8BAI/C,oBAAoB,KAAQ,aAAa;+BAIxC,oBAAoB,KAAQ,aAAa;qBAIpD,aAAa;4BAEjB,IAAI,CACX,oBAAoB,EACpB,oBAAoB,GAAG,QAAQ,GAAG,YAAY,CAC/C,KACA,aAAa;CACjB,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACtC,oBAAoB,CAAC,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC7D,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,KAAK,CAAC,EAAE,UAAU,GAAG,YAAY,CAAC;IAClC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,gBAAgB,GAAG;IAC7C,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,gBAAgB,GAAG;IACjD,IAAI,EAAE;QACJ,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,gBAAgB,GAAG;IACjD,aAAa,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACtC,qBAAqB,CAAC,EAAE,qBAAqB,CAAC;IAC9C,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAgBF,cAAM,SAAS,CAAC,KAAK;IACnB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;gBAEV,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK;CAK5C;AAED,qBAAa,QAAS,SAAQ,SAAS,CAAC,aAAa,CAAC;CAAG;AAEzD,qBAAa,YAAa,SAAQ,SAAS,CAAC,iBAAiB,CAAC;CAAG;AAEjE,qBAAa,UAAW,SAAQ,SAAS,CAAC,iBAAiB,CAAC;CAAG;AAE/D,qBAAa,YAAa,SAAQ,SAAS,CAAC,iBAAiB,CAAC;CAAG;AAEjE,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,WAAW,CAAC;CACnB,CAAC;AAEF,eAAO,MAAM,sBAAsB;uCAEjB,MAAM,WACX;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,KAC5C,qBAAqB;CAKzB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,GAAG,CAAC;CACV,CAAC;AAEF,qBAAa,mBAAoB,SAAQ,SAAS,CAAC,wBAAwB,CAAC;CAAG"}
@@ -1,47 +1,76 @@
1
1
  export const Frequency = {
2
+ EVERY_1H: 60,
3
+ EVERY_1M: 1,
2
4
  EVERY_10M: 10,
3
5
  EVERY_12H: 12 * 60,
4
6
  EVERY_15M: 15,
5
7
  EVERY_24H: 24 * 60,
6
8
  EVERY_2H: 2 * 60,
9
+ EVERY_2M: 2,
7
10
  EVERY_30M: 30,
8
11
  EVERY_3H: 3 * 60,
12
+ EVERY_5M: 5,
9
13
  EVERY_6H: 6 * 60,
10
14
  };
11
- function assertionChain(source) {
15
+ function assertionChain(source, property) {
16
+ const assertion = (comparison, target) => ({
17
+ comparison,
18
+ ...(property ? { property } : {}),
19
+ source,
20
+ ...(target !== undefined ? { target } : {}),
21
+ });
12
22
  return {
13
- contains: (target) => ({ operator: "contains", source, target }),
14
- equals: (target) => ({ operator: "equals", source, target }),
15
- isEmpty: () => ({ operator: "isEmpty", source }),
16
- isNotNull: () => ({ operator: "isNotNull", source }),
23
+ contains: (target) => assertion("CONTAINS", target),
24
+ equals: (target) => assertion("EQUALS", target),
25
+ greaterThan: (target) => assertion("GREATER_THAN", target),
26
+ hasKey: (target) => assertion("HAS_KEY", target),
27
+ hasValue: (target) => assertion("HAS_VALUE", target),
28
+ isEmpty: () => assertion("IS_EMPTY"),
29
+ isNotNull: () => assertion("IS_NOT_NULL"),
30
+ isNull: () => assertion("IS_NULL"),
31
+ lessThan: (target) => assertion("LESS_THAN", target),
32
+ notContains: (target) => assertion("NOT_CONTAINS", target),
33
+ notEmpty: () => assertion("NOT_EMPTY"),
34
+ notEquals: (target) => assertion("NOT_EQUALS", target),
35
+ notHasKey: (target) => assertion("NOT_HAS_KEY", target),
36
+ notHasValue: (target) => assertion("NOT_HAS_VALUE", target),
17
37
  };
18
38
  }
19
39
  export const AssertionBuilder = {
20
- jsonBody: (path) => assertionChain(`jsonBody:${path}`),
21
- statusCode: () => assertionChain("statusCode"),
22
- textBody: () => assertionChain("textBody"),
40
+ headers: (property) => assertionChain("HEADERS", property),
41
+ jsonBody: (property) => assertionChain("JSON_BODY", property),
42
+ responseTime: () => assertionChain("RESPONSE_TIME"),
43
+ statusCode: () => assertionChain("STATUS_CODE"),
44
+ textBody: (property) => assertionChain("TEXT_BODY", property),
23
45
  };
24
46
  export const RetryStrategyBuilder = {
25
- exponentialStrategy: (options) => ({
47
+ exponentialStrategy: (options = {}) => ({
26
48
  ...options,
27
49
  type: "EXPONENTIAL",
28
50
  }),
29
- fixedStrategy: (options) => ({
51
+ fixedStrategy: (options = {}) => ({
30
52
  ...options,
31
53
  type: "FIXED",
32
54
  }),
33
- linearStrategy: (options) => ({
55
+ linearStrategy: (options = {}) => ({
34
56
  ...options,
35
57
  type: "LINEAR",
36
58
  }),
37
59
  noRetries: () => ({ maxRetries: 0, type: "NO_RETRIES" }),
60
+ singleRetry: (options = {}) => ({ ...options, type: "SINGLE_RETRY" }),
38
61
  };
62
+ const constructCollectorSymbol = Symbol.for("@selfchecks/selfchecks/construct-collector");
63
+ function collectConstruct(construct) {
64
+ const collector = globalThis[constructCollectorSymbol];
65
+ collector?.push(construct);
66
+ }
39
67
  class Construct {
40
68
  logicalId;
41
69
  props;
42
70
  constructor(logicalId, props) {
43
71
  this.logicalId = logicalId;
44
72
  this.props = props;
73
+ collectConstruct({ kind: this.constructor.name, logicalId, props });
45
74
  }
46
75
  }
47
76
  export class ApiCheck extends Construct {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@selfchecks/selfchecks",
3
- "version": "0.1.25",
3
+ "version": "0.1.26",
4
4
  "description": "Checkly-compatible constructs supported by Selfchecks",
5
5
  "license": "Elastic-2.0",
6
6
  "type": "module",
@@ -19,12 +19,19 @@
19
19
  "./constructs": {
20
20
  "types": "./dist/constructs.d.ts",
21
21
  "import": "./dist/constructs.js"
22
+ },
23
+ "./compiler": {
24
+ "types": "./dist/compiler.d.ts",
25
+ "import": "./dist/compiler.js"
22
26
  }
23
27
  },
24
28
  "typesVersions": {
25
29
  "*": {
26
30
  "constructs": [
27
31
  "dist/constructs.d.ts"
32
+ ],
33
+ "compiler": [
34
+ "dist/compiler.d.ts"
28
35
  ]
29
36
  }
30
37
  },
@@ -41,11 +48,14 @@
41
48
  },
42
49
  "scripts": {
43
50
  "build": "tsc -p tsconfig.json",
44
- "test": "vitest run --root ../.. packages/checkly-compat/src/index.test.ts",
51
+ "test": "vitest run --root ../.. packages/checkly-compat/src",
45
52
  "typecheck": "tsc -p tsconfig.json --noEmit"
46
53
  },
47
54
  "devDependencies": {
48
55
  "typescript": "^5.8.3",
49
56
  "vitest": "^3.2.4"
57
+ },
58
+ "dependencies": {
59
+ "tsx": "^4.20.3"
50
60
  }
51
61
  }