@optique/inquirer 1.2.0-dev.2187 → 1.2.0-dev.2192

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/index.js CHANGED
@@ -1,8 +1,6 @@
1
1
  import { Separator, checkbox, confirm, editor, expand, input, number, password, rawlist, select } from "@inquirer/prompts";
2
- import { getAnnotations } from "@optique/core/annotations";
3
- import { defineTraits, delegateSuggestNodes, getTraits, inheritAnnotations, injectAnnotations, mapSourceMetadata, unwrapInjectedAnnotationState, withAnnotationView } from "@optique/core/extension";
4
- import { fluent } from "@optique/core/fluent";
5
2
  import { message } from "@optique/core/message";
3
+ import { createPromptAdapter } from "@optique/prompt";
6
4
 
7
5
  //#region src/index.ts
8
6
  const promptFunctionsOverrideSymbol = Symbol.for("@optique/inquirer/prompt-functions");
@@ -48,406 +46,146 @@ function getPromptFunctions() {
48
46
  function isExitPromptError(error) {
49
47
  return typeof error === "object" && error != null && "name" in error && error.name === "ExitPromptError";
50
48
  }
51
- function shouldDeferPrompt(parser, state, exec) {
52
- return typeof parser.shouldDeferCompletion === "function" && parser.shouldDeferCompletion(state, exec) === true;
53
- }
54
- function deferredPromptResult(placeholderValue) {
55
- if (placeholderValue == null || typeof placeholderValue !== "object") return {
56
- success: true,
57
- value: placeholderValue,
58
- deferred: true
59
- };
60
- const isArray = Array.isArray(placeholderValue);
61
- const keys = /* @__PURE__ */ new Map();
62
- for (const key of Reflect.ownKeys(placeholderValue)) {
63
- if (isArray && key === "length") continue;
64
- keys.set(key, null);
65
- }
66
- return {
67
- success: true,
68
- value: placeholderValue,
69
- deferred: true,
70
- deferredKeys: keys
71
- };
72
- }
73
- function withAnnotatedInnerState(sourceState, innerState, run) {
74
- const annotations = getAnnotations(sourceState);
75
- if (annotations == null || innerState == null || typeof innerState !== "object" || getAnnotations(innerState) != null) return run(innerState);
76
- const inheritedState = inheritAnnotations(sourceState, innerState);
77
- if (inheritedState !== innerState) return run(inheritedState);
78
- return run(withAnnotationView(innerState, annotations));
79
- }
49
+ const validPromptTypes = new Set([
50
+ "confirm",
51
+ "number",
52
+ "input",
53
+ "password",
54
+ "editor",
55
+ "select",
56
+ "rawlist",
57
+ "expand",
58
+ "checkbox"
59
+ ]);
80
60
  /**
81
61
  * Wraps a parser with an interactive Inquirer.js prompt fallback.
82
62
  *
83
- * When the inner parser finds a value in the CLI arguments (consumed tokens),
84
- * that value is used directly. When no CLI value is found, an interactive
85
- * prompt is shown to the user.
86
- *
87
- * The returned parser always has `mode: "async"` because Inquirer.js prompts
88
- * are inherently asynchronous.
89
- *
90
- * Example:
91
- *
92
- * ```typescript
93
- * import { option } from "@optique/core/primitives";
94
- * import { string } from "@optique/core/valueparser";
95
- * import { prompt } from "@optique/inquirer";
96
- *
97
- * const nameParser = prompt(option("--name", string()), {
98
- * type: "input",
99
- * message: "Enter your name:",
100
- * });
101
- * ```
63
+ * When the inner parser finds a value in the CLI arguments, that value is used
64
+ * directly. When no CLI value is found, an interactive prompt is shown to the
65
+ * user.
102
66
  *
103
67
  * @param parser Inner parser that reads CLI values.
104
68
  * @param config Type-safe Inquirer.js prompt configuration.
105
69
  * @returns A parser with interactive prompt fallback, always in async mode.
106
- * @throws {Error} If prompt execution fails with an unexpected error or if
107
- * the inner parser throws while parsing or completing.
70
+ * @throws {Error} If prompt execution fails with an unexpected error or if the
71
+ * inner parser throws while parsing or completing.
108
72
  * @since 1.0.0
109
73
  */
110
74
  function prompt(parser, config) {
111
- const promptBindStateKey = Symbol("@optique/inquirer/promptState");
112
- function isPromptBindState(value) {
113
- return value != null && typeof value === "object" && promptBindStateKey in value;
114
- }
75
+ const promptWithAdapter = createPromptAdapter({
76
+ execute: (cfg) => executePromptRaw(cfg),
77
+ getDefaultValue: getConfigDefault
78
+ });
79
+ return promptWithAdapter(parser, config);
80
+ }
81
+ function getConfigDefault(config) {
82
+ if (config != null && typeof config === "object" && "default" in config) return config.default;
83
+ return void 0;
84
+ }
85
+ async function executePromptRaw(config) {
115
86
  const cfg = config;
116
- function shouldAttemptInnerCompletion(cliState, state) {
117
- if (cliState == null) return false;
118
- const cliStateHasAnnotations = getAnnotations(cliState) != null;
119
- if (cliStateHasAnnotations) return true;
120
- if (getAnnotations(state) == null || typeof cliState !== "object") return false;
121
- if ("hasCliValue" in cliState) return true;
122
- if (Array.isArray(cliState)) return typeof parser.shouldDeferCompletion === "function";
123
- const prototype = Object.getPrototypeOf(cliState);
124
- return prototype !== Object.prototype && prototype !== null;
125
- }
126
- function hasSourceBindingMarker(state) {
127
- return state != null && typeof state === "object" && "hasCliValue" in state && Object.getOwnPropertySymbols(state).length > 0;
128
- }
129
- function shouldCompleteFromSourceBinding(cliState, state) {
130
- const cliStateIsInjectedAnnotationWrapper = cliState != null && typeof cliState === "object" && unwrapInjectedAnnotationState(cliState) !== cliState;
131
- const requiresSourceBindingForAnnotationWrapper = getTraits(parser).requiresSourceBinding === true;
132
- const hasNestedSourceBinding = hasSourceBindingMarker(cliState) || Array.isArray(cliState) && cliState.length === 1 && (hasSourceBindingMarker(cliState[0]) || cliState[0] != null && typeof cliState[0] === "object" && getAnnotations(cliState[0]) != null);
133
- if (cliStateIsInjectedAnnotationWrapper && requiresSourceBindingForAnnotationWrapper) return hasNestedSourceBinding;
134
- return shouldAttemptInnerCompletion(cliState, state) || hasNestedSourceBinding;
135
- }
136
- /**
137
- * Executes the configured prompt and normalizes its result.
138
- *
139
- * Converts `ExitPromptError` into a parse failure and returns prompt values
140
- * in Optique's `ValueParserResult` shape.
141
- *
142
- * @returns The normalized prompt result.
143
- * @throws {Error} Rethrows unexpected prompt failures after converting
144
- * `ExitPromptError` cancellations into parse failures.
145
- */
146
- function validatePromptedValue(result) {
147
- return result;
148
- }
149
- const validPromptTypes = new Set([
150
- "confirm",
151
- "number",
152
- "input",
153
- "password",
154
- "editor",
155
- "select",
156
- "rawlist",
157
- "expand",
158
- "checkbox"
159
- ]);
160
- async function executePromptRaw() {
161
- const prompts = getPromptFunctions();
162
- try {
163
- if (!validPromptTypes.has(cfg.type)) throw new TypeError(`Unsupported prompt type: ${cfg.type}`);
164
- if ("prompter" in cfg && cfg.prompter != null) {
165
- const value = await cfg.prompter();
166
- if (cfg.type === "number" && value === void 0) return {
87
+ const prompts = getPromptFunctions();
88
+ try {
89
+ if (!validPromptTypes.has(cfg.type)) throw new TypeError(`Unsupported prompt type: ${cfg.type}`);
90
+ if ("prompter" in cfg && cfg.prompter != null) {
91
+ const value = await cfg.prompter();
92
+ if (cfg.type === "number" && value === void 0) return {
93
+ success: false,
94
+ error: message`No number provided.`
95
+ };
96
+ return {
97
+ success: true,
98
+ value
99
+ };
100
+ }
101
+ switch (cfg.type) {
102
+ case "confirm": return {
103
+ success: true,
104
+ value: await prompts.confirm({
105
+ message: cfg.message,
106
+ ...cfg.default !== void 0 ? { default: cfg.default } : {}
107
+ })
108
+ };
109
+ case "number": {
110
+ const numResult = await prompts.number({
111
+ message: cfg.message,
112
+ ...cfg.default !== void 0 ? { default: cfg.default } : {},
113
+ ...cfg.min !== void 0 ? { min: cfg.min } : {},
114
+ ...cfg.max !== void 0 ? { max: cfg.max } : {},
115
+ ...cfg.step !== void 0 ? { step: cfg.step } : {}
116
+ });
117
+ if (numResult === void 0) return {
167
118
  success: false,
168
119
  error: message`No number provided.`
169
120
  };
170
121
  return {
171
122
  success: true,
172
- value
123
+ value: numResult
173
124
  };
174
125
  }
175
- switch (cfg.type) {
176
- case "confirm": return {
177
- success: true,
178
- value: await prompts.confirm({
179
- message: cfg.message,
180
- ...cfg.default !== void 0 ? { default: cfg.default } : {}
181
- })
182
- };
183
- case "number": {
184
- const numResult = await prompts.number({
185
- message: cfg.message,
186
- ...cfg.default !== void 0 ? { default: cfg.default } : {},
187
- ...cfg.min !== void 0 ? { min: cfg.min } : {},
188
- ...cfg.max !== void 0 ? { max: cfg.max } : {},
189
- ...cfg.step !== void 0 ? { step: cfg.step } : {}
190
- });
191
- if (numResult === void 0) return {
192
- success: false,
193
- error: message`No number provided.`
194
- };
195
- return {
196
- success: true,
197
- value: numResult
198
- };
199
- }
200
- case "input": return {
201
- success: true,
202
- value: await prompts.input({
203
- message: cfg.message,
204
- ...cfg.default !== void 0 ? { default: cfg.default } : {},
205
- ...cfg.validate !== void 0 ? { validate: cfg.validate } : {}
206
- })
207
- };
208
- case "password": return {
209
- success: true,
210
- value: await prompts.password({
211
- message: cfg.message,
212
- ...cfg.mask !== void 0 ? { mask: cfg.mask } : {},
213
- ...cfg.validate !== void 0 ? { validate: cfg.validate } : {}
214
- })
215
- };
216
- case "editor": return {
217
- success: true,
218
- value: await prompts.editor({
219
- message: cfg.message,
220
- ...cfg.default !== void 0 ? { default: cfg.default } : {},
221
- ...cfg.validate !== void 0 ? { validate: cfg.validate } : {}
222
- })
223
- };
224
- case "select": return {
225
- success: true,
226
- value: await prompts.select({
227
- message: cfg.message,
228
- choices: normalizeChoices(cfg.choices),
229
- ...cfg.default !== void 0 ? { default: cfg.default } : {}
230
- })
231
- };
232
- case "rawlist": return {
233
- success: true,
234
- value: await prompts.rawlist({
235
- message: cfg.message,
236
- choices: normalizeChoices(cfg.choices),
237
- ...cfg.default !== void 0 ? { default: cfg.default } : {}
238
- })
239
- };
240
- case "expand": return {
241
- success: true,
242
- value: await prompts.expand({
243
- message: cfg.message,
244
- choices: cfg.choices,
245
- ...cfg.default !== void 0 ? { default: cfg.default } : {}
246
- })
247
- };
248
- case "checkbox": return {
249
- success: true,
250
- value: await prompts.checkbox({
251
- message: cfg.message,
252
- choices: normalizeChoices(cfg.choices)
253
- })
254
- };
255
- }
256
- } catch (error) {
257
- if (isExitPromptError(error)) return {
258
- success: false,
259
- error: message`Prompt cancelled.`
126
+ case "input": return {
127
+ success: true,
128
+ value: await prompts.input({
129
+ message: cfg.message,
130
+ ...cfg.default !== void 0 ? { default: cfg.default } : {},
131
+ ...cfg.validate !== void 0 ? { validate: cfg.validate } : {}
132
+ })
260
133
  };
261
- throw error;
262
- }
263
- }
264
- async function executePrompt() {
265
- const result = await executePromptRaw();
266
- return validatePromptedValue(result);
267
- }
268
- const promptedParser = {
269
- mode: "async",
270
- $valueType: parser.$valueType,
271
- $stateType: parser.$stateType,
272
- priority: parser.priority,
273
- usage: parser.usage.length === 1 && parser.usage[0].type === "optional" ? parser.usage : [{
274
- type: "optional",
275
- terms: parser.usage
276
- }],
277
- leadingNames: parser.leadingNames,
278
- acceptingAnyToken: parser.acceptingAnyToken,
279
- shouldDeferCompletion(state) {
280
- return !isPromptBindState(state) || !state.hasCliValue;
281
- },
282
- getSuggestRuntimeNodes(state, path) {
283
- const innerState = isPromptBindState(state) ? state.cliState === void 0 ? parser.initialState : state.cliState : state;
284
- return delegateSuggestNodes(parser, promptedParser, state, path, innerState, "prepend");
285
- },
286
- initialState: {
287
- [promptBindStateKey]: true,
288
- hasCliValue: false
289
- },
290
- parse: (context) => {
291
- const annotations = getAnnotations(context.state);
292
- const innerState = isPromptBindState(context.state) ? context.state.hasCliValue ? context.state.cliState : parser.initialState : context.state;
293
- const baseInnerContext = innerState !== context.state ? {
294
- ...context,
295
- state: innerState
296
- } : context;
297
- const effectiveInnerState = annotations != null && innerState == null && getTraits(parser).inheritsAnnotations === true ? injectAnnotations(innerState, annotations) : innerState;
298
- const processResult = (result$1) => {
299
- if (result$1.success) {
300
- const cliState = annotations != null && result$1.next.state != null && typeof result$1.next.state === "object" && getAnnotations(result$1.next.state) !== annotations ? injectAnnotations(result$1.next.state, annotations) : result$1.next.state;
301
- const cliConsumed = result$1.consumed.length > 0;
302
- const nextState$1 = injectAnnotations({
303
- [promptBindStateKey]: true,
304
- hasCliValue: cliConsumed,
305
- cliState
306
- }, annotations);
307
- return {
308
- success: true,
309
- ...result$1.provisional ? { provisional: true } : {},
310
- next: {
311
- ...result$1.next,
312
- state: nextState$1
313
- },
314
- consumed: result$1.consumed
315
- };
316
- }
317
- if (result$1.consumed > 0) return result$1;
318
- const nextState = injectAnnotations({
319
- [promptBindStateKey]: true,
320
- hasCliValue: false
321
- }, annotations);
322
- return {
323
- success: true,
324
- next: {
325
- ...baseInnerContext,
326
- state: nextState
327
- },
328
- consumed: []
329
- };
134
+ case "password": return {
135
+ success: true,
136
+ value: await prompts.password({
137
+ message: cfg.message,
138
+ ...cfg.mask !== void 0 ? { mask: cfg.mask } : {},
139
+ ...cfg.validate !== void 0 ? { validate: cfg.validate } : {}
140
+ })
330
141
  };
331
- const result = withAnnotatedInnerState(context.state, effectiveInnerState, (annotatedInnerState) => {
332
- const innerContext = annotatedInnerState !== context.state ? {
333
- ...context,
334
- state: annotatedInnerState
335
- } : context;
336
- return parser.parse(innerContext);
337
- });
338
- if (result instanceof Promise) return result.then(processResult);
339
- return Promise.resolve(processResult(result));
340
- },
341
- complete: (state, exec) => {
342
- if (isPromptBindState(state) && state.hasCliValue) {
343
- const r = withAnnotatedInnerState(state, state.cliState, (annotatedInnerState) => parser.complete(annotatedInnerState, exec));
344
- if (r instanceof Promise) return r;
345
- return Promise.resolve(r);
346
- }
347
- const isProbe = exec != null && exec.phase !== "complete";
348
- const annotations = getAnnotations(state);
349
- const innerInitialState = parser.initialState;
350
- const shouldInheritInitialStateAnnotations = annotations != null && (innerInitialState == null || typeof innerInitialState === "object");
351
- const effectiveInitialState = shouldInheritInitialStateAnnotations ? inheritAnnotations(state, innerInitialState) : innerInitialState;
352
- const readPlaceholder = () => {
353
- try {
354
- return "placeholder" in parser ? parser.placeholder : void 0;
355
- } catch {
356
- return void 0;
357
- }
142
+ case "editor": return {
143
+ success: true,
144
+ value: await prompts.editor({
145
+ message: cfg.message,
146
+ ...cfg.default !== void 0 ? { default: cfg.default } : {},
147
+ ...cfg.validate !== void 0 ? { validate: cfg.validate } : {}
148
+ })
358
149
  };
359
- const finalizePrompt = () => {
360
- const shouldDefer = withAnnotatedInnerState(state, effectiveInitialState, (annotatedInnerState) => shouldDeferPrompt(parser, annotatedInnerState, exec));
361
- if (shouldDefer) return Promise.resolve(deferredPromptResult(readPlaceholder()));
362
- if (isProbe) return Promise.resolve({
363
- success: true,
364
- value: readPlaceholder()
365
- });
366
- return executePrompt();
150
+ case "select": return {
151
+ success: true,
152
+ value: await prompts.select({
153
+ message: cfg.message,
154
+ choices: normalizeChoices(cfg.choices),
155
+ ...cfg.default !== void 0 ? { default: cfg.default } : {}
156
+ })
367
157
  };
368
- const hasDeferHook = typeof parser.shouldDeferCompletion === "function";
369
- const decideFromParse = (parseResult) => {
370
- const consumed = parseResult.success ? parseResult.consumed.length : 0;
371
- const cliState = parseResult.success && consumed === 0 ? parseResult.next.state : void 0;
372
- const cliStateIsInjected = cliState != null && typeof cliState === "object" && unwrapInjectedAnnotationState(cliState) !== cliState;
373
- const isSourceBinding = shouldCompleteFromSourceBinding(cliState, state);
374
- if (!isSourceBinding) return finalizePrompt();
375
- const completeState = parseResult.success ? parseResult.next.state : effectiveInitialState;
376
- const innerR = parser.complete(completeState, exec);
377
- const handleCompleteResult = (res) => {
378
- if (res.success && res.value === void 0 && cliStateIsInjected) return finalizePrompt();
379
- if (!res.success) return finalizePrompt();
380
- return Promise.resolve(res);
381
- };
382
- if (innerR instanceof Promise) return innerR.then(handleCompleteResult);
383
- return handleCompleteResult(innerR);
158
+ case "rawlist": return {
159
+ success: true,
160
+ value: await prompts.rawlist({
161
+ message: cfg.message,
162
+ choices: normalizeChoices(cfg.choices),
163
+ ...cfg.default !== void 0 ? { default: cfg.default } : {}
164
+ })
165
+ };
166
+ case "expand": return {
167
+ success: true,
168
+ value: await prompts.expand({
169
+ message: cfg.message,
170
+ choices: cfg.choices,
171
+ ...cfg.default !== void 0 ? { default: cfg.default } : {}
172
+ })
173
+ };
174
+ case "checkbox": return {
175
+ success: true,
176
+ value: await prompts.checkbox({
177
+ message: cfg.message,
178
+ choices: normalizeChoices(cfg.choices)
179
+ })
384
180
  };
385
- if (hasDeferHook) {
386
- const innerR = withAnnotatedInnerState(state, effectiveInitialState, (annotatedInnerState) => parser.complete(annotatedInnerState, exec));
387
- const handleDeferHookResult = (res) => {
388
- if (res.success && res.value === void 0) return finalizePrompt();
389
- if (!res.success) return finalizePrompt();
390
- return Promise.resolve(res);
391
- };
392
- if (innerR instanceof Promise) return innerR.then(handleDeferHookResult);
393
- return handleDeferHookResult(innerR);
394
- }
395
- const simParseR = withAnnotatedInnerState(state, effectiveInitialState, (annotatedState) => parser.parse({
396
- buffer: [],
397
- state: annotatedState,
398
- optionsTerminated: false,
399
- usage: parser.usage
400
- }));
401
- if (simParseR instanceof Promise) return simParseR.then(decideFromParse);
402
- return decideFromParse(simParseR);
403
- },
404
- suggest: (context, prefix) => {
405
- const innerState = isPromptBindState(context.state) ? context.state.cliState === void 0 ? parser.initialState : context.state.cliState : context.state;
406
- const innerContext = innerState !== context.state ? {
407
- ...context,
408
- state: innerState
409
- } : context;
410
- const innerResult = parser.suggest(innerContext, prefix);
411
- return async function* () {
412
- yield* innerResult;
413
- }();
414
- },
415
- getDocFragments(state, upperDefaultValue) {
416
- const configDefault = "default" in cfg ? cfg.default : void 0;
417
- const defaultValue = upperDefaultValue ?? configDefault;
418
- return parser.getDocFragments(state, defaultValue);
419
- }
420
- };
421
- defineTraits(promptedParser, { inheritsAnnotations: true });
422
- if ("placeholder" in parser) Object.defineProperty(promptedParser, "placeholder", {
423
- get() {
424
- try {
425
- return parser.placeholder;
426
- } catch {
427
- return void 0;
428
- }
429
- },
430
- configurable: true,
431
- enumerable: false
432
- });
433
- if (typeof parser.normalizeValue === "function") Object.defineProperty(promptedParser, "normalizeValue", {
434
- value: parser.normalizeValue.bind(parser),
435
- configurable: true,
436
- enumerable: false
437
- });
438
- const dependencyMetadata = mapSourceMetadata(parser, (source) => ({
439
- ...source,
440
- extractSourceValue: (state) => {
441
- if (!isPromptBindState(state)) return source.extractSourceValue(state);
442
- return source.extractSourceValue(state.cliState ?? state);
443
181
  }
444
- }));
445
- if (dependencyMetadata != null) Object.defineProperty(promptedParser, "dependencyMetadata", {
446
- value: dependencyMetadata,
447
- configurable: true,
448
- enumerable: false
449
- });
450
- return fluent(promptedParser);
182
+ } catch (error) {
183
+ if (isExitPromptError(error)) return {
184
+ success: false,
185
+ error: message`Prompt cancelled.`
186
+ };
187
+ throw error;
188
+ }
451
189
  }
452
190
  /** Normalize choices to the format Inquirer.js expects. */
453
191
  function normalizeChoices(choices) {
@@ -462,7 +200,8 @@ function normalizeChoices(choices) {
462
200
  ...c.name !== void 0 ? { name: c.name } : {},
463
201
  ..."description" in c && c.description !== void 0 ? { description: c.description } : {},
464
202
  ..."short" in c && c.short !== void 0 ? { short: c.short } : {},
465
- ..."disabled" in c && c.disabled !== void 0 ? { disabled: c.disabled } : {}
203
+ ..."disabled" in c && c.disabled !== void 0 ? { disabled: c.disabled } : {},
204
+ ..."checked" in c && c.checked !== void 0 ? { checked: c.checked } : {}
466
205
  };
467
206
  });
468
207
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@optique/inquirer",
3
- "version": "1.2.0-dev.2187",
4
- "description": "Interactive prompt support for Optique via Inquirer.js",
3
+ "version": "1.2.0-dev.2192",
4
+ "description": "Inquirer.js prompt support for Optique",
5
5
  "keywords": [
6
6
  "CLI",
7
7
  "command-line",
@@ -62,16 +62,17 @@
62
62
  "sideEffects": false,
63
63
  "dependencies": {
64
64
  "@inquirer/prompts": "^8.3.0",
65
- "@optique/core": "1.2.0-dev.2187+6112b083"
65
+ "@optique/core": "1.2.0-dev.2192+fbd9db90",
66
+ "@optique/prompt": "1.2.0-dev.2192+fbd9db90"
66
67
  },
67
68
  "devDependencies": {
68
69
  "@types/node": "^24.0.0",
69
70
  "fast-check": "^4.7.0",
70
71
  "tsdown": "^0.13.0",
71
72
  "typescript": "^5.8.3",
72
- "@optique/config": "1.2.0-dev.2187+6112b083",
73
- "@optique/run": "1.2.0-dev.2187+6112b083",
74
- "@optique/env": "1.2.0-dev.2187+6112b083"
73
+ "@optique/env": "1.2.0-dev.2192+fbd9db90",
74
+ "@optique/config": "1.2.0-dev.2192+fbd9db90",
75
+ "@optique/run": "1.2.0-dev.2192+fbd9db90"
75
76
  },
76
77
  "scripts": {
77
78
  "build": "tsdown",