sasat 0.19.15 → 0.19.17

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.
@@ -28,7 +28,7 @@ ${new ImportDeclaration(['relationMap', 'tableInfo'], './__generated__/relationM
28
28
  export abstract class BaseDBDataSource<
29
29
  Entity extends EntityType,
30
30
  Identifiable extends object,
31
- Creatable,
31
+ Creatable extends EntityType,
32
32
  Updatable extends Identifiable,
33
33
  EntityFields extends Fields<Entity>,
34
34
  QueryResult extends Partial<Entity> & Identifiable,
@@ -10,7 +10,11 @@ const makeTypedefString = (typeName, typedef, type) => {
10
10
  return `\
11
11
  ${type} ${typeName} {
12
12
  ${entries
13
- .map(([field, value]) => ` ${field}${makeArgs(value.args)}: ${value.return}`)
13
+ .map(([field, value]) => {
14
+ if (!value.return)
15
+ throw new Error(`Return type required: ${typeName}.${field}`);
16
+ return ` ${field}${makeArgs(value.args)}: ${value.return}`;
17
+ })
14
18
  .join('\n')}
15
19
  }
16
20
  `;
@@ -8,6 +8,7 @@ type ValueSet = {
8
8
  export type Create = {
9
9
  table: string;
10
10
  values: ValueSet[];
11
+ upsert?: string[];
11
12
  };
12
13
  export type Update = {
13
14
  table: string;
@@ -2,9 +2,18 @@ import { SqlString } from '../../sql/sqlString.js';
2
2
  import { Sql } from '../query/sql/nodeToSql.js';
3
3
  const escape = SqlString.escape;
4
4
  const escapeId = SqlString.escapeId;
5
+ const onDuplicateKeyUpdate = (columns) => {
6
+ if (!columns || columns.length === 0)
7
+ return '';
8
+ return (' ON DUPLICATE KEY UPDATE ' +
9
+ columns
10
+ .map(escapeId)
11
+ .map(it => `${it} = VALUES(${it})`)
12
+ .join(','));
13
+ };
5
14
  export const createToSql = (dsl, tableInfo) => {
6
15
  const map = tableInfo[dsl.table].columnMap;
7
- return `INSERT INTO ${escapeId(dsl.table)}(${dsl.values.map(it => escapeId(map[it.field]))}) VALUES(${dsl.values.map(it => escape(it.value))})`;
16
+ return `INSERT INTO ${escapeId(dsl.table)}(${dsl.values.map(it => escapeId(map[it.field]))}) VALUES(${dsl.values.map(it => escape(it.value))})${onDuplicateKeyUpdate(dsl.upsert)}`;
8
17
  };
9
18
  export const updateToSql = (dsl, tableInfo) => {
10
19
  const map = tableInfo[dsl.table].columnMap;
@@ -23,7 +23,7 @@ export type QueryOptions = {
23
23
  offset?: number;
24
24
  lock?: LockMode;
25
25
  };
26
- export declare abstract class SasatDBDatasource<Entity extends EntityType, Identifiable extends object, Creatable, Updatable extends Identifiable, EntityFields extends Fields<Entity>, QueryResult extends Partial<Entity> & Identifiable> implements Repository<Entity, Identifiable, Creatable, Updatable> {
26
+ export declare abstract class SasatDBDatasource<Entity extends EntityType, Identifiable extends object, Creatable extends EntityType, Updatable extends Identifiable, EntityFields extends Fields<Entity>, QueryResult extends Partial<Entity> & Identifiable> implements Repository<Entity, Identifiable, Creatable, Updatable> {
27
27
  protected client: SQLExecutor;
28
28
  protected abstract relationMap: RelationMap<any>;
29
29
  protected abstract tableInfo: TableInfo;
@@ -33,11 +33,15 @@ export declare abstract class SasatDBDatasource<Entity extends EntityType, Ident
33
33
  protected abstract readonly identifyFields: string[];
34
34
  protected abstract readonly autoIncrementColumn?: string;
35
35
  protected queryLogger: (sql: string) => void;
36
+ protected commandLogger: (sql: string) => void;
36
37
  constructor(client?: SQLExecutor);
37
38
  protected abstract getDefaultValueString(): Partial<{
38
39
  [P in keyof Entity]: Entity[P] | string | null;
39
40
  }>;
40
- create(entity: Creatable): Promise<Entity>;
41
+ create(entity: Creatable, upsert?: {
42
+ updateColumns: string[];
43
+ }): Promise<Entity>;
44
+ upsert<T extends Creatable & Partial<Entity>>(entity: T, updateFields?: (keyof T)[]): Promise<Entity>;
41
45
  update(entity: Updatable): Promise<CommandResponse>;
42
46
  delete(entity: Identifiable): Promise<CommandResponse>;
43
47
  first(fields?: EntityFields, option?: Omit<QueryOptions, 'limit' | 'offset'>, context?: unknown): Promise<QueryResult | null>;
@@ -53,5 +57,6 @@ export declare abstract class SasatDBDatasource<Entity extends EntityType, Ident
53
57
  getRelationMap(): {
54
58
  [to: string]: import("./dsl/query/createQueryResolveInfo.js").RelationInfo<any>;
55
59
  };
60
+ protected fieldToColumn(fields: string[]): string[];
56
61
  }
57
62
  export {};
@@ -8,8 +8,9 @@ export class SasatDBDatasource {
8
8
  constructor(client = getDbClient()) {
9
9
  this.client = client;
10
10
  this.queryLogger = noop;
11
+ this.commandLogger = noop;
11
12
  }
12
- async create(entity) {
13
+ async create(entity, upsert) {
13
14
  const obj = {
14
15
  ...this.getDefaultValueString(),
15
16
  ...entity,
@@ -20,8 +21,11 @@ export class SasatDBDatasource {
20
21
  field: column,
21
22
  value,
22
23
  })),
24
+ upsert: upsert?.updateColumns,
23
25
  };
24
- const response = await this.client.rawCommand(createToSql(dsl, this.tableInfo));
26
+ const sql = createToSql(dsl, this.tableInfo);
27
+ this.commandLogger(sql);
28
+ const response = await this.client.rawCommand(sql);
25
29
  if (!this.autoIncrementColumn)
26
30
  return obj;
27
31
  return {
@@ -29,6 +33,11 @@ export class SasatDBDatasource {
29
33
  [this.autoIncrementColumn]: response.insertId,
30
34
  };
31
35
  }
36
+ async upsert(entity, updateFields = this.primaryKeys) {
37
+ return this.create(entity, {
38
+ updateColumns: this.fieldToColumn(updateFields),
39
+ });
40
+ }
32
41
  update(entity) {
33
42
  const dsl = {
34
43
  table: this.tableName,
@@ -38,14 +47,18 @@ export class SasatDBDatasource {
38
47
  })),
39
48
  where: this.createIdentifiableExpression(entity),
40
49
  };
41
- return this.client.rawCommand(updateToSql(dsl, this.tableInfo));
50
+ const sql = updateToSql(dsl, this.tableInfo);
51
+ this.commandLogger(sql);
52
+ return this.client.rawCommand(sql);
42
53
  }
43
54
  async delete(entity) {
44
55
  const dsl = {
45
56
  table: this.tableName,
46
57
  where: this.createIdentifiableExpression(entity),
47
58
  };
48
- return this.client.rawCommand(deleteToSql(dsl));
59
+ const sql = deleteToSql(dsl);
60
+ this.commandLogger(sql);
61
+ return this.client.rawCommand(sql);
49
62
  }
50
63
  async first(fields, option, context) {
51
64
  const result = await this.find(fields, option, context);
@@ -88,5 +101,8 @@ export class SasatDBDatasource {
88
101
  getRelationMap() {
89
102
  return this.relationMap[this.tableName];
90
103
  }
104
+ fieldToColumn(fields) {
105
+ return fields.map(it => this.tableInfo[this.tableName].columnMap[it] || it);
106
+ }
91
107
  }
92
108
  const noop = () => { };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sasat",
3
- "version": "0.19.15",
3
+ "version": "0.19.17",
4
4
  "repository": "https://github.com/nin138/sasat.git",
5
5
  "author": "nin138 <ninian138@gmail.com>",
6
6
  "license": "MIT",
@@ -44,22 +44,22 @@
44
44
  "devDependencies": {
45
45
  "@apollo/server": "^4.3.0",
46
46
  "@types/fs-extra": "11.0.1",
47
- "@types/jest": "29.4.0",
47
+ "@types/jest": "29.5.2",
48
48
  "@types/js-yaml": "4.0.5",
49
- "@types/node": "18.13.0",
49
+ "@types/node": "18.16.18",
50
50
  "@types/pluralize": "0.0.29",
51
- "@types/prettier": "2.7.2",
51
+ "@types/prettier": "2.7.3",
52
52
  "@types/sqlstring": "2.3.0",
53
- "@typescript-eslint/eslint-plugin": "5.51.0",
54
- "@typescript-eslint/parser": "5.51.0",
53
+ "@typescript-eslint/eslint-plugin": "5.59.11",
54
+ "@typescript-eslint/parser": "5.59.11",
55
55
  "env-cmd": "10.1.0",
56
- "eslint": "8.33.0",
57
- "eslint-config-prettier": "8.6.0",
56
+ "eslint": "8.42.0",
57
+ "eslint-config-prettier": "8.8.0",
58
58
  "eslint-plugin-import": "^2.26.0",
59
59
  "eslint-plugin-prettier": "4.2.1",
60
60
  "husky": "8.0.3",
61
- "jest": "29.4.2",
62
- "lint-staged": "13.1.1",
61
+ "jest": "29.5.0",
62
+ "lint-staged": "13.2.2",
63
63
  "sasat": "link:./lib",
64
64
  "ts-jest": "29.0.5",
65
65
  "ts-node": "10.9.1",