tempest-express-sdk 0.30.0 → 0.32.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/dist/{chunk-DK46733U.js → chunk-VLNTZE7Q.js} +3 -3
- package/dist/chunk-VLNTZE7Q.js.map +1 -0
- package/dist/cli.cjs +1 -1
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/index.cjs +285 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +296 -9
- package/dist/index.d.ts +296 -9
- package/dist/index.js +279 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-DK46733U.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -15829,8 +15829,40 @@ function registerExceptionHandlers(app, options = {}) {
|
|
|
15829
15829
|
})
|
|
15830
15830
|
);
|
|
15831
15831
|
}
|
|
15832
|
+
function normalizeSchema(refId, schema) {
|
|
15833
|
+
const candidate = schema;
|
|
15834
|
+
if (typeof candidate.openapi === "function") return schema;
|
|
15835
|
+
if (typeof candidate.meta === "function") {
|
|
15836
|
+
return candidate.meta({ id: refId });
|
|
15837
|
+
}
|
|
15838
|
+
throw new Error(
|
|
15839
|
+
`Cannot register "${refId}" for OpenAPI: the value carries neither \`.openapi()\` nor zod v4's \`.meta()\`. This usually means it is not a zod schema, or it comes from a second copy of zod in node_modules \u2014 check \`npm ls zod\` shows a single deduped instance.`
|
|
15840
|
+
);
|
|
15841
|
+
}
|
|
15842
|
+
var TempestOpenApiRegistry = class extends zodToOpenapi.OpenAPIRegistry {
|
|
15843
|
+
/**
|
|
15844
|
+
* Register a component schema, normalizing it first.
|
|
15845
|
+
*
|
|
15846
|
+
* @param refId - The component name.
|
|
15847
|
+
* @param zodSchema - The schema to register.
|
|
15848
|
+
* @returns The registered schema, as the library returns it.
|
|
15849
|
+
*/
|
|
15850
|
+
register(refId, zodSchema) {
|
|
15851
|
+
return super.register(refId, normalizeSchema(refId, zodSchema));
|
|
15852
|
+
}
|
|
15853
|
+
/**
|
|
15854
|
+
* Register a parameter schema, normalizing it first.
|
|
15855
|
+
*
|
|
15856
|
+
* @param refId - The parameter name.
|
|
15857
|
+
* @param zodSchema - The schema to register.
|
|
15858
|
+
* @returns The registered schema, as the library returns it.
|
|
15859
|
+
*/
|
|
15860
|
+
registerParameter(refId, zodSchema) {
|
|
15861
|
+
return super.registerParameter(refId, normalizeSchema(refId, zodSchema));
|
|
15862
|
+
}
|
|
15863
|
+
};
|
|
15832
15864
|
function createOpenApiRegistry() {
|
|
15833
|
-
return new
|
|
15865
|
+
return new TempestOpenApiRegistry();
|
|
15834
15866
|
}
|
|
15835
15867
|
function generateOpenApiDocument(registry, options) {
|
|
15836
15868
|
const config = {
|
|
@@ -16054,6 +16086,239 @@ function makeMetricsRouter(options = {}) {
|
|
|
16054
16086
|
});
|
|
16055
16087
|
return router;
|
|
16056
16088
|
}
|
|
16089
|
+
var PERSPECTIVE_EXTENSION = "x-tempest-perspective";
|
|
16090
|
+
var ASYNCAPI_VERSION = "3.0.0";
|
|
16091
|
+
function actionFor(direction) {
|
|
16092
|
+
return direction === "clientToServer" ? "receive" : "send";
|
|
16093
|
+
}
|
|
16094
|
+
var AsyncApiRegistry = class {
|
|
16095
|
+
/** Channels by `name`. */
|
|
16096
|
+
channels = /* @__PURE__ */ new Map();
|
|
16097
|
+
/** Messages by `name`. */
|
|
16098
|
+
messages = /* @__PURE__ */ new Map();
|
|
16099
|
+
/** Operations, in registration order. */
|
|
16100
|
+
operations = [];
|
|
16101
|
+
/**
|
|
16102
|
+
* Register the connection a socket is served on.
|
|
16103
|
+
*
|
|
16104
|
+
* @param channel - The channel definition.
|
|
16105
|
+
* @returns This registry, for chaining.
|
|
16106
|
+
* @throws Error When `name` is already registered.
|
|
16107
|
+
*/
|
|
16108
|
+
registerChannel(channel) {
|
|
16109
|
+
if (this.channels.has(channel.name)) {
|
|
16110
|
+
throw new Error(`AsyncAPI channel "${channel.name}" is already registered.`);
|
|
16111
|
+
}
|
|
16112
|
+
this.channels.set(channel.name, channel);
|
|
16113
|
+
return this;
|
|
16114
|
+
}
|
|
16115
|
+
/**
|
|
16116
|
+
* Register one frame the socket carries.
|
|
16117
|
+
*
|
|
16118
|
+
* @param message - The message definition.
|
|
16119
|
+
* @returns This registry, for chaining.
|
|
16120
|
+
* @throws Error When `name` is already registered.
|
|
16121
|
+
*/
|
|
16122
|
+
registerMessage(message) {
|
|
16123
|
+
if (this.messages.has(message.name)) {
|
|
16124
|
+
throw new Error(`AsyncAPI message "${message.name}" is already registered.`);
|
|
16125
|
+
}
|
|
16126
|
+
this.messages.set(message.name, message);
|
|
16127
|
+
return this;
|
|
16128
|
+
}
|
|
16129
|
+
/**
|
|
16130
|
+
* Register a set of messages travelling one way on one channel.
|
|
16131
|
+
*
|
|
16132
|
+
* @param operation - The operation definition.
|
|
16133
|
+
* @returns This registry, for chaining.
|
|
16134
|
+
* @throws Error When `name` is already registered.
|
|
16135
|
+
*/
|
|
16136
|
+
registerOperation(operation) {
|
|
16137
|
+
if (this.operations.some((existing) => existing.name === operation.name)) {
|
|
16138
|
+
throw new Error(`AsyncAPI operation "${operation.name}" is already registered.`);
|
|
16139
|
+
}
|
|
16140
|
+
this.operations.push(operation);
|
|
16141
|
+
return this;
|
|
16142
|
+
}
|
|
16143
|
+
/**
|
|
16144
|
+
* Render the AsyncAPI document.
|
|
16145
|
+
*
|
|
16146
|
+
* @param options - The `info` block, optional servers and default content
|
|
16147
|
+
* type.
|
|
16148
|
+
* @returns The document, JSON-serializable.
|
|
16149
|
+
* @throws Error When an operation names a channel or a message that was
|
|
16150
|
+
* never registered. A dangling `$ref` produces a document that validates
|
|
16151
|
+
* structurally and generates a client missing the frame, so it fails
|
|
16152
|
+
* here instead.
|
|
16153
|
+
*/
|
|
16154
|
+
generate(options) {
|
|
16155
|
+
this.assertReferencesResolve();
|
|
16156
|
+
const schemas = this.renderPayloads();
|
|
16157
|
+
const messages = this.renderMessages();
|
|
16158
|
+
const channels = this.renderChannels(schemas);
|
|
16159
|
+
const operations = this.renderOperations();
|
|
16160
|
+
return {
|
|
16161
|
+
asyncapi: ASYNCAPI_VERSION,
|
|
16162
|
+
[PERSPECTIVE_EXTENSION]: "server",
|
|
16163
|
+
info: {
|
|
16164
|
+
title: options.info.title,
|
|
16165
|
+
version: options.info.version,
|
|
16166
|
+
...options.info.description !== void 0 ? { description: options.info.description } : {}
|
|
16167
|
+
},
|
|
16168
|
+
...options.servers !== void 0 ? { servers: options.servers } : {},
|
|
16169
|
+
defaultContentType: options.defaultContentType ?? "application/json",
|
|
16170
|
+
channels,
|
|
16171
|
+
operations,
|
|
16172
|
+
components: { messages, schemas }
|
|
16173
|
+
};
|
|
16174
|
+
}
|
|
16175
|
+
/**
|
|
16176
|
+
* Fail when an operation points at something that was never registered.
|
|
16177
|
+
*
|
|
16178
|
+
* @throws Error Naming the operation and what it could not resolve.
|
|
16179
|
+
*/
|
|
16180
|
+
assertReferencesResolve() {
|
|
16181
|
+
for (const operation of this.operations) {
|
|
16182
|
+
if (!this.channels.has(operation.channel)) {
|
|
16183
|
+
throw new Error(
|
|
16184
|
+
`AsyncAPI operation "${operation.name}" refers to channel "${operation.channel}", which is not registered.`
|
|
16185
|
+
);
|
|
16186
|
+
}
|
|
16187
|
+
for (const message of operation.messages) {
|
|
16188
|
+
if (!this.messages.has(message)) {
|
|
16189
|
+
throw new Error(
|
|
16190
|
+
`AsyncAPI operation "${operation.name}" refers to message "${message}", which is not registered.`
|
|
16191
|
+
);
|
|
16192
|
+
}
|
|
16193
|
+
}
|
|
16194
|
+
}
|
|
16195
|
+
}
|
|
16196
|
+
/**
|
|
16197
|
+
* Render every payload schema through the OpenAPI generator.
|
|
16198
|
+
*
|
|
16199
|
+
* @returns Component schemas keyed by message name, plus any handshake
|
|
16200
|
+
* schema a channel declared.
|
|
16201
|
+
*
|
|
16202
|
+
* AsyncAPI 3 payloads are JSON Schema, and `generateComponents` emits
|
|
16203
|
+
* exactly that from the Zod objects already validating at runtime. Reusing
|
|
16204
|
+
* it is what keeps the document from describing a shape the server would
|
|
16205
|
+
* reject.
|
|
16206
|
+
*/
|
|
16207
|
+
renderPayloads() {
|
|
16208
|
+
const registry = createOpenApiRegistry();
|
|
16209
|
+
for (const message of this.messages.values()) {
|
|
16210
|
+
registry.register(message.name, message.schema);
|
|
16211
|
+
}
|
|
16212
|
+
for (const channel of this.channels.values()) {
|
|
16213
|
+
if (channel.handshakeHeaders !== void 0) {
|
|
16214
|
+
registry.register(`${channel.name}Headers`, channel.handshakeHeaders);
|
|
16215
|
+
}
|
|
16216
|
+
if (channel.handshakeQuery !== void 0) {
|
|
16217
|
+
registry.register(`${channel.name}Query`, channel.handshakeQuery);
|
|
16218
|
+
}
|
|
16219
|
+
}
|
|
16220
|
+
const components = new zodToOpenapi.OpenApiGeneratorV31(registry.definitions).generateComponents();
|
|
16221
|
+
const schemas = components.components?.schemas ?? {};
|
|
16222
|
+
return schemas;
|
|
16223
|
+
}
|
|
16224
|
+
/**
|
|
16225
|
+
* Render `components.messages`.
|
|
16226
|
+
*
|
|
16227
|
+
* @returns Message objects keyed by name, each pointing at its payload.
|
|
16228
|
+
*/
|
|
16229
|
+
renderMessages() {
|
|
16230
|
+
const rendered = {};
|
|
16231
|
+
for (const [name, message] of this.messages) {
|
|
16232
|
+
rendered[name] = {
|
|
16233
|
+
name,
|
|
16234
|
+
contentType: message.contentType ?? "application/json",
|
|
16235
|
+
...message.summary !== void 0 ? { summary: message.summary } : {},
|
|
16236
|
+
...message.description !== void 0 ? { description: message.description } : {},
|
|
16237
|
+
payload: { $ref: `#/components/schemas/${name}` }
|
|
16238
|
+
};
|
|
16239
|
+
}
|
|
16240
|
+
return rendered;
|
|
16241
|
+
}
|
|
16242
|
+
/**
|
|
16243
|
+
* Render `channels`, each listing every message it can carry.
|
|
16244
|
+
*
|
|
16245
|
+
* @param schemas - The rendered component schemas, to inline the
|
|
16246
|
+
* handshake ones into the binding.
|
|
16247
|
+
* @returns Channel objects keyed by name.
|
|
16248
|
+
*
|
|
16249
|
+
* The handshake schemas are **inlined** rather than `$ref`-ed. The
|
|
16250
|
+
* specification types the binding's `headers` and `query` as
|
|
16251
|
+
* `oneOf: [Schema, Reference]`, and a bare `{"$ref": ...}` object
|
|
16252
|
+
* satisfies both branches — so `oneOf` sees two matches and the document
|
|
16253
|
+
* fails validation against AsyncAPI's own JSON Schema. Measured: the same
|
|
16254
|
+
* binding with the schema inlined validates clean.
|
|
16255
|
+
*
|
|
16256
|
+
* A channel lists every registered message rather than only those its own
|
|
16257
|
+
* operations use: the specification requires an operation's `messages` to
|
|
16258
|
+
* be a subset of its channel's, and with one connection per document the
|
|
16259
|
+
* distinction buys nothing.
|
|
16260
|
+
*/
|
|
16261
|
+
renderChannels(schemas) {
|
|
16262
|
+
const everyMessage = {};
|
|
16263
|
+
for (const name of this.messages.keys()) {
|
|
16264
|
+
everyMessage[name] = { $ref: `#/components/messages/${name}` };
|
|
16265
|
+
}
|
|
16266
|
+
const rendered = {};
|
|
16267
|
+
for (const [name, channel] of this.channels) {
|
|
16268
|
+
const bindings = {
|
|
16269
|
+
bindingVersion: "0.1.0",
|
|
16270
|
+
method: "GET"
|
|
16271
|
+
};
|
|
16272
|
+
if (channel.handshakeHeaders !== void 0) {
|
|
16273
|
+
bindings.headers = schemas[`${name}Headers`];
|
|
16274
|
+
}
|
|
16275
|
+
if (channel.handshakeQuery !== void 0) {
|
|
16276
|
+
bindings.query = schemas[`${name}Query`];
|
|
16277
|
+
}
|
|
16278
|
+
rendered[name] = {
|
|
16279
|
+
address: channel.address,
|
|
16280
|
+
...channel.title !== void 0 ? { title: channel.title } : {},
|
|
16281
|
+
...channel.description !== void 0 ? { description: channel.description } : {},
|
|
16282
|
+
messages: everyMessage,
|
|
16283
|
+
bindings: { ws: bindings }
|
|
16284
|
+
};
|
|
16285
|
+
}
|
|
16286
|
+
return rendered;
|
|
16287
|
+
}
|
|
16288
|
+
/**
|
|
16289
|
+
* Render `operations`, translating each direction into an `action`.
|
|
16290
|
+
*
|
|
16291
|
+
* @returns Operation objects keyed by name.
|
|
16292
|
+
*/
|
|
16293
|
+
renderOperations() {
|
|
16294
|
+
const rendered = {};
|
|
16295
|
+
for (const operation of this.operations) {
|
|
16296
|
+
rendered[operation.name] = {
|
|
16297
|
+
action: actionFor(operation.direction),
|
|
16298
|
+
channel: { $ref: `#/channels/${operation.channel}` },
|
|
16299
|
+
...operation.summary !== void 0 ? { summary: operation.summary } : {},
|
|
16300
|
+
...operation.description !== void 0 ? { description: operation.description } : {},
|
|
16301
|
+
messages: operation.messages.map((message) => ({
|
|
16302
|
+
$ref: `#/channels/${operation.channel}/messages/${message}`
|
|
16303
|
+
}))
|
|
16304
|
+
};
|
|
16305
|
+
}
|
|
16306
|
+
return rendered;
|
|
16307
|
+
}
|
|
16308
|
+
};
|
|
16309
|
+
function createAsyncApiRegistry() {
|
|
16310
|
+
return new AsyncApiRegistry();
|
|
16311
|
+
}
|
|
16312
|
+
function generateAsyncApiDocument(registry, options) {
|
|
16313
|
+
return registry.generate(options);
|
|
16314
|
+
}
|
|
16315
|
+
|
|
16316
|
+
// src/asyncapi/mount.ts
|
|
16317
|
+
function mountAsyncApiJson(app, path, document) {
|
|
16318
|
+
app.get(path, (_req, res) => {
|
|
16319
|
+
res.json(document);
|
|
16320
|
+
});
|
|
16321
|
+
}
|
|
16057
16322
|
var logger4 = new JSONLogger("tempest_express_sdk.api.server");
|
|
16058
16323
|
function corsMiddleware(origins) {
|
|
16059
16324
|
const allowAll = origins === "*";
|
|
@@ -16102,6 +16367,14 @@ async function createApp(options = {}) {
|
|
|
16102
16367
|
mountRedoc(app, redocPath ?? "/redoc", specPath, redoc ?? {});
|
|
16103
16368
|
}
|
|
16104
16369
|
}
|
|
16370
|
+
if (options.asyncapi) {
|
|
16371
|
+
const { registry, jsonPath, ...genOptions } = options.asyncapi;
|
|
16372
|
+
mountAsyncApiJson(
|
|
16373
|
+
app,
|
|
16374
|
+
jsonPath ?? "/asyncapi.json",
|
|
16375
|
+
generateAsyncApiDocument(registry, genOptions)
|
|
16376
|
+
);
|
|
16377
|
+
}
|
|
16105
16378
|
registerExceptionHandlers(app, {
|
|
16106
16379
|
...options.errorHandling,
|
|
16107
16380
|
...options.catalog !== void 0 ? { catalog: options.catalog } : {}
|
|
@@ -16994,12 +17267,16 @@ async function withTestDatabase(models, fn) {
|
|
|
16994
17267
|
}
|
|
16995
17268
|
|
|
16996
17269
|
// src/version.ts
|
|
16997
|
-
var VERSION = "0.
|
|
17270
|
+
var VERSION = "0.32.0";
|
|
16998
17271
|
|
|
16999
17272
|
Object.defineProperty(exports, "OpenAPIRegistry", {
|
|
17000
17273
|
enumerable: true,
|
|
17001
17274
|
get: function () { return zodToOpenapi.OpenAPIRegistry; }
|
|
17002
17275
|
});
|
|
17276
|
+
Object.defineProperty(exports, "extendZodWithOpenApi", {
|
|
17277
|
+
enumerable: true,
|
|
17278
|
+
get: function () { return zodToOpenapi.extendZodWithOpenApi; }
|
|
17279
|
+
});
|
|
17003
17280
|
Object.defineProperty(exports, "z", {
|
|
17004
17281
|
enumerable: true,
|
|
17005
17282
|
get: function () { return zod.z; }
|
|
@@ -17149,6 +17426,7 @@ Object.defineProperty(exports, "update", {
|
|
|
17149
17426
|
get: function () { return tempestDbJs.update; }
|
|
17150
17427
|
});
|
|
17151
17428
|
exports.ADMIN_CSS = ADMIN_CSS;
|
|
17429
|
+
exports.ASYNCAPI_VERSION = ASYNCAPI_VERSION;
|
|
17152
17430
|
exports.ActivationService = ActivationService;
|
|
17153
17431
|
exports.AdminJsonSite = AdminJsonSite;
|
|
17154
17432
|
exports.AdminModel = AdminModel;
|
|
@@ -17156,6 +17434,7 @@ exports.AdminPermission = AdminPermission;
|
|
|
17156
17434
|
exports.AdminSessionStore = AdminSessionStore;
|
|
17157
17435
|
exports.AdminSite = AdminSite;
|
|
17158
17436
|
exports.AppException = AppException;
|
|
17437
|
+
exports.AsyncApiRegistry = AsyncApiRegistry;
|
|
17159
17438
|
exports.AttemptThrottle = AttemptThrottle;
|
|
17160
17439
|
exports.AuditAction = AuditAction;
|
|
17161
17440
|
exports.BaseAuditLogModel = BaseAuditLogModel;
|
|
@@ -17217,6 +17496,7 @@ exports.OAuthError = OAuthError;
|
|
|
17217
17496
|
exports.OIDCProvider = OIDCProvider;
|
|
17218
17497
|
exports.OutboxRelay = OutboxRelay;
|
|
17219
17498
|
exports.OutboxStatus = OutboxStatus;
|
|
17499
|
+
exports.PERSPECTIVE_EXTENSION = PERSPECTIVE_EXTENSION;
|
|
17220
17500
|
exports.PHONE_BR_PATTERN = PHONE_BR_PATTERN;
|
|
17221
17501
|
exports.PasswordResetService = PasswordResetService;
|
|
17222
17502
|
exports.PasswordUtils = PasswordUtils;
|
|
@@ -17288,6 +17568,7 @@ exports.corsSettingsShape = corsSettingsShape;
|
|
|
17288
17568
|
exports.cpfField = cpfField;
|
|
17289
17569
|
exports.cpfOrCnpjField = cpfOrCnpjField;
|
|
17290
17570
|
exports.createApp = createApp;
|
|
17571
|
+
exports.createAsyncApiRegistry = createAsyncApiRegistry;
|
|
17291
17572
|
exports.createOpenApiRegistry = createOpenApiRegistry;
|
|
17292
17573
|
exports.createTestDatabase = createTestDatabase;
|
|
17293
17574
|
exports.createdByColumn = createdByColumn;
|
|
@@ -17313,6 +17594,7 @@ exports.foreignKeyLabel = foreignKeyLabel;
|
|
|
17313
17594
|
exports.foreignKeyTable = foreignKeyTable;
|
|
17314
17595
|
exports.formatCellValue = formatCellValue;
|
|
17315
17596
|
exports.formatFieldValue = formatFieldValue;
|
|
17597
|
+
exports.generateAsyncApiDocument = generateAsyncApiDocument;
|
|
17316
17598
|
exports.generateCsrfToken = generateCsrfToken;
|
|
17317
17599
|
exports.generateOAuthState = generateOAuthState;
|
|
17318
17600
|
exports.generateOpaqueToken = generateOpaqueToken;
|
|
@@ -17373,6 +17655,7 @@ exports.mfaCodeSchema = mfaCodeSchema;
|
|
|
17373
17655
|
exports.mfaEnrollResponseSchema = mfaEnrollResponseSchema;
|
|
17374
17656
|
exports.minioSettingsShape = minioSettingsShape;
|
|
17375
17657
|
exports.modifyDict = modifyDict;
|
|
17658
|
+
exports.mountAsyncApiJson = mountAsyncApiJson;
|
|
17376
17659
|
exports.mountOpenApiJson = mountOpenApiJson;
|
|
17377
17660
|
exports.mountRedoc = mountRedoc;
|
|
17378
17661
|
exports.mountSwaggerUi = mountSwaggerUi;
|