@apisr/drizzle-model 0.0.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/.turbo/turbo-check-types.log +2 -0
- package/ROADMAP.md +1 -0
- package/TODO.md +64 -0
- package/drizzle.config.ts +11 -0
- package/package.json +35 -0
- package/src/index.ts +1 -0
- package/src/model/builder.ts +46 -0
- package/src/model/config.ts +35 -0
- package/src/model/core/joins.ts +279 -0
- package/src/model/core/projection.ts +47 -0
- package/src/model/core/runtime.ts +249 -0
- package/src/model/core/thenable.ts +85 -0
- package/src/model/core/transform.ts +45 -0
- package/src/model/core/where.ts +183 -0
- package/src/model/core/with.ts +28 -0
- package/src/model/dialect.ts +11 -0
- package/src/model/foreigns.ts +31 -0
- package/src/model/format.ts +19 -0
- package/src/model/index.ts +1 -0
- package/src/model/methods/exclude.ts +32 -0
- package/src/model/methods/include.ts +3 -0
- package/src/model/methods/insert.ts +16 -0
- package/src/model/methods/levels.ts +2 -0
- package/src/model/methods/query/where.ts +48 -0
- package/src/model/methods/return.ts +39 -0
- package/src/model/methods/select.ts +38 -0
- package/src/model/methods/update.ts +4 -0
- package/src/model/methods/upsert.ts +54 -0
- package/src/model/methods/with.ts +40 -0
- package/src/model/model.ts +148 -0
- package/src/model/options.ts +64 -0
- package/src/model/query/operations.ts +170 -0
- package/src/model/relation.ts +121 -0
- package/src/model/result.ts +91 -0
- package/src/model/shape.ts +8 -0
- package/src/model/table.ts +127 -0
- package/src/types.ts +16 -0
- package/tests/builder-v2-mysql.type-test.ts +40 -0
- package/tests/builder-v2.type-test.ts +343 -0
- package/tests/builder.test.ts +63 -0
- package/tests/db.ts +25 -0
- package/tests/find.test.ts +155 -0
- package/tests/insert.test.ts +233 -0
- package/tests/relations.ts +38 -0
- package/tests/schema.ts +49 -0
- package/tsconfig.json +36 -0
- package/tsdown.config.ts +12 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
TableRelationalConfig,
|
|
3
|
+
TablesRelationalConfig,
|
|
4
|
+
} from "drizzle-orm/relations";
|
|
5
|
+
import type { ModelIdentifier } from "./model.ts";
|
|
6
|
+
import type { IsTable, TableOutput } from "./table.ts";
|
|
7
|
+
import type { RecursiveBooleanRecord } from "../types.ts";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Defines the cardinality of a relation: "one" (hasOne) or "many" (hasMany).
|
|
11
|
+
*/
|
|
12
|
+
export type RelationKind = "one" | "many";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Utility type to wrap a type T in an array if the relation kind is "many",
|
|
16
|
+
* otherwise returns T as is.
|
|
17
|
+
*
|
|
18
|
+
* @typeParam Kind - "one" or "many"
|
|
19
|
+
* @typeParam T - The type to potentially wrap
|
|
20
|
+
*/
|
|
21
|
+
export type ApplyRelationCardinality<
|
|
22
|
+
Kind extends RelationKind,
|
|
23
|
+
T,
|
|
24
|
+
> = Kind extends "many" ? T[] : T;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Extracts the metadata for a specific relation from a table's configuration.
|
|
28
|
+
*
|
|
29
|
+
* @typeParam TTable - Relational configuration for the table
|
|
30
|
+
* @typeParam Key - Name of the relation field
|
|
31
|
+
*/
|
|
32
|
+
export type RelationMeta<
|
|
33
|
+
TTable extends TableRelationalConfig,
|
|
34
|
+
Key extends string,
|
|
35
|
+
> = TTable["relations"][Key];
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Resolves the configuration of the target table in a relation.
|
|
39
|
+
*
|
|
40
|
+
* @typeParam TSchema - Full relational schema
|
|
41
|
+
* @typeParam Meta - Metadata object containing the target table name
|
|
42
|
+
*/
|
|
43
|
+
export type TargetTable<
|
|
44
|
+
TSchema extends TablesRelationalConfig,
|
|
45
|
+
Meta extends { targetTableName: string; },
|
|
46
|
+
> = TSchema[Meta["targetTableName"]];
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Resolves the raw row type of a related table.
|
|
50
|
+
*
|
|
51
|
+
* @typeParam Key - Name of the relation
|
|
52
|
+
* @typeParam TSchema - Full relational schema
|
|
53
|
+
* @typeParam TTable - Relational configuration for the source table
|
|
54
|
+
*/
|
|
55
|
+
export type RelationTargetRow<
|
|
56
|
+
Key extends string,
|
|
57
|
+
TSchema extends TablesRelationalConfig,
|
|
58
|
+
TTable extends TableRelationalConfig,
|
|
59
|
+
> = TableOutput<
|
|
60
|
+
IsTable<TargetTable<TSchema, RelationMeta<TTable, Key>>["table"]>
|
|
61
|
+
>;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Resolves the type of a single relation field based on the selection value.
|
|
65
|
+
*
|
|
66
|
+
* If the value is a nested selection object, it recursively resolves that selection
|
|
67
|
+
* and merges it with the target row type.
|
|
68
|
+
* Finally, it applies the correct cardinality (array or single object).
|
|
69
|
+
*
|
|
70
|
+
* @typeParam Key - Name of the relation
|
|
71
|
+
* @typeParam Value - The selection value (boolean or nested object)
|
|
72
|
+
* @typeParam TSchema - Full relational schema
|
|
73
|
+
* @typeParam TTable - Relational configuration for the source table
|
|
74
|
+
*/
|
|
75
|
+
export type ResolveSingleRelation<
|
|
76
|
+
Key extends string,
|
|
77
|
+
Value,
|
|
78
|
+
TSchema extends TablesRelationalConfig,
|
|
79
|
+
TTable extends TableRelationalConfig,
|
|
80
|
+
> = Value extends Record<string, any>
|
|
81
|
+
? ApplyRelationCardinality<
|
|
82
|
+
RelationMeta<TTable, Key>["relationType"],
|
|
83
|
+
ResolveRelationSelection<
|
|
84
|
+
Value,
|
|
85
|
+
TSchema,
|
|
86
|
+
TargetTable<TSchema, RelationMeta<TTable, Key>>
|
|
87
|
+
> &
|
|
88
|
+
RelationTargetRow<Key, TSchema, TTable>
|
|
89
|
+
>
|
|
90
|
+
: ApplyRelationCardinality<
|
|
91
|
+
RelationMeta<TTable, Key>["relationType"],
|
|
92
|
+
RelationTargetRow<Key, TSchema, TTable>
|
|
93
|
+
>;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Recursively resolves a selection object into a typed result object.
|
|
97
|
+
*
|
|
98
|
+
* Iterates over keys in the selection that are true or objects, resolving
|
|
99
|
+
* each relation and building the final output type.
|
|
100
|
+
*
|
|
101
|
+
* @typeParam TSelection - The selection object passed to .with()
|
|
102
|
+
* @typeParam TSchema - Full relational schema
|
|
103
|
+
* @typeParam TTable - Relational configuration for the current table
|
|
104
|
+
*/
|
|
105
|
+
export type ResolveRelationSelection<
|
|
106
|
+
TSelection extends Record<string, any>,
|
|
107
|
+
TSchema extends TablesRelationalConfig,
|
|
108
|
+
TTable extends TableRelationalConfig,
|
|
109
|
+
> = {
|
|
110
|
+
[Key in keyof TSelection as TSelection[Key] extends
|
|
111
|
+
| true
|
|
112
|
+
| RecursiveBooleanRecord
|
|
113
|
+
| ModelIdentifier<any>
|
|
114
|
+
? Key & string
|
|
115
|
+
: never]: ResolveSingleRelation<
|
|
116
|
+
Key & string,
|
|
117
|
+
TSelection[Key],
|
|
118
|
+
TSchema,
|
|
119
|
+
TTable
|
|
120
|
+
>;
|
|
121
|
+
};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
TableRelationalConfig,
|
|
3
|
+
TablesRelationalConfig,
|
|
4
|
+
} from "drizzle-orm/relations";
|
|
5
|
+
import type { MethodWithResult, MethodWithValue } from "./methods/with.ts";
|
|
6
|
+
import type { MethodSelectResult, MethodSelectValue } from "./methods/select.ts";
|
|
7
|
+
import type {
|
|
8
|
+
MethodExcludeResult,
|
|
9
|
+
MethodExcludeValue,
|
|
10
|
+
} from "./methods/exclude.ts";
|
|
11
|
+
import type { MethodReturnResult } from "./methods/return.ts";
|
|
12
|
+
import type { ReturningIdDialects } from "./dialect.ts";
|
|
13
|
+
import type { TableOutput } from "./table.ts";
|
|
14
|
+
import type { ModelConfig } from "./config.ts";
|
|
15
|
+
import type { ResolveOptionsFormat } from "./options.ts";
|
|
16
|
+
import type { ModelFormatValue } from "./format.ts";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Represents the result of a model operation (like findMany or findFirst).
|
|
20
|
+
*
|
|
21
|
+
* It extends Promise to be awaitable, returning the result data.
|
|
22
|
+
* It also exposes a `.with()` method for chaining relation loading.
|
|
23
|
+
*
|
|
24
|
+
* @typeParam TResult - The type of the data returned (e.g. Row[])
|
|
25
|
+
* @typeParam TSchema - Full relational schema
|
|
26
|
+
* @typeParam TTable - Relational configuration for the current table
|
|
27
|
+
*/
|
|
28
|
+
export interface ModelQueryResult<
|
|
29
|
+
TResult extends Record<string, any>,
|
|
30
|
+
TConfig extends ModelConfig,
|
|
31
|
+
TExcludedKeys extends string = string,
|
|
32
|
+
TSchema extends TablesRelationalConfig = TConfig["schema"],
|
|
33
|
+
TTable extends TableRelationalConfig = TConfig["table"],
|
|
34
|
+
TFormat extends Record<string, any> | undefined = ResolveOptionsFormat<TConfig["options"]["format"]>
|
|
35
|
+
> extends Promise<ModelFormatValue<TResult, TFormat>> {
|
|
36
|
+
with<TValue extends MethodWithValue<TSchema, TTable["relations"]>, TExcludeKeys extends string = TExcludedKeys | "with">(
|
|
37
|
+
value: TValue,
|
|
38
|
+
): ModelQueryResult<
|
|
39
|
+
MethodWithResult<TValue, TResult, TSchema, TTable>,
|
|
40
|
+
TConfig,
|
|
41
|
+
TExcludeKeys
|
|
42
|
+
>,
|
|
43
|
+
|
|
44
|
+
select<TValue extends MethodSelectValue<TResult>, TExcludeKeys extends string = TExcludedKeys | "select">(
|
|
45
|
+
value: TValue,
|
|
46
|
+
): ModelQueryResult<
|
|
47
|
+
MethodSelectResult<TValue, TResult>,
|
|
48
|
+
TConfig,
|
|
49
|
+
TExcludeKeys
|
|
50
|
+
>,
|
|
51
|
+
|
|
52
|
+
exclude<TValue extends MethodExcludeValue<TResult>, TExcludeKeys extends string = TExcludedKeys | "exclude">(
|
|
53
|
+
value: TValue,
|
|
54
|
+
): ModelQueryResult<
|
|
55
|
+
MethodExcludeResult<TValue, TResult>,
|
|
56
|
+
TConfig,
|
|
57
|
+
TExcludeKeys
|
|
58
|
+
>,
|
|
59
|
+
|
|
60
|
+
raw<TExcludeKeys extends string = TExcludedKeys | "raw">(): ModelQueryResult<TResult, TConfig, TExcludeKeys, TSchema, TTable, undefined>;
|
|
61
|
+
|
|
62
|
+
debug(): any;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface ModelMutateResult<
|
|
66
|
+
TBaseResult extends Record<string, any> | void,
|
|
67
|
+
TConfig extends ModelConfig,
|
|
68
|
+
TResultType extends string = "one"
|
|
69
|
+
> extends Promise<TBaseResult> {
|
|
70
|
+
// TODO: Planned for future
|
|
71
|
+
// with<TValue extends MethodWithInsertValue<TSchema, TTable["relations"]>>(
|
|
72
|
+
// value: TValue,
|
|
73
|
+
// ): void;
|
|
74
|
+
|
|
75
|
+
return<
|
|
76
|
+
TValue extends MethodSelectValue<TableOutput<TConfig["table"]>> | undefined,
|
|
77
|
+
TReturnResult extends MethodReturnResult<TResultType, TConfig> = MethodReturnResult<TResultType, TConfig>,
|
|
78
|
+
TResult extends Record<string, any> = TValue extends undefined ? TReturnResult : MethodSelectResult<Exclude<TValue, undefined>, TReturnResult>,
|
|
79
|
+
>(
|
|
80
|
+
value?: TConfig["dialect"] extends ReturningIdDialects
|
|
81
|
+
? never
|
|
82
|
+
: TValue,
|
|
83
|
+
): Omit<
|
|
84
|
+
ModelMutateResult<
|
|
85
|
+
TResult,
|
|
86
|
+
TConfig,
|
|
87
|
+
TResultType
|
|
88
|
+
>,
|
|
89
|
+
"with"
|
|
90
|
+
>;
|
|
91
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ModelConfig } from "./config.ts";
|
|
2
|
+
import type { ModelBase, ModelIdentifier } from "./model.ts";
|
|
3
|
+
import type { ResolveOptionsMethods } from "./options.ts";
|
|
4
|
+
|
|
5
|
+
export type ModelShape<TConfig extends ModelConfig> =
|
|
6
|
+
ModelIdentifier<TConfig["table"]["name"]> &
|
|
7
|
+
ModelBase<TConfig> &
|
|
8
|
+
ResolveOptionsMethods<TConfig["options"]["methods"]>;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import type { InferInsertModel, InferSelectModel, Table } from "drizzle-orm";
|
|
2
|
+
import type { SchemaEntry, TableRelationalConfig } from "drizzle-orm/relations";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Extracts the column definitions from a Drizzle table configuration.
|
|
6
|
+
*
|
|
7
|
+
* This utility resolves the actual Drizzle table type and maps it
|
|
8
|
+
* to its available column metadata.
|
|
9
|
+
*
|
|
10
|
+
* @typeParam TTable - Relational configuration for the table
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Returns the column map from the underlying Drizzle table definition.
|
|
14
|
+
*
|
|
15
|
+
* @typeParam TTable - Relational configuration for the table
|
|
16
|
+
*/
|
|
17
|
+
export type TableColumns<TTable extends TableRelationalConfig> = IsTable<TTable["table"]>["_"]["columns"];
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Resolves a single column definition from a table by column name.
|
|
21
|
+
*
|
|
22
|
+
* @typeParam TColumnName - Name of the column to extract
|
|
23
|
+
* @typeParam TTable - Relational configuration for the table
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* Selects a single column definition by name.
|
|
27
|
+
*
|
|
28
|
+
* @typeParam TColumnName - Name of the column to extract
|
|
29
|
+
* @typeParam TTable - Relational configuration for the table
|
|
30
|
+
*/
|
|
31
|
+
export type TableColumn<
|
|
32
|
+
TColumnName extends string,
|
|
33
|
+
TTable extends TableRelationalConfig,
|
|
34
|
+
> = TableColumns<TTable>[TColumnName];
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Resolves the inferred select model for a table-like input.
|
|
38
|
+
*
|
|
39
|
+
* @typeParam TTable - Relation config, schema entry, or table
|
|
40
|
+
*/
|
|
41
|
+
export type TableOutput<TTable extends TableRelationalConfig | SchemaEntry | Table> =
|
|
42
|
+
NormalizeTable<TTable> extends Table ? InferSelectModel<NormalizeTable<TTable>> : never;
|
|
43
|
+
// Is relation?
|
|
44
|
+
// (TTable extends TableRelationalConfig
|
|
45
|
+
// ? InferSelectModel<IsTable<TTable["table"]>>
|
|
46
|
+
// : (TTable extends SchemaEntry
|
|
47
|
+
// // Is schema entry (view/table)?
|
|
48
|
+
// ? InferSelectModel<IsTable<TTable>>
|
|
49
|
+
// : (TTable extends Table
|
|
50
|
+
// // Is Table?
|
|
51
|
+
// ? InferSelectModel<TTable>
|
|
52
|
+
// : never)));
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Normalizes relation config and schema entries into a Drizzle table type.
|
|
56
|
+
*
|
|
57
|
+
* @typeParam TTable - Relation config, schema entry, or table
|
|
58
|
+
*/
|
|
59
|
+
export type NormalizeTable<TTable extends TableRelationalConfig | SchemaEntry | Table> =
|
|
60
|
+
// Is relation?
|
|
61
|
+
(TTable extends TableRelationalConfig
|
|
62
|
+
? IsTable<TTable["table"]>
|
|
63
|
+
: (TTable extends SchemaEntry
|
|
64
|
+
// Is schema entry (view/table)?
|
|
65
|
+
? IsTable<TTable>
|
|
66
|
+
: (TTable extends Table
|
|
67
|
+
// Is Table?
|
|
68
|
+
? TTable
|
|
69
|
+
: never)));
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Collects target table names from all relations.
|
|
73
|
+
*
|
|
74
|
+
* @typeParam TTable - Relational configuration for the table
|
|
75
|
+
*/
|
|
76
|
+
export type TableRelationsTableName<
|
|
77
|
+
TTable extends TableRelationalConfig
|
|
78
|
+
> = {
|
|
79
|
+
[K in keyof TTable["relations"]]:
|
|
80
|
+
TTable["relations"][K]["targetTableName"]
|
|
81
|
+
}[keyof TTable["relations"]];
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Maps non-"many" relations to their target table names.
|
|
85
|
+
*
|
|
86
|
+
* @typeParam TTable - Relational configuration for the table
|
|
87
|
+
*/
|
|
88
|
+
type TableOneRelationsMap<TTable extends TableRelationalConfig> = {
|
|
89
|
+
[K in keyof TTable["relations"]as
|
|
90
|
+
TTable["relations"][K]["relationType"] extends "many"
|
|
91
|
+
? never
|
|
92
|
+
: K
|
|
93
|
+
]: TTable["relations"][K]["targetTableName"]
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Collects target table names for non-"many" relations.
|
|
98
|
+
*
|
|
99
|
+
* @typeParam TTable - Relational configuration for the table
|
|
100
|
+
*/
|
|
101
|
+
export type TableOneRelationsTableName<
|
|
102
|
+
TTable extends TableRelationalConfig
|
|
103
|
+
> = TableOneRelationsMap<TTable>[keyof TableOneRelationsMap<TTable>];
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Narrows a type to a Drizzle table when possible.
|
|
107
|
+
*
|
|
108
|
+
* @typeParam T - Candidate table type
|
|
109
|
+
*/
|
|
110
|
+
export type IsTable<T> = T extends Table ? T : never;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Infers insert model for a Drizzle table.
|
|
114
|
+
*
|
|
115
|
+
* @typeParam TTable - Drizzle table type
|
|
116
|
+
*/
|
|
117
|
+
export type TableInsertModel<TTable extends Table> =
|
|
118
|
+
InferInsertModel<TTable>;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Accepts a single insert payload or a batch of insert payloads.
|
|
122
|
+
*
|
|
123
|
+
* @typeParam TTable - Drizzle table type
|
|
124
|
+
*/
|
|
125
|
+
export type TableInsertValues<TTable extends Table> =
|
|
126
|
+
| InferInsertModel<TTable>
|
|
127
|
+
| InferInsertModel<TTable>[];
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type Compose<T, U> = T & U;
|
|
2
|
+
export type Fallback<A, B> = A extends undefined ? B : A;
|
|
3
|
+
export type Replace<T, R> = Omit<T, keyof R> & R;
|
|
4
|
+
export type UnwrapArray<T> = T extends (infer R)[] ? R : T;
|
|
5
|
+
|
|
6
|
+
export type AddToValues<T extends Record<PropertyKey, any>, A> = {
|
|
7
|
+
[K in keyof T]: T[K] & A
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export type AddUnionToValues<T extends Record<PropertyKey, any>, A> = {
|
|
11
|
+
[K in keyof T]: T[K] | A
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export interface RecursiveBooleanRecord {
|
|
15
|
+
[key: string]: boolean | RecursiveBooleanRecord;
|
|
16
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { mysqlDb } from "./db";
|
|
2
|
+
import { modelBuilder } from "src/model";
|
|
3
|
+
import { boolean, int, text, mysqlTable, varchar } from 'drizzle-orm/mysql-core';
|
|
4
|
+
import { defineRelations } from "drizzle-orm";
|
|
5
|
+
import { esc } from "@/model/query/operations";
|
|
6
|
+
|
|
7
|
+
const usersTable = mysqlTable('users', {
|
|
8
|
+
id: int('id').primaryKey(),
|
|
9
|
+
name: text('name').notNull(),
|
|
10
|
+
verified: boolean('verified').notNull().default(false),
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const usersTableDefFn = mysqlTable('users_default_fn', {
|
|
14
|
+
customId: varchar('id', { length: 256 }).primaryKey().$defaultFn(() => "123"),
|
|
15
|
+
name: text('name').notNull(),
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const schema = {
|
|
19
|
+
usersTable,
|
|
20
|
+
usersTableDefFn
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const relations = defineRelations(schema, (r) => ({
|
|
24
|
+
usersTable: {}
|
|
25
|
+
}));
|
|
26
|
+
|
|
27
|
+
const model = modelBuilder({
|
|
28
|
+
schema,
|
|
29
|
+
db: mysqlDb,
|
|
30
|
+
relations,
|
|
31
|
+
dialect: "MySQL"
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const userModel = model("usersTableDefFn", {});
|
|
35
|
+
|
|
36
|
+
const testRaw1 = await userModel.where({
|
|
37
|
+
customId: esc("123")
|
|
38
|
+
}).delete().return();
|
|
39
|
+
|
|
40
|
+
// testRaw1[0].
|