@asla/yoursql 0.3.0 → 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.
package/dist/mod.d.ts CHANGED
@@ -5,4 +5,5 @@ export * from "./select/select.ts";
5
5
  export * from "./select/selectable.ts";
6
6
  export * from "./select/TableQuery.ts";
7
7
  export * from "./util.ts";
8
+ export * from "./your_table/mod.ts";
8
9
  //# sourceMappingURL=mod.d.ts.map
package/dist/mod.js CHANGED
@@ -55,7 +55,79 @@ function getObjectListKeys(objectList, keepUndefinedKey) {
55
55
  return Array.from(keys);
56
56
  }
57
57
 
58
- var _SqlRaw_value;
58
+ /**
59
+ * 可选择项。可以是 table、查询结果等,它能被 select 语句选择
60
+ * @example
61
+ * ```ts
62
+ * declare const item: SqlSelectable<any>
63
+ * await query(`select * from ${item.toSelect()}`)
64
+ *
65
+ * ```
66
+ * @public
67
+ */
68
+ class SqlSelectable {
69
+ constructor(columns) {
70
+ // Reflect.set(this, SQL_SELECTABLE, undefined);
71
+ let readonlyColumns;
72
+ if (typeof columns[Symbol.iterator] === "function") {
73
+ let iterable = columns;
74
+ readonlyColumns = [];
75
+ let iter = iterable[Symbol.iterator]();
76
+ let i = 0;
77
+ let item = iter.next();
78
+ while (!item.done) {
79
+ readonlyColumns[i++] = item.value;
80
+ item = iter.next();
81
+ }
82
+ // readonlyColumns.length = i;
83
+ }
84
+ else {
85
+ let arrayLike = columns;
86
+ readonlyColumns = new Array(arrayLike.length);
87
+ // readonlyColumns.length = arrayLike.length;
88
+ for (let i = 0; i < arrayLike.length; i++) {
89
+ readonlyColumns[i] = arrayLike[i];
90
+ }
91
+ }
92
+ this.columns = readonlyColumns;
93
+ }
94
+ }
95
+ /**
96
+ * 数据库表
97
+ * @public
98
+ */
99
+ class DbTable extends SqlSelectable {
100
+ constructor(name, columns) {
101
+ if (!(columns instanceof Array))
102
+ columns = Object.keys(columns);
103
+ super(columns);
104
+ this.name = name;
105
+ }
106
+ toSelect() {
107
+ return this.name;
108
+ }
109
+ toString() {
110
+ return this.name;
111
+ }
112
+ }
113
+ /**
114
+ * SELECT 以及 UPDATE、DELETE、INSERT INTO 带结果的 SQL 语句
115
+ * @public
116
+ */
117
+ class SqlQueryStatement extends SqlSelectable {
118
+ constructor(sql, columns) {
119
+ super(columns);
120
+ this.sql = sql;
121
+ }
122
+ toString() {
123
+ return this.sql;
124
+ }
125
+ toSelect() {
126
+ return "(" + this.toString() + ")";
127
+ }
128
+ }
129
+
130
+ var _SqlRaw_value, _YourValuesAs_asName, _YourValuesAs_valuesStr, _YourValuesAs_sql;
59
131
  /**
60
132
  * SQL 原始字符对象
61
133
  * @public
@@ -217,7 +289,70 @@ class SqlValuesCreator {
217
289
  toValues(values) {
218
290
  return values.map((v) => this.toSqlStr(v)).join(",");
219
291
  }
292
+ createValues(asName, values, valuesTypes) {
293
+ if (values.length === 0)
294
+ throw new Error("values 不能为空");
295
+ const insertKeys = Object.keys(valuesTypes);
296
+ const defaultValues = [];
297
+ const valuesStr = new Array(values.length);
298
+ {
299
+ const column0 = new Array(insertKeys.length);
300
+ let columnName;
301
+ let item;
302
+ let type;
303
+ let value;
304
+ for (let i = 0; i < insertKeys.length; i++) {
305
+ columnName = insertKeys[i];
306
+ item = valuesTypes[columnName];
307
+ if (typeof item === "string") {
308
+ type = item;
309
+ defaultValues[i] = "NULL";
310
+ }
311
+ else {
312
+ type = item.sqlType;
313
+ defaultValues[i] = item.sqlDefault ?? "NULL";
314
+ }
315
+ value = values[0][columnName];
316
+ if (value === undefined)
317
+ column0[i] = defaultValues[i] + "::" + type;
318
+ else
319
+ column0[i] = this.toSqlStr(value) + "::" + type;
320
+ }
321
+ valuesStr[0] = "(" + column0.join(",") + ")";
322
+ }
323
+ let items = new Array(insertKeys.length);
324
+ let value;
325
+ for (let i = 1; i < values.length; i++) {
326
+ for (let j = 0; j < insertKeys.length; j++) {
327
+ value = values[i][insertKeys[j]];
328
+ if (value === undefined)
329
+ items[j] = defaultValues[j];
330
+ else
331
+ items[j] = this.toSqlStr(value);
332
+ }
333
+ valuesStr[i] = "(" + items.join(",") + ")";
334
+ }
335
+ return new YourValuesAs(insertKeys, asName, valuesStr.join(",\n"));
336
+ }
337
+ }
338
+ class YourValuesAs extends SqlSelectable {
339
+ constructor(columns, asName, valuesStr) {
340
+ super(columns);
341
+ _YourValuesAs_asName.set(this, void 0);
342
+ _YourValuesAs_valuesStr.set(this, void 0);
343
+ _YourValuesAs_sql.set(this, void 0);
344
+ __classPrivateFieldSet(this, _YourValuesAs_asName, asName, "f");
345
+ __classPrivateFieldSet(this, _YourValuesAs_valuesStr, valuesStr, "f");
346
+ __classPrivateFieldSet(this, _YourValuesAs_sql, `(VALUES\n${__classPrivateFieldGet(this, _YourValuesAs_valuesStr, "f")})\nAS ${__classPrivateFieldGet(this, _YourValuesAs_asName, "f")}(${this.columns.join(",")})`, "f");
347
+ }
348
+ toSelect() {
349
+ return __classPrivateFieldGet(this, _YourValuesAs_sql, "f");
350
+ }
351
+ toString() {
352
+ return __classPrivateFieldGet(this, _YourValuesAs_sql, "f");
353
+ }
220
354
  }
355
+ _YourValuesAs_asName = new WeakMap(), _YourValuesAs_valuesStr = new WeakMap(), _YourValuesAs_sql = new WeakMap();
221
356
  function toKeyType(object, keys_types) {
222
357
  let type = {};
223
358
  let keys;
@@ -259,78 +394,6 @@ const pgSqlTransformer = new Map([
259
394
  [Date, (value) => SqlValuesCreator.string(value.toISOString())],
260
395
  ]);
261
396
 
262
- /**
263
- * 可选择项。可以是 table、查询结果等,它能被 select 语句选择
264
- * @example
265
- * ```ts
266
- * declare const item: SqlSelectable<any>
267
- * await query(`select * from ${item.toSelect()}`)
268
- *
269
- * ```
270
- * @public
271
- */
272
- class SqlSelectable {
273
- constructor(columns) {
274
- // Reflect.set(this, SQL_SELECTABLE, undefined);
275
- let readonlyColumns;
276
- if (typeof columns[Symbol.iterator] === "function") {
277
- let iterable = columns;
278
- readonlyColumns = [];
279
- let iter = iterable[Symbol.iterator]();
280
- let i = 0;
281
- let item = iter.next();
282
- while (!item.done) {
283
- readonlyColumns[i++] = item.value;
284
- item = iter.next();
285
- }
286
- // readonlyColumns.length = i;
287
- }
288
- else {
289
- let arrayLike = columns;
290
- readonlyColumns = new Array(arrayLike.length);
291
- // readonlyColumns.length = arrayLike.length;
292
- for (let i = 0; i < arrayLike.length; i++) {
293
- readonlyColumns[i] = arrayLike[i];
294
- }
295
- }
296
- this.columns = readonlyColumns;
297
- }
298
- }
299
- /**
300
- * 数据库表
301
- * @public
302
- */
303
- class DbTable extends SqlSelectable {
304
- constructor(name, columns) {
305
- if (!(columns instanceof Array))
306
- columns = Object.keys(columns);
307
- super(columns);
308
- this.name = name;
309
- }
310
- toSelect() {
311
- return this.name;
312
- }
313
- toString() {
314
- return this.name;
315
- }
316
- }
317
- /**
318
- * SELECT 以及 UPDATE、DELETE、INSERT INTO 带结果的 SQL 语句
319
- * @public
320
- */
321
- class SqlQueryStatement extends SqlSelectable {
322
- constructor(sql, columns) {
323
- super(columns);
324
- this.sql = sql;
325
- }
326
- toString() {
327
- return this.sql;
328
- }
329
- toSelect() {
330
- return "(" + this.toString() + ")";
331
- }
332
- }
333
-
334
397
  function genOderBy(orderBy, orderNullRule) {
335
398
  let select = [];
336
399
  let v;
@@ -612,7 +675,6 @@ class TableRepeatError extends Error {
612
675
  class DbTableQuery extends DbTable {
613
676
  constructor(name, columns, statement) {
614
677
  super(name, columns);
615
- this.name = name;
616
678
  this.statement = statement;
617
679
  }
618
680
  select(columns, option) {
@@ -707,4 +769,175 @@ function genWhere(where) {
707
769
  return "\nWHERE " + where;
708
770
  }
709
771
 
710
- export { DbTable, DbTableQuery, SqlQueryStatement, SqlRaw, SqlSelectable, SqlValuesCreator, createSelect, getObjectListKeys, pgSqlTransformer };
772
+ /**
773
+ * 表格列的信息
774
+ * @public
775
+ */
776
+ class ColumnMeta {
777
+ constructor(type,
778
+ /** 数据库原始数据类型 */
779
+ sqlType,
780
+ /** 是否非空 */
781
+ notNull = false,
782
+ /** 是否是数组类型 */
783
+ isArray = false,
784
+ /** 数据库原始默认值 */
785
+ sqlDefault) {
786
+ this.type = type;
787
+ this.sqlType = sqlType;
788
+ this.notNull = notNull;
789
+ this.isArray = isArray;
790
+ this.sqlDefault = sqlDefault;
791
+ }
792
+ /** 校验 value 的类型 */
793
+ checkValue(value) {
794
+ if (typeof this.type === "function")
795
+ return value instanceof this.type;
796
+ return this.type.is(value);
797
+ }
798
+ }
799
+ /**
800
+ * 数据库类型到JS类型的映射
801
+ * @public
802
+ */
803
+ class YourTypeMap {
804
+ static create(rawTypeMap) {
805
+ return new this(rawTypeMap);
806
+ }
807
+ constructor(typeMap = {}) {
808
+ this.typeMap = typeMap;
809
+ }
810
+ genColumn(type, notNull, defaultValue) {
811
+ const constructor = Reflect.get(this.typeMap, type);
812
+ const column = new ColumnMeta(constructor, type, notNull, false, defaultValue);
813
+ return column;
814
+ }
815
+ genArrColumn(type, notNull, defaultValue) {
816
+ const constructor = Reflect.get(this.typeMap, type);
817
+ const column = new ColumnMeta(constructor, type + "[]", notNull, true, defaultValue);
818
+ return column;
819
+ }
820
+ }
821
+ function baseType(v) {
822
+ return typeof v === this.name;
823
+ }
824
+ /**
825
+ * 自定义数据类型
826
+ * @public
827
+ */
828
+ class CustomDbType {
829
+ constructor(is, name) {
830
+ this.is = is;
831
+ this.name = name;
832
+ }
833
+ }
834
+ CustomDbType.bigint = new CustomDbType(baseType, "bigint");
835
+ CustomDbType.number = new CustomDbType(baseType, "number");
836
+ CustomDbType.string = new CustomDbType(baseType, "string");
837
+ CustomDbType.boolean = new CustomDbType(baseType, "boolean");
838
+
839
+ /** @public */
840
+ class TypeChecker {
841
+ constructor(map) {
842
+ this.map = map;
843
+ }
844
+ check(value) {
845
+ const map = this.map;
846
+ let v;
847
+ for (const [k, expect] of map) {
848
+ v = value[k];
849
+ let err;
850
+ if (v === null) {
851
+ if (expect.notNull)
852
+ throw new Error(`${k} 不能为空`);
853
+ continue;
854
+ }
855
+ else if (v === undefined) {
856
+ if (expect.sqlDefault === undefined && expect.notNull)
857
+ throw new Error(`${k} 不能为 undefined`);
858
+ continue;
859
+ }
860
+ else if (expect.isArray) {
861
+ if (v instanceof Array)
862
+ err = this.checkArray(v, expect.type);
863
+ else
864
+ err = getErrStr(`Array<${expect.type.name}>`, typeof v);
865
+ }
866
+ else {
867
+ err = this.checkItem(v, expect.type);
868
+ }
869
+ if (err)
870
+ throw new Error(`Key ${k} error: ${err}`);
871
+ }
872
+ return value;
873
+ }
874
+ checkList(value) {
875
+ let i = 0;
876
+ try {
877
+ for (let i = 0; i < value.length; i++) {
878
+ this.check(value[i]);
879
+ }
880
+ return value;
881
+ }
882
+ catch (error) {
883
+ throw new Error(`Item ${i}, ${error.message}`);
884
+ }
885
+ }
886
+ checkArray(v, expect) {
887
+ let err;
888
+ for (let i = 0; i < v.length; i++) {
889
+ err = this.checkItem(v[i], expect);
890
+ if (err)
891
+ return `Item[${i}] ${err}`;
892
+ }
893
+ }
894
+ checkItem(v, expect) {
895
+ if (expect instanceof CustomDbType) {
896
+ if (expect.is(v))
897
+ return;
898
+ }
899
+ else {
900
+ if (v instanceof expect)
901
+ return;
902
+ }
903
+ let actName = typeof v;
904
+ if (actName === "object") {
905
+ if (v === null)
906
+ actName = "null";
907
+ else
908
+ actName = v.constructor?.name ?? "object";
909
+ }
910
+ return getErrStr(expect.name, typeof v);
911
+ }
912
+ }
913
+ function getErrStr(expect, actual) {
914
+ return `Expect ${expect}, Actual ${actual}`;
915
+ }
916
+
917
+ /**
918
+ * 完整数据库表数据
919
+ * @public
920
+ */
921
+ class YourTable extends DbTableQuery {
922
+ constructor(name, define, sqlValue) {
923
+ super(name, Object.keys(define), sqlValue);
924
+ this.define = define;
925
+ }
926
+ getColumnMeta(name) {
927
+ return Reflect.get(this.define, name);
928
+ }
929
+ createTypeChecker(keys) {
930
+ let map = new Map();
931
+ let defined = this.define;
932
+ let k;
933
+ for (let i = 0; i < keys.length; i++) {
934
+ k = keys[i];
935
+ if (defined[k] === undefined)
936
+ throw new Error(`key ${k} 未定义`);
937
+ map.set(k, defined[k]);
938
+ }
939
+ return new TypeChecker(map);
940
+ }
941
+ }
942
+
943
+ export { ColumnMeta, CustomDbType, DbTable, DbTableQuery, SqlQueryStatement, SqlRaw, SqlSelectable, SqlValuesCreator, TypeChecker, YourTable, YourTypeMap, createSelect, getObjectListKeys, pgSqlTransformer };
@@ -4,7 +4,6 @@ import { Select, SelectTableOption } from "./select.ts";
4
4
  import { DbTable, SqlQueryStatement } from "./selectable.ts";
5
5
  /** @public */
6
6
  export declare class DbTableQuery<T extends TableType = Record<string, any>, C extends TableType = Partial<T>> extends DbTable<T> {
7
- readonly name: string;
8
7
  private statement;
9
8
  constructor(name: string, columns: readonly string[], statement: SqlValuesCreator);
10
9
  /** 选择全部列 */
@@ -1,5 +1,5 @@
1
1
  import { SqlSelectable, InferQueryResult, SqlQueryStatement } from "./selectable.ts";
2
- import type { ColumnsSelected, RowsOrder, SelectColumns, TableType } from "./type.ts";
2
+ import type { ColumnsSelected, OrderValue, RowsOrder, SelectColumns, TableType } from "./type.ts";
3
3
  interface AddTableFn<T extends TableType> {
4
4
  <Q extends SqlSelectable<any>, A extends InferQueryResult<Q>>(tb: Q, columns?: undefined, option?: SelectTableOption): Select<T>;
5
5
  <Q extends SqlSelectable<any>, A extends InferQueryResult<Q>, C extends ColumnsSelected<A>>(tb: Q, columns: C, option?: SelectTableOption): Select<T & SelectColumns<A, C>>;
@@ -18,7 +18,9 @@ export interface SelectFilterOption<T extends object> {
18
18
  }
19
19
  /** @public */
20
20
  export interface FinalSelect<T extends TableType> extends SqlSelectable<T> {
21
- toQuery(option?: SelectFilterOption<T>): SqlQueryStatement<T>;
21
+ toQuery(option?: SelectFilterOption<T & {
22
+ [key: string]: OrderValue;
23
+ }>): SqlQueryStatement<T>;
22
24
  }
23
25
  /** @public */
24
26
  export interface JoinSelect<T extends TableType> extends FinalSelect<T> {
@@ -1,3 +1,4 @@
1
+ import { SqlSelectable } from "../select/selectable.ts";
1
2
  declare const SQL_RAW: unique symbol;
2
3
  /**
3
4
  * SQL 原始字符对象
@@ -65,6 +66,22 @@ export declare class SqlValuesCreator {
65
66
  * @example 返回示例: " 'abc', '6', 'now()' "
66
67
  */
67
68
  toValues(values: readonly any[]): string;
69
+ /**
70
+ * @public 创建 VALUES AS 语句
71
+ * @example
72
+ * ```ts
73
+ * sqlValue.createValues(
74
+ * "customName",
75
+ * [{age:8, name:"hhh"}, {age:9, name:"row2"}],
76
+ * {age:"INT", name:"TEXT"}
77
+ * )
78
+ * // (VALUES (8:INT,'hhh':TEXT),(9,'row2')) AS customName(age, name)
79
+ * ```
80
+ */
81
+ createValues<T extends {}>(asName: string, values: T[], valuesTypes: Record<string, string | {
82
+ sqlType: string;
83
+ sqlDefault?: string;
84
+ }>): SqlSelectable<T>;
68
85
  }
69
86
  export {};
70
87
  //# sourceMappingURL=sql_value.d.ts.map
@@ -0,0 +1,13 @@
1
+ import { ColumnMeta } from "./infer_db_type.ts";
2
+ /** @public */
3
+ export declare class TypeChecker<T> {
4
+ private map;
5
+ constructor(map: Map<string, ColumnMeta<any>>);
6
+ check(value: {
7
+ [key: string]: any;
8
+ }): T;
9
+ checkList(value: any[]): T[];
10
+ private checkArray;
11
+ private checkItem;
12
+ }
13
+ //# sourceMappingURL=checker.d.ts.map
@@ -0,0 +1,74 @@
1
+ /**
2
+ * 表格列的信息
3
+ * @public
4
+ */
5
+ export declare class ColumnMeta<T> {
6
+ readonly type: CustomDbType<T> | (new (...args: any[]) => T);
7
+ /** 数据库原始数据类型 */
8
+ readonly sqlType: string;
9
+ /** 是否非空 */
10
+ readonly notNull: boolean;
11
+ /** 是否是数组类型 */
12
+ readonly isArray: boolean;
13
+ /** 数据库原始默认值 */
14
+ readonly sqlDefault?: string | undefined;
15
+ constructor(type: CustomDbType<T> | (new (...args: any[]) => T),
16
+ /** 数据库原始数据类型 */
17
+ sqlType: string,
18
+ /** 是否非空 */
19
+ notNull?: boolean,
20
+ /** 是否是数组类型 */
21
+ isArray?: boolean,
22
+ /** 数据库原始默认值 */
23
+ sqlDefault?: string | undefined);
24
+ /** 校验 value 的类型 */
25
+ checkValue(value: any): boolean;
26
+ }
27
+ /**
28
+ * 数据库类型到JS类型的映射
29
+ * @public
30
+ */
31
+ export declare class YourTypeMap<M extends TypeMapDefined> {
32
+ private readonly typeMap;
33
+ static create<T extends TypeMapDefined>(rawTypeMap?: T): YourTypeMap<{
34
+ [key in keyof T]: InferTypeMapDefined<T[key]>;
35
+ }>;
36
+ constructor(typeMap?: M);
37
+ genColumn<T extends keyof M>(type: T, noNull: true, defaultValue?: string): ColumnMeta<M[T]>;
38
+ genColumn<T extends keyof M>(type: T, noNull?: boolean, defaultValue?: string): ColumnMeta<M[T] | null>;
39
+ genColumn<T>(type: keyof M, noNull: true, defaultValue?: string): ColumnMeta<T>;
40
+ genColumn<T>(type: keyof M, noNull?: boolean, defaultValue?: string): ColumnMeta<T | null>;
41
+ genArrColumn<T extends keyof M>(type: T, noNull: true, defaultValue?: string): ColumnMeta<M[T][]>;
42
+ genArrColumn<T extends keyof M>(type: T, noNull?: boolean, defaultValue?: string): ColumnMeta<M[T][] | null>;
43
+ genArrColumn<T>(type: keyof M, notNull: true, defaultValue?: string): ColumnMeta<T[]>;
44
+ genArrColumn<T>(type: keyof M, notNull?: boolean, defaultValue?: string): ColumnMeta<T[] | null>;
45
+ }
46
+ type Constructor<T = any> = new (...args: any[]) => T;
47
+ /**
48
+ * 自定义数据类型
49
+ * @public
50
+ */
51
+ export declare class CustomDbType<T> {
52
+ readonly is: (this: CustomDbType<T>, value: any) => boolean;
53
+ readonly name: string;
54
+ static readonly bigint: CustomDbType<bigint>;
55
+ static readonly number: CustomDbType<number>;
56
+ static readonly string: CustomDbType<string>;
57
+ static readonly boolean: CustomDbType<boolean>;
58
+ constructor(is: (this: CustomDbType<T>, value: any) => boolean, name: string);
59
+ }
60
+ type TypeMapDefined = {
61
+ [key: string]: Constructor | CustomDbType<any>;
62
+ };
63
+ type InferTypeMapDefined<T> = T extends Constructor<infer P> ? TRaw<P> : T extends CustomDbType<infer Q> ? Q : never;
64
+ type TRaw<T> = T extends Number ? number : T extends BigInt ? bigint : T extends String ? string : T extends Boolean ? boolean : T;
65
+ /** @public */
66
+ export type TableDefined = {
67
+ [key: string]: ColumnMeta<any>;
68
+ };
69
+ /** @public */
70
+ export type InferTableDefined<T extends TableDefined> = {
71
+ [key in keyof T]: T[key] extends ColumnMeta<infer P> ? P : unknown;
72
+ };
73
+ export {};
74
+ //# sourceMappingURL=infer_db_type.d.ts.map
@@ -0,0 +1,4 @@
1
+ export * from "./checker.ts";
2
+ export * from "./infer_db_type.ts";
3
+ export * from "./table.ts";
4
+ //# sourceMappingURL=mod.d.ts.map
@@ -0,0 +1,16 @@
1
+ import { DbTableQuery } from "../select/TableQuery.ts";
2
+ import type { TableType } from "../select/type.ts";
3
+ import type { SqlValuesCreator } from "../sql_value/sql_value.ts";
4
+ import type { ColumnMeta, TableDefined } from "./infer_db_type.ts";
5
+ import { TypeChecker } from "./checker.ts";
6
+ /**
7
+ * 完整数据库表数据
8
+ * @public
9
+ */
10
+ export declare class YourTable<T extends TableType = TableType, C extends TableType = T> extends DbTableQuery<T, C> {
11
+ private define;
12
+ constructor(name: string, define: TableDefined, sqlValue: SqlValuesCreator);
13
+ getColumnMeta(name: keyof T): ColumnMeta<unknown>;
14
+ createTypeChecker<T>(keys: readonly string[]): TypeChecker<T>;
15
+ }
16
+ //# sourceMappingURL=table.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asla/yoursql",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "types": "./dist/mod.d.ts",
@@ -10,6 +10,7 @@
10
10
  "build": "pnpm rollup -c build/rollup.config.js && pnpm run ci:check-api -l",
11
11
  "test": "vitest",
12
12
  "type:check": "tsc",
13
+ "publish-check": "deno publish --dry-run --allow-dirty",
13
14
  "ci:check-api": "api-extractor run -c api-extractor.jsonc -v"
14
15
  },
15
16
  "devDependencies": {