@procedures/procedure 0.0.0-stage → 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.
Files changed (40) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/LICENSE +21 -0
  3. package/README.md +405 -2
  4. package/dist/.tsbuildinfo +1 -0
  5. package/dist/index.d.ts +9 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +12 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/module.d.ts +17 -0
  10. package/dist/module.d.ts.map +1 -0
  11. package/dist/module.js +41 -0
  12. package/dist/module.js.map +1 -0
  13. package/dist/procedures/procedure/index.d.ts +5 -0
  14. package/dist/procedures/procedure/index.d.ts.map +1 -0
  15. package/dist/procedures/procedure/index.js +5 -0
  16. package/dist/procedures/procedure/index.js.map +1 -0
  17. package/dist/procedures/procedure/new.d.ts +54 -0
  18. package/dist/procedures/procedure/new.d.ts.map +1 -0
  19. package/dist/procedures/procedure/new.js +442 -0
  20. package/dist/procedures/procedure/new.js.map +1 -0
  21. package/dist/procedures/procedure/registry.d.ts +10 -0
  22. package/dist/procedures/procedure/registry.d.ts.map +1 -0
  23. package/dist/procedures/procedure/registry.js +67 -0
  24. package/dist/procedures/procedure/registry.js.map +1 -0
  25. package/dist/register.d.ts +8 -0
  26. package/dist/register.d.ts.map +1 -0
  27. package/dist/register.js +16 -0
  28. package/dist/register.js.map +1 -0
  29. package/dist/types.d.ts +29 -0
  30. package/dist/types.d.ts.map +1 -0
  31. package/dist/types.js +34 -0
  32. package/dist/types.js.map +1 -0
  33. package/package.json +72 -3
  34. package/src/index.ts +14 -0
  35. package/src/module.ts +50 -0
  36. package/src/procedures/procedure/index.ts +5 -0
  37. package/src/procedures/procedure/new.ts +493 -0
  38. package/src/procedures/procedure/registry.ts +92 -0
  39. package/src/register.ts +19 -0
  40. package/src/types.ts +63 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,10 @@
