@astrojs/db 0.2.2 → 0.3.1

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.
Files changed (39) hide show
  1. package/config-augment.d.ts +1 -1
  2. package/dist/core/cli/commands/link/index.d.ts +8 -0
  3. package/dist/core/cli/commands/link/index.js +64 -0
  4. package/dist/core/cli/commands/login/index.d.ts +6 -0
  5. package/dist/core/cli/commands/login/index.js +46 -0
  6. package/dist/core/cli/commands/logout/index.d.ts +6 -0
  7. package/dist/core/cli/commands/logout/index.js +9 -0
  8. package/dist/core/cli/commands/push/index.js +71 -43
  9. package/dist/core/cli/commands/shell/index.js +5 -8
  10. package/dist/core/cli/commands/sync/index.js +22 -29
  11. package/dist/core/cli/commands/verify/index.d.ts +1 -1
  12. package/dist/core/cli/commands/verify/index.js +20 -16
  13. package/dist/core/cli/index.js +29 -8
  14. package/dist/core/cli/migration-queries.d.ts +19 -11
  15. package/dist/core/cli/migration-queries.js +124 -161
  16. package/dist/core/cli/migrations.d.ts +22 -1
  17. package/dist/core/cli/migrations.js +66 -2
  18. package/dist/core/errors.d.ts +5 -1
  19. package/dist/core/errors.js +35 -5
  20. package/dist/core/integration/index.js +32 -17
  21. package/dist/core/integration/typegen.js +2 -2
  22. package/dist/core/integration/vite-plugin-db.d.ts +1 -1
  23. package/dist/core/integration/vite-plugin-db.js +6 -4
  24. package/dist/core/queries.d.ts +57 -1
  25. package/dist/core/queries.js +70 -23
  26. package/dist/core/tokens.d.ts +11 -0
  27. package/dist/core/tokens.js +131 -0
  28. package/dist/core/types.d.ts +7049 -1903
  29. package/dist/core/types.js +133 -60
  30. package/dist/core/utils.d.ts +1 -0
  31. package/dist/core/utils.js +6 -1
  32. package/dist/index.d.ts +2 -1
  33. package/dist/index.js +8 -2
  34. package/dist/runtime/db-client.js +1 -1
  35. package/dist/runtime/index.d.ts +5 -1
  36. package/dist/runtime/index.js +36 -21
  37. package/dist/runtime/types.d.ts +13 -3
  38. package/dist/runtime/types.js +8 -0
  39. package/package.json +5 -3
@@ -1,36 +1,100 @@
1
+ import { SQLiteAsyncDialect } from "drizzle-orm/sqlite-core";
2
+ import { collectionToTable } from "../runtime/index.js";
1
3
  import { z } from "zod";
4
+ import { SQL } from "drizzle-orm";
5
+ import { errorMap } from "./integration/error-map.js";
6
+ import { SERIALIZED_SQL_KEY } from "../runtime/types.js";
7
+ const sqlite = new SQLiteAsyncDialect();
8
+ const sqlSchema = z.instanceof(SQL).transform(
9
+ (sqlObj) => ({
10
+ [SERIALIZED_SQL_KEY]: true,
11
+ sql: sqlite.sqlToQuery(sqlObj).sql
12
+ })
13
+ );
2
14
  const baseFieldSchema = z.object({
3
15
  label: z.string().optional(),
4
16
  optional: z.boolean().optional(),
5
- unique: z.boolean().optional()
17
+ unique: z.boolean().optional(),
18
+ // Defined when `defineCollection()` is called
19
+ name: z.string().optional(),
20
+ collection: z.string().optional()
6
21
  });
