ts-procedures 10.1.2 → 10.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.
- package/CHANGELOG.md +33 -86
- package/README.md +11 -6
- package/agent_config/bin/postinstall.mjs +20 -89
- package/agent_config/bin/setup.mjs +51 -264
- package/agent_config/lib/install-skills.mjs +108 -0
- package/agent_config/{claude-code/skills → skills}/ts-procedures/anti-patterns.md +8 -0
- package/agent_config/{claude-code/skills → skills}/ts-procedures/api-reference.md +25 -22
- package/agent_config/{claude-code/skills → skills}/ts-procedures/patterns.md +24 -13
- package/build/adapters/hono/envelope-parity.test.js +6 -17
- package/build/adapters/hono/envelope-parity.test.js.map +1 -1
- package/build/adapters/hono/handlers/http-stream.d.ts +2 -1
- package/build/adapters/hono/handlers/http-stream.js +9 -2
- package/build/adapters/hono/handlers/http-stream.js.map +1 -1
- package/build/adapters/hono/handlers/http.d.ts +2 -1
- package/build/adapters/hono/handlers/http.js +9 -2
- package/build/adapters/hono/handlers/http.js.map +1 -1
- package/build/adapters/hono/handlers/rpc.d.ts +2 -1
- package/build/adapters/hono/handlers/rpc.js +9 -2
- package/build/adapters/hono/handlers/rpc.js.map +1 -1
- package/build/adapters/hono/handlers/stream.d.ts +2 -1
- package/build/adapters/hono/handlers/stream.js +9 -2
- package/build/adapters/hono/handlers/stream.js.map +1 -1
- package/build/adapters/hono/index.d.ts +14 -7
- package/build/adapters/hono/index.js +45 -5
- package/build/adapters/hono/index.js.map +1 -1
- package/build/adapters/hono/index.test.js +55 -0
- package/build/adapters/hono/index.test.js.map +1 -1
- package/build/adapters/hono/request.d.ts +7 -0
- package/build/adapters/hono/request.js +15 -0
- package/build/adapters/hono/request.js.map +1 -1
- package/build/adapters/hono/types.d.ts +31 -0
- package/build/adapters/hono/types.js.map +1 -1
- package/build/codegen/bin/cli.js +1 -1
- package/build/codegen/bin/cli.js.map +1 -1
- package/build/codegen/constants.js +2 -2
- package/build/codegen/constants.js.map +1 -1
- package/build/codegen/emit/api-route.js +1 -1
- package/build/codegen/emit/api-route.js.map +1 -1
- package/build/codegen/emit/scope-file.js +1 -1
- package/build/codegen/emit/scope-file.js.map +1 -1
- package/build/codegen/emit-errors.integration.test.js +2 -2
- package/build/codegen/emit-errors.integration.test.js.map +1 -1
- package/build/codegen/resolve-envelope.js +1 -1
- package/build/codegen/resolve-envelope.js.map +1 -1
- package/build/codegen/test-helpers/run-tsc.js +1 -1
- package/build/codegen/test-helpers/run-tsc.js.map +1 -1
- package/build/core/create-http-stream.d.ts +3 -14
- package/build/core/create-http-stream.js +4 -2
- package/build/core/create-http-stream.js.map +1 -1
- package/build/core/create-http.d.ts +2 -9
- package/build/core/create-http.js +3 -2
- package/build/core/create-http.js.map +1 -1
- package/build/core/create-http.test-d.js +104 -0
- package/build/core/create-http.test-d.js.map +1 -0
- package/build/core/create-stream.js +6 -2
- package/build/core/create-stream.js.map +1 -1
- package/build/core/create.js +5 -4
- package/build/core/create.js.map +1 -1
- package/build/core/create.test.js +63 -0
- package/build/core/create.test.js.map +1 -1
- package/build/core/internal.d.ts +16 -0
- package/build/core/internal.js +22 -0
- package/build/core/internal.js.map +1 -1
- package/build/core/procedures.d.ts +9 -16
- package/build/core/procedures.js +4 -0
- package/build/core/procedures.js.map +1 -1
- package/build/core/types.d.ts +85 -4
- package/build/errors.d.ts +33 -0
- package/build/errors.js +91 -0
- package/build/errors.js.map +1 -0
- package/build/errors.test.d.ts +1 -0
- package/build/errors.test.js +122 -0
- package/build/errors.test.js.map +1 -0
- package/build/exports.d.ts +1 -2
- package/build/exports.js +0 -4
- package/build/exports.js.map +1 -1
- package/build/implementations/http/doc-registry.d.ts +28 -0
- package/build/implementations/http/doc-registry.js +96 -0
- package/build/implementations/http/doc-registry.js.map +1 -0
- package/build/implementations/http/doc-registry.test.d.ts +1 -0
- package/build/implementations/http/doc-registry.test.js +516 -0
- package/build/implementations/http/doc-registry.test.js.map +1 -0
- package/build/implementations/http/error-taxonomy.d.ts +249 -0
- package/build/implementations/http/error-taxonomy.js +252 -0
- package/build/implementations/http/error-taxonomy.js.map +1 -0
- package/build/implementations/http/error-taxonomy.test.d.ts +1 -0
- package/build/implementations/http/error-taxonomy.test.js +399 -0
- package/build/implementations/http/error-taxonomy.test.js.map +1 -0
- package/build/implementations/http/express-rpc/error-taxonomy.test.d.ts +1 -0
- package/build/implementations/http/express-rpc/error-taxonomy.test.js +83 -0
- package/build/implementations/http/express-rpc/error-taxonomy.test.js.map +1 -0
- package/build/implementations/http/express-rpc/index.d.ts +125 -0
- package/build/implementations/http/express-rpc/index.js +216 -0
- package/build/implementations/http/express-rpc/index.js.map +1 -0
- package/build/implementations/http/express-rpc/index.test.d.ts +1 -0
- package/build/implementations/http/express-rpc/index.test.js +684 -0
- package/build/implementations/http/express-rpc/index.test.js.map +1 -0
- package/build/implementations/http/express-rpc/types.d.ts +11 -0
- package/build/implementations/http/express-rpc/types.js +2 -0
- package/build/implementations/http/express-rpc/types.js.map +1 -0
- package/build/implementations/http/hono-api/error-taxonomy.test.d.ts +1 -0
- package/build/implementations/http/hono-api/error-taxonomy.test.js +137 -0
- package/build/implementations/http/hono-api/error-taxonomy.test.js.map +1 -0
- package/build/implementations/http/hono-api/index.d.ts +151 -0
- package/build/implementations/http/hono-api/index.js +344 -0
- package/build/implementations/http/hono-api/index.js.map +1 -0
- package/build/implementations/http/hono-api/index.test.d.ts +1 -0
- package/build/implementations/http/hono-api/index.test.js +992 -0
- package/build/implementations/http/hono-api/index.test.js.map +1 -0
- package/build/implementations/http/hono-api/types.d.ts +13 -0
- package/build/implementations/http/hono-api/types.js +2 -0
- package/build/implementations/http/hono-api/types.js.map +1 -0
- package/build/implementations/http/hono-rpc/error-taxonomy.test.d.ts +1 -0
- package/build/implementations/http/hono-rpc/error-taxonomy.test.js +64 -0
- package/build/implementations/http/hono-rpc/error-taxonomy.test.js.map +1 -0
- package/build/implementations/http/hono-rpc/index.d.ts +130 -0
- package/build/implementations/http/hono-rpc/index.js +209 -0
- package/build/implementations/http/hono-rpc/index.js.map +1 -0
- package/build/implementations/http/hono-rpc/index.test.d.ts +1 -0
- package/build/implementations/http/hono-rpc/index.test.js +828 -0
- package/build/implementations/http/hono-rpc/index.test.js.map +1 -0
- package/build/implementations/http/hono-rpc/types.d.ts +11 -0
- package/build/implementations/http/hono-rpc/types.js +2 -0
- package/build/implementations/http/hono-rpc/types.js.map +1 -0
- package/build/implementations/http/hono-stream/error-taxonomy.test.d.ts +1 -0
- package/build/implementations/http/hono-stream/error-taxonomy.test.js +159 -0
- package/build/implementations/http/hono-stream/error-taxonomy.test.js.map +1 -0
- package/build/implementations/http/hono-stream/index.d.ts +171 -0
- package/build/implementations/http/hono-stream/index.js +415 -0
- package/build/implementations/http/hono-stream/index.js.map +1 -0
- package/build/implementations/http/hono-stream/index.test.d.ts +1 -0
- package/build/implementations/http/hono-stream/index.test.js +1383 -0
- package/build/implementations/http/hono-stream/index.test.js.map +1 -0
- package/build/implementations/http/hono-stream/types.d.ts +15 -0
- package/build/implementations/http/hono-stream/types.js +2 -0
- package/build/implementations/http/hono-stream/types.js.map +1 -0
- package/build/implementations/http/on-request-error.test.d.ts +1 -0
- package/build/implementations/http/on-request-error.test.js +173 -0
- package/build/implementations/http/on-request-error.test.js.map +1 -0
- package/build/implementations/http/route-errors.test.d.ts +1 -0
- package/build/implementations/http/route-errors.test.js +139 -0
- package/build/implementations/http/route-errors.test.js.map +1 -0
- package/build/implementations/types.d.ts +192 -0
- package/build/implementations/types.js +2 -0
- package/build/implementations/types.js.map +1 -0
- package/build/index.d.ts +165 -0
- package/build/index.js +258 -0
- package/build/index.js.map +1 -0
- package/build/index.test.d.ts +1 -0
- package/build/index.test.js +920 -0
- package/build/index.test.js.map +1 -0
- package/build/schema/compute-schema.js +1 -5
- package/build/schema/compute-schema.js.map +1 -1
- package/build/schema/compute-schema.test.js +0 -13
- package/build/schema/compute-schema.test.js.map +1 -1
- package/build/schema/extract-json-schema.d.ts +2 -0
- package/build/schema/extract-json-schema.js +12 -0
- package/build/schema/extract-json-schema.js.map +1 -0
- package/build/schema/extract-json-schema.test.d.ts +1 -0
- package/build/schema/extract-json-schema.test.js +23 -0
- package/build/schema/extract-json-schema.test.js.map +1 -0
- package/build/schema/parser.d.ts +28 -0
- package/build/schema/parser.js +170 -0
- package/build/schema/parser.js.map +1 -0
- package/build/schema/parser.test.d.ts +1 -0
- package/build/schema/parser.test.js +120 -0
- package/build/schema/parser.test.js.map +1 -0
- package/build/schema/resolve-schema-lib.d.ts +12 -0
- package/build/schema/resolve-schema-lib.js +11 -0
- package/build/schema/resolve-schema-lib.js.map +1 -0
- package/build/schema/resolve-schema-lib.test.d.ts +1 -0
- package/build/schema/resolve-schema-lib.test.js +17 -0
- package/build/schema/resolve-schema-lib.test.js.map +1 -0
- package/build/schema/typebox.d.ts +1 -1
- package/build/schema/typebox.js +2 -20
- package/build/schema/typebox.js.map +1 -1
- package/build/schema/typebox.test.js +0 -10
- package/build/schema/typebox.test.js.map +1 -1
- package/build/schema/types.d.ts +8 -0
- package/build/schema/types.js +2 -0
- package/build/schema/types.js.map +1 -0
- package/build/server/context.d.ts +12 -2
- package/build/server/context.js +49 -4
- package/build/server/context.js.map +1 -1
- package/build/server/context.test.js +32 -1
- package/build/server/context.test.js.map +1 -1
- package/build/server/doc-registry.js +0 -3
- package/build/server/doc-registry.js.map +1 -1
- package/build/server/doc-registry.test.js +0 -31
- package/build/server/doc-registry.test.js.map +1 -1
- package/build/server/index.d.ts +0 -1
- package/build/server/index.js +0 -1
- package/build/server/index.js.map +1 -1
- package/build/server/types.d.ts +6 -27
- package/build/stack-utils.d.ts +25 -0
- package/build/stack-utils.js +95 -0
- package/build/stack-utils.js.map +1 -0
- package/build/stack-utils.test.d.ts +1 -0
- package/build/stack-utils.test.js +80 -0
- package/build/stack-utils.test.js.map +1 -0
- package/docs/ai-agent-setup.md +19 -27
- package/docs/client-error-handling.md +1 -1
- package/docs/core.md +8 -0
- package/docs/http-integrations.md +42 -28
- package/package.json +8 -8
- package/src/adapters/astro/README.md +2 -0
- package/src/adapters/hono/envelope-parity.test.ts +6 -18
- package/src/adapters/hono/handlers/http-stream.ts +12 -3
- package/src/adapters/hono/handlers/http.ts +12 -3
- package/src/adapters/hono/handlers/rpc.ts +12 -3
- package/src/adapters/hono/handlers/stream.ts +12 -3
- package/src/adapters/hono/index.test.ts +70 -0
- package/src/adapters/hono/index.ts +53 -11
- package/src/adapters/hono/request.ts +18 -0
- package/src/adapters/hono/types.ts +37 -0
- package/src/codegen/bin/cli.ts +1 -1
- package/src/codegen/constants.ts +2 -2
- package/src/codegen/emit/api-route.ts +1 -1
- package/src/codegen/emit/scope-file.ts +1 -2
- package/src/codegen/emit-errors.integration.test.ts +2 -2
- package/src/codegen/resolve-envelope.ts +1 -1
- package/src/codegen/test-helpers/run-tsc.ts +0 -1
- package/src/core/create-http-stream.ts +20 -13
- package/src/core/create-http.test-d.ts +154 -0
- package/src/core/create-http.ts +19 -8
- package/src/core/create-stream.ts +12 -4
- package/src/core/create.test.ts +74 -0
- package/src/core/create.ts +10 -5
- package/src/core/internal.ts +35 -0
- package/src/core/procedures.ts +4 -0
- package/src/core/types.ts +99 -4
- package/src/exports.ts +6 -4
- package/src/schema/compute-schema.test.ts +0 -16
- package/src/schema/compute-schema.ts +1 -5
- package/src/schema/typebox.test.ts +0 -12
- package/src/schema/typebox.ts +2 -21
- package/src/server/context.test.ts +39 -1
- package/src/server/context.ts +54 -4
- package/src/server/doc-registry.test.ts +0 -34
- package/src/server/doc-registry.ts +0 -3
- package/src/server/index.ts +0 -1
- package/src/server/types.ts +8 -27
- package/agent_config/claude-code/.claude-plugin/plugin.json +0 -5
- package/agent_config/claude-code/agents/ts-procedures-architect.md +0 -138
- package/agent_config/copilot/copilot-instructions.md +0 -521
- package/agent_config/cursor/cursorrules +0 -521
- package/agent_config/lib/install-claude.mjs +0 -57
- package/build/schema/strip-internal-keywords.d.ts +0 -18
- package/build/schema/strip-internal-keywords.js +0 -33
- package/build/schema/strip-internal-keywords.js.map +0 -1
- package/build/schema/strip-internal-keywords.test.js +0 -38
- package/build/schema/strip-internal-keywords.test.js.map +0 -1
- package/build/server/spec-version.d.ts +0 -24
- package/build/server/spec-version.js +0 -26
- package/build/server/spec-version.js.map +0 -1
- package/build/version.d.ts +0 -9
- package/build/version.js +0 -11
- package/build/version.js.map +0 -1
- package/docs/doc-envelope-spec-v1.md +0 -296
- package/docs/doc-envelope-v1.schema.json +0 -253
- package/src/schema/strip-internal-keywords.test.ts +0 -43
- package/src/schema/strip-internal-keywords.ts +0 -36
- package/src/server/spec-version.ts +0 -27
- package/src/version.ts +0 -11
- /package/agent_config/{claude-code/skills → skills}/ts-procedures/SKILL.md +0 -0
- /package/agent_config/{claude-code/skills → skills}/ts-procedures/checklist.md +0 -0
- /package/agent_config/{claude-code/skills → skills}/ts-procedures/templates/astro-catchall.md +0 -0
- /package/agent_config/{claude-code/skills → skills}/ts-procedures/templates/client.md +0 -0
- /package/agent_config/{claude-code/skills → skills}/ts-procedures/templates/hono.md +0 -0
- /package/agent_config/{claude-code/skills → skills}/ts-procedures/templates/procedure.md +0 -0
- /package/agent_config/{claude-code/skills → skills}/ts-procedures/templates/stream-procedure.md +0 -0
- /package/build/{schema/strip-internal-keywords.test.d.ts → core/create-http.test-d.d.ts} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,111 +4,58 @@ All notable changes to **ts-procedures** are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Unreleased
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
as enumerable properties. Complements the detection fix in 10.1.1.
|
|
9
|
+
## 10.2.1 — 2026-06-26
|
|
11
10
|
|
|
12
|
-
###
|
|
13
|
-
|
|
14
|
-
- **`Type.Optional(Type.Unsafe({...}))` no longer crashes registration or leaks
|
|
15
|
-
markers.** Most TypeBox `~`-prefixed markers are non-enumerable and stay out of
|
|
16
|
-
the JSON Schema, but some compositions — notably `Type.Optional` wrapping
|
|
17
|
-
`Type.Unsafe` — emit `~unsafe`/`~optional` as **enumerable** own properties.
|
|
18
|
-
Those then (a) made strict AJV throw `unknown keyword: "~unsafe"` at
|
|
19
|
-
registration and (b) leaked into serialized DocEnvelope/codegen output. JSON
|
|
20
|
-
Schema extracted from any channel is now deep-stripped of `~`-prefixed keys
|
|
21
|
-
(`stripInternalKeywords`) at the single extraction chokepoint, so both runtime
|
|
22
|
-
validation and emitted docs/codegen are clean. Stripping by the `~`-prefix
|
|
23
|
-
convention (not a fixed name list) stays robust against future markers.
|
|
24
|
-
|
|
25
|
-
### Notes
|
|
26
|
-
|
|
27
|
-
- AJV stays strict (no `strictSchema: false`) — stripping cleans the output too
|
|
28
|
-
and keeps AJV's unknown-keyword safety net for genuine schema typos.
|
|
29
|
-
- 10.1.1 fixed *recognition* of a bare top-level `Type.Unsafe(...)`; this release
|
|
30
|
-
fixes the distinct *enumerable-marker leak* in nested compositions. Schemas
|
|
31
|
-
built only from `Type.Object`/primitives were never affected by either.
|
|
32
|
-
|
|
33
|
-
## 10.1.1 — 2026-06-24
|
|
11
|
+
### Changed
|
|
34
12
|
|
|
35
|
-
|
|
36
|
-
|
|
13
|
+
- **AI agent config is now a single spec-compliant [Agent Skill](https://www.anthropic.com/engineering/equipping-agents-for-the-real-world-with-agent-skills).** Replaced the per-tool config directories (`claude-code/`, `cursor/`, `copilot/`) with one source of truth at `agent_config/skills/ts-procedures/`. `npx ts-procedures-setup` now installs that one skill into the standard agent roots — `.agents/skills/ts-procedures/` (read by Codex, Cursor, GitHub Copilot, Gemini CLI, and 30+ tools) and `.claude/skills/ts-procedures/` (Claude Code native) — eliminating the hand-synced duplicate `.cursorrules` / `.github/copilot-instructions.md` files and their marker-merge machinery.
|
|
14
|
+
- `ts-procedures-setup` CLI simplified to `--dry-run` / `--check` / `--help` (per-tool `targets` and `--force` removed; the install is a force-overwrite copy). The postinstall auto-update remains opt-in (only refreshes once the skill is already installed).
|
|
37
15
|
|
|
38
|
-
###
|
|
16
|
+
### Removed
|
|
39
17
|
|
|
40
|
-
-
|
|
41
|
-
|
|
42
|
-
the built-in TypeBox adapter — which only looked for `~kind` — failed to detect
|
|
43
|
-
a bare top-level `Type.Unsafe(...)` used as a channel schema (e.g.
|
|
44
|
-
`schema: { params: Type.Unsafe(...) }`), throwing a `ProcedureRegistrationError`
|
|
45
|
-
at registration. Detection now keys off TypeBox v1's `~`-prefix marker
|
|
46
|
-
*convention* (via `Reflect.ownKeys`, since the markers are non-enumerable)
|
|
47
|
-
rather than a fixed list of names, so current and future `~*` markers are
|
|
48
|
-
recognized without further changes. `Type.Unsafe` nested inside a
|
|
49
|
-
`Type.Object(...)` was never affected.
|
|
18
|
+
- The Claude-only `ts-procedures-architect` agent and the Claude Code plugin manifest (`.claude-plugin/plugin.json`). The unified `ts-procedures` skill covers reference, scaffold, and review modes.
|
|
19
|
+
- Downstream cleanup note: a previously installed `.claude/agents/ts-procedures-architect.md` is now orphaned and can be deleted manually.
|
|
50
20
|
|
|
51
|
-
|
|
21
|
+
## 10.2.0 — 2026-06-25
|
|
52
22
|
|
|
53
|
-
|
|
54
|
-
non-enumerable, so they never reached `JSON.stringify` (DocEnvelope, codegen)
|
|
55
|
-
or AJV. The frozen codegen goldens and DocEnvelope parity fixtures are
|
|
56
|
-
unchanged. App devs only need to upgrade; no code changes required.
|
|
23
|
+
### Added
|
|
57
24
|
|
|
58
|
-
|
|
25
|
+
- **Factory middleware via `Procedures({ middleware })`.** Declare middleware at the factory level that runs with the *final* resolved context (your `TContext` + injected `error()` + `signal`) and the validated incoming call data. Enables "parse the incoming call" patterns for authorization, tenancy enforcement, enrichment, etc.
|
|
59
26
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
27
|
+
```ts
|
|
28
|
+
const Protected = Procedures<Ctx>({
|
|
29
|
+
middleware: [({ ctx, input, next }) => {
|
|
30
|
+
// ctx is fully resolved; input is schema-validated
|
|
31
|
+
if (input && 'orgId' in input && !ctx.user.tenants.includes(input.orgId)) {
|
|
32
|
+
throw ctx.error('tenant violation')
|
|
33
|
+
}
|
|
34
|
+
return next({ ctx: { ...ctx, checked: true } }) // optional augmentation
|
|
35
|
+
}]
|
|
36
|
+
})
|
|
37
|
+
```
|
|
63
38
|
|
|
64
|
-
|
|
39
|
+
Works for `Create*` / `CreateHttp*`, direct calls, and all adapters. Complements (runs after) builder-level middleware.
|
|
65
40
|
|
|
66
|
-
-
|
|
67
|
-
identifying the envelope wire format, emitted on every envelope produced by
|
|
68
|
-
`DocRegistry.toJSON()` / `builder.toDocEnvelope()`. Bumped **only** when the
|
|
69
|
-
envelope shape changes — never on routine package releases — so consumers get
|
|
70
|
-
a stable signal to branch their parser on. An absent `specVersion` MUST be
|
|
71
|
-
treated as `1`. Exported as `DOC_ENVELOPE_SPEC_VERSION` from `ts-procedures`
|
|
72
|
-
and `ts-procedures/server`.
|
|
73
|
-
- **`DocEnvelope.generatorVersion`** — the ts-procedures package version that
|
|
74
|
-
produced the envelope (e.g. `"10.1.0"`), for telemetry/debugging only; not a
|
|
75
|
-
parse-compatibility signal. Exported as `DOC_ENVELOPE_GENERATOR_VERSION` from
|
|
76
|
-
`ts-procedures/server`. Strippable via the `transform` hook for servers that
|
|
77
|
-
don't want to advertise the version on a public docs endpoint.
|
|
78
|
-
- **DocEnvelope wire-contract docs** — `docs/doc-envelope-spec-v1.md` plus a
|
|
79
|
-
validatable JSON Schema at `docs/doc-envelope-v1.schema.json` (filenames pinned
|
|
80
|
-
to the envelope `specVersion`), for building third-party tools against the
|
|
81
|
-
served envelope.
|
|
41
|
+
- **HonoAppBuilder middleware & context composition.** First-class support on the builder:
|
|
82
42
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
-
|
|
86
|
-
both the codegen file header and the doc-envelope metadata.
|
|
43
|
+
- `new HonoAppBuilder({ middleware: [mw...] })`
|
|
44
|
+
- `builder.use(mw)` (or `use(pattern, mw)`)
|
|
45
|
+
- `.register(factory, ctx, { middleware: [...], context?: extraLayer })`
|
|
87
46
|
|
|
88
|
-
|
|
47
|
+
Added `HonoRequestMiddleware`, `RegisterOptions`, and improved server `resolveFactoryContext` / `composeContextInits` to support arrays of context initializers (left-to-right shallow merge).
|
|
89
48
|
|
|
90
|
-
|
|
91
|
-
across the board. There are **no source API changes** — every public export,
|
|
92
|
-
the codegen output (byte-identical against the frozen goldens), the client
|
|
93
|
-
runtime, and the DocEnvelope shape are unchanged. The version is bumped to major
|
|
94
|
-
purely to signal the dependency floor shift below.
|
|
49
|
+
- Updated documentation in `docs/core.md`, `docs/http-integrations.md`, `README.md`, and agent guidance to cover both layers and the recommended patterns (replacing manual `app.use` + stashing for protected surfaces).
|
|
95
50
|
|
|
96
51
|
### Changed
|
|
97
52
|
|
|
98
|
-
-
|
|
99
|
-
9 → 10, `globals` 15 → 17. The full gate (typecheck + 1251 tests including the
|
|
100
|
-
frozen codegen goldens + lint) passes on the new versions. The only code touched
|
|
101
|
-
was lint conformance for ESLint 10's newly-recommended rules
|
|
102
|
-
(`preserve-caught-error`, `no-useless-assignment`) — internal, no behavior change.
|
|
103
|
-
- **Astro optional peer: 6 → 7.** The optional peer range remains
|
|
104
|
-
`6.x.x || 7.x.x`, so existing Astro 6 consumers are unaffected; Astro 7 is now
|
|
105
|
-
tested and supported.
|
|
53
|
+
- Agent config now recommends "Prefer middleware + layered context for access levels" instead of always using separate factories.
|
|
106
54
|
|
|
107
|
-
|
|
55
|
+
## 9.3.0 — 2026-06-25
|
|
108
56
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
now targets TypeScript 6.
|
|
57
|
+
### Improved
|
|
58
|
+
- **DX: autocomplete for HTTP procedure schema channels.** `CreateHttp` and `CreateHttpStream` now surface `THttpReqInput` (and its alias `APIInput`) / `THttpResInput` inside `TCreateHttpConfig` so IDEs offer `pathParams | query | body | headers` (and `body | headers` for res) when writing `schema: { req: { ... }, res: { ... } }`. A small `HttpSchemaInput` helper keeps the public bag generics (`TReq`/`TRes`) while making literal keys visible. `satisfies APIInput` continues to work for extra checking. Same shapes are reused by `CreateHttpStream` for consistency.
|
|
112
59
|
|
|
113
60
|
## 9.2.0 — 2026-06-19
|
|
114
61
|
|
package/README.md
CHANGED
|
@@ -155,6 +155,8 @@ for await (const event of api.users.WatchUsers({})) { ... } // TypedStream
|
|
|
155
155
|
still fail fast at registration).
|
|
156
156
|
- Plug in another schema library with a 3-line `SchemaAdapter`
|
|
157
157
|
(`Procedures({ schema: { adapters: [zodAdapter] } })`).
|
|
158
|
+
- Factory middleware (ctx + input aware, runs for all procedures):
|
|
159
|
+
`Procedures({ middleware: [({ ctx, input, next }) => ...] })`.
|
|
158
160
|
|
|
159
161
|
## Streaming
|
|
160
162
|
|
|
@@ -189,17 +191,20 @@ implementation.
|
|
|
189
191
|
|
|
190
192
|
## AI assistant setup
|
|
191
193
|
|
|
192
|
-
The package ships
|
|
193
|
-
|
|
194
|
+
The package ships a single spec-compliant [Agent Skill](https://www.anthropic.com/engineering/equipping-agents-for-the-real-world-with-agent-skills)
|
|
195
|
+
so your AI tooling knows the framework's patterns and footguns. One skill is
|
|
196
|
+
installed into the standard agent directories (`.agents/skills/` — read by
|
|
197
|
+
Codex, Cursor, Copilot, Gemini CLI and 30+ others — plus `.claude/skills/` for
|
|
198
|
+
Claude Code):
|
|
194
199
|
|
|
195
200
|
```bash
|
|
196
|
-
npx ts-procedures-setup #
|
|
197
|
-
npx ts-procedures-setup claude # Claude Code only
|
|
201
|
+
npx ts-procedures-setup # install the skill
|
|
198
202
|
npx ts-procedures-setup --dry-run # preview
|
|
203
|
+
npx ts-procedures-setup --check # CI gate: fail if outdated
|
|
199
204
|
```
|
|
200
205
|
|
|
201
|
-
|
|
202
|
-
postinstall hook.
|
|
206
|
+
The installed skill auto-updates on subsequent `npm install` via the package's
|
|
207
|
+
postinstall hook. See [docs/ai-agent-setup.md](docs/ai-agent-setup.md).
|
|
203
208
|
|
|
204
209
|
## Migrating from v8
|
|
205
210
|
|
|
@@ -1,105 +1,36 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import { resolve, join, dirname } from 'node:path';
|
|
3
|
+
import { resolve, dirname } from 'node:path';
|
|
5
4
|
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { installSkills, isInstalled } from '../lib/install-skills.mjs';
|
|
6
6
|
|
|
7
7
|
const __filename = fileURLToPath(import.meta.url);
|
|
8
8
|
const __dirname = dirname(__filename);
|
|
9
|
-
const AGENT_CONFIG_DIR = resolve(__dirname, '..');
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
const
|
|
10
|
+
// ─── Per-project config (keep in sync with bin/setup.mjs) ────────────────────
|
|
11
|
+
const CONFIG = {
|
|
12
|
+
packageName: 'ts-procedures',
|
|
13
|
+
sourceDir: resolve(__dirname, '..', 'skills'),
|
|
14
|
+
skills: ['ts-procedures'],
|
|
15
|
+
targetRoots: ['.agents/skills', '.claude/skills'],
|
|
16
|
+
};
|
|
13
17
|
|
|
14
|
-
// INIT_CWD is set by npm/yarn/pnpm during lifecycle scripts —
|
|
18
|
+
// INIT_CWD is set by npm/yarn/pnpm during lifecycle scripts — the project root.
|
|
15
19
|
const projectRoot = process.env.INIT_CWD;
|
|
20
|
+
if (!projectRoot) process.exit(0);
|
|
16
21
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// Detect self-install (developing ts-procedures itself) — skip
|
|
22
|
-
const ownPackageRoot = resolve(__dirname, '../..');
|
|
23
|
-
if (resolve(projectRoot) === ownPackageRoot) {
|
|
24
|
-
process.exit(0);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// ─── Helpers ──────────────────────────────────────────────
|
|
28
|
-
|
|
29
|
-
function readSourceFile(relativePath) {
|
|
30
|
-
return readFileSync(join(AGENT_CONFIG_DIR, relativePath), 'utf-8');
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function wrapWithMarkers(content) {
|
|
34
|
-
return `${MARKER_BEGIN}\n${content.trim()}\n${MARKER_END}`;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function replaceMarkerSection(existingContent, newContent) {
|
|
38
|
-
const beginIdx = existingContent.indexOf(MARKER_BEGIN);
|
|
39
|
-
const endIdx = existingContent.indexOf(MARKER_END);
|
|
40
|
-
|
|
41
|
-
if (beginIdx !== -1 && endIdx !== -1) {
|
|
42
|
-
const before = existingContent.slice(0, beginIdx);
|
|
43
|
-
const after = existingContent.slice(endIdx + MARKER_END.length);
|
|
44
|
-
return before + wrapWithMarkers(newContent) + after;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return null; // No existing markers — don't modify
|
|
48
|
-
}
|
|
22
|
+
// Skip when developing this package itself.
|
|
23
|
+
if (resolve(projectRoot) === resolve(__dirname, '..', '..')) process.exit(0);
|
|
49
24
|
|
|
50
|
-
|
|
51
|
-
if (!existsSync(targetPath)) return false;
|
|
25
|
+
const cfg = { ...CONFIG, projectRoot };
|
|
52
26
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const sourceContent = readSourceFile(sourceRelativePath);
|
|
57
|
-
const updated = replaceMarkerSection(existing, sourceContent);
|
|
58
|
-
if (updated) {
|
|
59
|
-
writeFileSync(targetPath, updated, 'utf-8');
|
|
60
|
-
return true;
|
|
61
|
-
}
|
|
62
|
-
return false;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// ─── Auto-update ──────────────────────────────────────────
|
|
66
|
-
|
|
67
|
-
const claudeSkillDir = join(projectRoot, '.claude', 'skills', 'ts-procedures');
|
|
68
|
-
const cursorFile = join(projectRoot, '.cursorrules');
|
|
69
|
-
const copilotFile = join(projectRoot, '.github', 'copilot-instructions.md');
|
|
70
|
-
|
|
71
|
-
// Check if any target was previously set up
|
|
72
|
-
const hasAnySetup = existsSync(claudeSkillDir) || existsSync(cursorFile) || existsSync(copilotFile);
|
|
73
|
-
|
|
74
|
-
if (hasAnySetup) {
|
|
27
|
+
// Opt-in only: refresh skills the user has already installed; never create on
|
|
28
|
+
// first install (rely on README / `npx <pkg>-setup`).
|
|
29
|
+
if (isInstalled(cfg)) {
|
|
75
30
|
try {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
// Auto-update Claude Code files
|
|
79
|
-
if (existsSync(claudeSkillDir)) {
|
|
80
|
-
const { installClaude } = await import('../lib/install-claude.mjs');
|
|
81
|
-
installClaude(projectRoot);
|
|
82
|
-
updated.push('Claude Code');
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Auto-update Cursor rules (only if markers present)
|
|
86
|
-
if (updateMarkedFile(cursorFile, 'cursor/cursorrules')) {
|
|
87
|
-
updated.push('Cursor');
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Auto-update Copilot instructions (only if markers present)
|
|
91
|
-
if (updateMarkedFile(copilotFile, 'copilot/copilot-instructions.md')) {
|
|
92
|
-
updated.push('Copilot');
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if (updated.length > 0) {
|
|
96
|
-
console.log('');
|
|
97
|
-
console.log(` ts-procedures — AI agent rules updated (${updated.join(', ')})`);
|
|
98
|
-
console.log('');
|
|
99
|
-
}
|
|
31
|
+
installSkills(cfg);
|
|
32
|
+
console.log(`\n ${CONFIG.packageName} — Agent Skill updated\n`);
|
|
100
33
|
} catch {
|
|
101
|
-
// Never break npm install
|
|
34
|
+
// Never break npm install.
|
|
102
35
|
}
|
|
103
36
|
}
|
|
104
|
-
|
|
105
|
-
// No invitation message if not opted in — rely on README / npx ts-procedures-setup --help
|
|
@@ -1,297 +1,84 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { existsSync } from 'node:fs';
|
|
4
|
+
import { dirname, resolve } from 'node:path';
|
|
5
5
|
import { fileURLToPath } from 'node:url';
|
|
6
|
-
import {
|
|
7
|
-
import { installClaude } from '../lib/install-claude.mjs';
|
|
6
|
+
import { installSkills, planSkills, outdatedSkillFiles } from '../lib/install-skills.mjs';
|
|
8
7
|
|
|
9
8
|
const __filename = fileURLToPath(import.meta.url);
|
|
10
9
|
const __dirname = dirname(__filename);
|
|
11
|
-
const AGENT_CONFIG_DIR = resolve(__dirname, '..');
|
|
12
|
-
const PROJECT_DIR = process.cwd();
|
|
13
|
-
|
|
14
|
-
const MARKER_BEGIN = '<!-- BEGIN ts-procedures -->';
|
|
15
|
-
const MARKER_END = '<!-- END ts-procedures -->';
|
|
16
10
|
|
|
17
|
-
|
|
11
|
+
// ─── Per-project config (the only thing a consuming library customizes) ──────
|
|
12
|
+
const CONFIG = {
|
|
13
|
+
packageName: 'ts-procedures',
|
|
14
|
+
sourceDir: resolve(__dirname, '..', 'skills'),
|
|
15
|
+
skills: ['ts-procedures'],
|
|
16
|
+
// `.agents/skills` is read by 30+ agent tools (Codex, Cursor, Copilot,
|
|
17
|
+
// Gemini CLI, …); `.claude/skills` is Claude Code's native project location.
|
|
18
|
+
// One source, fanned out to both.
|
|
19
|
+
targetRoots: ['.agents/skills', '.claude/skills'],
|
|
20
|
+
};
|
|
18
21
|
|
|
19
|
-
|
|
22
|
+
const PROJECT_DIR = process.cwd();
|
|
20
23
|
|
|
21
24
|
function printUsage() {
|
|
22
25
|
console.log(`
|
|
23
|
-
Usage: npx
|
|
26
|
+
Usage: npx ${CONFIG.packageName}-setup [options]
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
all Set up all targets (default)
|
|
28
|
+
Installs the ${CONFIG.packageName} Agent Skill into the standard agent
|
|
29
|
+
directories so any compatible AI coding tool picks it up automatically:
|
|
30
|
+
|
|
31
|
+
${CONFIG.targetRoots.map((r) => `${r}/${CONFIG.skills.join(', ')}`).join('\n ')}
|
|
30
32
|
|
|
31
33
|
Options:
|
|
32
34
|
--help Show this help message
|
|
33
|
-
--force Overwrite existing files without prompting
|
|
34
35
|
--dry-run Show what would be created/updated without writing files
|
|
35
|
-
--check Exit with code 1 if any files are outdated (
|
|
36
|
+
--check Exit with code 1 if any installed files are outdated (CI gate)
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
npx ts-procedures-setup # Set up all targets
|
|
39
|
-
npx ts-procedures-setup cursor # Set up Cursor only
|
|
40
|
-
npx ts-procedures-setup cursor copilot # Set up Cursor and Copilot
|
|
41
|
-
npx ts-procedures-setup --force # Overwrite without prompting
|
|
42
|
-
npx ts-procedures-setup --dry-run # Preview changes
|
|
43
|
-
npx ts-procedures-setup --check # Verify files are up to date
|
|
38
|
+
The files auto-update on every \`npm install\` once installed.
|
|
44
39
|
`);
|
|
45
40
|
}
|
|
46
41
|
|
|
47
|
-
function
|
|
48
|
-
const fullPath = join(AGENT_CONFIG_DIR, relativePath);
|
|
49
|
-
return readFileSync(fullPath, 'utf-8');
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function wrapWithMarkers(content) {
|
|
53
|
-
return `${MARKER_BEGIN}\n${content.trim()}\n${MARKER_END}`;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function replaceMarkerSection(existingContent, newContent) {
|
|
57
|
-
const beginIdx = existingContent.indexOf(MARKER_BEGIN);
|
|
58
|
-
const endIdx = existingContent.indexOf(MARKER_END);
|
|
59
|
-
|
|
60
|
-
if (beginIdx !== -1 && endIdx !== -1) {
|
|
61
|
-
const before = existingContent.slice(0, beginIdx);
|
|
62
|
-
const after = existingContent.slice(endIdx + MARKER_END.length);
|
|
63
|
-
return before + wrapWithMarkers(newContent) + after;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const separator = existingContent.trim() ? '\n\n' : '';
|
|
67
|
-
return existingContent.trim() + separator + wrapWithMarkers(newContent) + '\n';
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
async function confirm(message) {
|
|
71
|
-
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
72
|
-
return new Promise((resolve) => {
|
|
73
|
-
rl.question(`${message} (y/N) `, (answer) => {
|
|
74
|
-
rl.close();
|
|
75
|
-
resolve(answer.toLowerCase() === 'y');
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// ─── Check Mode ───────────────────────────────────────────
|
|
81
|
-
|
|
82
|
-
function isFileOutdated(targetPath, expectedContent) {
|
|
83
|
-
if (!existsSync(targetPath)) return true;
|
|
84
|
-
const current = readFileSync(targetPath, 'utf-8');
|
|
85
|
-
return current !== expectedContent;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// ─── Target Handlers ──────────────────────────────────────
|
|
89
|
-
|
|
90
|
-
function setupClaude({ dryRun, check } = {}) {
|
|
91
|
-
if (dryRun) {
|
|
92
|
-
// Mirror install-claude.mjs: copy every file under each source skill dir, plus the agent.
|
|
93
|
-
const claudeFiles = [];
|
|
94
|
-
const skillsSrc = join(AGENT_CONFIG_DIR, 'claude-code', 'skills');
|
|
95
|
-
for (const skill of ['ts-procedures']) {
|
|
96
|
-
const walk = (dir, prefix) => {
|
|
97
|
-
for (const entry of readdirSync(dir)) {
|
|
98
|
-
const full = join(dir, entry);
|
|
99
|
-
if (statSync(full).isDirectory()) {
|
|
100
|
-
walk(full, `${prefix}/${entry}`);
|
|
101
|
-
} else {
|
|
102
|
-
claudeFiles.push(`${prefix}/${entry}`);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
walk(join(skillsSrc, skill), `.claude/skills/${skill}`);
|
|
107
|
-
}
|
|
108
|
-
claudeFiles.push('.claude/agents/ts-procedures-architect.md');
|
|
109
|
-
|
|
110
|
-
console.log('\n Claude Code (dry run)');
|
|
111
|
-
console.log(' ─────────────────────');
|
|
112
|
-
for (const f of claudeFiles) {
|
|
113
|
-
const status = existsSync(join(PROJECT_DIR, f)) ? 'update' : 'create';
|
|
114
|
-
console.log(` [${status}] ${f}`);
|
|
115
|
-
}
|
|
116
|
-
console.log('');
|
|
117
|
-
return false;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const { files } = installClaude(PROJECT_DIR);
|
|
121
|
-
|
|
122
|
-
if (check) return false; // installClaude always writes — check mode handled at main level
|
|
123
|
-
|
|
124
|
-
console.log('\n Claude Code');
|
|
125
|
-
console.log(' ───────────');
|
|
126
|
-
console.log(' Installed (updates automatically on npm install/update):\n');
|
|
127
|
-
for (const f of files) {
|
|
128
|
-
console.log(` ${f}`);
|
|
129
|
-
}
|
|
130
|
-
console.log('');
|
|
131
|
-
console.log(' Skills: ts-procedures (use `/ts-procedures review <path>` and `/ts-procedures scaffold <type> <Name>`; Kotlin/Swift codegen reference included)');
|
|
132
|
-
console.log(' Agent: ts-procedures-architect (architecture planning)\n');
|
|
133
|
-
return false;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
async function setupCursor(force, { dryRun, check } = {}) {
|
|
137
|
-
const targetPath = join(PROJECT_DIR, '.cursorrules');
|
|
138
|
-
const sourceContent = readSourceFile('cursor/cursorrules');
|
|
139
|
-
|
|
140
|
-
if (dryRun || check) {
|
|
141
|
-
const exists = existsSync(targetPath);
|
|
142
|
-
const hasMarkers = exists && readFileSync(targetPath, 'utf-8').includes(MARKER_BEGIN);
|
|
143
|
-
const label = dryRun ? 'dry run' : 'check';
|
|
144
|
-
const status = !exists ? 'create' : hasMarkers ? 'update' : 'append';
|
|
145
|
-
console.log(`\n Cursor (${label})`);
|
|
146
|
-
console.log(` ──────`);
|
|
147
|
-
console.log(` [${status}] .cursorrules\n`);
|
|
148
|
-
return check && (status === 'create' || status === 'update');
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
console.log('\n Cursor');
|
|
152
|
-
console.log(' ──────');
|
|
153
|
-
|
|
154
|
-
if (existsSync(targetPath)) {
|
|
155
|
-
const existing = readFileSync(targetPath, 'utf-8');
|
|
156
|
-
|
|
157
|
-
if (existing.includes(MARKER_BEGIN)) {
|
|
158
|
-
const updated = replaceMarkerSection(existing, sourceContent);
|
|
159
|
-
writeFileSync(targetPath, updated, 'utf-8');
|
|
160
|
-
console.log(' Updated ts-procedures section in .cursorrules\n');
|
|
161
|
-
return false;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
if (!force) {
|
|
165
|
-
const ok = await confirm(' .cursorrules already exists. Append ts-procedures rules?');
|
|
166
|
-
if (!ok) {
|
|
167
|
-
console.log(' Skipped.\n');
|
|
168
|
-
return false;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const updated = replaceMarkerSection(existing, sourceContent);
|
|
173
|
-
writeFileSync(targetPath, updated, 'utf-8');
|
|
174
|
-
console.log(' Appended ts-procedures rules to .cursorrules\n');
|
|
175
|
-
} else {
|
|
176
|
-
writeFileSync(targetPath, wrapWithMarkers(sourceContent) + '\n', 'utf-8');
|
|
177
|
-
console.log(' Created .cursorrules\n');
|
|
178
|
-
}
|
|
179
|
-
return false;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
async function setupCopilot(force, { dryRun, check } = {}) {
|
|
183
|
-
const githubDir = join(PROJECT_DIR, '.github');
|
|
184
|
-
const targetPath = join(githubDir, 'copilot-instructions.md');
|
|
185
|
-
const sourceContent = readSourceFile('copilot/copilot-instructions.md');
|
|
186
|
-
|
|
187
|
-
if (dryRun || check) {
|
|
188
|
-
const exists = existsSync(targetPath);
|
|
189
|
-
const hasMarkers = exists && readFileSync(targetPath, 'utf-8').includes(MARKER_BEGIN);
|
|
190
|
-
const label = dryRun ? 'dry run' : 'check';
|
|
191
|
-
const status = !exists ? 'create' : hasMarkers ? 'update' : 'append';
|
|
192
|
-
console.log(`\n GitHub Copilot (${label})`);
|
|
193
|
-
console.log(` ──────────────`);
|
|
194
|
-
console.log(` [${status}] .github/copilot-instructions.md\n`);
|
|
195
|
-
return check && (status === 'create' || status === 'update');
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
console.log('\n GitHub Copilot');
|
|
199
|
-
console.log(' ──────────────');
|
|
200
|
-
|
|
201
|
-
if (!existsSync(githubDir)) {
|
|
202
|
-
mkdirSync(githubDir, { recursive: true });
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
if (existsSync(targetPath)) {
|
|
206
|
-
const existing = readFileSync(targetPath, 'utf-8');
|
|
207
|
-
|
|
208
|
-
if (existing.includes(MARKER_BEGIN)) {
|
|
209
|
-
const updated = replaceMarkerSection(existing, sourceContent);
|
|
210
|
-
writeFileSync(targetPath, updated, 'utf-8');
|
|
211
|
-
console.log(' Updated ts-procedures section in .github/copilot-instructions.md\n');
|
|
212
|
-
return false;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
if (!force) {
|
|
216
|
-
const ok = await confirm(' .github/copilot-instructions.md already exists. Append ts-procedures instructions?');
|
|
217
|
-
if (!ok) {
|
|
218
|
-
console.log(' Skipped.\n');
|
|
219
|
-
return false;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
const updated = replaceMarkerSection(existing, sourceContent);
|
|
224
|
-
writeFileSync(targetPath, updated, 'utf-8');
|
|
225
|
-
console.log(' Appended ts-procedures instructions to .github/copilot-instructions.md\n');
|
|
226
|
-
} else {
|
|
227
|
-
writeFileSync(targetPath, wrapWithMarkers(sourceContent) + '\n', 'utf-8');
|
|
228
|
-
console.log(' Created .github/copilot-instructions.md\n');
|
|
229
|
-
}
|
|
230
|
-
return false;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// ─── Main ─────────────────────────────────────────────────
|
|
234
|
-
|
|
235
|
-
async function main() {
|
|
42
|
+
function main() {
|
|
236
43
|
const args = process.argv.slice(2);
|
|
237
|
-
|
|
238
|
-
const dryRun = args.includes('--dry-run');
|
|
239
|
-
const check = args.includes('--check');
|
|
240
|
-
const help = args.includes('--help') || args.includes('-h');
|
|
241
|
-
const targets = args.filter(a => !a.startsWith('--') && !a.startsWith('-'));
|
|
242
|
-
|
|
243
|
-
if (help) {
|
|
44
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
244
45
|
printUsage();
|
|
245
46
|
process.exit(0);
|
|
246
47
|
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
console.error(`Unknown target: "${t}". Valid targets: ${VALID_TARGETS.join(', ')}`);
|
|
251
|
-
process.exit(1);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
const selectedTargets = targets.length === 0 || targets.includes('all')
|
|
256
|
-
? ['claude', 'cursor', 'copilot']
|
|
257
|
-
: targets;
|
|
48
|
+
const dryRun = args.includes('--dry-run');
|
|
49
|
+
const check = args.includes('--check');
|
|
50
|
+
const cfg = { ...CONFIG, projectRoot: PROJECT_DIR };
|
|
258
51
|
|
|
259
52
|
const mode = dryRun ? ' (dry run)' : check ? ' (check)' : '';
|
|
260
|
-
console.log(`\
|
|
261
|
-
console.log('
|
|
262
|
-
|
|
263
|
-
const opts = { dryRun, check };
|
|
264
|
-
let outdated = false;
|
|
265
|
-
|
|
266
|
-
if (selectedTargets.includes('claude')) {
|
|
267
|
-
outdated = setupClaude(opts) || outdated;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
if (selectedTargets.includes('cursor')) {
|
|
271
|
-
outdated = (await setupCursor(force, opts)) || outdated;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
if (selectedTargets.includes('copilot')) {
|
|
275
|
-
outdated = (await setupCopilot(force, opts)) || outdated;
|
|
276
|
-
}
|
|
53
|
+
console.log(`\n${CONFIG.packageName} — Agent Skill setup${mode}`);
|
|
54
|
+
console.log('═'.repeat(40));
|
|
277
55
|
|
|
278
56
|
if (check) {
|
|
279
|
-
|
|
280
|
-
|
|
57
|
+
const outdated = outdatedSkillFiles(cfg);
|
|
58
|
+
if (outdated.length) {
|
|
59
|
+
console.log('\n Outdated or missing:');
|
|
60
|
+
for (const f of outdated) console.log(` ${f}`);
|
|
61
|
+
console.log(`\n Run: npx ${CONFIG.packageName}-setup\n`);
|
|
281
62
|
process.exit(1);
|
|
282
|
-
} else {
|
|
283
|
-
console.log(' All files are up to date.\n');
|
|
284
63
|
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
console.log('
|
|
64
|
+
console.log('\n All files are up to date.\n');
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (dryRun) {
|
|
69
|
+
console.log('');
|
|
70
|
+
for (const { rel, dest } of planSkills(cfg)) {
|
|
71
|
+
console.log(` [${existsSync(dest) ? 'update' : 'create'}] ${rel}`);
|
|
72
|
+
}
|
|
73
|
+
console.log('\n No files were modified (dry run).\n');
|
|
74
|
+
return;
|
|
291
75
|
}
|
|
76
|
+
|
|
77
|
+
const { files } = installSkills(cfg);
|
|
78
|
+
console.log('\n Installed (auto-updates on npm install):\n');
|
|
79
|
+
for (const f of files) console.log(` ${f}`);
|
|
80
|
+
console.log('\n Tip: these are generated — you may add the install roots to .gitignore.\n');
|
|
81
|
+
console.log('Done!\n');
|
|
292
82
|
}
|
|
293
83
|
|
|
294
|
-
main()
|
|
295
|
-
console.error('Error:', err.message);
|
|
296
|
-
process.exit(1);
|
|
297
|
-
});
|
|
84
|
+
main();
|