@spine-event-engine/proto-tools 2.0.0-snapshot.2 → 2.0.0-snapshot.5
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/README.md +46 -45
- package/REFERENCE.md +11 -1
- package/bin/spine-proto.mjs +0 -0
- package/dist/src/generation/build-time-handler-analyzer.d.ts +158 -0
- package/dist/src/generation/build-time-handler-analyzer.d.ts.map +1 -0
- package/dist/src/generation/build-time-handler-analyzer.js +1158 -0
- package/dist/src/generation/build-time-handler-analyzer.js.map +1 -0
- package/dist/src/generation/generated-registry-writer.d.ts +58 -0
- package/dist/src/generation/generated-registry-writer.d.ts.map +1 -0
- package/dist/src/generation/generated-registry-writer.js +458 -0
- package/dist/src/generation/generated-registry-writer.js.map +1 -0
- package/dist/src/generation/generation-reuse.mjs +24 -2
- package/dist/src/generation/handler-codegen.d.ts +48 -0
- package/dist/src/generation/handler-codegen.d.ts.map +1 -0
- package/dist/src/generation/handler-codegen.js +214 -0
- package/dist/src/generation/handler-codegen.js.map +1 -0
- package/dist/src/generation/handler-generator.js +1 -1
- package/dist/src/generation/handler-generator.js.map +1 -1
- package/dist/src/testing/index.d.ts +8 -0
- package/dist/src/testing/index.d.ts.map +1 -0
- package/dist/src/testing/index.js +20 -0
- package/dist/src/testing/index.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +9 -6
package/README.md
CHANGED
|
@@ -1,33 +1,34 @@
|
|
|
1
1
|
# Protobuf tooling for Spine applications
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
commands, events, and state used by Aggregates or Projections
|
|
6
|
-
|
|
3
|
+
Use this build-time package to generate TypeScript from application Proto
|
|
4
|
+
models, assemble model registries, and generate handler registries. Models can
|
|
5
|
+
define commands, events, and state used by Aggregates or Projections; this tool
|
|
6
|
+
does not run inside a server process.
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
This is an experimental snapshot. Install the snapshot explicitly while its CLI
|
|
9
|
+
and generated-output contract continue to evolve:
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
authored interface in the same model module. Do not edit output: rerun the
|
|
14
|
-
generator instead.
|
|
11
|
+
```sh
|
|
12
|
+
pnpm add -D @spine-event-engine/proto-tools@snapshot
|
|
13
|
+
```
|
|
15
14
|
|
|
16
|
-
For
|
|
17
|
-
[
|
|
15
|
+
For configuration, manifest, and generated-output details, read the
|
|
16
|
+
[reference](REFERENCE.md).
|
|
18
17
|
|
|
19
|
-
## 💡
|
|
18
|
+
## 💡 Who should use it?
|
|
20
19
|
|
|
21
|
-
- ✅
|
|
22
|
-
- ✅
|
|
23
|
-
|
|
24
|
-
-
|
|
20
|
+
- ✅ Authors of Node.js/pnpm Spine model packages and application packages.
|
|
21
|
+
- ✅ Teams with canonical `.proto` sources, the `spine-proto` CLI, and the
|
|
22
|
+
required Protobuf compiler/plugins available to their workspace.
|
|
23
|
+
- ❌ Runtime application code; import the generated model module and registry
|
|
24
|
+
instead of invoking this CLI from a server.
|
|
25
25
|
|
|
26
|
-
## 🚀
|
|
26
|
+
## 🚀 Generate and compile one model
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
Start in a Node.js/pnpm workspace with the CLI installed, a model package, and
|
|
29
|
+
the Protobuf compiler/plugin toolchain available. A model package keeps its
|
|
30
|
+
canonical `.proto` files under `proto/` and declares its generated locations in
|
|
31
|
+
`spine-proto.json`:
|
|
31
32
|
|
|
32
33
|
```json
|
|
33
34
|
{
|
|
@@ -42,17 +43,19 @@ contexts; a small application may use one combined model package.
|
|
|
42
43
|
}
|
|
43
44
|
```
|
|
44
45
|
|
|
45
|
-
|
|
46
|
+
From that model package directory, generate the model. The command emits
|
|
47
|
+
Protobuf-ES source under `generated/`, an importable `generated/proto-module.ts`,
|
|
48
|
+
and `spine-proto-manifest.json`; then compile the package.
|
|
46
49
|
|
|
47
50
|
```sh
|
|
48
|
-
spine-proto generate
|
|
51
|
+
pnpm exec spine-proto generate
|
|
52
|
+
tsc -b
|
|
49
53
|
```
|
|
50
54
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
`spine-proto-manifest.json`. Do not edit generated output by hand.
|
|
55
|
+
Do not edit generated output by hand: change the Proto source or configuration,
|
|
56
|
+
then run generation again.
|
|
54
57
|
|
|
55
|
-
## 🧩 Compose an application
|
|
58
|
+
## 🧩 Compose an application after the first model succeeds
|
|
56
59
|
|
|
57
60
|
An application lists its direct model packages and a source location for the
|
|
58
61
|
generated registry.
|
|
@@ -67,36 +70,34 @@ generated registry.
|
|
|
67
70
|
```
|
|
68
71
|
|
|
69
72
|
```sh
|
|
70
|
-
spine-proto compose
|
|
71
|
-
spine-proto handlers
|
|
73
|
+
pnpm exec spine-proto compose
|
|
74
|
+
pnpm exec spine-proto handlers
|
|
72
75
|
tsc -b
|
|
73
76
|
```
|
|
74
77
|
|
|
75
78
|
`compose` follows declared model dependencies transitively. `handlers` creates
|
|
76
|
-
the generated handler registry for decorated application classes.
|
|
77
|
-
|
|
79
|
+
the generated handler registry for decorated application classes. Its emitted
|
|
80
|
+
source imports the Server handler-registry contract as a type from
|
|
81
|
+
`@spine-event-engine/server/spi/handler-registry`; the CLI itself has no Server
|
|
82
|
+
runtime dependency. Run both after the related model or handler changes.
|
|
78
83
|
|
|
79
|
-
The public CLI is `spine-proto`.
|
|
80
|
-
|
|
84
|
+
The public CLI is `spine-proto`. Programmatic config and manifest readers are
|
|
85
|
+
for build tooling that needs the same validated package contracts; application
|
|
81
86
|
code should import generated model modules instead.
|
|
82
87
|
|
|
83
|
-
|
|
84
|
-
// docs-snippet-path: packages/proto-tools/src/index.ts
|
|
85
|
-
import { ProtoConfig } from "@spine-event-engine/proto-tools";
|
|
86
|
-
|
|
87
|
-
const config = ProtoConfig.read(".");
|
|
88
|
-
void config;
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
## ⚠️ Build-time only
|
|
88
|
+
## ⚠️ Cleanup and limits
|
|
92
89
|
|
|
93
90
|
Run this tooling after changing Proto files or decorated handlers. Generated
|
|
94
91
|
files are outputs, not source: never edit them by hand. Application runtime code
|
|
95
92
|
imports the generated model module and registry; it does not invoke the CLI.
|
|
96
93
|
|
|
94
|
+
Keep model-package dependencies explicit in both `package.json` and
|
|
95
|
+
`spine-proto.json`. `compose` follows declared model dependencies transitively;
|
|
96
|
+
it does not discover undeclared packages or create a running application.
|
|
97
|
+
|
|
97
98
|
## 🔗 Learn more
|
|
98
99
|
|
|
99
|
-
- [Spine Protobuf package](
|
|
100
|
-
- [Core message tools](
|
|
101
|
-
- [Message Board model example](
|
|
100
|
+
- [Spine Protobuf package](https://github.com/SpineEventEngine/spine-ts/blob/main/packages/proto/README.md)
|
|
101
|
+
- [Core message tools](https://github.com/SpineEventEngine/spine-ts/blob/main/packages/core/README.md)
|
|
102
|
+
- [Message Board model example](https://github.com/SpineEventEngine/spine-ts/blob/main/examples/message-board/model/README.md)
|
|
102
103
|
- [Reference for coding agents](REFERENCE.md)
|
package/REFERENCE.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# @spine-event-engine/proto-tools reference
|
|
2
2
|
|
|
3
|
+
## Testing entry point
|
|
4
|
+
|
|
5
|
+
`@spine-event-engine/proto-tools/testing` supports compiler-focused framework
|
|
6
|
+
tests that analyze or render handler registries. Direct implementation modules
|
|
7
|
+
under `src/generation` remain private; only this deliberate testing subpath is
|
|
8
|
+
available to package-test consumers, with test-infrastructure stability only.
|
|
9
|
+
|
|
3
10
|
This reference describes the public build-time Proto tooling for coding agents.
|
|
4
11
|
|
|
5
12
|
## Interface discovery and provenance
|
|
@@ -23,7 +30,10 @@ whose `spine-proto.json` it should read:
|
|
|
23
30
|
- `spine-proto compose` accepts only application configuration and writes the
|
|
24
31
|
configured model registry source;
|
|
25
32
|
- `spine-proto handlers` accepts an application package and writes
|
|
26
|
-
`generated/handler/generated-handler-registry.ts`.
|
|
33
|
+
`generated/handler/generated-handler-registry.ts`. The emitted module imports
|
|
34
|
+
`GeneratedHandlerRegistry` as a type from
|
|
35
|
+
`@spine-event-engine/server/spi/handler-registry`; handler analysis and
|
|
36
|
+
rendering remain tooling-owned and never load Server at CLI runtime.
|
|
27
37
|
|
|
28
38
|
The package also exposes `manifestFormatVersion`, `ProtoConfig`, and
|
|
29
39
|
`ProtoManifest` for build tooling that needs to read or validate the same
|
package/bin/spine-proto.mjs
CHANGED
|
File without changes
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
type GeneratedHandlerKind = "command-assignment" | "command-reaction" | "event-subscription" | "state-subscription" | "event-reaction";
|
|
3
|
+
type GeneratedHandlerParameterCount = 1 | 2;
|
|
4
|
+
/**
|
|
5
|
+
* Build-time analysis result for bare decorated entity handler methods.
|
|
6
|
+
*/
|
|
7
|
+
export interface BuildHandlerAnalysis {
|
|
8
|
+
/**
|
|
9
|
+
* Entity groups in source-file and class declaration order.
|
|
10
|
+
*/
|
|
11
|
+
readonly entities: readonly BuildEntityHandlers[];
|
|
12
|
+
/**
|
|
13
|
+
* Deterministic diagnostics for unsupported handler declarations.
|
|
14
|
+
*/
|
|
15
|
+
readonly diagnostics: readonly BuildHandlerDiagnostic[];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Build-time entity group shaped for later generated registry rendering.
|
|
19
|
+
*/
|
|
20
|
+
export interface BuildEntityHandlers {
|
|
21
|
+
/**
|
|
22
|
+
* Entity class declaration name.
|
|
23
|
+
*/
|
|
24
|
+
readonly className: string;
|
|
25
|
+
/**
|
|
26
|
+
* Source file where the entity class is declared.
|
|
27
|
+
*/
|
|
28
|
+
readonly sourceFile: string;
|
|
29
|
+
/**
|
|
30
|
+
* Importable generated schema reference for entity state.
|
|
31
|
+
*/
|
|
32
|
+
readonly stateSchema: SchemaReference;
|
|
33
|
+
/**
|
|
34
|
+
* Analyzed bare-decorator handler records.
|
|
35
|
+
*/
|
|
36
|
+
readonly handlers: readonly BuildHandlerRecord[];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Importable generated schema reference used by later source rendering.
|
|
40
|
+
*/
|
|
41
|
+
export interface SchemaReference {
|
|
42
|
+
/**
|
|
43
|
+
* Module specifier exactly as declared by analyzed source.
|
|
44
|
+
*/
|
|
45
|
+
readonly moduleSpecifier: string;
|
|
46
|
+
/**
|
|
47
|
+
* Generated schema export name in that module.
|
|
48
|
+
*/
|
|
49
|
+
readonly exportName: string;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Build-time handler record before generated source rendering.
|
|
53
|
+
*/
|
|
54
|
+
export interface BuildHandlerRecord {
|
|
55
|
+
/**
|
|
56
|
+
* Handler role inferred from the bare decorator.
|
|
57
|
+
*/
|
|
58
|
+
readonly kind: GeneratedHandlerKind;
|
|
59
|
+
/**
|
|
60
|
+
* String method name selected by the generated metadata.
|
|
61
|
+
*/
|
|
62
|
+
readonly methodName: string;
|
|
63
|
+
/**
|
|
64
|
+
* Generated schema accepted by the first handler parameter.
|
|
65
|
+
*/
|
|
66
|
+
readonly signalSchema: SchemaReference;
|
|
67
|
+
/**
|
|
68
|
+
* Generated schemas emitted by the handler return type.
|
|
69
|
+
*/
|
|
70
|
+
readonly emittedSchemas: readonly SchemaReference[];
|
|
71
|
+
/**
|
|
72
|
+
* Public method arity: `handler(signal)` or `handler(signal, context)`.
|
|
73
|
+
*/
|
|
74
|
+
readonly parameterCount: GeneratedHandlerParameterCount;
|
|
75
|
+
/**
|
|
76
|
+
* Origin declared on the first receptor parameter.
|
|
77
|
+
*/
|
|
78
|
+
readonly origin: "domestic" | "external";
|
|
79
|
+
/**
|
|
80
|
+
* Optional statically declared Event field filter.
|
|
81
|
+
*/
|
|
82
|
+
readonly where?: BuildWhereOptions;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Build-time representation of one `@Where` declaration.
|
|
86
|
+
*/
|
|
87
|
+
export interface BuildWhereOptions {
|
|
88
|
+
/**
|
|
89
|
+
* Proto source-name path selected by the declaration.
|
|
90
|
+
*/
|
|
91
|
+
readonly eventField: string;
|
|
92
|
+
/**
|
|
93
|
+
* Declared field value in Stringifier text form.
|
|
94
|
+
*/
|
|
95
|
+
readonly equals: string;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Stable diagnostic codes emitted by build-time handler analysis.
|
|
99
|
+
*/
|
|
100
|
+
export type BuildHandlerDiagnosticCode = "APPLY_DECORATOR" | "FRAMEWORK_ENVELOPE_RETURN" | "INVALID_EMITTED_SCHEMA" | "INVALID_HANDLER_NAME" | "INVALID_HANDLER_VISIBILITY" | "INVALID_PARAMETER_COUNT" | "INVALID_SIGNAL_TYPE" | "INVALID_EXTERNAL_ORIGIN" | "EXTERNAL_COMMAND_RECEIVER" | "INVALID_SUBSCRIBE_RETURN" | "INVALID_WHERE" | "MISSING_EMITTED_SCHEMAS" | "MISSING_ENTITY_STATE_SCHEMA" | "MISSING_RETURN_TYPE" | "MISSING_SIGNAL_TYPE" | "NON_EXPORTED_ENTITY_CLASS" | "SCHEMA_BEARING_DECORATOR" | "TYPESCRIPT_SYNTAX_ERROR" | "UNSUPPORTED_ENTITY_EXPORT" | "UNSUPPORTED_RETURN_TYPE";
|
|
101
|
+
/**
|
|
102
|
+
* One build-time analyzer diagnostic.
|
|
103
|
+
*/
|
|
104
|
+
export interface BuildHandlerDiagnostic {
|
|
105
|
+
/**
|
|
106
|
+
* Stable machine-readable diagnostic code.
|
|
107
|
+
*/
|
|
108
|
+
readonly code: BuildHandlerDiagnosticCode;
|
|
109
|
+
/**
|
|
110
|
+
* Source file where the diagnostic was found.
|
|
111
|
+
*/
|
|
112
|
+
readonly sourceFile: string;
|
|
113
|
+
/**
|
|
114
|
+
* One-based source line.
|
|
115
|
+
*/
|
|
116
|
+
readonly line: number;
|
|
117
|
+
/**
|
|
118
|
+
* One-based source column.
|
|
119
|
+
*/
|
|
120
|
+
readonly column: number;
|
|
121
|
+
/**
|
|
122
|
+
* Human-readable diagnostic message.
|
|
123
|
+
*/
|
|
124
|
+
readonly message: string;
|
|
125
|
+
/**
|
|
126
|
+
* Entity class name when available.
|
|
127
|
+
*/
|
|
128
|
+
readonly className?: string;
|
|
129
|
+
/**
|
|
130
|
+
* Handler method name when available.
|
|
131
|
+
*/
|
|
132
|
+
readonly methodName?: string;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Inspects configured TypeScript source files for bare Spine handler decorators.
|
|
136
|
+
*/
|
|
137
|
+
export interface BuildHandlerAnalyzer {
|
|
138
|
+
/**
|
|
139
|
+
* Inspects source files and returns entity handler records with deterministic diagnostics.
|
|
140
|
+
*
|
|
141
|
+
* @param program TypeScript program that owns the source files and diagnostics.
|
|
142
|
+
* @param sourceFiles Application source files to inspect; defaults to program files.
|
|
143
|
+
* @returns Entity handler records and deterministic diagnostics.
|
|
144
|
+
*/
|
|
145
|
+
analyze(program: ts.Program, sourceFiles?: readonly ts.SourceFile[]): BuildHandlerAnalysis;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Provides build-time analysis for bare Spine handler decorators.
|
|
149
|
+
*/
|
|
150
|
+
export declare const BuildHandlerAnalyzer: BuildHandlerAnalyzer;
|
|
151
|
+
/**
|
|
152
|
+
* Finds the package identity that owns an analyzed source file.
|
|
153
|
+
*/
|
|
154
|
+
export declare const PackageIdentity: Readonly<{
|
|
155
|
+
nameFor(sourceFile: string): string | undefined;
|
|
156
|
+
}>;
|
|
157
|
+
export {};
|
|
158
|
+
//# sourceMappingURL=build-time-handler-analyzer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build-time-handler-analyzer.d.ts","sourceRoot":"","sources":["../../../src/generation/build-time-handler-analyzer.ts"],"names":[],"mappings":"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"}
|