7
- const booleanFieldSchema = baseFieldSchema.extend({
22
+ const booleanFieldSchema = z.object({
8
23
  type: z.literal("boolean"),
9
- default: z.boolean().optional()
24
+ schema: baseFieldSchema.extend({
25
+ default: z.union([z.boolean(), sqlSchema]).optional()
26
+ })
10
27
  });
11
- const numberFieldSchema = baseFieldSchema.extend({
28
+ const numberFieldBaseSchema = baseFieldSchema.omit({ optional: true }).and(
29
+ z.union([
30
+ z.object({
31
+ primaryKey: z.literal(false).optional(),
32
+ optional: z.boolean().optional(),
33
+ default: z.union([z.number(), sqlSchema]).optional()
34
+ }),
35
+ z.object({
36
+ // `integer primary key` uses ROWID as the default value.
37
+ // `optional` and `default` do not have an effect,
38
+ // so disable these config options for primary keys.
39
+ primaryKey: z.literal(true),
40
+ optional: z.literal(false).optional(),
41
+ default: z.literal(void 0).optional()
42
+ })
43
+ ])
44
+ );
45
+ const numberFieldOptsSchema = numberFieldBaseSchema.and(
46
+ z.object({
47
+ references: z.function().returns(z.lazy(() => numberFieldSchema)).optional().transform((fn) => fn?.())
48
+ })
49
+ );
50
+ const numberFieldSchema = z.object({
12
51
  type: z.literal("number"),
13
- default: z.number().optional(),
14
- primaryKey: z.boolean().optional()
52
+ schema: numberFieldOptsSchema
15
53
  });
16
- const textFieldSchema = baseFieldSchema.extend({
54
+ const textFieldBaseSchema = baseFieldSchema.omit({ optional: true }).extend({
55
+ default: z.union([z.string(), sqlSchema]).optional(),
56
+ multiline: z.boolean().optional()
57
+ }).and(
58
+ z.union([
59
+ z.object({
60
+ primaryKey: z.literal(false).optional(),
61
+ optional: z.boolean().optional()
62
+ }),
63
+ z.object({
64
+ // text primary key allows NULL values.
65
+ // NULL values bypass unique checks, which could
66
+ // lead to duplicate URLs per record in Astro Studio.
67
+ // disable `optional` for primary keys.
68
+ primaryKey: z.literal(true),
69
+ optional: z.literal(false).optional()
70
+ })
71
+ ])
72
+ );
73
+ const textFieldOptsSchema = textFieldBaseSchema.and(
74
+ z.object({
75
+ references: z.function().returns(z.lazy(() => textFieldSchema)).optional().transform((fn) => fn?.())
76
+ })
77
+ );
78
+ const textFieldSchema = z.object({
17
79
  type: z.literal("text"),
18
- multiline: z.boolean().optional(),
19
- default: z.string().optional(),
20
- primaryKey: z.boolean().optional()
80
+ schema: textFieldOptsSchema
21
81
  });
22
- const dateFieldSchema = baseFieldSchema.extend({
82
+ const dateFieldSchema = z.object({
23
83
  type: z.literal("date"),
24
- default: z.union([
25
- z.literal("now"),
26
- // allow date-like defaults in user config,
27
- // transform to ISO string for D1 storage
28
- z.coerce.date().transform((d) => d.toISOString())
29
- ]).optional()
84
+ schema: baseFieldSchema.extend({
85
+ default: z.union([
86
+ sqlSchema,
87
+ // allow date-like defaults in user config,
88
+ // transform to ISO string for D1 storage
89
+ z.coerce.date().transform((d) => d.toISOString())
90
+ ]).optional()
91
+ })
30
92
  });
31
- const jsonFieldSchema = baseFieldSchema.extend({
93
+ const jsonFieldSchema = z.object({
32
94
  type: z.literal("json"),
33
- default: z.unknown().optional()
95
+ schema: baseFieldSchema.extend({
96
+ default: z.unknown().optional()
97
+ })
34
98
  });
35
99
  const fieldSchema = z.union([
36
100
  booleanFieldSchema,
@@ -39,17 +103,20 @@ const fieldSchema = z.union([
39
103
  dateFieldSchema,
40
104
  jsonFieldSchema
41
105
  ]);
106
+ const referenceableFieldSchema = z.union([textFieldSchema, numberFieldSchema]);
42
107
  const fieldsSchema = z.record(fieldSchema);
43
108
  const indexSchema = z.object({
44
109
  on: z.string().or(z.array(z.string())),
45
110
  unique: z.boolean().optional()
46
111
  });
47
- const indexesSchema = z.record(indexSchema);
112
+ const foreignKeysSchema = z.object({
113
+ fields: z.string().or(z.array(z.string())),
114
+ references: z.function().returns(z.lazy(() => referenceableFieldSchema.or(z.array(referenceableFieldSchema)))).transform((fn) => fn())
115
+ });
48
116
  const baseCollectionSchema = z.object({
49
117
  fields: fieldsSchema,
50
- indexes: indexesSchema.optional(),
51
- table: z.any(),
52
- _setMeta: z.function().optional()
118
+ indexes: z.record(indexSchema).optional(),
119
+ foreignKeys: z.array(foreignKeysSchema).optional()
53
120
  });
54
121
  const readableCollectionSchema = baseCollectionSchema.extend({
55
122
  writable: z.literal(false)
@@ -58,7 +125,24 @@ const writableCollectionSchema = baseCollectionSchema.extend({
58
125
  writable: z.literal(true)
59
126
  });
60
127
  const collectionSchema = z.union([readableCollectionSchema, writableCollectionSchema]);
61
- const collectionsSchema = z.record(collectionSchema);
128
+ const collectionsSchema = z.preprocess((rawCollections) => {
129
+ const collections = z.record(z.any()).parse(rawCollections, { errorMap });
130
+ for (const [collectionName, collection] of Object.entries(collections)) {
131
+ collection.table = collectionToTable(
132
+ collectionName,
133
+ collectionSchema.parse(collection, { errorMap })
134
+ );
135
+ const { fields } = z.object({ fields: z.record(z.any()) }).parse(collection, { errorMap });
136
+ for (const [fieldName, field2] of Object.entries(fields)) {
137
+ field2.schema.name = fieldName;
138
+ field2.schema.collection = collectionName;
139
+ }
140
+ }
141
+ return rawCollections;
142
+ }, z.record(collectionSchema));
143
+ function defineData(fn) {
144
+ return fn;
145
+ }
62
146
  const dbConfigSchema = z.object({
63
147
  studio: z.boolean().optional(),
64
148
  collections: collectionsSchema.optional(),
@@ -67,57 +151,44 @@ const dbConfigSchema = z.object({
67
151
  const astroConfigWithDbSchema = z.object({
68
152
  db: dbConfigSchema.optional()
69
153
  });
70
- function defineCollection(userConfig) {
71
- const meta = { table: null };
72
- function _setMeta(values) {
73
- Object.assign(meta, values);
74
- }
154
+ function baseDefineCollection(userConfig, writable) {
75
155
  return {
76
156
  ...userConfig,
77
- writable: false,
78
- get table() {
79
- return meta.table;
80
- },
81
- // @ts-expect-error private field
82
- _setMeta
157
+ writable,
158
+ // set at runtime to get the table name
159
+ table: null
83
160
  };
84
161
  }
162
+ function defineCollection(userConfig) {
163
+ return baseDefineCollection(userConfig, false);
164
+ }
85
165
  function defineWritableCollection(userConfig) {
86
- const meta = { table: null };
87
- function _setMeta(values) {
88
- Object.assign(meta, values);
89
- }
166
+ return baseDefineCollection(userConfig, true);
167
+ }
168
+ function createField(type, schema) {
90
169
  return {
91
- ...userConfig,
92
- writable: true,
93
- get table() {
94
- return meta.table;
95
- },
96
- // @ts-expect-error private field
97
- _setMeta
170
+ type,
171
+ /**
172
+ * @internal
173
+ */
174
+ schema
98
175
  };
99
176
  }
100
- const baseDefaults = {
101
- optional: false,
102
- unique: false,
103
- label: void 0,
104
- default: void 0
105
- };
106
177
  const field = {
107
- number(opts = {}) {
108
- return { type: "number", ...baseDefaults, ...opts };
178
+ number: (opts = {}) => {
179
+ return createField("number", opts);
109
180
  },
110
- boolean(opts = {}) {
111
- return { type: "boolean", ...baseDefaults, ...opts };
181
+ boolean: (opts = {}) => {
182
+ return createField("boolean", opts);
112
183
  },
113
- text(opts = {}) {
114
- return { type: "text", multiline: false, ...baseDefaults, ...opts };
184
+ text: (opts = {}) => {
185
+ return createField("text", opts);
115
186
  },
116
187
  date(opts = {}) {
117
- return { type: "date", ...baseDefaults, ...opts };
188
+ return createField("date", opts);
118
189
  },
119
190
  json(opts = {}) {
120
- return { type: "json", ...baseDefaults, ...opts };
191
+ return createField("json", opts);
121
192
  }
122
193
  };
123
194
  export {
@@ -126,9 +197,11 @@ export {
126
197
  collectionsSchema,
127
198
  dbConfigSchema,
128
199
  defineCollection,
200
+ defineData,
129
201
  defineWritableCollection,
130
202
  field,
131
203
  indexSchema,
132
204
  readableCollectionSchema,
205
+ referenceableFieldSchema,
133
206
  writableCollectionSchema
134
207
  };
@@ -2,3 +2,4 @@ import type { AstroConfig } from 'astro';
2
2
  export type VitePlugin = Required<AstroConfig['vite']>['plugins'][number];
3
3
  export declare function getAstroStudioEnv(envMode?: string): Record<`ASTRO_STUDIO_${string}`, string>;
4
4
  export declare function getRemoteDatabaseUrl(): string;
5
+ export declare function getAstroStudioUrl(): string;
@@ -5,9 +5,14 @@ function getAstroStudioEnv(envMode = "") {
5
5
  }
6
6
  function getRemoteDatabaseUrl() {
7
7
  const env = getAstroStudioEnv();
8
- return env.ASTRO_STUDIO_REMOTE_DB_URL;
8
+ return env.ASTRO_STUDIO_REMOTE_DB_URL || "https://studio-gateway.fly.dev";
9
+ }
10
+ function getAstroStudioUrl() {
11
+ const env = getAstroStudioEnv();
12
+ return env.ASTRO_STUDIO_URL || "https://stardate.astro.build";
9
13
  }
10
14
  export {
11
15
  getAstroStudioEnv,
16
+ getAstroStudioUrl,
12
17
  getRemoteDatabaseUrl
13
18
  };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- export { defineCollection, defineWritableCollection, field } from './core/types.js';
1
+ export { defineCollection, defineWritableCollection, defineData, field } from './core/types.js';
2
2
  export type { ResolvedCollectionConfig, DBDataContext } from './core/types.js';
3
3
  export { cli } from './core/cli/index.js';
4
4
  export { integration as default } from './core/integration/index.js';
5
+ export { sql, NOW, TRUE, FALSE } from './runtime/index.js';
package/dist/index.js CHANGED
@@ -1,10 +1,16 @@
1
- import { defineCollection, defineWritableCollection, field } from "./core/types.js";
1
+ import { defineCollection, defineWritableCollection, defineData, field } from "./core/types.js";
2
2
  import { cli } from "./core/cli/index.js";
3
3
  import { integration } from "./core/integration/index.js";
4
+ import { sql, NOW, TRUE, FALSE } from "./runtime/index.js";
4
5
  export {
6
+ FALSE,
7
+ NOW,
8
+ TRUE,
5
9
  cli,
6
10
  integration as default,
7
11
  defineCollection,
12
+ defineData,
8
13
  defineWritableCollection,
9
- field
14
+ field,
15
+ sql
10
16
  };
@@ -40,7 +40,7 @@ function checkIfModificationIsAllowed(collections, Table) {
40
40
  }
41
41
  }
42
42
  function createRemoteDatabaseClient(appToken, remoteDbURL) {
43
- const url = new URL("./db/query/", remoteDbURL);
43
+ const url = new URL("/db/query", remoteDbURL);
44
44
  const db = drizzleProxy(async (sql, parameters, method) => {
45
45
  const requestBody = { sql, args: parameters };
46
46
  console.info(JSON.stringify(requestBody));
@@ -1,10 +1,14 @@
1
1
  import type { SqliteRemoteDatabase } from 'drizzle-orm/sqlite-proxy';
2
2
  import { type DBCollection, type DBField } from '../core/types.js';
3
- import { type ColumnDataType } from 'drizzle-orm';
3
+ import { type ColumnDataType, sql, SQL } from 'drizzle-orm';
4
+ export { sql };
4
5
  export type SqliteDB = SqliteRemoteDatabase;
5
6
  export type { Table } from './types.js';
6
7
  export { createRemoteDatabaseClient, createLocalDatabaseClient } from './db-client.js';
7
8
  export declare function hasPrimaryKey(field: DBField): boolean;
9
+ export declare const NOW: SQL<unknown>;
10
+ export declare const TRUE: SQL<unknown>;
11
+ export declare const FALSE: SQL<unknown>;
8
12
  export declare function collectionToTable(name: string, collection: DBCollection, isJsonSerializable?: boolean): import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
9
13
  name: string;
10
14
  schema: undefined;
@@ -1,5 +1,5 @@
1
1
  import {} from "../core/types.js";
2
- import { sql } from "drizzle-orm";
2
+ import { sql, SQL } from "drizzle-orm";
3
3
  import {
4
4
  customType,
5
5
  integer,
@@ -8,10 +8,14 @@ import {
8
8
  index
9
9
  } from "drizzle-orm/sqlite-core";
10
10
  import { z } from "zod";
11
+ import { isSerializedSQL } from "./types.js";
11
12
  import { createRemoteDatabaseClient, createLocalDatabaseClient } from "./db-client.js";
12
13
  function hasPrimaryKey(field) {
13
- return "primaryKey" in field && !!field.primaryKey;
14
+ return "primaryKey" in field.schema && !!field.schema.primaryKey;
14
15
  }
16
+ const NOW = sql`CURRENT_TIMESTAMP`;
17
+ const TRUE = sql`TRUE`;
18
+ const FALSE = sql`FALSE`;
15
19
  const dateType = customType({
16
20
  dataType() {
17
21
  return "text";
@@ -63,45 +67,46 @@ function columnMapper(fieldName, field, isJsonSerializable) {
63
67
  switch (field.type) {
64
68
  case "text": {
65
69
  c = text(fieldName);
66
- if (field.default !== void 0)
67
- c = c.default(field.default);
68
- if (field.primaryKey === true)
70
+ if (field.schema.default !== void 0)
71
+ c = c.default(handleSerializedSQL(field.schema.default));
72
+ if (field.schema.primaryKey === true)
69
73
  c = c.primaryKey();
70
74
  break;
71
75
  }
72
76
  case "number": {
73
77
  c = integer(fieldName);
74
- if (field.default !== void 0)
75
- c = c.default(field.default);
76
- if (field.primaryKey === true)
77
- c = c.primaryKey({ autoIncrement: true });
78
+ if (field.schema.default !== void 0)
79
+ c = c.default(handleSerializedSQL(field.schema.default));
80
+ if (field.schema.primaryKey === true)
81
+ c = c.primaryKey();
78
82
  break;
79
83
  }
80
84
  case "boolean": {
81
85
  c = integer(fieldName, { mode: "boolean" });
82
- if (field.default !== void 0)
83
- c = c.default(field.default);
86
+ if (field.schema.default !== void 0)
87
+ c = c.default(handleSerializedSQL(field.schema.default));
84
88
  break;
85
89
  }
86
90
  case "json":
87
91
  c = jsonType(fieldName);
88
- if (field.default !== void 0)
89
- c = c.default(field.default);
92
+ if (field.schema.default !== void 0)
93
+ c = c.default(field.schema.default);
90
94
  break;
91
95
  case "date": {
92
96
  if (isJsonSerializable) {
93
97
  c = text(fieldName);
94
- if (field.default !== void 0) {
95
- c = c.default(field.default === "now" ? sql`CURRENT_TIMESTAMP` : field.default);
98
+ if (field.schema.default !== void 0) {
99
+ c = c.default(handleSerializedSQL(field.schema.default));
96
100
  }
97
101
  } else {
98
102
  c = dateType(fieldName);
99
- if (field.default !== void 0) {
103
+ if (field.schema.default !== void 0) {
104
+ const def = handleSerializedSQL(field.schema.default);
100
105
  c = c.default(
101
- field.default === "now" ? sql`CURRENT_TIMESTAMP` : (
106
+ def instanceof SQL ? def : (
102
107
  // default comes pre-transformed to an ISO string for D1 storage.
103
108
  // parse back to a Date for Drizzle.
104
- z.coerce.date().parse(field.default)
109
+ z.coerce.date().parse(field.schema.default)
105
110
  )
106
111
  );
107
112
  }
@@ -109,15 +114,25 @@ function columnMapper(fieldName, field, isJsonSerializable) {
109
114
  break;
110
115
  }
111
116
  }
112
- if (!field.optional)
117
+ if (!field.schema.optional)
113
118
  c = c.notNull();
114
- if (field.unique)
119
+ if (field.schema.unique)
115
120
  c = c.unique();
116
121
  return c;
117
122
  }
123
+ function handleSerializedSQL(def) {
124
+ if (isSerializedSQL(def)) {
125
+ return sql.raw(def.sql);
126
+ }
127
+ return def;
128
+ }
118
129
  export {
130
+ FALSE,
131
+ NOW,
132
+ TRUE,
119
133
  collectionToTable,
120
134
  createLocalDatabaseClient,
121
135
  createRemoteDatabaseClient,
122
- hasPrimaryKey
136
+ hasPrimaryKey,
137
+ sql
123
138
  };
@@ -43,7 +43,7 @@ export type AstroJson<T extends GeneratedConfig<'custom'>> = SQLiteColumn<T & {
43
43
  baseColumn: never;
44
44
  }>;
45
45
  export type Column<T extends DBField['type'], S extends GeneratedConfig> = T extends 'boolean' ? AstroBoolean<S> : T extends 'number' ? AstroNumber<S> : T extends 'text' ? AstroText<S> : T extends 'date' ? AstroDate<S> : T extends 'json' ? AstroJson<S> : never;
46
- export type Table<TTableName extends string, TFields extends Record<string, Pick<DBField, 'type' | 'default' | 'optional'>>> = SQLiteTableWithColumns<{
46
+ export type Table<TTableName extends string, TFields extends Record<string, Pick<DBField, 'type' | 'schema'>>> = SQLiteTableWithColumns<{
47
47
  name: TTableName;
48
48
  schema: undefined;
49
49
  dialect: 'sqlite';
@@ -51,9 +51,19 @@ export type Table<TTableName extends string, TFields extends Record<string, Pick
51
51
  [K in Extract<keyof TFields, string>]: Column<TFields[K]['type'], {
52
52
  tableName: TTableName;
53
53
  name: K;
54
- hasDefault: TFields[K]['default'] extends undefined ? false : true;
55
- notNull: TFields[K]['optional'] extends true ? false : true;
54
+ hasDefault: TFields[K] extends {
55
+ default: NonNullable<unknown>;
56
+ } ? true : TFields[K] extends {
57
+ primaryKey: true;
58
+ } ? true : false;
59
+ notNull: TFields[K]['schema']['optional'] extends true ? false : true;
56
60
  }>;
57
61
  };
58
62
  }>;
63
+ export declare const SERIALIZED_SQL_KEY = "__serializedSQL";
64
+ export type SerializedSQL = {
65
+ [SERIALIZED_SQL_KEY]: true;
66
+ sql: string;
67
+ };
68
+ export declare function isSerializedSQL(value: any): value is SerializedSQL;
59
69
  export {};
@@ -0,0 +1,8 @@
1
+ const SERIALIZED_SQL_KEY = "__serializedSQL";
2
+ function isSerializedSQL(value) {
3
+ return typeof value === "object" && value !== null && SERIALIZED_SQL_KEY in value;
4
+ }
5
+ export {
6
+ SERIALIZED_SQL_KEY,
7
+ isSerializedSQL
8
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrojs/db",
3
- "version": "0.2.2",
3
+ "version": "0.3.1",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -52,17 +52,19 @@
52
52
  "drizzle-orm": "^0.28.6",
53
53
  "kleur": "^4.1.5",
54
54
  "nanoid": "^5.0.1",
55
+ "open": "^10.0.3",
56
+ "ora": "^7.0.1",
55
57
  "prompts": "^2.4.2",
56
58
  "yargs-parser": "^21.1.1",
57
59
  "zod": "^3.22.4"
58
60
  },
59
61
  "devDependencies": {
62
+ "@types/chai": "^4.3.6",
60
63
  "@types/deep-diff": "^1.0.5",
61
64
  "@types/diff": "^5.0.8",
62
- "@types/yargs-parser": "^21.0.3",
63
- "@types/chai": "^4.3.6",
64
65
  "@types/mocha": "^10.0.2",
65
66
  "@types/prompts": "^2.4.8",
67
+ "@types/yargs-parser": "^21.0.3",
66
68
  "chai": "^4.3.10",
67
69
  "cheerio": "1.0.0-rc.12",
68
70
  "mocha": "^10.2.0",