Skip to content

Commit 8b35420

Browse files
committed
1.1.0-alpha.0
1 parent be79531 commit 8b35420

7 files changed

Lines changed: 175 additions & 41 deletions

File tree

.npmignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ site
1616
.eslintignore
1717
.env.example
1818
tsconfig.json
19+
tsconfig-cjs.json
1920
.scannerwork
2021
sonar-project.properties
2122
coverage

package.json

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@grandlinex/bundle-postgresql",
3-
"version": "1.0.3",
3+
"version": "1.1.0-alpha.0",
44
"description": "",
55
"type": "module",
66
"exports": {
@@ -26,6 +26,7 @@
2626
"lint": "eslint src",
2727
"test": "jest --runInBand ",
2828
"run": "ts-node tests/run.ts",
29+
"pack": "eslint && npm run buildprep && npm pack",
2930
"test-converage": "jest --runInBand --ci --collectCoverage --coverageDirectory=\"./coverage\" --reporters=default --reporters=jest-junit",
3031
"makeDocs": "typedoc"
3132
},
@@ -42,35 +43,32 @@
4243
},
4344
"license": "BSD-3-Clause",
4445
"dependencies": {
45-
"@grandlinex/core": "1.0.1",
46-
"pg": "8.12.0",
46+
"@grandlinex/core": "1.1.0-alpha.0",
47+
"pg": "8.16.3",
4748
"moment": "2.30.1",
48-
"@types/pg": "8.11.6"
49+
"@types/pg": "8.15.5"
4950
},
5051
"devDependencies": {
51-
"@types/jest": "29.5.12",
52-
"@types/node": "22.0.0",
52+
"@types/jest": "29.5.14",
53+
"@types/node": "22.15.20",
5354
"@typescript-eslint/eslint-plugin": "7.18.0",
5455
"@typescript-eslint/parser": "7.18.0",
55-
"cross-env": "7.0.3",
56-
"eslint": "8.57.0",
57-
"eslint-config-airbnb": "^19.0.4",
58-
"eslint-config-airbnb-typescript": "^18.0.0",
59-
"eslint-config-prettier": "^9.1.0",
60-
"eslint-plugin-import": "^2.29.1",
61-
"eslint-plugin-jest": "^28.6.0",
62-
"eslint-plugin-jsx-a11y": "^6.9.0",
63-
"eslint-plugin-prettier": "^5.2.1",
64-
"eslint-plugin-react": "^7.35.0",
65-
"eslint-plugin-react-hooks": "^4.6.2",
56+
"eslint": "8.57.1",
57+
"eslint-config-airbnb": "19.0.4",
58+
"eslint-config-airbnb-typescript": "18.0.0",
59+
"eslint-config-prettier": "9.1.0",
60+
"eslint-plugin-import": "2.29.1",
61+
"eslint-plugin-jest": "28.6.0",
62+
"eslint-plugin-jsx-a11y": "6.9.0",
63+
"eslint-plugin-prettier": "5.2.1",
6664
"jest": "29.7.0",
6765
"jest-junit": "16.0.0",
68-
"prettier": "3.3.3",
69-
"ts-jest": "29.1.5",
70-
"ts-loader": "9.5.1",
66+
"prettier": "3.5.3",
67+
"ts-jest": "29.3.4",
68+
"ts-loader": "9.5.2",
7169
"ts-node": "10.9.2",
72-
"typedoc": "0.26.5",
73-
"typescript": "5.5.4"
70+
"typedoc": "0.28.10",
71+
"typescript": "5.9.2"
7472
},
7573
"repository": {
7674
"type": "git",

src/class/PGCon.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
ICorePresenter,
1414
IDataBase,
1515
IEntity,
16+
QInterfaceSearch,
1617
QueryInterface,
1718
RawQuery,
1819
} from '@grandlinex/core';
@@ -195,7 +196,7 @@ export default class PGCon<
195196

