@telorun/assert 0.1.3 → 0.1.5
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/events.d.ts +3 -1
- package/dist/events.js +17 -12
- package/dist/module-context.d.ts +17 -0
- package/dist/module-context.js +85 -0
- package/dist/schema.d.ts +3 -0
- package/dist/schema.js +20 -3
- package/package.json +4 -3
- package/dist/value.js +0 -3
package/dist/events.d.ts
CHANGED
|
@@ -13,5 +13,7 @@ export declare const schema: import("@sinclair/typebox").TObject<{
|
|
|
13
13
|
}>>;
|
|
14
14
|
}>;
|
|
15
15
|
type AssertManifest = Static<typeof schema>;
|
|
16
|
-
export declare function create(manifest: AssertManifest, ctx: ResourceContext): Promise<{
|
|
16
|
+
export declare function create(manifest: AssertManifest, ctx: ResourceContext): Promise<{
|
|
17
|
+
run: () => Promise<void>;
|
|
18
|
+
}>;
|
|
17
19
|
export {};
|
package/dist/events.js
CHANGED
|
@@ -102,22 +102,27 @@ function buildReport(name, captured, expect) {
|
|
|
102
102
|
export async function create(manifest, ctx) {
|
|
103
103
|
const captured = [];
|
|
104
104
|
const filters = manifest.filter ?? [{ type: "*" }];
|
|
105
|
+
let appStarted = false;
|
|
106
|
+
ctx.on("Kernel.Started", () => {
|
|
107
|
+
appStarted = true;
|
|
108
|
+
});
|
|
105
109
|
ctx.on("*", (event) => {
|
|
106
110
|
if (filters.some((f) => matchesPattern(f.type, event.name))) {
|
|
107
111
|
captured.push({ name: event.name, payload: event.payload });
|
|
108
112
|
}
|
|
109
113
|
});
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
if (report
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
114
|
+
return {
|
|
115
|
+
run: async () => {
|
|
116
|
+
const report = buildReport(manifest.metadata.name, captured, manifest.expect);
|
|
117
|
+
if (report) {
|
|
118
|
+
if (report.passed) {
|
|
119
|
+
process.stdout.write(report.report);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
process.stderr.write(report.report);
|
|
123
|
+
ctx.requestExit(1);
|
|
124
|
+
}
|
|
119
125
|
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
return {};
|
|
126
|
+
},
|
|
127
|
+
};
|
|
123
128
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Static } from "@sinclair/typebox";
|
|
2
|
+
import { ResourceContext, Runnable } from "@telorun/sdk";
|
|
3
|
+
export declare const schema: import("@sinclair/typebox").TObject<{
|
|
4
|
+
metadata: import("@sinclair/typebox").TObject<{
|
|
5
|
+
name: import("@sinclair/typebox").TString;
|
|
6
|
+
module: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
7
|
+
}>;
|
|
8
|
+
resources: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TObject<{
|
|
9
|
+
variables: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TAny>>;
|
|
10
|
+
secrets: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TAny>>;
|
|
11
|
+
}>>>;
|
|
12
|
+
variables: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TAny>>;
|
|
13
|
+
secrets: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TAny>>;
|
|
14
|
+
}>;
|
|
15
|
+
type ModuleContextManifest = Static<typeof schema>;
|
|
16
|
+
export declare function create(manifest: ModuleContextManifest, ctx: ResourceContext): Promise<Runnable>;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
const ImportEntry = Type.Object({
|
|
3
|
+
variables: Type.Optional(Type.Record(Type.String(), Type.Any())),
|
|
4
|
+
secrets: Type.Optional(Type.Record(Type.String(), Type.Any())),
|
|
5
|
+
});
|
|
6
|
+
export const schema = Type.Object({
|
|
7
|
+
metadata: Type.Object({
|
|
8
|
+
name: Type.String(),
|
|
9
|
+
module: Type.Optional(Type.String()),
|
|
10
|
+
}),
|
|
11
|
+
resources: Type.Optional(Type.Record(Type.String(), ImportEntry)),
|
|
12
|
+
variables: Type.Optional(Type.Record(Type.String(), Type.Any())),
|
|
13
|
+
secrets: Type.Optional(Type.Record(Type.String(), Type.Any())),
|
|
14
|
+
});
|
|
15
|
+
const useColor = process.stderr.isTTY;
|
|
16
|
+
const c = (code, text) => (useColor ? `\x1b[${code}m${text}\x1b[0m` : text);
|
|
17
|
+
const bold = (t) => c("1", t);
|
|
18
|
+
const red = (t) => c("31", t);
|
|
19
|
+
const green = (t) => c("32", t);
|
|
20
|
+
const yellow = (t) => c("33", t);
|
|
21
|
+
const dim = (t) => c("2", t);
|
|
22
|
+
function deepEqual(a, b) {
|
|
23
|
+
if (a === b)
|
|
24
|
+
return true;
|
|
25
|
+
if (a === null || b === null)
|
|
26
|
+
return false;
|
|
27
|
+
if (typeof a !== "object" || typeof b !== "object")
|
|
28
|
+
return false;
|
|
29
|
+
const aKeys = Object.keys(a);
|
|
30
|
+
const bKeys = Object.keys(b);
|
|
31
|
+
if (aKeys.length !== bKeys.length)
|
|
32
|
+
return false;
|
|
33
|
+
for (const key of aKeys) {
|
|
34
|
+
if (!deepEqual(a[key], b[key]))
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
export async function create(manifest, ctx) {
|
|
40
|
+
return {
|
|
41
|
+
run: async () => {
|
|
42
|
+
const declaringModule = manifest.metadata.module ?? "default";
|
|
43
|
+
const resourcesToCheck = manifest.resources ?? {};
|
|
44
|
+
const failures = [];
|
|
45
|
+
const passed = [];
|
|
46
|
+
const { resources } = ctx.moduleContext;
|
|
47
|
+
for (const [alias, expected] of Object.entries(resourcesToCheck)) {
|
|
48
|
+
if (!ctx.resolveModuleAlias(declaringModule, alias)) {
|
|
49
|
+
failures.push(`Import alias '${alias}' not found in module '${declaringModule}'`);
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const snap = resources[alias] ?? {};
|
|
53
|
+
const path = `resources.${alias}`;
|
|
54
|
+
for (const [key, expectedValue] of Object.entries(expected.variables ?? {})) {
|
|
55
|
+
const actual = snap?.variables?.[key];
|
|
56
|
+
if (deepEqual(actual, expectedValue)) {
|
|
57
|
+
passed.push(`${path}.variables.${key}`);
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
failures.push(`${path}.variables.${key}: expected ${yellow(JSON.stringify(expectedValue))}, got ${red(JSON.stringify(actual))}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
for (const [key, expectedValue] of Object.entries(expected.secrets ?? {})) {
|
|
64
|
+
const actual = snap?.secrets?.[key];
|
|
65
|
+
if (deepEqual(actual, expectedValue)) {
|
|
66
|
+
passed.push(`${path}.secrets.${key}`);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
failures.push(`${path}.secrets.${key}: ${dim("value mismatch")}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const name = manifest.metadata.name;
|
|
74
|
+
const passedLines = passed.map((p) => ` ${green("✓")} ${dim(p)}\n`).join("");
|
|
75
|
+
if (failures.length > 0) {
|
|
76
|
+
const failedLines = failures.map((f) => ` ${red("✗")} ${f}\n`).join("");
|
|
77
|
+
process.stderr.write(bold(red(`Assert.ModuleContext.${name}: assertion failed`)) + "\n" + passedLines + failedLines);
|
|
78
|
+
ctx.requestExit(1);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
process.stdout.write(bold(green(`Assert.ModuleContext.${name}: assertion passed`)) + "\n" + passedLines);
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
}
|
package/dist/schema.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { ResourceContext } from "@telorun/sdk";
|
|
2
2
|
import { Static } from "@sinclair/typebox";
|
|
3
3
|
export declare const schema: import("@sinclair/typebox").TObject<{
|
|
4
|
+
metadata: import("@sinclair/typebox").TObject<{
|
|
5
|
+
name: import("@sinclair/typebox").TString;
|
|
6
|
+
}>;
|
|
4
7
|
schema: import("@sinclair/typebox").TObject<{
|
|
5
8
|
type: import("@sinclair/typebox").TString;
|
|
6
9
|
}>;
|
package/dist/schema.js
CHANGED
|
@@ -1,15 +1,32 @@
|
|
|
1
1
|
import { Type } from "@sinclair/typebox";
|
|
2
2
|
export const schema = Type.Object({
|
|
3
|
+
metadata: Type.Object({
|
|
4
|
+
name: Type.String(),
|
|
5
|
+
}),
|
|
3
6
|
schema: Type.Object({
|
|
4
7
|
type: Type.String(),
|
|
5
8
|
}),
|
|
6
|
-
}
|
|
9
|
+
});
|
|
10
|
+
const useColor = process.stderr.isTTY;
|
|
11
|
+
const c = (code, text) => (useColor ? `\x1b[${code}m${text}\x1b[0m` : text);
|
|
12
|
+
const bold = (t) => c("1", t);
|
|
13
|
+
const red = (t) => c("31", t);
|
|
14
|
+
const green = (t) => c("32", t);
|
|
15
|
+
const dim = (t) => c("2", t);
|
|
7
16
|
export async function create(manifest, ctx) {
|
|
8
17
|
const validator = ctx.createSchemaValidator(manifest.schema);
|
|
18
|
+
const name = manifest.metadata.name;
|
|
9
19
|
return {
|
|
10
20
|
invoke: (data) => {
|
|
11
|
-
|
|
12
|
-
|
|
21
|
+
try {
|
|
22
|
+
validator.validate(data);
|
|
23
|
+
process.stdout.write(bold(green(`Assert.Schema.${name}: assertion passed`)) + "\n" + ` ${green("✓")} ${dim(JSON.stringify(data))}\n`);
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
process.stderr.write(bold(red(`Assert.Schema.${name}: assertion failed`)) + "\n" + ` ${red("✗")} ${err?.message ?? String(err)}\n`);
|
|
28
|
+
throw err;
|
|
29
|
+
}
|
|
13
30
|
},
|
|
14
31
|
};
|
|
15
32
|
}
|
package/package.json
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@telorun/assert",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
"./schema": "./src/schema.ts",
|
|
7
|
-
"./events": "./src/events.ts"
|
|
7
|
+
"./events": "./src/events.ts",
|
|
8
|
+
"./module-context": "./src/module-context.ts"
|
|
8
9
|
},
|
|
9
10
|
"files": [
|
|
10
11
|
"dist/**"
|
|
11
12
|
],
|
|
12
13
|
"dependencies": {
|
|
13
14
|
"@sinclair/typebox": "^0.34.48",
|
|
14
|
-
"@telorun/sdk": "0.2.
|
|
15
|
+
"@telorun/sdk": "0.2.6"
|
|
15
16
|
},
|
|
16
17
|
"devDependencies": {
|
|
17
18
|
"@types/node": "^20.0.0",
|
package/dist/value.js
DELETED