@telorun/assert 0.1.3 → 0.1.4

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 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
- ctx.on("Runtime.Stopping", () => {
111
- const report = buildReport(manifest.metadata.name, captured, manifest.expect);
112
- if (report) {
113
- if (report.passed) {
114
- process.stdout.write(report.report);
115
- }
116
- else {
117
- process.stderr.write(report.report);
118
- ctx.requestExit(1);
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,15 @@
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
+ imports: 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
+ }>;
13
+ type ModuleContextManifest = Static<typeof schema>;
14
+ export declare function create(manifest: ModuleContextManifest, ctx: ResourceContext): Promise<Runnable>;
15
+ export {};
@@ -0,0 +1,94 @@
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
+ imports: Type.Optional(Type.Record(Type.String(), ImportEntry)),
12
+ });
13
+ const useColor = process.stderr.isTTY;
14
+ const c = (code, text) => (useColor ? `\x1b[${code}m${text}\x1b[0m` : text);
15
+ const bold = (t) => c("1", t);
16
+ const red = (t) => c("31", t);
17
+ const green = (t) => c("32", t);
18
+ const yellow = (t) => c("33", t);
19
+ const dim = (t) => c("2", t);
20
+ function deepEqual(a, b) {
21
+ if (a === b)
22
+ return true;
23
+ if (a === null || b === null)
24
+ return false;
25
+ if (typeof a !== "object" || typeof b !== "object")
26
+ return false;
27
+ const aKeys = Object.keys(a);
28
+ const bKeys = Object.keys(b);
29
+ if (aKeys.length !== bKeys.length)
30
+ return false;
31
+ for (const key of aKeys) {
32
+ if (!deepEqual(a[key], b[key]))
33
+ return false;
34
+ }
35
+ return true;
36
+ }
37
+ export async function create(manifest, ctx) {
38
+ return {
39
+ run: async () => {
40
+ const declaringModule = manifest.metadata.module ?? "default";
41
+ const importsToCheck = manifest.imports ?? {};
42
+ const failures = [];
43
+ const passed = [];
44
+ for (const [alias, expected] of Object.entries(importsToCheck)) {
45
+ const realModule = ctx.resolveModuleAlias(declaringModule, alias);
46
+ if (!realModule) {
47
+ failures.push(`Import alias '${alias}' not found in module '${declaringModule}'`);
48
+ continue;
49
+ }
50
+ const moduleCtx = ctx.moduleContext;
51
+ const importSnap = moduleCtx.resources[alias] ?? {};
52
+ const expectedVariables = expected.variables ?? {};
53
+ const expectedSecrets = expected.secrets ?? {};
54
+ for (const [key, expectedValue] of Object.entries(expectedVariables)) {
55
+ const actualValue = importSnap?.variables?.[key];
56
+ if (!deepEqual(actualValue, expectedValue)) {
57
+ failures.push(`imports.${alias}.variables.${key}: expected ${yellow(JSON.stringify(expectedValue))}, got ${red(JSON.stringify(actualValue))}`);
58
+ }
59
+ else {
60
+ passed.push(`imports.${alias}.variables.${key}`);
61
+ }
62
+ }
63
+ for (const [key] of Object.entries(expectedSecrets)) {
64
+ const actualSecret = importSnap?.secrets?.[key];
65
+ if (!deepEqual(actualSecret, expectedSecrets[key])) {
66
+ failures.push(`imports.${alias}.secrets.${key}: ${dim("value mismatch")}`);
67
+ }
68
+ else {
69
+ passed.push(`imports.${alias}.secrets.${key}`);
70
+ }
71
+ }
72
+ }
73
+ const name = manifest.metadata.name;
74
+ if (failures.length > 0) {
75
+ let report = bold(red(`Assert.ModuleContext.${name}: assertion failed`)) + "\n";
76
+ for (const p of passed) {
77
+ report += ` ${green("✓")} ${dim(p)}\n`;
78
+ }
79
+ for (const f of failures) {
80
+ report += ` ${red("✗")} ${f}\n`;
81
+ }
82
+ process.stderr.write(report);
83
+ ctx.requestExit(1);
84
+ }
85
+ else {
86
+ let report = bold(green(`Assert.ModuleContext.${name}: assertion passed`)) + "\n";
87
+ for (const p of passed) {
88
+ report += ` ${green("✓")} ${dim(p)}\n`;
89
+ }
90
+ process.stdout.write(report);
91
+ }
92
+ },
93
+ };
94
+ }
package/package.json CHANGED
@@ -1,17 +1,18 @@
1
1
  {
2
2
  "name": "@telorun/assert",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
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.4"
15
+ "@telorun/sdk": "0.2.5"
15
16
  },
16
17
  "devDependencies": {
17
18
  "@types/node": "^20.0.0",
package/dist/value.js DELETED
@@ -1,3 +0,0 @@
1
- export async function create() {
2
- return {};
3
- }