@axiomify/cli 6.0.0 → 6.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/README.md CHANGED
@@ -1,6 +1,5 @@
1
1
  # @axiomify/cli
2
2
 
3
-
4
3
  [![npm version](https://img.shields.io/npm/v/@axiomify/cli.svg)](https://npmjs.com/package//@axiomify/cli)
5
4
  [![codecov](https://codecov.io/github/otopman/axiomify/graph/badge.svg)](https://codecov.io/github/otopman/axiomify)
6
5
  [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/OTopman/axiomify/badge)](https://securityscorecards.dev/viewer/?uri=github.com/OTopman/axiomify)
@@ -23,20 +22,21 @@ the same major as your `@axiomify/*` runtime packages.
23
22
 
24
23
  ## Commands at a glance
25
24
 
26
- | Command | Purpose |
27
- |---|---|
28
- | `axiomify init [directory]` | Bootstrap a new project |
29
- | `axiomify dev [entry]` | Hot-reload dev server (esbuild watch) |
30
- | `axiomify build [entry]` | Compile a production bundle to `dist/` |
31
- | `axiomify routes [entry]` | Inspect every HTTP + WebSocket route |
32
- | `axiomify openapi [entry]` | Generate the OpenAPI 3.0.3 spec |
33
- | `axiomify check [entry]` | Static production-readiness audit |
34
- | `axiomify doctor` | Diagnose the host environment |
25
+ | Command | Purpose |
26
+ | --------------------------- | ------------------------------------------------ |
27
+ | `axiomify init [directory]` | Bootstrap a new project |
28
+ | `axiomify dev [entry]` | Hot-reload dev server (esbuild watch) |
29
+ | `axiomify build [entry]` | Compile a production bundle to `dist/` |
30
+ | `axiomify routes [entry]` | Inspect every HTTP + WebSocket route |
31
+ | `axiomify openapi [entry]` | Generate the OpenAPI 3.0.3 spec |
32
+ | `axiomify check [entry]` | Static production-readiness audit |
33
+ | `axiomify doctor` | Diagnose the host environment |
34
+ | `axiomify sdk <subcommand>` | Manage, generate, build, validate, and diff SDKs |
35
35
 
36
36
  `[entry]` defaults to `src/index.ts` everywhere it's accepted.
37
37
 
38
38
  For the full reference (flags, exit codes, CI examples), see
39
- [`[./docs/packages/cli.md](./docs/packages/cli.md)`](https://github.com/OTopman/axiomify/blob/main/docs/packages/cli.md).
39
+ [`./docs/packages/cli.md`](https://github.com/OTopman/axiomify/blob/main/docs/packages/cli.md).
40
40
 
41
41
  ## `axiomify init`
42
42
 
@@ -65,7 +65,7 @@ hooks can drain, with a SIGKILL fallback after 3 seconds.
65
65
 
66
66
  ## `axiomify routes`
67
67
 
68
- Inspects the app *without* booting a listener. Prints a
68
+ Inspects the app _without_ booting a listener. Prints a
69
69
  Unicode-bordered table with colour-coded HTTP methods, validation
70
70
  badges, OpenAPI tags + `operationId`, plugin count, timeout, and
71
71
  deprecation marker.
@@ -144,14 +144,40 @@ alignment, uWS bindings load successfully, recent build artefact, port
144
144
  Run on a fresh clone or new CI runner before chasing test failures that
145
145
  turn out to be Node-version mismatches.
146
146
 
147
+ ## `axiomify sdk`
148
+
149
+ Subcommands for compiling type-safe client SDKs from specs:
150
+
151
+ ```bash
152
+ # Generate SDKs for TS, Python, and Go:
153
+ axiomify sdk generate spec.json --target typescript python go -o ./sdks
154
+
155
+ # Deep structural diff for breaking changes:
156
+ axiomify sdk diff old-spec.json new-spec.json
157
+
158
+ # Get client migration guidance:
159
+ axiomify sdk migrate old-spec.json new-spec.json
160
+
161
+ # Run generation hot-reloads on file change:
162
+ axiomify sdk watch spec.json --target typescript python
163
+
164
+ # Run local toolchain diagnostics:
165
+ axiomify sdk doctor
166
+
167
+ # Run compiler and emitter throughput benchmarks:
168
+ axiomify sdk benchmark
169
+ ```
170
+
147
171
  ## CI example
148
172
 
149
173
  ```yaml
150
- - run: npx axiomify doctor # environment sanity
151
- - run: npx axiomify check # static readiness audit
174
+ - run: npx axiomify doctor # environment sanity
175
+ - run: npx axiomify check # static readiness audit
152
176
  - run: npx axiomify build
153
177
  - run: npx axiomify openapi -o ./openapi.json --spec-version "$GITHUB_SHA"
154
- - run: npx axiomify routes --json > routes.json # surface snapshot
178
+ - run: npx axiomify routes --json > routes.json # surface snapshot
179
+ - run: npx axiomify sdk validate ./openapi.json # schema verification
180
+ - run: npx axiomify sdk diff old-spec.json ./openapi.json # check breaking changes
155
181
  ```
156
182
 
157
183
  Diff `routes.json` between commits to detect accidental API changes
@@ -64,7 +64,8 @@ var OpenApiGenerator = class {
64
64
  if (s.callbacks) operation.callbacks = s.callbacks;
65
65
  const body = this.extractBody(route);
66
66
  if (body) {
67
- if (s.requestBodyDescription) body.description = s.requestBodyDescription;
67
+ if (s.requestBodyDescription)
68
+ body.description = s.requestBodyDescription;
68
69
  operation.requestBody = body;
69
70
  }
70
71
  paths[openApiPath][method] = operation;
@@ -78,14 +79,23 @@ var OpenApiGenerator = class {
78
79
  extractParameters(route) {
79
80
  const parameters = [];
80
81
  if (route.schema?.params) {
81
- const paramSchema = zodSchemaToOpenApi(route.schema.params);
82
+ const paramSchema = zodSchemaToOpenApi(
83
+ route.schema.params
84
+ );
82
85
  const properties = paramSchema.properties ?? {};
83
86
  for (const [key, prop] of Object.entries(properties)) {
84
- parameters.push({ name: key, in: "path", required: true, schema: prop });
87
+ parameters.push({
88
+ name: key,
89
+ in: "path",
90
+ required: true,
91
+ schema: prop
92
+ });
85
93
  }
86
94
  }
87
95
  if (route.schema?.query) {
88
- const querySchema = zodSchemaToOpenApi(route.schema.query);
96
+ const querySchema = zodSchemaToOpenApi(
97
+ route.schema.query
98
+ );
89
99
  const properties = querySchema.properties ?? {};
90
100
  const required = querySchema.required ?? [];
91
101
  for (const [key, prop] of Object.entries(properties)) {
@@ -129,11 +139,18 @@ var OpenApiGenerator = class {
129
139
  if (!route.schema?.body && !route.schema?.files) return void 0;
130
140
  const hasFiles = !!route.schema.files;
131
141
  const contentType = hasFiles ? "multipart/form-data" : "application/json";
132
- let finalSchema = { type: "object", properties: {} };
142
+ let finalSchema = {
143
+ type: "object",
144
+ properties: {}
145
+ };
133
146
  if (route.schema.body) {
134
- const bodySchema = zodSchemaToOpenApi(route.schema.body);
147
+ const bodySchema = zodSchemaToOpenApi(
148
+ route.schema.body
149
+ );
135
150
  if (bodySchema.type === "object") {
136
- finalSchema.properties = { ...bodySchema.properties };
151
+ finalSchema.properties = {
152
+ ...bodySchema.properties
153
+ };
137
154
  if (bodySchema.required) finalSchema.required = bodySchema.required;
138
155
  if (bodySchema.additionalProperties !== void 0) {
139
156
  finalSchema.additionalProperties = bodySchema.additionalProperties;
@@ -155,7 +172,10 @@ var OpenApiGenerator = class {
155
172
  }
156
173
  finalSchema.properties = props;
157
174
  }
158
- return { required: true, content: { [contentType]: { schema: finalSchema } } };
175
+ return {
176
+ required: true,
177
+ content: { [contentType]: { schema: finalSchema } }
178
+ };
159
179
  }
160
180
  extractResponses(route) {
161
181
  const descriptions = route.schema?.responseDescriptions ?? {};
@@ -195,7 +215,7 @@ function escapeHtml(s) {
195
215
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
196
216
  }
197
217
  function escapeJsString(s) {
198
- return s.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
218
+ return JSON.stringify(s).replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
199
219
  }
200
220
  function defineSecuritySchemes(schemes) {
201
221
  return {
@@ -325,7 +345,7 @@ function useOpenAPI(app, options) {
325
345
  <script>
326
346
  window.onload = () => {
327
347
  window.ui = SwaggerUIBundle({
328
- url: '${escapeJsString(specUrl)}',
348
+ url: ${escapeJsString(specUrl)},
329
349
  dom_id: '#swagger-ui',
330
350
  });
331
351
  };