@sezzlee/openapi 0.0.0-stage → 0.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/LICENSE +21 -0
- package/README.md +108 -2
- package/dist/diagnostics.d.ts +61 -0
- package/dist/diagnostics.js +82 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +2 -0
- package/dist/ingest.d.ts +43 -0
- package/dist/ingest.js +80 -0
- package/dist/ir/brand.d.ts +13 -0
- package/dist/ir/brand.js +18 -0
- package/dist/ir/json.d.ts +14 -0
- package/dist/ir/json.js +14 -0
- package/dist/lower/body.d.ts +6 -0
- package/dist/lower/body.js +127 -0
- package/dist/lower/operations.d.ts +20 -0
- package/dist/lower/operations.js +212 -0
- package/dist/lower/parameters.d.ts +30 -0
- package/dist/lower/parameters.js +143 -0
- package/dist/lower/responses.d.ts +6 -0
- package/dist/lower/responses.js +63 -0
- package/dist/lower/security.d.ts +41 -0
- package/dist/lower/security.js +113 -0
- package/dist/lower/servers.d.ts +22 -0
- package/dist/lower/servers.js +50 -0
- package/dist/normalize/external.d.ts +9 -0
- package/dist/normalize/external.js +93 -0
- package/dist/normalize/refs.d.ts +15 -0
- package/dist/normalize/refs.js +49 -0
- package/dist/normalize/schema.d.ts +24 -0
- package/dist/normalize/schema.js +354 -0
- package/dist/parse/parse.d.ts +5 -0
- package/dist/parse/parse.js +40 -0
- package/dist/parse/swagger2.d.ts +11 -0
- package/dist/parse/swagger2.js +394 -0
- package/package.json +58 -3
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
import { childPointer, rootPointer } from "../ir/brand.js";
|
|
2
|
+
import { arrayOf, entriesOf, isObject, objectOf, stringOf, } from "../ir/json.js";
|
|
3
|
+
const methods = [
|
|
4
|
+
"get",
|
|
5
|
+
"put",
|
|
6
|
+
"post",
|
|
7
|
+
"delete",
|
|
8
|
+
"options",
|
|
9
|
+
"head",
|
|
10
|
+
"patch",
|
|
11
|
+
];
|
|
12
|
+
const schemaKeys = [
|
|
13
|
+
"type",
|
|
14
|
+
"format",
|
|
15
|
+
"items",
|
|
16
|
+
"enum",
|
|
17
|
+
"default",
|
|
18
|
+
"minimum",
|
|
19
|
+
"maximum",
|
|
20
|
+
"exclusiveMinimum",
|
|
21
|
+
"exclusiveMaximum",
|
|
22
|
+
"minLength",
|
|
23
|
+
"maxLength",
|
|
24
|
+
"pattern",
|
|
25
|
+
"minItems",
|
|
26
|
+
"maxItems",
|
|
27
|
+
"uniqueItems",
|
|
28
|
+
"multipleOf",
|
|
29
|
+
];
|
|
30
|
+
function located(context, node, at) {
|
|
31
|
+
context.origins.set(node, at);
|
|
32
|
+
return node;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Rewrites every 2.0 reference target to its 3.x home. `#/parameters` and `#/responses` point at
|
|
36
|
+
* 2.0 shapes that are converted in place under the same names, so their references move with them.
|
|
37
|
+
*/
|
|
38
|
+
function rewriteRefs(value) {
|
|
39
|
+
if (Array.isArray(value)) {
|
|
40
|
+
return value.map(rewriteRefs);
|
|
41
|
+
}
|
|
42
|
+
if (!isObject(value)) {
|
|
43
|
+
return value;
|
|
44
|
+
}
|
|
45
|
+
const out = {};
|
|
46
|
+
for (const [key, child] of entriesOf(value)) {
|
|
47
|
+
if (key === "$ref" && typeof child === "string") {
|
|
48
|
+
out[key] = child
|
|
49
|
+
.replace(/^#\/definitions\//, "#/components/schemas/")
|
|
50
|
+
.replace(/^#\/parameters\//, "#/components/parameters/")
|
|
51
|
+
.replace(/^#\/responses\//, "#/components/responses/");
|
|
52
|
+
}
|
|
53
|
+
else if (key === "x-nullable" && child === true) {
|
|
54
|
+
out["nullable"] = true;
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
out[key] = rewriteRefs(child);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (out["type"] === "file") {
|
|
61
|
+
out["type"] = "string";
|
|
62
|
+
out["format"] = "binary";
|
|
63
|
+
}
|
|
64
|
+
return out;
|
|
65
|
+
}
|
|
66
|
+
function resolveParameter(context, parameter) {
|
|
67
|
+
const node = objectOf(parameter);
|
|
68
|
+
const ref = stringOf(node?.["$ref"]);
|
|
69
|
+
if (ref === undefined) {
|
|
70
|
+
return node;
|
|
71
|
+
}
|
|
72
|
+
const name = /^#\/parameters\/(.+)$/.exec(ref)?.[1];
|
|
73
|
+
return name === undefined
|
|
74
|
+
? undefined
|
|
75
|
+
: objectOf(objectOf(context.document["parameters"])?.[name]);
|
|
76
|
+
}
|
|
77
|
+
function styleFor(location, collectionFormat, context, at) {
|
|
78
|
+
switch (collectionFormat ?? "csv") {
|
|
79
|
+
case "csv":
|
|
80
|
+
return location === "path" || location === "header"
|
|
81
|
+
? { style: "simple", explode: false }
|
|
82
|
+
: { style: "form", explode: false };
|
|
83
|
+
case "ssv":
|
|
84
|
+
if (location === "query") {
|
|
85
|
+
return { style: "spaceDelimited", explode: false };
|
|
86
|
+
}
|
|
87
|
+
break;
|
|
88
|
+
case "pipes":
|
|
89
|
+
if (location === "query") {
|
|
90
|
+
return { style: "pipeDelimited", explode: false };
|
|
91
|
+
}
|
|
92
|
+
break;
|
|
93
|
+
case "multi":
|
|
94
|
+
if (location === "query") {
|
|
95
|
+
return { style: "form", explode: true };
|
|
96
|
+
}
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
context.diagnostics.report("unsupported_collection_format", at, `collectionFormat '${collectionFormat ?? "csv"}' has no ${location} form.`);
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
function schemaOfSimple(node) {
|
|
103
|
+
const schema = {};
|
|
104
|
+
for (const key of schemaKeys) {
|
|
105
|
+
if (node[key] !== undefined) {
|
|
106
|
+
schema[key] = rewriteRefs(node[key]);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return schema;
|
|
110
|
+
}
|
|
111
|
+
function upgradeParameter(context, parameter, at) {
|
|
112
|
+
const location = stringOf(parameter["in"]) ?? "query";
|
|
113
|
+
const out = {
|
|
114
|
+
name: parameter["name"],
|
|
115
|
+
in: location,
|
|
116
|
+
...(parameter["required"] === undefined
|
|
117
|
+
? {}
|
|
118
|
+
: { required: parameter["required"] }),
|
|
119
|
+
...(parameter["description"] === undefined
|
|
120
|
+
? {}
|
|
121
|
+
: { description: parameter["description"] }),
|
|
122
|
+
schema: schemaOfSimple(parameter),
|
|
123
|
+
};
|
|
124
|
+
if (parameter["allowEmptyValue"] !== undefined) {
|
|
125
|
+
out["allowEmptyValue"] = parameter["allowEmptyValue"];
|
|
126
|
+
}
|
|
127
|
+
if (parameter["type"] === "array") {
|
|
128
|
+
const style = styleFor(location, stringOf(parameter["collectionFormat"]), context, at);
|
|
129
|
+
if (style === undefined) {
|
|
130
|
+
return "drop";
|
|
131
|
+
}
|
|
132
|
+
Object.assign(out, style);
|
|
133
|
+
}
|
|
134
|
+
return located(context, out, at);
|
|
135
|
+
}
|
|
136
|
+
function upgradeParameters(context, parameters, consumes, at) {
|
|
137
|
+
const out = [];
|
|
138
|
+
const form = { type: "object", properties: {} };
|
|
139
|
+
const formRequired = [];
|
|
140
|
+
let hasFormField = false;
|
|
141
|
+
let hasFile = false;
|
|
142
|
+
let requestBody;
|
|
143
|
+
let dropped = false;
|
|
144
|
+
parameters.forEach((raw, index) => {
|
|
145
|
+
const parameterAt = childPointer(at, index);
|
|
146
|
+
const parameter = resolveParameter(context, raw);
|
|
147
|
+
if (parameter === undefined) {
|
|
148
|
+
out.push(rewriteRefs(raw));
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const location = stringOf(parameter["in"]);
|
|
152
|
+
if (location === "body") {
|
|
153
|
+
const content = {};
|
|
154
|
+
for (const mediaType of consumes) {
|
|
155
|
+
content[mediaType] = {
|
|
156
|
+
schema: rewriteRefs(parameter["schema"] ?? {}),
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
requestBody = located(context, {
|
|
160
|
+
content,
|
|
161
|
+
required: parameter["required"] === true,
|
|
162
|
+
...(parameter["description"] === undefined
|
|
163
|
+
? {}
|
|
164
|
+
: { description: parameter["description"] }),
|
|
165
|
+
}, parameterAt);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
if (location === "formData") {
|
|
169
|
+
hasFormField = true;
|
|
170
|
+
const name = stringOf(parameter["name"]) ?? "";
|
|
171
|
+
const schema = schemaOfSimple(parameter);
|
|
172
|
+
if (schema["type"] === "file") {
|
|
173
|
+
hasFile = true;
|
|
174
|
+
schema["type"] = "string";
|
|
175
|
+
schema["format"] = "binary";
|
|
176
|
+
}
|
|
177
|
+
const collectionFormat = stringOf(parameter["collectionFormat"]);
|
|
178
|
+
if (parameter["type"] === "array" &&
|
|
179
|
+
collectionFormat !== undefined &&
|
|
180
|
+
collectionFormat !== "multi") {
|
|
181
|
+
context.diagnostics.report("unsupported_encoding", parameterAt, `A form field with collectionFormat '${collectionFormat}' has no form-body writer; only repeated keys are written.`);
|
|
182
|
+
dropped = true;
|
|
183
|
+
}
|
|
184
|
+
form["properties"][name] = located(context, schema, parameterAt);
|
|
185
|
+
if (parameter["required"] === true) {
|
|
186
|
+
formRequired.push(name);
|
|
187
|
+
}
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
const upgraded = upgradeParameter(context, parameter, parameterAt);
|
|
191
|
+
if (upgraded === "drop") {
|
|
192
|
+
dropped = true;
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
out.push(upgraded);
|
|
196
|
+
});
|
|
197
|
+
if (hasFormField) {
|
|
198
|
+
const mediaType = hasFile || consumes.includes("multipart/form-data")
|
|
199
|
+
? "multipart/form-data"
|
|
200
|
+
: "application/x-www-form-urlencoded";
|
|
201
|
+
if (formRequired.length > 0) {
|
|
202
|
+
form["required"] = formRequired;
|
|
203
|
+
}
|
|
204
|
+
requestBody = {
|
|
205
|
+
content: { [mediaType]: { schema: form } },
|
|
206
|
+
required: formRequired.length > 0,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
return {
|
|
210
|
+
parameters: out,
|
|
211
|
+
...(requestBody === undefined ? {} : { requestBody }),
|
|
212
|
+
dropped,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
function upgradeResponses(context, responses, produces, at) {
|
|
216
|
+
const out = {};
|
|
217
|
+
for (const [code, raw] of entriesOf(responses)) {
|
|
218
|
+
const response = objectOf(raw);
|
|
219
|
+
if (response === undefined) {
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
if (stringOf(response["$ref"]) !== undefined) {
|
|
223
|
+
out[code] = rewriteRefs(response);
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
const converted = {
|
|
227
|
+
description: response["description"] ?? "",
|
|
228
|
+
};
|
|
229
|
+
if (response["schema"] !== undefined) {
|
|
230
|
+
const content = {};
|
|
231
|
+
for (const mediaType of produces) {
|
|
232
|
+
content[mediaType] = { schema: rewriteRefs(response["schema"]) };
|
|
233
|
+
}
|
|
234
|
+
converted["content"] = content;
|
|
235
|
+
}
|
|
236
|
+
out[code] = located(context, converted, childPointer(at, code));
|
|
237
|
+
}
|
|
238
|
+
return out;
|
|
239
|
+
}
|
|
240
|
+
function upgradeSecuritySchemes(definitions) {
|
|
241
|
+
const out = {};
|
|
242
|
+
for (const [name, raw] of entriesOf(definitions)) {
|
|
243
|
+
const scheme = objectOf(raw);
|
|
244
|
+
if (scheme === undefined) {
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
switch (stringOf(scheme["type"])) {
|
|
248
|
+
case "basic":
|
|
249
|
+
out[name] = { type: "http", scheme: "basic" };
|
|
250
|
+
break;
|
|
251
|
+
case "apiKey":
|
|
252
|
+
out[name] = { type: "apiKey", in: scheme["in"], name: scheme["name"] };
|
|
253
|
+
break;
|
|
254
|
+
case "oauth2": {
|
|
255
|
+
const flow = {
|
|
256
|
+
implicit: "implicit",
|
|
257
|
+
password: "password",
|
|
258
|
+
application: "clientCredentials",
|
|
259
|
+
accessCode: "authorizationCode",
|
|
260
|
+
}[stringOf(scheme["flow"]) ?? ""] ?? "clientCredentials";
|
|
261
|
+
out[name] = {
|
|
262
|
+
type: "oauth2",
|
|
263
|
+
flows: {
|
|
264
|
+
[flow]: {
|
|
265
|
+
...(scheme["authorizationUrl"] === undefined
|
|
266
|
+
? {}
|
|
267
|
+
: { authorizationUrl: scheme["authorizationUrl"] }),
|
|
268
|
+
...(scheme["tokenUrl"] === undefined
|
|
269
|
+
? {}
|
|
270
|
+
: { tokenUrl: scheme["tokenUrl"] }),
|
|
271
|
+
scopes: scheme["scopes"] ?? {},
|
|
272
|
+
},
|
|
273
|
+
},
|
|
274
|
+
};
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return out;
|
|
280
|
+
}
|
|
281
|
+
function serversOf(document) {
|
|
282
|
+
const basePath = stringOf(document["basePath"]) ?? "";
|
|
283
|
+
const host = stringOf(document["host"]);
|
|
284
|
+
if (host === undefined) {
|
|
285
|
+
return [{ url: basePath === "" ? "/" : basePath }];
|
|
286
|
+
}
|
|
287
|
+
const schemes = arrayOf(document["schemes"])
|
|
288
|
+
.map(stringOf)
|
|
289
|
+
.filter((scheme) => scheme !== undefined);
|
|
290
|
+
const ordered = schemes.length === 0 ? ["https"] : schemes;
|
|
291
|
+
return [...ordered]
|
|
292
|
+
.sort((a, b) => Number(b === "https") - Number(a === "https"))
|
|
293
|
+
.map((scheme) => ({ url: `${scheme}://${host}${basePath}` }));
|
|
294
|
+
}
|
|
295
|
+
const mediaTypes = (value) => {
|
|
296
|
+
const list = arrayOf(value)
|
|
297
|
+
.map(stringOf)
|
|
298
|
+
.filter((item) => item !== undefined);
|
|
299
|
+
return list.length === 0 ? undefined : list;
|
|
300
|
+
};
|
|
301
|
+
/**
|
|
302
|
+
* Converts a Swagger 2.0 document to the OpenAPI 3 shape the rest of ingestion reads, following
|
|
303
|
+
* swagger2openapi's rules. Nodes that move are recorded in `origins` so a diagnostic still points
|
|
304
|
+
* into the author's document.
|
|
305
|
+
*/
|
|
306
|
+
export function upgradeSwagger2(document, diagnostics, origins) {
|
|
307
|
+
const context = { document, diagnostics, origins };
|
|
308
|
+
const rootConsumes = mediaTypes(document["consumes"]) ?? ["application/json"];
|
|
309
|
+
const rootProduces = mediaTypes(document["produces"]) ?? ["application/json"];
|
|
310
|
+
const componentParameters = {};
|
|
311
|
+
for (const [name, raw] of entriesOf(document["parameters"])) {
|
|
312
|
+
const parameter = objectOf(raw);
|
|
313
|
+
const location = stringOf(parameter?.["in"]);
|
|
314
|
+
if (parameter !== undefined &&
|
|
315
|
+
location !== "body" &&
|
|
316
|
+
location !== "formData") {
|
|
317
|
+
const upgraded = upgradeParameter(context, parameter, childPointer(rootPointer, "parameters", name));
|
|
318
|
+
if (upgraded !== "drop") {
|
|
319
|
+
componentParameters[name] = upgraded;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
const paths = {};
|
|
324
|
+
for (const [path, rawItem] of entriesOf(document["paths"])) {
|
|
325
|
+
const item = objectOf(rawItem);
|
|
326
|
+
if (item === undefined) {
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
const itemAt = childPointer(rootPointer, "paths", path);
|
|
330
|
+
const shared = arrayOf(item["parameters"]);
|
|
331
|
+
const converted = {};
|
|
332
|
+
for (const method of methods) {
|
|
333
|
+
const operation = objectOf(item[method]);
|
|
334
|
+
if (operation === undefined) {
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
337
|
+
const operationAt = childPointer(itemAt, method);
|
|
338
|
+
const consumes = mediaTypes(operation["consumes"]) ?? rootConsumes;
|
|
339
|
+
const produces = mediaTypes(operation["produces"]) ?? rootProduces;
|
|
340
|
+
const own = arrayOf(operation["parameters"]);
|
|
341
|
+
const ownKeys = new Set(own
|
|
342
|
+
.map((parameter) => resolveParameter(context, parameter))
|
|
343
|
+
.map((parameter) => parameter === undefined
|
|
344
|
+
? ""
|
|
345
|
+
: `${stringOf(parameter["in"])}|${stringOf(parameter["name"])}`));
|
|
346
|
+
const inherited = shared.filter((parameter) => {
|
|
347
|
+
const resolved = resolveParameter(context, parameter);
|
|
348
|
+
return (resolved === undefined ||
|
|
349
|
+
!ownKeys.has(`${stringOf(resolved["in"])}|${stringOf(resolved["name"])}`));
|
|
350
|
+
});
|
|
351
|
+
const upgraded = upgradeParameters(context, [...inherited, ...own], consumes, childPointer(operationAt, "parameters"));
|
|
352
|
+
const out = {};
|
|
353
|
+
for (const [key, value] of entriesOf(operation)) {
|
|
354
|
+
if (key === "parameters" ||
|
|
355
|
+
key === "consumes" ||
|
|
356
|
+
key === "produces" ||
|
|
357
|
+
key === "responses" ||
|
|
358
|
+
key === "schemes") {
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
361
|
+
out[key] = rewriteRefs(value);
|
|
362
|
+
}
|
|
363
|
+
out["parameters"] = upgraded.parameters;
|
|
364
|
+
if (upgraded.requestBody !== undefined) {
|
|
365
|
+
out["requestBody"] = upgraded.requestBody;
|
|
366
|
+
}
|
|
367
|
+
out["responses"] = upgradeResponses(context, operation["responses"], produces, childPointer(operationAt, "responses"));
|
|
368
|
+
if (upgraded.dropped) {
|
|
369
|
+
out["x-sezzlee-dropped"] = true;
|
|
370
|
+
}
|
|
371
|
+
converted[method] = located(context, out, operationAt);
|
|
372
|
+
}
|
|
373
|
+
paths[path] = located(context, converted, itemAt);
|
|
374
|
+
}
|
|
375
|
+
const componentResponses = {};
|
|
376
|
+
const upgradedResponses = upgradeResponses(context, document["responses"], rootProduces, childPointer(rootPointer, "responses"));
|
|
377
|
+
Object.assign(componentResponses, upgradedResponses);
|
|
378
|
+
return {
|
|
379
|
+
openapi: "3.0.3",
|
|
380
|
+
info: document["info"] ?? {},
|
|
381
|
+
servers: serversOf(document),
|
|
382
|
+
paths,
|
|
383
|
+
components: {
|
|
384
|
+
schemas: rewriteRefs(document["definitions"] ?? {}),
|
|
385
|
+
parameters: componentParameters,
|
|
386
|
+
responses: componentResponses,
|
|
387
|
+
securitySchemes: upgradeSecuritySchemes(document["securityDefinitions"]),
|
|
388
|
+
},
|
|
389
|
+
...(document["security"] === undefined
|
|
390
|
+
? {}
|
|
391
|
+
: { security: document["security"] }),
|
|
392
|
+
...(document["tags"] === undefined ? {} : { tags: document["tags"] }),
|
|
393
|
+
};
|
|
394
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,61 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sezzlee/openapi",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Ingests a Swagger 2.0 or OpenAPI 3.0–3.2 document into the endpoint descriptors the sezzlee catalog is built from.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"mcp",
|
|
7
|
+
"model-context-protocol",
|
|
8
|
+
"sezzlee",
|
|
9
|
+
"openapi",
|
|
10
|
+
"swagger",
|
|
11
|
+
"agents",
|
|
12
|
+
"typescript"
|
|
13
|
+
],
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "git+https://github.com/sezzlee/mcp.git",
|
|
18
|
+
"directory": "packages/http/openapi"
|
|
19
|
+
},
|
|
20
|
+
"homepage": "https://github.com/sezzlee/mcp/tree/main/packages/http/openapi#readme",
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/sezzlee/mcp/issues"
|
|
23
|
+
},
|
|
24
|
+
"type": "module",
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=22"
|
|
27
|
+
},
|
|
28
|
+
"main": "./dist/index.js",
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"exports": {
|
|
31
|
+
".": {
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"default": "./dist/index.js"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"dist"
|
|
38
|
+
],
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@sezzlee/core": "^0.2.0",
|
|
44
|
+
"yaml": "^2.9.1"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@sezzlee/oxlint-config": "0.0.0",
|
|
48
|
+
"@sezzlee/typescript-config": "0.0.0",
|
|
49
|
+
"@types/node": "^24.3.0",
|
|
50
|
+
"oxlint": "1.85.0",
|
|
51
|
+
"typescript": "7.0.2",
|
|
52
|
+
"vitest": "^3.2.4"
|
|
53
|
+
},
|
|
54
|
+
"scripts": {
|
|
55
|
+
"build": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\" && tsc",
|
|
56
|
+
"dev": "tsc --watch",
|
|
57
|
+
"lint": "oxlint --deny-warnings",
|
|
58
|
+
"check-types": "tsc -p tsconfig.test.json",
|
|
59
|
+
"test": "vitest run"
|
|
60
|
+
}
|
|
6
61
|
}
|