@procedures/lib 0.1.0 → 0.2.1

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.
@@ -2,9 +2,11 @@
2
2
  * lib.new procedure
3
3
  *
4
4
  * Creates a new client package in the workspace, at packages/<name>, with the
5
- * structure the other client packages have: cue-config files, src/index.ts (which
6
- * imports src/register.ts), src/register.ts, src/types.ts, the "./register" export and the
7
- * "client.procedures" field. `mark procedure new` then adds procedures that compile.
5
+ * structure the other client packages have: cue-config files, src/module.ts (the procedures as
6
+ * data), src/register.ts (the only file with a side effect), src/index.ts, src/types.ts, the
7
+ * "./module" and "./register" exports and the "client.procedures" field. Importing the package
8
+ * root registers nothing (ARCHITECTURE-PROPOSALS-2026-10, P9). `mark procedure new` then adds
9
+ * procedures to the module, and they compile.
8
10
  * Uses fs.* and shell.* procedures via ctx.client.call() for all operations.
9
11
  *
10
12
  * After it, run `pnpm install` and `pnpm build` in the workspace root.
@@ -22,9 +24,9 @@ interface ShellRunOutput {
22
24
  success: boolean;
23
25
  }
24
26
 
25
- // Importing the package registers its procedures, as in the other client packages
26
- const INDEX_TS = `// Entry point: importing the package registers its procedures
27
- export * from "./register.js";
27
+ // The root registers nothing: `import "<package>/register"` or `createRegistry()` registers the procedures
28
+ const INDEX_TS = `// The root registers nothing: import "<package>/register", or give the module to createRegistry()
29
+ export * from "./module.js";
28
30
  export * from "./types.js";
29
31
  `;
30
32
 
@@ -39,22 +41,52 @@ const TYPES_TS = `/**
39
41
  export {};
40
42
  `;
41
43
 
42
- function registerTs(name: string): string {
44
+ /** The names of a package folder in code: "my-package" gives "myPackage" and "MyPackage". */
45
+ function codeNames(name: string): { camel: string; pascal: string } {
46
+ const pascal = name
47
+ .split(/[^A-Za-z0-9]+/)
48
+ .filter(Boolean)
49
+ .map((part) => part[0]!.toUpperCase() + part.slice(1))
50
+ .join("");
51
+ return { camel: pascal[0]!.toLowerCase() + pascal.slice(1), pascal };
52
+ }
53
+
54
+ function moduleTs(name: string, packageName: string): string {
55
+ const { camel, pascal } = codeNames(name);
43
56
  return `/**
44
- * Procedure registration for ${name}
57
+ * The procedures of ${packageName} as data. Importing this file registers nothing.
45
58
  *
46
- * Add each procedure of this package to the registerProcedures() array.
47
59
  * Scaffold a procedure with: mark procedure new <name> --path packages/${name}
48
60
  */
49
61
 
50
- import { registerProcedures } from "@procedures/client";
62
+ import { defineModule, registerModules, PROCEDURE_REGISTRY, type ProcedureModule, type ProcedureRegistry } from "@procedures/client";
63
+
64
+ export const ${camel}Module: ProcedureModule = defineModule("${packageName}", []);
65
+
66
+ export default ${camel}Module;
51
67
 
52
- export function register(): void {
53
- registerProcedures([]);
68
+ /**
69
+ * This function registers the procedures of ${packageName} in a registry. The default is the
70
+ * global registry.
71
+ */
72
+ export function register${pascal}Procedures(registry: ProcedureRegistry = PROCEDURE_REGISTRY): void {
73
+ registerModules(registry, [${camel}Module]);
54
74
  }
75
+ `;
76
+ }
77
+
78
+ function registerTs(name: string, packageName: string): string {
79
+ const { pascal } = codeNames(name);
80
+ return `/**
81
+ * Importing this file registers the procedures of ${packageName} in the global registry:
82
+ * \`import "${packageName}/register"\`. The package root registers nothing.
83
+ */
84
+
85
+ import { register${pascal}Procedures } from "./module.js";
86
+
87
+ export * from "./module.js";
55
88
 
56
- // Auto-register
57
- register();
89
+ register${pascal}Procedures();
58
90
  `;
59
91
  }
60
92
 
@@ -121,6 +153,7 @@ export async function libNew(input: LibNewInput, ctx: ProcedureContext): Promise
121
153
 
