@procedures/playground 0.0.0-stage → 0.2.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 +14 -0
- package/LICENSE +21 -0
- package/README.md +694 -2
- package/dist/.tsbuildinfo +1 -0
- package/dist/index.d.ts +120 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +136 -0
- package/dist/index.js.map +1 -0
- package/package.json +62 -3
- package/src/index.ts +219 -0
package/package.json
CHANGED
|
@@ -1,6 +1,65 @@
|
|
|
1
1
|
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/package",
|
|
2
3
|
"name": "@procedures/playground",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
4
|
+
"version": "0.2.0",
|
|
5
|
+
"description": "A typed fluent API to write procedure programs in TypeScript (proc, ref, run) with autocomplete, then run them with the client.",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"dsl",
|
|
8
|
+
"fluent-api",
|
|
9
|
+
"procedures",
|
|
10
|
+
"typescript",
|
|
11
|
+
"workflow"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://mark1russell7.github.io/client/",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/mark1russell7/client/issues"
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/mark1russell7/client.git",
|
|
20
|
+
"directory": "packages/client-playground"
|
|
21
|
+
},
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"author": "Mark Russell (https://github.com/mark1russell7)",
|
|
24
|
+
"type": "module",
|
|
25
|
+
"main": "./dist/index.js",
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"import": "./dist/index.js"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"dist",
|
|
35
|
+
"src",
|
|
36
|
+
"!src/**/*.test.ts",
|
|
37
|
+
"!src/**/*.test.tsx",
|
|
38
|
+
"!src/**/__tests__",
|
|
39
|
+
"CHANGELOG.md"
|
|
40
|
+
],
|
|
41
|
+
"sideEffects": false,
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=22"
|
|
44
|
+
},
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public",
|
|
47
|
+
"provenance": true
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"@procedures/client": "0.2.0"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"typescript": "^7.0.2",
|
|
54
|
+
"@types/node": "^22.0.0",
|
|
55
|
+
"@mark1russell7/cue": "^1.0.0",
|
|
56
|
+
"vitest": "^5.0.3"
|
|
57
|
+
},
|
|
58
|
+
"scripts": {
|
|
59
|
+
"build": "tsc -b",
|
|
60
|
+
"typecheck": "tsc --noEmit",
|
|
61
|
+
"clean": "rm -rf dist .tsbuildinfo",
|
|
62
|
+
"test": "vitest run --passWithNoTests",
|
|
63
|
+
"test:watch": "vitest"
|
|
64
|
+
}
|
|
6
65
|
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client Playground
|
|
3
|
+
*
|
|
4
|
+
* Type-safe aggregation building for procedure compositions.
|
|
5
|
+
* Write aggregations in TypeScript with full autocomplete, then run them.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* // my-agg.play.ts
|
|
10
|
+
* import { proc, ref, run } from "@procedures/playground";
|
|
11
|
+
*
|
|
12
|
+
* run(
|
|
13
|
+
* proc(["dag", "traverse"]).input({
|
|
14
|
+
* visit: [
|
|
15
|
+
* proc(["pnpm", "install"]).ref,
|
|
16
|
+
* proc(["git", "hasChanges"]).name("changes").ref,
|
|
17
|
+
* proc(["client", "conditional"]).input({
|
|
18
|
+
* condition: ref("changes.value"),
|
|
19
|
+
* then: proc(["git", "add"]).input({ all: true }).ref,
|
|
20
|
+
* }).ref,
|
|
21
|
+
* ],
|
|
22
|
+
* }).ref
|
|
23
|
+
* );
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* Run with: `npx tsx my-agg.play.ts`
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import type { ProcedurePath, ProcedureRefJson } from "@procedures/client";
|
|
30
|
+
|
|
31
|
+
// =============================================================================
|
|
32
|
+
// Output Reference
|
|
33
|
+
// =============================================================================
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* An output reference for referencing named stage outputs.
|
|
37
|
+
*/
|
|
38
|
+
export interface OutputRef {
|
|
39
|
+
readonly $ref: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Create an output reference.
|
|
44
|
+
*
|
|
45
|
+
* @param path - Reference path (e.g., "stageName.value" or "$last.value")
|
|
46
|
+
* @returns Output reference object
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```typescript
|
|
50
|
+
* ref("changes.value") // Reference the .value field of "changes" output
|
|
51
|
+
* ref("$last") // Reference the previous step's output
|
|
52
|
+
* ref("$last.success") // Reference the .success field of previous output
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export function ref(path: string): OutputRef {
|
|
56
|
+
return { $ref: path };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// =============================================================================
|
|
60
|
+
// Procedure Reference Builder
|
|
61
|
+
// =============================================================================
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Builder for creating procedure references with a fluent API.
|
|
65
|
+
*/
|
|
66
|
+
export interface ProcBuilder<TInput = unknown> {
|
|
67
|
+
/**
|
|
68
|
+
* Set the input for this procedure.
|
|
69
|
+
*/
|
|
70
|
+
input<T>(input: T): ProcBuilder<T>;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Name this stage for later reference with $ref.
|
|
74
|
+
*/
|
|
75
|
+
name(name: string): ProcBuilder<TInput>;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Set when this reference should be executed.
|
|
79
|
+
* @param when - "$immediate", "$never", "$parent", or a named context
|
|
80
|
+
*/
|
|
81
|
+
when(when: string): ProcBuilder<TInput>;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Get the procedure reference object.
|
|
85
|
+
*/
|
|
86
|
+
readonly ref: ProcedureRefJson<TInput>;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Create a procedure reference builder.
|
|
91
|
+
*
|
|
92
|
+
* @param path - Path to the procedure (e.g., ["git", "add"])
|
|
93
|
+
* @returns Builder for the procedure reference
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* // Simple reference
|
|
98
|
+
* proc(["git", "add"]).input({ all: true }).ref
|
|
99
|
+
*
|
|
100
|
+
* // Named reference for $ref
|
|
101
|
+
* proc(["git", "hasChanges"]).name("changes").ref
|
|
102
|
+
*
|
|
103
|
+
* // With execution timing
|
|
104
|
+
* proc(["git", "add"]).input({ all: true }).when("$parent").ref
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
export function proc(path: ProcedurePath): ProcBuilder<unknown> {
|
|
108
|
+
let _input: unknown = {};
|
|
109
|
+
let _name: string | undefined;
|
|
110
|
+
let _when: string | undefined;
|
|
111
|
+
|
|
112
|
+
const builder: ProcBuilder<unknown> = {
|
|
113
|
+
input<T>(input: T): ProcBuilder<T> {
|
|
114
|
+
_input = input;
|
|
115
|
+
return builder as ProcBuilder<T>;
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
name(name: string): ProcBuilder<unknown> {
|
|
119
|
+
_name = name;
|
|
120
|
+
return builder;
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
when(when: string): ProcBuilder<unknown> {
|
|
124
|
+
_when = when;
|
|
125
|
+
return builder;
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
get ref(): ProcedureRefJson<unknown> {
|
|
129
|
+
const result: ProcedureRefJson<unknown> = {
|
|
130
|
+
$proc: path,
|
|
131
|
+
input: _input,
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
if (_name) {
|
|
135
|
+
(result as { $name?: string }).$name = _name;
|
|
136
|
+
}
|
|
137
|
+
if (_when) {
|
|
138
|
+
(result as { $when?: string }).$when = _when;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return result;
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
return builder;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// =============================================================================
|
|
149
|
+
// Execution
|
|
150
|
+
// =============================================================================
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Options for running a procedure.
|
|
154
|
+
*/
|
|
155
|
+
export interface RunOptions {
|
|
156
|
+
/** Whether to print the result (default: true) */
|
|
157
|
+
print?: boolean;
|
|
158
|
+
|
|
159
|
+
/** Output format (default: "json") */
|
|
160
|
+
format?: "json" | "text";
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Run a procedure reference.
|
|
165
|
+
*
|
|
166
|
+
* This function executes the procedure and prints the result.
|
|
167
|
+
* Use this in your playground files to execute aggregations.
|
|
168
|
+
*
|
|
169
|
+
* @param procedureRef - The procedure reference to execute
|
|
170
|
+
* @param options - Execution options
|
|
171
|
+
* @returns The result of the procedure
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* ```typescript
|
|
175
|
+
* // Run and print result
|
|
176
|
+
* await run(proc(["git", "status"]).ref);
|
|
177
|
+
*
|
|
178
|
+
* // Run without printing
|
|
179
|
+
* const result = await run(proc(["git", "status"]).ref, { print: false });
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
182
|
+
export async function run<T = unknown>(
|
|
183
|
+
procedureRef: ProcedureRefJson,
|
|
184
|
+
options: RunOptions = {}
|
|
185
|
+
): Promise<T> {
|
|
186
|
+
const { print: shouldPrint = true, format = "json" } = options;
|
|
187
|
+
|
|
188
|
+
// Dynamic import to avoid bundling all of client
|
|
189
|
+
const { Client, LocalTransport, PROCEDURE_REGISTRY } = await import(
|
|
190
|
+
"@procedures/client"
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
// The transport runs each procedure of the registry through invokeProcedure()
|
|
194
|
+
// (ARCHITECTURE-PROPOSALS P1). Before, this file had its own copy of the bridge, without
|
|
195
|
+
// input validation.
|
|
196
|
+
const transport = new LocalTransport({ registry: PROCEDURE_REGISTRY });
|
|
197
|
+
|
|
198
|
+
const client = new Client({ transport });
|
|
199
|
+
|
|
200
|
+
// Execute the procedure
|
|
201
|
+
const result = await client.exec(procedureRef);
|
|
202
|
+
|
|
203
|
+
// Print result
|
|
204
|
+
if (shouldPrint) {
|
|
205
|
+
if (format === "json") {
|
|
206
|
+
console.log(JSON.stringify(result, null, 2));
|
|
207
|
+
} else {
|
|
208
|
+
console.log(result);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return result as T;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// =============================================================================
|
|
216
|
+
// Convenience Exports
|
|
217
|
+
// =============================================================================
|
|
218
|
+
|
|
219
|
+
export type { ProcedurePath, ProcedureRefJson } from "@procedures/client";
|