1
+ # @procedures/procedure
2
+
3
+ ## 0.1.0
4
+
5
+ The first release on npm. The packages of the client monorepo have one version together.
6
+
7
+ ### Breaking changes (from the versions on GitHub)
8
+
9
+ - `client-procedure` does not register its own `procedure.list` and `procedure.get`. The procedures of the core answer for both. Before, the result depended on the imports of the host. The package keeps `procedure.new` and `procedure.export`.
10
+ - `procedure.get` gives `{ found: false }` for a path that has no procedure, not `null`.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-2026 Mark Russell
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,406 @@
1
- # Temporary Holding Version
1
+ # @procedures/procedure
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ [![npm version](https://img.shields.io/npm/v/@procedures/procedure.svg)](https://www.npmjs.com/package/@procedures/procedure)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.9-blue.svg)](https://www.typescriptlang.org/)
6
+
7
+ **Procedure scaffolding and meta-procedures for runtime procedure management.**
8
+
9
+ ## Table of Contents
10
+
11
+ - [Overview](#overview)
12
+ - [Installation](#installation)
13
+ - [Architecture](#architecture)
14
+ - [Quick Start](#quick-start)
15
+ - [API Reference](#api-reference)
16
+ - [Examples](#examples)
17
+ - [Integration](#integration)
18
+
19
+ ## Overview
20
+
21
+ `@procedures/procedure` provides utilities for creating and managing procedures:
22
+
23
+ - **procedure.new**: Scaffold new procedures with types and registration boilerplate
24
+ - **procedure.list**: List all registered procedures in the runtime registry
25
+ - **procedure.get**: Get metadata for a specific procedure
26
+ - **procedure.export**: Export procedure definitions as JSON
27
+
28
+ This package simplifies procedure development by automating the creation of procedure files, type definitions, and registration code.
29
+
30
+ ## Installation
31
+
32
+ ```bash
33
+ npm install github:mark1russell7/client-procedure#main
34
+ ```
35
+
36
+ **Dependencies:**
37
+ - `@procedures/client` (peer dependency)
38
+ - `zod` ^3.24.0
39
+
40
+ ## Architecture
41
+
42
+ ```mermaid
43
+ graph TB
44
+ subgraph "Procedure Scaffolding"
45
+ ProcNew[procedure.new]
46
+ Templates[Code Templates]
47
+ FileGen[File Generator]
48
+ end
49
+
50
+ subgraph "Generated Files"
51
+ ProcFile[src/procedures/namespace/operation.ts]
52
+ TypesFile[src/types.ts]
53
+ IndexFile[src/procedures/namespace/index.ts]
54
+ RegisterFile[src/register.ts]
55
+ end
56
+
57
+ subgraph "Meta-Procedures"
58
+ ProcList[procedure.list]
59
+ ProcGet[procedure.get]
60
+ ProcExport[procedure.export]
61
+ end
62
+
63
+ subgraph "Runtime Registry"
64
+ Registry[PROCEDURE_REGISTRY]
65
+ Procedures[Registered Procedures]
66
+ end
67
+
68
+ ProcNew --> Templates
69
+ Templates --> FileGen
70
+ FileGen --> ProcFile
71
+ FileGen --> TypesFile
72
+ FileGen --> IndexFile
73
+
74
+ ProcList --> Registry
75
+ ProcGet --> Registry
76
+ ProcExport --> Registry
77
+ Registry --> Procedures
78
+ ```
79
+
80
+ ### Scaffolding Flow
81
+
82
+ ```mermaid
83
+ sequenceDiagram
84
+ participant User
85
+ participant ProcNew as procedure.new
86
+ participant FS as File System
87
+ participant Templates
88
+
89
+ User->>ProcNew: procedure.new { name: "user.create" }
90
+ ProcNew->>Templates: Generate procedure code
91
+ Templates-->>ProcNew: Procedure file content
92
+ ProcNew->>FS: Write src/procedures/user/create.ts
93
+ ProcNew->>Templates: Generate types
94
+ Templates-->>ProcNew: Type definitions
95
+ ProcNew->>FS: Append to src/types.ts
96
+ ProcNew->>Templates: Generate exports
97
+ Templates-->>ProcNew: Export statement
98
+ ProcNew->>FS: Update src/procedures/user/index.ts
99
+ ProcNew->>FS: Add the procedure to src/register.ts
100
+ ProcNew-->>User: Success + next steps
101
+ ```
102
+
103
+ The scaffolded code compiles with the strict options of the workspace. A name whose path, file, type names or registration exists already is an error, and then nothing is written.
104
+
105
+ ## Quick Start
106
+
107
+ ```typescript
108
+ import { Client, LocalTransport, PROCEDURE_REGISTRY } from "@procedures/client";
109
+ import "@procedures/procedure"; // registers its procedures
110
+
111
+ const client = new Client(new LocalTransport({ registry: PROCEDURE_REGISTRY }));
112
+
113
+ // Scaffold a new procedure
114
+ const result = await client.exec(["procedure", "new"], {
115
+ name: "user.create",
116
+ description: "Create a new user account",
117
+ });
118
+
119
+ console.log(result.operations);
120
+ // [
121
+ // "Creating directory: /project/src/procedures/user",
122
+ // "Creating procedure file: /project/src/procedures/user/create.ts",
123
+ // "Creating index: /project/src/procedures/user/index.ts",
124
+ // "Appending types to: /project/src/types.ts",
125
+ // "Next steps: ..."
126
+ // ]
127
+ ```
128
+
129
+ ## API Reference
130
+
131
+ ### Procedures
132
+
133
+ #### `procedure.new`
134
+
135
+ Scaffold a new procedure with type definitions and boilerplate.
136
+
137
+ ```typescript
138
+ interface ProcedureNewInput {
139
+ name: string; // Dot-notation name (e.g., "user.create" or "fs.readJson")
140
+ namespace?: string; // Namespace override: the folder under src/procedures (defaults to first segment)
141
+ description?: string; // Procedure description
142
+ path?: string; // Project path (defaults to cwd)
143
+ dryRun?: boolean; // Preview without creating files
144
+ }
145
+
146
+ interface ProcedureNewOutput {
147
+ success: boolean;
148
+ procedurePath: string[]; // e.g., ["user", "create"]
149
+ created: string[]; // Files created
150
+ modified: string[]; // Files modified
151
+ operations: string[]; // Operations performed
152
+ errors: string[]; // Any errors
153
+ }
154
+ ```
155
+
156
+ **Example:**
157
+ ```typescript
158
+ const result = await client.exec(["procedure", "new"], {
159
+ name: "user.create",
160
+ description: "Create a new user",
161
+ path: "/path/to/package",
162
+ });
163
+ ```
164
+
165
+ **Generated Files:**
166
+
167
+ The file of a procedure is `src/procedures/<first segment>/<middle segments>/<last segment>.ts`: `api.v2.users.create` gives `src/procedures/api/v2/users/create.ts`.
168
+
169
+ 1. **Procedure File** (`src/procedures/user/create.ts`):
170
+ ```typescript
171
+ /**
172
+ * user.create procedure
173
+ *
174
+ * Create a new user
175
+ */
176
+
177
+ import type { UserCreateInput, UserCreateOutput } from "../../types.js";
178
+
179
+ /**
180
+ * Create a new user
181
+ */
182
+ export async function userCreate(_input: UserCreateInput): Promise<UserCreateOutput> {
183
+ // TODO: Implement user.create (rename _input to input when the code uses it)
184
+ return {
185
+ success: true,
186
+ message: "Hello from user.create",
187
+ };
188
+ }
189
+ ```
190
+
191
+ 2. **Type Definitions** (appended to `src/types.ts`, which gets `import { z } from "zod"` if it has none, or is created):
192
+ ```typescript
193
+ // =============================================================================
194
+ // user.create Types - Create a new user
195
+ // =============================================================================
196
+
197
+ export const UserCreateInputSchema: z.ZodObject<{
198
+ // TODO: Add input fields
199
+ }> = z.object({
200
+ // TODO: Add input fields
201
+ });
202
+
203
+ export type UserCreateInput = z.infer<typeof UserCreateInputSchema>;
204
+
205
+ export interface UserCreateOutput {
206
+ /** Whether the operation succeeded */
207
+ success: boolean;
208
+ /** Response message */
209
+ message: string;
210
+ }
211
+ ```
212
+
213
+ 3. **Index Export** (appended to `src/procedures/user/index.ts`):
214
+ ```typescript
215
+ export { userCreate } from "./create.js";
216
+ ```
217
+
218
+ 4. **Registration** (added to `src/register.ts`: the imports, the definition, and the item of the `registerProcedures([...])` array):
219
+ ```typescript
220
+ import { createProcedure, outputSchema, registerProcedures, zodAdapter } from "@procedures/client";
221
+ import { userCreate } from "./procedures/user/create.js";
222
+ import { UserCreateInputSchema, type UserCreateInput, type UserCreateOutput } from "./types.js";
223
+
224
+ const userCreateProcedure = createProcedure()
225
+ .path(["user", "create"])
226
+ .input(zodAdapter<UserCreateInput>(UserCreateInputSchema))
227
+ .output(outputSchema<UserCreateOutput>())
228
+ .meta({
229
+ description: "Create a new user",
230
+ args: [],
231
+ shorts: {},
232
+ output: "text",
233
+ })
234
+ .handler(async (input: UserCreateInput): Promise<UserCreateOutput> => userCreate(input))
235
+ .build();
236
+
237
+ export function register(): void {
238
+ registerProcedures([userCreateProcedure]);
239
+ }
240
+ ```
241
+
242
+ If `src/register.ts` has no `registerProcedures([...])` or `registerAll([...])` call, the operations say what to add.
243
+
244
+ #### `procedure.list`
245
+
246
+ List the procedures of the registry, with an optional namespace filter.
247
+
248
+ ```typescript
249
+ interface ProcedureListInput {
250
+ namespace?: string; // Only the procedures of this first path segment
251
+ includeMetadata?: boolean; // Default: false
252
+ }
253
+
254
+ interface ProcedureListOutput {
255
+ procedures: Array<{
256
+ path: string[];
257
+ key: string; // "git.commit"
258
+ description?: string;
259
+ tags?: string[];
260
+ hasHandler: boolean;
261
+ }>;
262
+ count: number;
263
+ }
264
+ ```
265
+
266
+ ```typescript
267
+ const { procedures, count } = await client.exec(["procedure", "list"], { namespace: "git" });
268
+ ```
269
+
270
+ #### `procedure.get`
271
+
272
+ Get the metadata of one procedure.
273
+
274
+ ```typescript
275
+ interface ProcedureGetInput {
276
+ path: string[] | string; // ["git", "commit"] or "git.commit"
277
+ }
278
+
279
+ interface ProcedureGetOutput {
280
+ found: boolean;
281
+ path?: string[];
282
+ metadata?: Record<string, unknown>;
283
+ hasHandler?: boolean;
284
+ hasInputSchema?: boolean;
285
+ hasOutputSchema?: boolean;
286
+ }
287
+ ```
288
+
289
+ #### `procedure.export`
290
+
291
+ Export the path and the metadata of one procedure as a call (`$proc`).
292
+
293
+ ```typescript
294
+ interface ProcedureExportInput {
295
+ path: string[] | string;
296
+ }
297
+
298
+ interface ProcedureExportOutput {
299
+ success: boolean;
300
+ definition?: { $proc: string[]; metadata?: Record<string, unknown> };
301
+ error?: string; // When the procedure does not exist
302
+ }
303
+ ```
304
+
305
+ > [!NOTE]
306
+ > The core package `client` also has `procedure.list` and `procedure.get`, for the procedures that `procedure.define` made. `client-procedure` registers its own versions with `override: true`. Thus the result depends on whether the host imports `client-procedure`: `mark` and the MCP server do.
307
+
308
+ ## Examples
309
+
310
+ ### Scaffold a Nested Procedure
311
+
312
+ ```typescript
313
+ const result = await client.exec(["procedure", "new"], {
314
+ name: "api.users.permissions.grant",
315
+ description: "Grant permission to a user",
316
+ });
317
+
318
+ // Generated path: ["api", "users", "permissions", "grant"]
319
+ // File: src/procedures/api/users/permissions/grant.ts
320
+ ```
321
+
322
+ ### Dry Run Mode
323
+
324
+ ```typescript
325
+ // The plan of the scaffold, without a change of a file
326
+ const preview = await client.exec(["procedure", "new"], {
327
+ name: "product.update",
328
+ dryRun: true,
329
+ });
330
+
331
+ console.log(preview.operations);
332
+ ```
333
+
334
+ ## Integration
335
+
336
+ ### Use with CLI
337
+
338
+ The `procedure.new` command is also available via the Mark CLI:
339
+
340
+ ```bash
341
+ # Scaffold a new procedure
342
+ node packages/mark/dist/cli.js procedure new user.create --path packages/my-package
343
+
344
+ # With options
345
+ node packages/mark/dist/cli.js procedure new user.update \
346
+ --description "Update user information" \
347
+ --path packages/my-package \
348
+ --dry-run
349
+ ```
350
+
351
+ ### Use in Package Development
352
+
353
+ 1. **Create package structure**:
354
+ ```bash
355
+ node packages/mark/dist/cli.js lib new my-client-package
356
+ pnpm install
357
+ ```
358
+
359
+ 2. **Scaffold procedures**:
360
+ ```bash
361
+ node packages/mark/dist/cli.js procedure new myapp.start --path packages/myapp
362
+ node packages/mark/dist/cli.js procedure new myapp.stop --path packages/myapp
363
+ node packages/mark/dist/cli.js procedure new myapp.status --path packages/myapp
364
+ ```
365
+
366
+ 3. **Implement handlers**:
367
+ Edit the generated files in `src/procedures/myapp/*.ts`. `procedure new` registered each procedure in `src/register.ts`.
368
+
369
+ 4. **Build and test**:
370
+ ```bash
371
+ pnpm build
372
+ pnpm test
373
+ ```
374
+
375
+ ## Naming Conventions
376
+
377
+ Procedure names follow dot-notation:
378
+ - **Single segment**: `greet` → `["greet"]`
379
+ - **Two segments**: `user.create` → `["user", "create"]`
380
+ - **Nested**: `api.users.permissions.grant` → `["api", "users", "permissions", "grant"]`
381
+ - **camelCase segments**: `fs.readJson` → `["fs", "readJson"]`
382
+
383
+ Generated identifiers:
384
+ - **camelCase** for function names: `user.create` → `userCreate`
385
+ - **PascalCase** for types: `user.create` → `UserCreate`
386
+ - **Files**: the last segment, in the folders of the other segments: `user.create` → `user/create.ts`, `api.users.permissions.grant` → `api/users/permissions/grant.ts`
387
+
388
+ Two names can give the same identifiers (`a.b.c` and `a.bC` both give `aBC`). The second one is an error.
389
+
390
+ ## Requirements
391
+
392
+ - **Node.js**: >= 22
393
+ - **TypeScript**: >= 5.0
394
+ - **Dependencies**:
395
+ - `@procedures/client` (`workspace:*`)
396
+ - `zod` ^3.24.0
397
+
398
+ ## License
399
+
400
+ MIT
401
+
402
+ ## See Also
403
+
404
+ - `@procedures/client` - Core client/procedure system
405
+ - `@procedures/mark` - CLI that uses procedure.new for scaffolding
406
+ - Package scaffolding guide in ecosystem documentation