122
154
  const files = [
123
155
  join(packagePath, "src", "index.ts"),
156
+ join(packagePath, "src", "module.ts"),
124
157
  join(packagePath, "src", "register.ts"),
125
158
  join(packagePath, "src", "types.ts"),
126
159
  join(packagePath, "dependencies.json"),
@@ -136,7 +169,7 @@ export async function libNew(input: LibNewInput, ctx: ProcedureContext): Promise
136
169
  packagePath,
137
170
  created: [`${packagePath}/`, `${join(packagePath, "src")}/`, ...files],
138
171
  operations: [
139
- "Would create packages/" + input.name + " with src/index.ts, src/register.ts and src/types.ts",
172
+ "Would create packages/" + input.name + " with src/index.ts, src/module.ts, src/register.ts and src/types.ts",
140
173
  `Would run cue-config init --preset ${input.preset}`,
141
174
  "Would run cue-config generate",
142
175
  `Would set the package name to ${packageName}, the exports, client.procedures and the client dependency`,
@@ -157,7 +190,8 @@ export async function libNew(input: LibNewInput, ctx: ProcedureContext): Promise
157
190
 
158
191
  for (const [file, content] of [
159
192
  [join(packagePath, "src", "index.ts"), INDEX_TS],
160
- [join(packagePath, "src", "register.ts"), registerTs(input.name)],
193
+ [join(packagePath, "src", "module.ts"), moduleTs(input.name, packageName)],
194
+ [join(packagePath, "src", "register.ts"), registerTs(input.name, packageName)],
161
195
  [join(packagePath, "src", "types.ts"), TYPES_TS],
162
196
  ] as const) {
163
197
  await ctx.client.call<{ path: string; content: string }, { path: string; bytesWritten: number }>(
@@ -188,8 +222,11 @@ export async function libNew(input: LibNewInput, ctx: ProcedureContext): Promise
188
222
  pkgJson["name"] = packageName;
189
223
  pkgJson["exports"] = {
190
224
  ".": { types: "./dist/index.d.ts", import: "./dist/index.js" },
225
+ "./module": { types: "./dist/module.d.ts", import: "./dist/module.js" },
191
226
  "./register": { types: "./dist/register.d.ts", import: "./dist/register.js" },
192
227
  };
228
+ // Only the register entry has a side effect, so a bundler can drop the rest
229
+ pkgJson["sideEffects"] = ["./dist/register.js"];
193
230
  pkgJson["client"] = { procedures: "./dist/register.js" };
194
231
  pkgJson["dependencies"] = {
195
232
  ...((pkgJson["dependencies"] as Record<string, string> | undefined) ?? {}),
package/src/register.ts CHANGED
@@ -1,23 +1,11 @@
1
1
  /**
2
- * Importing this file registers the procedures of @procedures/lib in the global registry
3
- * (DECISIONS-2026-10, "Every package root registers its procedures"). The procedures as data
4
- * are in `module.ts`, which registers nothing: a host with its own registry uses that one.
2
+ * Importing this file registers the procedures of @procedures/lib, and of the modules that it
3
+ * requires, in the global registry: `import "@procedures/lib/register"`. The package root and the
4
+ * `./module` entry register nothing (ARCHITECTURE-PROPOSALS-2026-10, P9).
5
5
  */
6
6
 
7
- // The lib procedures call fs.* and git.* (their `calls` below). Importing those packages registers
8
- // them, so client-lib works alone. (Docs review DOC-5: before, lib.scan alone found no packages,
9
- // and over MCP its git calls failed with NOT_FOUND.)
10
- import "@procedures/fs";
11
- import "@procedures/git";
12
-
13
- import { registerProcedures } from "@procedures/client";
14
- import { libModule } from "./module.js";
7
+ import { registerLibProcedures } from "./module.js";
15
8
 
16
9
  export * from "./module.js";
17
10
 
18
- export function registerLibProcedures(): void {
19
- registerProcedures(libModule.procedures);
20
- }
21
-
22
- // Auto-register when this module is loaded
23
11
  registerLibProcedures();
@@ -1,17 +0,0 @@
1
- /**
2
- * An input schema for a runner: a procedure that takes its input raw and runs the procedure
3
- * refs in it (`core.catch`, `dag.traverse`).
4
- *
5
- * The caller gives a raw input with its scope (`withScope()`), so the runner can resolve the
6
- * `$ref` names of an outer chain. The scope is a hidden property, and a Zod parse makes a new
7
- * object without it. This schema validates with Zod, then puts the scope of the input on the
8
- * result. (The general fix is in the core: `invokeProcedure` could keep the scope across the
9
- * validation of every procedure.)
10
- */
11
- import { type ZodLikeSchema } from "@mark1russell7/client";
12
- export declare function scopedInput<T>(schema: {
13
- parse: (data: unknown) => T;
14
- _def?: unknown;
15
- shape?: unknown;
16
- }): ZodLikeSchema<T>;
17
- //# sourceMappingURL=scoped-input.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"scoped-input.d.ts","sourceRoot":"","sources":["../src/scoped-input.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAkC,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAE3F,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE;IAAE,KAAK,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,CAAC,CAAC;IAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,aAAa,CAAC,CAAC,CAAC,CAQzH"}
@@ -1,23 +0,0 @@
1
- /**
2
- * An input schema for a runner: a procedure that takes its input raw and runs the procedure
3
- * refs in it (`core.catch`, `dag.traverse`).
4
- *
5
- * The caller gives a raw input with its scope (`withScope()`), so the runner can resolve the
6
- * `$ref` names of an outer chain. The scope is a hidden property, and a Zod parse makes a new
7
- * object without it. This schema validates with Zod, then puts the scope of the input on the
8
- * result. (The general fix is in the core: `invokeProcedure` could keep the scope across the
9
- * validation of every procedure.)
10
- */
11
- import { scopeOf, withScope, zodAdapter } from "@mark1russell7/client";
12
- export function scopedInput(schema) {
13
- const scoped = {
14
- parse: (data) => withScope(schema.parse(data), scopeOf(data)),
15
- };
16
- // zodAdapter shows _def and shape, so the CLI help and the MCP schema still see the fields
17
- if (schema._def !== undefined)
18
- scoped._def = schema._def;
19
- if (schema.shape !== undefined)
20
- scoped.shape = schema.shape;
21
- return zodAdapter(scoped);
22
- }
23
- //# sourceMappingURL=scoped-input.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"scoped-input.js","sourceRoot":"","sources":["../src/scoped-input.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAsB,MAAM,uBAAuB,CAAC;AAE3F,MAAM,UAAU,WAAW,CAAI,MAAwE;IACrG,MAAM,MAAM,GAAqE;QAC/E,KAAK,EAAE,CAAC,IAAa,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;KACvE,CAAC;IACF,2FAA2F;IAC3F,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS;QAAE,MAAM,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;IACzD,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS;QAAE,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;IAC5D,OAAO,UAAU,CAAI,MAAM,CAAC,CAAC;AAC/B,CAAC"}