196197
async findEntity<E extends CoreEntity>(
197198
config: EntityConfig<E>,
198-
search: { [D in keyof E]?: E[D] | undefined },
199+
search: QInterfaceSearch<E>,
199200
): Promise<E | null> {
200201
let searchQ = '';
201202
const param: any[] = [];

src/class/PGUpdate.ts

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import { CoreDBUpdate, RawQuery, XUtil } from '@grandlinex/core';
2+
import PGCon from './PGCon.js';
3+
4+
export default abstract class PGUpdate extends CoreDBUpdate<PGCon> {
5+
/**
6+
* Initialize a new table in the database.
7+
* This method is used to create a new table in the database.
8+
* @param className
9+
*/
10+
protected initNewTable(className: string): Promise<boolean> {
11+
return this.getDb().getEntityWrapper(className)!.init();
12+
}
13+
14+
/**
15+
* Alter a table to add a new column.
16+
* @param className
17+
* @param columName
18+
* @param type
19+
* @param notNull
20+
* @param defaultValue
21+
* @param deleteDefault
22+
* @protected
23+
*/
24+
protected async alterTableAddColumn(
25+
className: string,
26+
columName: string,
27+
type: string,
28+
notNull: boolean,
29+
defaultValue?: any,
30+
deleteDefault?: boolean,
31+
): Promise<boolean> {
32+
const db = this.getDb();
33+
const tableName = XUtil.camelToSnakeCase(className);
34+
const query: RawQuery[] = [];
35+
36+
if (notNull && defaultValue !== undefined) {
37+
query.push({
38+
exec: `ALTER TABLE ${db.schemaName}.${tableName} ADD ${columName} ${type} NOT NULL DEFAULT $1;`,
39+
param: [defaultValue],
40+
});
41+
} else if (notNull) {
42+
query.push({
43+
exec: `ALTER TABLE ${db.schemaName}.${tableName} ADD ${columName} ${type} NOT NULL;`,
44+
param: [defaultValue],
45+
});
46+
} else {
47+
query.push({
48+
exec: `ALTER TABLE ${db.schemaName}.${tableName} ADD ${columName} ${type};`,
49+
param: [defaultValue],
50+
});
51+
}
52+
53+
if (defaultValue !== undefined && deleteDefault) {
54+
query.push({
55+
exec: `ALTER TABLE ${db.schemaName}.${tableName} ALTER COLUMN ${columName} DROP DEFAULT ;`,
56+
param: [],
57+
});
58+
}
59+
return (await db.execScripts(query)).every((e) => e !== null);
60+
}
61+
62+
/**
63+
* Alter a table to delete a column.
64+
* This method is used to remove a column from an existing table in the database.
65+
* @param className
66+
* @param columName
67+
* @protected
68+
*/
69+
protected async alterTableDeleteColumn(
70+
className: string,
71+
columName: string,
72+
): Promise<boolean> {
73+
const db = this.getDb();
74+
const tableName = XUtil.camelToSnakeCase(className);
75+
const query: RawQuery[] = [];
76+
query.push({
77+
exec: `ALTER TABLE ${db.schemaName}.${tableName} DROP COLUMN ${columName};`,
78+
param: [],
79+
});
80+
return (await db.execScripts(query)).every((e) => e !== null);
81+
}
82+
}

src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import PGCon from './class/PGCon.js';
2+
import PGUpdate from './class/PGUpdate.js';
23

34
export * from './util/index.js';
4-
export { PGCon };
5+
export { PGCon, PGUpdate };
56
export default PGCon;

src/util/buildSearchQ.ts

Lines changed: 63 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,77 @@
1-
import { EntityConfig } from '@grandlinex/core';
1+
import {
2+
CoreEntity,
3+
EntityConfig,
4+
isQInterfaceSearchAdvanced,
5+
isQInterfaceSearchAdvancedArr,
6+
QInterfaceSearch,
7+
QInterfaceSearchAdvanced,
8+
} from '@grandlinex/core';
29
import { convertSpecialFields } from './converter.js';
310

4-
export default function buildSearchQ<E>(
11+
class ParamCounter {
12+
private count;
13+
14+
constructor() {
15+
this.count = 1;
16+
}
17+
18+
next() {
19+
return `$${this.count++}`;
20+
}
21+
}
22+
23+
function aFilter<E extends CoreEntity>(
24+
key: string,
25+
s: QInterfaceSearchAdvanced<QInterfaceSearch<E>, keyof E>,
26+
count: ParamCounter,
27+
): string {
28+
switch (s.mode) {
29+
case 'equals':
30+
return `${key} = ${count.next()}`;
31+
case 'not':
32+
return `${key} != ${count.next()}`;
33+
case 'like':
34+
return `${key} like '%' || ${count.next()} || '%'`;
35+
case 'smallerThan':
36+
return `${key} < ${count.next()}`;
37+
case 'greaterThan':
38+
return `${key} > ${count.next()}`;
39+
default:
40+
throw new Error(`Unknown mode: ${s.mode}`);
41+
}
42+
}
43+
44+
export default function buildSearchQ<E extends CoreEntity>(
545
config: EntityConfig<E>,
6-
search: { [P in keyof E]?: E[P] },
46+
search: QInterfaceSearch<E>,
747
param: any[],
848
searchQ: string,
949
) {
1050
let temp = searchQ;
1151
const keys: (keyof E)[] = Object.keys(search) as (keyof E)[];
1252
if (keys.length > 0) {
1353
const filter: string[] = [];
14-
let count = 1;
54+
const count = new ParamCounter();
1555
for (const key of keys) {
16-
if (search[key] !== undefined) {
17-
const meta = config.meta.get(key);
18-
if (!meta) {
19-
throw new Error('Missing meta');
20-
}
21-
filter.push(`${String(key)} = $${count++}`);
22-
convertSpecialFields(meta, search, key, param);
56+
const s: QInterfaceSearch<E>[keyof E] = search[key];
57+
const meta = config.meta.get(key);
58+
if (!meta) {
59+
throw new Error('Missing meta');
60+
}
61+
if (isQInterfaceSearchAdvanced(s)) {
62+
filter.push(aFilter(String(key), s, count));
63+
convertSpecialFields(meta, s.value, param);
64+
} else if (isQInterfaceSearchAdvancedArr(s)) {
65+
filter.push(
66+
...s.map((e) => {
67+
const ax = aFilter(String(key), e, count);
68+
convertSpecialFields(meta, e.value, param);
69+
return ax;
70+
}),
71+
);
72+
} else {
73+
filter.push(`${String(key)} = ${count.next()}`);
74+
convertSpecialFields(meta, search[key], param);
2375
}
2476
}
2577
if (filter.length > 0) {

src/util/converter.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,15 @@ import {
55
EUpDateProperties,
66
} from '@grandlinex/core';
77

8-
export function convertSpecialFields<E>(
8+
export function convertSpecialFields(
99
meta: ColumnProps,
10-
clone: any,
11-
key: keyof E,
10+
value: any,
1211
params: any[],
1312
) {
1413
if (meta.dataType === 'json') {
15-
params.push(JSON.stringify(clone[key]));
14+
params.push(JSON.stringify(value));
1615
} else {
17-
params.push(clone[key]);
16+
params.push(value);
1817
}
1918
}
2019

@@ -38,7 +37,7 @@ export function objToTable<E extends CoreEntity>(
3837
if (meta.primaryKey && update) {
3938
return;
4039
}
41-
convertSpecialFields<E>(meta, clone, key, params);
40+
convertSpecialFields(meta, clone[key], params);
4241
if (update) {
4342
values.push(`${String(key)}=$${pCount}`);
4443
} else {

0 commit comments

Comments
 (0)