@ttoss/http-server-mcp-openapi 0.2.13 → 0.2.14
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 +5 -0
- package/dist/index.cjs +97 -9
- package/dist/index.d.cts +18 -8
- package/dist/index.d.mts +18 -8
- package/dist/index.mjs +97 -9
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -69,6 +69,11 @@ path-item one with the same `name`+`in`.
|
|
|
69
69
|
Tool arguments are **camelCase** (`agentId`, `projectId`); the generated
|
|
70
70
|
request path, query string, and body use the original **snake_case** names.
|
|
71
71
|
|
|
72
|
+
Query params honour their declared `style` and `explode`. `form` (the default)
|
|
73
|
+
repeats array values, `spaceDelimited`/`pipeDelimited` join them, and
|
|
74
|
+
`deepObject` emits bracketed keys — including nested objects and arrays, so
|
|
75
|
+
`{ documentId: { $eq: 'doc_1' } }` becomes `filters[documentId][$eq]=doc_1`.
|
|
76
|
+
|
|
72
77
|
## `registerOpenApiTools`
|
|
73
78
|
|
|
74
79
|
| Field | Description |
|
package/dist/index.cjs
CHANGED
|
@@ -117,22 +117,108 @@ var buildPathFn = (pathTemplate, pathParams) => {
|
|
|
117
117
|
return result;
|
|
118
118
|
};
|
|
119
119
|
};
|
|
120
|
+
var NON_EXPLODED_DELIMITERS = {
|
|
121
|
+
form: ",",
|
|
122
|
+
spaceDelimited: " ",
|
|
123
|
+
pipeDelimited: "|"
|
|
124
|
+
};
|
|
125
|
+
var isRecord = value => {
|
|
126
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
127
|
+
};
|
|
128
|
+
/**
|
|
129
|
+
* Appends a `deepObject` value as bracketed keys — `filters[documentId][$eq]`.
|
|
130
|
+
* OpenAPI only defines one level, but the APIs that ask for `deepObject`
|
|
131
|
+
* (Strapi, Directus) nest, so nested objects and arrays recurse instead of
|
|
132
|
+
* being stringified into `[object Object]`.
|
|
133
|
+
*/
|
|
134
|
+
var appendDeepObject = args => {
|
|
135
|
+
if (args.value === void 0 || args.value === null) return;
|
|
136
|
+
if (Array.isArray(args.value)) {
|
|
137
|
+
for (const [index, item] of args.value.entries()) appendDeepObject({
|
|
138
|
+
search: args.search,
|
|
139
|
+
key: `${args.key}[${index}]`,
|
|
140
|
+
value: item
|
|
141
|
+
});
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
if (isRecord(args.value)) {
|
|
145
|
+
for (const [property, propertyValue] of Object.entries(args.value)) appendDeepObject({
|
|
146
|
+
search: args.search,
|
|
147
|
+
key: `${args.key}[${property}]`,
|
|
148
|
+
value: propertyValue
|
|
149
|
+
});
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
args.search.append(args.key, String(args.value));
|
|
153
|
+
};
|
|
154
|
+
var appendArrayValue = args => {
|
|
155
|
+
if (args.explode) {
|
|
156
|
+
for (const item of args.value) args.search.append(args.name, String(item));
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
args.search.append(args.name, args.value.map(String).join(args.delimiter));
|
|
160
|
+
};
|
|
161
|
+
var appendObjectValue = args => {
|
|
162
|
+
const entries = Object.entries(args.value).filter(([, entryValue]) => {
|
|
163
|
+
return entryValue !== void 0 && entryValue !== null;
|
|
164
|
+
});
|
|
165
|
+
if (args.explode) {
|
|
166
|
+
for (const [property, entryValue] of entries) args.search.append(property, String(entryValue));
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
args.search.append(args.name, entries.flatMap(([property, entryValue]) => {
|
|
170
|
+
return [property, String(entryValue)];
|
|
171
|
+
}).join(args.delimiter));
|
|
172
|
+
};
|
|
173
|
+
var appendQueryValue = args => {
|
|
174
|
+
const style = args.param.style ?? "form";
|
|
175
|
+
if (style === "deepObject") {
|
|
176
|
+
appendDeepObject({
|
|
177
|
+
search: args.search,
|
|
178
|
+
key: args.param.name,
|
|
179
|
+
value: args.value
|
|
180
|
+
});
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
const serialization = {
|
|
184
|
+
search: args.search,
|
|
185
|
+
name: args.param.name,
|
|
186
|
+
explode: args.param.explode ?? style === "form",
|
|
187
|
+
delimiter: NON_EXPLODED_DELIMITERS[style] ?? ","
|
|
188
|
+
};
|
|
189
|
+
if (Array.isArray(args.value)) {
|
|
190
|
+
appendArrayValue({
|
|
191
|
+
...serialization,
|
|
192
|
+
value: args.value
|
|
193
|
+
});
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
if (isRecord(args.value)) {
|
|
197
|
+
appendObjectValue({
|
|
198
|
+
...serialization,
|
|
199
|
+
value: args.value
|
|
200
|
+
});
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
args.search.append(args.param.name, String(args.value));
|
|
204
|
+
};
|
|
120
205
|
/**
|
|
121
206
|
* Builds a function that serialises query params into a query string
|
|
122
|
-
* (including the leading `?`)
|
|
123
|
-
*
|
|
207
|
+
* (including the leading `?`), honouring each param's OpenAPI `style` and
|
|
208
|
+
* `explode`. Returns `undefined` when the op has no query params.
|
|
124
209
|
*/
|
|
125
210
|
var buildQueryFn = queryParams => {
|
|
126
211
|
if (queryParams.length === 0) return void 0;
|
|
127
212
|
return args => {
|
|
128
213
|
const search = new URLSearchParams();
|
|
129
|
-
for (const {
|
|
130
|
-
|
|
131
|
-
camelName
|
|
132
|
-
} of queryParams) {
|
|
133
|
-
const value = args[camelName];
|
|
214
|
+
for (const param of queryParams) {
|
|
215
|
+
const value = args[param.camelName];
|
|
134
216
|
if (value === void 0 || value === null) continue;
|
|
135
|
-
|
|
217
|
+
appendQueryValue({
|
|
218
|
+
search,
|
|
219
|
+
param,
|
|
220
|
+
value
|
|
221
|
+
});
|
|
136
222
|
}
|
|
137
223
|
const qs = search.toString();
|
|
138
224
|
return qs ? `?${qs}` : "";
|
|
@@ -275,7 +361,9 @@ var extractQueryParams = args => {
|
|
|
275
361
|
camelName: snakeToCamel(p.name || ""),
|
|
276
362
|
description: p.description || "",
|
|
277
363
|
required: p.required || false,
|
|
278
|
-
type: p.schema?.type || "string"
|
|
364
|
+
type: p.schema?.type || "string",
|
|
365
|
+
style: p.style,
|
|
366
|
+
explode: p.explode
|
|
279
367
|
};
|
|
280
368
|
}));
|
|
281
369
|
};
|
package/dist/index.d.cts
CHANGED
|
@@ -93,7 +93,9 @@ interface OperationSpec {
|
|
|
93
93
|
name?: string;
|
|
94
94
|
in?: string;
|
|
95
95
|
required?: boolean;
|
|
96
|
-
description?: string;
|
|
96
|
+
description?: string; /** Query serialisation style, e.g. `form` (default) or `deepObject`. */
|
|
97
|
+
style?: string; /** Whether each value gets its own key. Defaults to `true` for `form`. */
|
|
98
|
+
explode?: boolean;
|
|
97
99
|
schema?: {
|
|
98
100
|
type?: string;
|
|
99
101
|
items?: {
|
|
@@ -212,6 +214,8 @@ declare const resolveParameter: (param: Record<string, unknown> | undefined, spe
|
|
|
212
214
|
in?: string;
|
|
213
215
|
required?: boolean;
|
|
214
216
|
description?: string;
|
|
217
|
+
style?: string;
|
|
218
|
+
explode?: boolean;
|
|
215
219
|
schema?: {
|
|
216
220
|
type?: string;
|
|
217
221
|
items?: {
|
|
@@ -224,15 +228,19 @@ declare const buildPathFn: (pathTemplate: string, pathParams: Array<{
|
|
|
224
228
|
name: string;
|
|
225
229
|
camelName: string;
|
|
226
230
|
}>) => ((args: Record<string, unknown>) => string);
|
|
231
|
+
/** Query parameter with the OpenAPI serialisation rules declared for it. */
|
|
232
|
+
type QueryParamSerialization = {
|
|
233
|
+
name: string;
|
|
234
|
+
camelName: string; /** OpenAPI `style` (`form`, `deepObject`, `spaceDelimited`, `pipeDelimited`). */
|
|
235
|
+
style?: string; /** OpenAPI `explode`. Defaults to `true` for `form`, `false` otherwise. */
|
|
236
|
+
explode?: boolean;
|
|
237
|
+
};
|
|
227
238
|
/**
|
|
228
239
|
* Builds a function that serialises query params into a query string
|
|
229
|
-
* (including the leading `?`)
|
|
230
|
-
*
|
|
240
|
+
* (including the leading `?`), honouring each param's OpenAPI `style` and
|
|
241
|
+
* `explode`. Returns `undefined` when the op has no query params.
|
|
231
242
|
*/
|
|
232
|
-
declare const buildQueryFn: (queryParams:
|
|
233
|
-
name: string;
|
|
234
|
-
camelName: string;
|
|
235
|
-
}>) => ((args: Record<string, unknown>) => string) | undefined;
|
|
243
|
+
declare const buildQueryFn: (queryParams: QueryParamSerialization[]) => ((args: Record<string, unknown>) => string) | undefined;
|
|
236
244
|
/**
|
|
237
245
|
* Builds a function that maps camelCase args back to a snake_case request
|
|
238
246
|
* body, skipping `undefined` args. Returns `undefined` when the op has no body.
|
|
@@ -296,6 +304,8 @@ declare const extractQueryParams: (args: {
|
|
|
296
304
|
description: string;
|
|
297
305
|
required: boolean;
|
|
298
306
|
type: string;
|
|
307
|
+
style?: string;
|
|
308
|
+
explode?: boolean;
|
|
299
309
|
}>;
|
|
300
310
|
/**
|
|
301
311
|
* snake_case names of every top-level property an operation's request schema
|
|
@@ -360,4 +370,4 @@ declare const openApiToToolDefinitions: (args: {
|
|
|
360
370
|
options?: OpenApiToToolsOptions;
|
|
361
371
|
}) => ToolDefinition[];
|
|
362
372
|
//#endregion
|
|
363
|
-
export { DEFAULT_EXCLUDE_EXTENSION, DEFAULT_SERVER_MANAGED_EXTENSION, type JsonSchemaProperty, type OpenApiSpec, type OpenApiToToolsOptions, type OperationSpec, type RegisterOpenApiToolsArgs, type RequestBodySpec, type ResolvedRequest, type ToolDefinition, buildBodyFn, buildInputSchema, buildPathFn, buildQueryFn, dereferenceSchema, extractAcceptedBodyFields, extractBodyProps, extractPathParams, extractQueryParams, getJsonSchemaType, openApiToToolDefinitions, operationIdToToolName, processOperation, processPath, registerOpenApiTools, resolveParameter, resolveSchema, snakeToCamel };
|
|
373
|
+
export { DEFAULT_EXCLUDE_EXTENSION, DEFAULT_SERVER_MANAGED_EXTENSION, type JsonSchemaProperty, type OpenApiSpec, type OpenApiToToolsOptions, type OperationSpec, type QueryParamSerialization, type RegisterOpenApiToolsArgs, type RequestBodySpec, type ResolvedRequest, type ToolDefinition, buildBodyFn, buildInputSchema, buildPathFn, buildQueryFn, dereferenceSchema, extractAcceptedBodyFields, extractBodyProps, extractPathParams, extractQueryParams, getJsonSchemaType, openApiToToolDefinitions, operationIdToToolName, processOperation, processPath, registerOpenApiTools, resolveParameter, resolveSchema, snakeToCamel };
|
package/dist/index.d.mts
CHANGED
|
@@ -93,7 +93,9 @@ interface OperationSpec {
|
|
|
93
93
|
name?: string;
|
|
94
94
|
in?: string;
|
|
95
95
|
required?: boolean;
|
|
96
|
-
description?: string;
|
|
96
|
+
description?: string; /** Query serialisation style, e.g. `form` (default) or `deepObject`. */
|
|
97
|
+
style?: string; /** Whether each value gets its own key. Defaults to `true` for `form`. */
|
|
98
|
+
explode?: boolean;
|
|
97
99
|
schema?: {
|
|
98
100
|
type?: string;
|
|
99
101
|
items?: {
|
|
@@ -212,6 +214,8 @@ declare const resolveParameter: (param: Record<string, unknown> | undefined, spe
|
|
|
212
214
|
in?: string;
|
|
213
215
|
required?: boolean;
|
|
214
216
|
description?: string;
|
|
217
|
+
style?: string;
|
|
218
|
+
explode?: boolean;
|
|
215
219
|
schema?: {
|
|
216
220
|
type?: string;
|
|
217
221
|
items?: {
|
|
@@ -224,15 +228,19 @@ declare const buildPathFn: (pathTemplate: string, pathParams: Array<{
|
|
|
224
228
|
name: string;
|
|
225
229
|
camelName: string;
|
|
226
230
|
}>) => ((args: Record<string, unknown>) => string);
|
|
231
|
+
/** Query parameter with the OpenAPI serialisation rules declared for it. */
|
|
232
|
+
type QueryParamSerialization = {
|
|
233
|
+
name: string;
|
|
234
|
+
camelName: string; /** OpenAPI `style` (`form`, `deepObject`, `spaceDelimited`, `pipeDelimited`). */
|
|
235
|
+
style?: string; /** OpenAPI `explode`. Defaults to `true` for `form`, `false` otherwise. */
|
|
236
|
+
explode?: boolean;
|
|
237
|
+
};
|
|
227
238
|
/**
|
|
228
239
|
* Builds a function that serialises query params into a query string
|
|
229
|
-
* (including the leading `?`)
|
|
230
|
-
*
|
|
240
|
+
* (including the leading `?`), honouring each param's OpenAPI `style` and
|
|
241
|
+
* `explode`. Returns `undefined` when the op has no query params.
|
|
231
242
|
*/
|
|
232
|
-
declare const buildQueryFn: (queryParams:
|
|
233
|
-
name: string;
|
|
234
|
-
camelName: string;
|
|
235
|
-
}>) => ((args: Record<string, unknown>) => string) | undefined;
|
|
243
|
+
declare const buildQueryFn: (queryParams: QueryParamSerialization[]) => ((args: Record<string, unknown>) => string) | undefined;
|
|
236
244
|
/**
|
|
237
245
|
* Builds a function that maps camelCase args back to a snake_case request
|
|
238
246
|
* body, skipping `undefined` args. Returns `undefined` when the op has no body.
|
|
@@ -296,6 +304,8 @@ declare const extractQueryParams: (args: {
|
|
|
296
304
|
description: string;
|
|
297
305
|
required: boolean;
|
|
298
306
|
type: string;
|
|
307
|
+
style?: string;
|
|
308
|
+
explode?: boolean;
|
|
299
309
|
}>;
|
|
300
310
|
/**
|
|
301
311
|
* snake_case names of every top-level property an operation's request schema
|
|
@@ -360,4 +370,4 @@ declare const openApiToToolDefinitions: (args: {
|
|
|
360
370
|
options?: OpenApiToToolsOptions;
|
|
361
371
|
}) => ToolDefinition[];
|
|
362
372
|
//#endregion
|
|
363
|
-
export { DEFAULT_EXCLUDE_EXTENSION, DEFAULT_SERVER_MANAGED_EXTENSION, type JsonSchemaProperty, type OpenApiSpec, type OpenApiToToolsOptions, type OperationSpec, type RegisterOpenApiToolsArgs, type RequestBodySpec, type ResolvedRequest, type ToolDefinition, buildBodyFn, buildInputSchema, buildPathFn, buildQueryFn, dereferenceSchema, extractAcceptedBodyFields, extractBodyProps, extractPathParams, extractQueryParams, getJsonSchemaType, openApiToToolDefinitions, operationIdToToolName, processOperation, processPath, registerOpenApiTools, resolveParameter, resolveSchema, snakeToCamel };
|
|
373
|
+
export { DEFAULT_EXCLUDE_EXTENSION, DEFAULT_SERVER_MANAGED_EXTENSION, type JsonSchemaProperty, type OpenApiSpec, type OpenApiToToolsOptions, type OperationSpec, type QueryParamSerialization, type RegisterOpenApiToolsArgs, type RequestBodySpec, type ResolvedRequest, type ToolDefinition, buildBodyFn, buildInputSchema, buildPathFn, buildQueryFn, dereferenceSchema, extractAcceptedBodyFields, extractBodyProps, extractPathParams, extractQueryParams, getJsonSchemaType, openApiToToolDefinitions, operationIdToToolName, processOperation, processPath, registerOpenApiTools, resolveParameter, resolveSchema, snakeToCamel };
|
package/dist/index.mjs
CHANGED
|
@@ -114,22 +114,108 @@ var buildPathFn = (pathTemplate, pathParams) => {
|
|
|
114
114
|
return result;
|
|
115
115
|
};
|
|
116
116
|
};
|
|
117
|
+
var NON_EXPLODED_DELIMITERS = {
|
|
118
|
+
form: ",",
|
|
119
|
+
spaceDelimited: " ",
|
|
120
|
+
pipeDelimited: "|"
|
|
121
|
+
};
|
|
122
|
+
var isRecord = value => {
|
|
123
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
124
|
+
};
|
|
125
|
+
/**
|
|
126
|
+
* Appends a `deepObject` value as bracketed keys — `filters[documentId][$eq]`.
|
|
127
|
+
* OpenAPI only defines one level, but the APIs that ask for `deepObject`
|
|
128
|
+
* (Strapi, Directus) nest, so nested objects and arrays recurse instead of
|
|
129
|
+
* being stringified into `[object Object]`.
|
|
130
|
+
*/
|
|
131
|
+
var appendDeepObject = args => {
|
|
132
|
+
if (args.value === void 0 || args.value === null) return;
|
|
133
|
+
if (Array.isArray(args.value)) {
|
|
134
|
+
for (const [index, item] of args.value.entries()) appendDeepObject({
|
|
135
|
+
search: args.search,
|
|
136
|
+
key: `${args.key}[${index}]`,
|
|
137
|
+
value: item
|
|
138
|
+
});
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (isRecord(args.value)) {
|
|
142
|
+
for (const [property, propertyValue] of Object.entries(args.value)) appendDeepObject({
|
|
143
|
+
search: args.search,
|
|
144
|
+
key: `${args.key}[${property}]`,
|
|
145
|
+
value: propertyValue
|
|
146
|
+
});
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
args.search.append(args.key, String(args.value));
|
|
150
|
+
};
|
|
151
|
+
var appendArrayValue = args => {
|
|
152
|
+
if (args.explode) {
|
|
153
|
+
for (const item of args.value) args.search.append(args.name, String(item));
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
args.search.append(args.name, args.value.map(String).join(args.delimiter));
|
|
157
|
+
};
|
|
158
|
+
var appendObjectValue = args => {
|
|
159
|
+
const entries = Object.entries(args.value).filter(([, entryValue]) => {
|
|
160
|
+
return entryValue !== void 0 && entryValue !== null;
|
|
161
|
+
});
|
|
162
|
+
if (args.explode) {
|
|
163
|
+
for (const [property, entryValue] of entries) args.search.append(property, String(entryValue));
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
args.search.append(args.name, entries.flatMap(([property, entryValue]) => {
|
|
167
|
+
return [property, String(entryValue)];
|
|
168
|
+
}).join(args.delimiter));
|
|
169
|
+
};
|
|
170
|
+
var appendQueryValue = args => {
|
|
171
|
+
const style = args.param.style ?? "form";
|
|
172
|
+
if (style === "deepObject") {
|
|
173
|
+
appendDeepObject({
|
|
174
|
+
search: args.search,
|
|
175
|
+
key: args.param.name,
|
|
176
|
+
value: args.value
|
|
177
|
+
});
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
const serialization = {
|
|
181
|
+
search: args.search,
|
|
182
|
+
name: args.param.name,
|
|
183
|
+
explode: args.param.explode ?? style === "form",
|
|
184
|
+
delimiter: NON_EXPLODED_DELIMITERS[style] ?? ","
|
|
185
|
+
};
|
|
186
|
+
if (Array.isArray(args.value)) {
|
|
187
|
+
appendArrayValue({
|
|
188
|
+
...serialization,
|
|
189
|
+
value: args.value
|
|
190
|
+
});
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
if (isRecord(args.value)) {
|
|
194
|
+
appendObjectValue({
|
|
195
|
+
...serialization,
|
|
196
|
+
value: args.value
|
|
197
|
+
});
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
args.search.append(args.param.name, String(args.value));
|
|
201
|
+
};
|
|
117
202
|
/**
|
|
118
203
|
* Builds a function that serialises query params into a query string
|
|
119
|
-
* (including the leading `?`)
|
|
120
|
-
*
|
|
204
|
+
* (including the leading `?`), honouring each param's OpenAPI `style` and
|
|
205
|
+
* `explode`. Returns `undefined` when the op has no query params.
|
|
121
206
|
*/
|
|
122
207
|
var buildQueryFn = queryParams => {
|
|
123
208
|
if (queryParams.length === 0) return void 0;
|
|
124
209
|
return args => {
|
|
125
210
|
const search = new URLSearchParams();
|
|
126
|
-
for (const {
|
|
127
|
-
|
|
128
|
-
camelName
|
|
129
|
-
} of queryParams) {
|
|
130
|
-
const value = args[camelName];
|
|
211
|
+
for (const param of queryParams) {
|
|
212
|
+
const value = args[param.camelName];
|
|
131
213
|
if (value === void 0 || value === null) continue;
|
|
132
|
-
|
|
214
|
+
appendQueryValue({
|
|
215
|
+
search,
|
|
216
|
+
param,
|
|
217
|
+
value
|
|
218
|
+
});
|
|
133
219
|
}
|
|
134
220
|
const qs = search.toString();
|
|
135
221
|
return qs ? `?${qs}` : "";
|
|
@@ -272,7 +358,9 @@ var extractQueryParams = args => {
|
|
|
272
358
|
camelName: snakeToCamel(p.name || ""),
|
|
273
359
|
description: p.description || "",
|
|
274
360
|
required: p.required || false,
|
|
275
|
-
type: p.schema?.type || "string"
|
|
361
|
+
type: p.schema?.type || "string",
|
|
362
|
+
style: p.style,
|
|
363
|
+
explode: p.explode
|
|
276
364
|
};
|
|
277
365
|
}));
|
|
278
366
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttoss/http-server-mcp-openapi",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.14",
|
|
4
4
|
"description": "Generate Model Context Protocol (MCP) tools from an OpenAPI specification for @ttoss/http-server-mcp",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
"jest": "^30.4.2",
|
|
43
43
|
"supertest": "^7.2.2",
|
|
44
44
|
"tsdown": "^0.22.2",
|
|
45
|
-
"@ttoss/
|
|
46
|
-
"@ttoss/
|
|
45
|
+
"@ttoss/config": "^1.38.0",
|
|
46
|
+
"@ttoss/http-server": "^0.8.1"
|
|
47
47
|
},
|
|
48
48
|
"publishConfig": {
|
|
49
49
|
"access": "public",
|