webpipe-js 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.
@@ -0,0 +1,119 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+ import { describe, it, expect, beforeAll } from 'vitest';
4
+ import { parseProgram, type Program } from '../parser';
5
+
6
+ function loadFixture(name: string): string {
7
+ const file = resolve(process.cwd(), name);
8
+ return readFileSync(file, 'utf8');
9
+ }
10
+
11
+ describe('parseProgram - comprehensive_test.wp', () => {
12
+ let program: Program;
13
+
14
+ beforeAll(() => {
15
+ const src = loadFixture('comprehensive_test.wp');
16
+ program = parseProgram(src);
17
+ });
18
+
19
+ it('parses at least one route', () => {
20
+ expect(program.routes.length).toBeGreaterThan(0);
21
+ const hello = program.routes.find(r => r.path.startsWith('/hello'));
22
+ expect(hello).toBeTruthy();
23
+ expect(hello!.method).toBe('GET');
24
+ // First step should be jq with config string
25
+ if (hello!.pipeline.kind === 'Inline') {
26
+ const first = hello!.pipeline.pipeline.steps[0];
27
+ expect(first.kind).toBe('Regular');
28
+ if (first.kind === 'Regular') {
29
+ expect(first.name).toBe('jq');
30
+ expect(typeof first.config).toBe('string');
31
+ }
32
+ }
33
+ });
34
+
35
+ it('parses configs', () => {
36
+ expect(program.configs.length).toBeGreaterThan(0);
37
+ const pg = program.configs.find(c => c.name === 'pg');
38
+ expect(pg).toBeTruthy();
39
+ expect(pg!.properties.length).toBeGreaterThan(3);
40
+ const host = pg!.properties.find(p => p.key === 'host');
41
+ expect(host).toBeTruthy();
42
+ expect(host!.value.kind === 'EnvVar' || host!.value.kind === 'String').toBe(true);
43
+ });
44
+
45
+ it('parses named pipelines and references', () => {
46
+ const np = program.pipelines.find(p => p.name === 'getTeams');
47
+ expect(np).toBeTruthy();
48
+ const route = program.routes.find(r => r.path.startsWith('/page/'));
49
+ expect(route).toBeTruthy();
50
+ expect(route!.pipeline.kind).toBe('Inline');
51
+ if (route!.pipeline.kind === 'Inline') {
52
+ const step = route!.pipeline.pipeline.steps[0];
53
+ expect(step.kind).toBe('Regular');
54
+ if (step.kind === 'Regular') {
55
+ expect(step.name).toBe('pipeline');
56
+ expect(step.config).toBe('getTeams');
57
+ }
58
+ }
59
+ });
60
+
61
+ it('parses variables', () => {
62
+ expect(program.variables.length).toBeGreaterThan(0);
63
+ const teamsQuery = program.variables.find(v => v.name === 'teamsQuery');
64
+ expect(teamsQuery).toBeTruthy();
65
+ expect(teamsQuery!.varType).toBe('pg');
66
+ expect(typeof teamsQuery!.value).toBe('string');
67
+ });
68
+
69
+ it('parses describes and tests with conditions', () => {
70
+ expect(program.describes.length).toBeGreaterThan(0);
71
+ const d = program.describes.find(dd => dd.name.includes('hello'))!;
72
+ expect(d).toBeTruthy();
73
+ expect(d.tests.length).toBeGreaterThan(0);
74
+ const t0 = d.tests[0];
75
+ expect(t0.when).toBeTruthy();
76
+ expect(t0.conditions.length).toBeGreaterThan(0);
77
+ });
78
+ });
79
+
80
+ describe('parseProgram - focused samples', () => {
81
+ it('parses result branches', () => {
82
+ const src = `GET /test\n |> jq: \`{message: "x"}\`\n |> result\n ok(200):\n |> jq: \`{ok: true}\`\n default(500):\n |> jq: \`{ok: false}\``;
83
+ const program = parseProgram(src);
84
+ expect(program.routes.length).toBe(1);
85
+ const steps = (program.routes[0].pipeline as any).pipeline.steps as any[];
86
+ const res = steps.find(s => s.kind === 'Result');
87
+ expect(res).toBeTruthy();
88
+ expect(res.branches.length).toBe(2);
89
+ expect(res.branches[0].statusCode).toBe(200);
90
+ expect(res.branches[1].statusCode).toBe(500);
91
+ });
92
+
93
+ it('parses POST with body conversion pipeline', () => {
94
+ const src = `POST /users\n |> jq: \`{ name: .body.name }\``;
95
+ const program = parseProgram(src);
96
+ expect(program.routes[0].method).toBe('POST');
97
+ const first = (program.routes[0].pipeline as any).pipeline.steps[0];
98
+ expect(first.name).toBe('jq');
99
+ });
100
+
101
+ it('parses inline and named pipeline refs', () => {
102
+ const src = `pipeline p =\n |> jq: \`{x:1}\`\n\nGET /a\n |> pipeline: p`;
103
+ const program = parseProgram(src);
104
+ const p = program.pipelines.find(pp => pp.name === 'p');
105
+ expect(p).toBeTruthy();
106
+ const route = program.routes[0];
107
+ expect(route.pipeline.kind).toBe('Inline');
108
+ if (route.pipeline.kind === 'Inline') {
109
+ const step = route.pipeline.pipeline.steps[0];
110
+ expect(step.kind).toBe('Regular');
111
+ if (step.kind === 'Regular') {
112
+ expect(step.name).toBe('pipeline');
113
+ expect(step.config).toBe('p');
114
+ }
115
+ }
116
+ });
117
+ });
118
+
119
+
package/tsconfig.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ES2022",
5
+ "moduleResolution": "Node",
6
+ "strict": true,
7
+ "noImplicitAny": true,
8
+ "esModuleInterop": true,
9
+ "skipLibCheck": true,
10
+ "forceConsistentCasingInFileNames": true,
11
+ "rootDir": ".",
12
+ "outDir": "dist",
13
+ "declaration": true,
14
+ "types": ["vitest/globals"]
15
+ },
16
+ "include": ["**/*.ts"],
17
+ "exclude": ["node_modules", "dist"]
18
+ }