prostgles-server 4.2.157 → 4.2.159

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 (159) hide show
  1. package/dist/Auth/AuthHandler.js +2 -2
  2. package/dist/Auth/AuthHandler.js.map +1 -1
  3. package/dist/Auth/AuthTypes.d.ts +4 -8
  4. package/dist/Auth/AuthTypes.d.ts.map +1 -1
  5. package/dist/Auth/setAuthProviders.d.ts +1 -1
  6. package/dist/Auth/setAuthProviders.d.ts.map +1 -1
  7. package/dist/Auth/setAuthProviders.js +6 -7
  8. package/dist/Auth/setAuthProviders.js.map +1 -1
  9. package/dist/Auth/setEmailProvider.d.ts +1 -1
  10. package/dist/Auth/setEmailProvider.d.ts.map +1 -1
  11. package/dist/Auth/setEmailProvider.js +22 -2
  12. package/dist/Auth/setEmailProvider.js.map +1 -1
  13. package/dist/Auth/setupAuthRoutes.js +1 -1
  14. package/dist/Auth/setupAuthRoutes.js.map +1 -1
  15. package/dist/Prostgles.d.ts +1 -0
  16. package/dist/Prostgles.d.ts.map +1 -1
  17. package/dist/Prostgles.js +6 -0
  18. package/dist/Prostgles.js.map +1 -1
  19. package/dist/initProstgles.d.ts.map +1 -1
  20. package/dist/initProstgles.js +2 -6
  21. package/dist/initProstgles.js.map +1 -1
  22. package/package.json +1 -1
  23. package/lib/Auth/AuthHandler.ts +0 -436
  24. package/lib/Auth/AuthTypes.ts +0 -285
  25. package/lib/Auth/getSafeReturnURL.ts +0 -35
  26. package/lib/Auth/sendEmail.ts +0 -83
  27. package/lib/Auth/setAuthProviders.ts +0 -129
  28. package/lib/Auth/setEmailProvider.ts +0 -63
  29. package/lib/Auth/setupAuthRoutes.ts +0 -161
  30. package/lib/DBEventsManager.ts +0 -178
  31. package/lib/DBSchemaBuilder.ts +0 -225
  32. package/lib/DboBuilder/DboBuilder.ts +0 -319
  33. package/lib/DboBuilder/DboBuilderTypes.ts +0 -361
  34. package/lib/DboBuilder/QueryBuilder/Functions.ts +0 -1153
  35. package/lib/DboBuilder/QueryBuilder/QueryBuilder.ts +0 -288
  36. package/lib/DboBuilder/QueryBuilder/getJoinQuery.ts +0 -263
  37. package/lib/DboBuilder/QueryBuilder/getNewQuery.ts +0 -271
  38. package/lib/DboBuilder/QueryBuilder/getSelectQuery.ts +0 -136
  39. package/lib/DboBuilder/QueryBuilder/prepareHaving.ts +0 -22
  40. package/lib/DboBuilder/QueryStreamer.ts +0 -250
  41. package/lib/DboBuilder/TableHandler/DataValidator.ts +0 -428
  42. package/lib/DboBuilder/TableHandler/TableHandler.ts +0 -205
  43. package/lib/DboBuilder/TableHandler/delete.ts +0 -115
  44. package/lib/DboBuilder/TableHandler/insert.ts +0 -183
  45. package/lib/DboBuilder/TableHandler/insertTest.ts +0 -78
  46. package/lib/DboBuilder/TableHandler/onDeleteFromFileTable.ts +0 -62
  47. package/lib/DboBuilder/TableHandler/runInsertUpdateQuery.ts +0 -134
  48. package/lib/DboBuilder/TableHandler/update.ts +0 -126
  49. package/lib/DboBuilder/TableHandler/updateBatch.ts +0 -49
  50. package/lib/DboBuilder/TableHandler/updateFile.ts +0 -48
  51. package/lib/DboBuilder/TableHandler/upsert.ts +0 -34
  52. package/lib/DboBuilder/ViewHandler/ViewHandler.ts +0 -393
  53. package/lib/DboBuilder/ViewHandler/count.ts +0 -38
  54. package/lib/DboBuilder/ViewHandler/find.ts +0 -153
  55. package/lib/DboBuilder/ViewHandler/getExistsCondition.ts +0 -73
  56. package/lib/DboBuilder/ViewHandler/getExistsFilters.ts +0 -74
  57. package/lib/DboBuilder/ViewHandler/getInfo.ts +0 -32
  58. package/lib/DboBuilder/ViewHandler/getTableJoinQuery.ts +0 -84
  59. package/lib/DboBuilder/ViewHandler/parseComplexFilter.ts +0 -96
  60. package/lib/DboBuilder/ViewHandler/parseFieldFilter.ts +0 -105
  61. package/lib/DboBuilder/ViewHandler/parseJoinPath.ts +0 -208
  62. package/lib/DboBuilder/ViewHandler/prepareSortItems.ts +0 -163
  63. package/lib/DboBuilder/ViewHandler/prepareWhere.ts +0 -90
  64. package/lib/DboBuilder/ViewHandler/size.ts +0 -37
  65. package/lib/DboBuilder/ViewHandler/subscribe.ts +0 -118
  66. package/lib/DboBuilder/ViewHandler/validateViewRules.ts +0 -70
  67. package/lib/DboBuilder/dboBuilderUtils.ts +0 -222
  68. package/lib/DboBuilder/getColumns.ts +0 -114
  69. package/lib/DboBuilder/getCondition.ts +0 -201
  70. package/lib/DboBuilder/getSubscribeRelatedTables.ts +0 -190
  71. package/lib/DboBuilder/getTablesForSchemaPostgresSQL.ts +0 -426
  72. package/lib/DboBuilder/insertNestedRecords.ts +0 -355
  73. package/lib/DboBuilder/parseUpdateRules.ts +0 -187
  74. package/lib/DboBuilder/prepareShortestJoinPaths.ts +0 -186
  75. package/lib/DboBuilder/runSQL.ts +0 -182
  76. package/lib/DboBuilder/runTransaction.ts +0 -50
  77. package/lib/DboBuilder/sqlErrCodeToMsg.ts +0 -254
  78. package/lib/DboBuilder/uploadFile.ts +0 -69
  79. package/lib/Event_Trigger_Tags.ts +0 -118
  80. package/lib/FileManager/FileManager.ts +0 -358
  81. package/lib/FileManager/getValidatedFileType.ts +0 -69
  82. package/lib/FileManager/initFileManager.ts +0 -187
  83. package/lib/FileManager/upload.ts +0 -62
  84. package/lib/FileManager/uploadStream.ts +0 -79
  85. package/lib/Filtering.ts +0 -463
  86. package/lib/JSONBValidation/validate_jsonb_schema_sql.ts +0 -502
  87. package/lib/JSONBValidation/validation.ts +0 -143
  88. package/lib/Logging.ts +0 -127
  89. package/lib/PostgresNotifListenManager.ts +0 -143
  90. package/lib/Prostgles.ts +0 -479
  91. package/lib/ProstglesTypes.ts +0 -196
  92. package/lib/PubSubManager/PubSubManager.ts +0 -609
  93. package/lib/PubSubManager/addSub.ts +0 -138
  94. package/lib/PubSubManager/addSync.ts +0 -141
  95. package/lib/PubSubManager/getCreatePubSubManagerError.ts +0 -72
  96. package/lib/PubSubManager/getPubSubManagerInitQuery.ts +0 -662
  97. package/lib/PubSubManager/initPubSubManager.ts +0 -79
  98. package/lib/PubSubManager/notifListener.ts +0 -173
  99. package/lib/PubSubManager/orphanTriggerCheck.ts +0 -70
  100. package/lib/PubSubManager/pushSubData.ts +0 -55
  101. package/lib/PublishParser/PublishParser.ts +0 -162
  102. package/lib/PublishParser/getFileTableRules.ts +0 -124
  103. package/lib/PublishParser/getSchemaFromPublish.ts +0 -141
  104. package/lib/PublishParser/getTableRulesWithoutFileTable.ts +0 -177
  105. package/lib/PublishParser/publishTypesAndUtils.ts +0 -399
  106. package/lib/RestApi.ts +0 -127
  107. package/lib/SchemaWatch/SchemaWatch.ts +0 -90
  108. package/lib/SchemaWatch/createSchemaWatchEventTrigger.ts +0 -3
  109. package/lib/SchemaWatch/getValidatedWatchSchemaType.ts +0 -45
  110. package/lib/SchemaWatch/getWatchSchemaTagList.ts +0 -27
  111. package/lib/SyncReplication.ts +0 -557
  112. package/lib/TableConfig/TableConfig.ts +0 -468
  113. package/lib/TableConfig/getColumnDefinitionQuery.ts +0 -111
  114. package/lib/TableConfig/getConstraintDefinitionQueries.ts +0 -95
  115. package/lib/TableConfig/getFutureTableSchema.ts +0 -64
  116. package/lib/TableConfig/getPGIndexes.ts +0 -53
  117. package/lib/TableConfig/getTableColumnQueries.ts +0 -129
  118. package/lib/TableConfig/initTableConfig.ts +0 -326
  119. package/lib/index.ts +0 -13
  120. package/lib/initProstgles.ts +0 -322
  121. package/lib/onSocketConnected.ts +0 -102
  122. package/lib/runClientRequest.ts +0 -129
  123. package/lib/shortestPath.ts +0 -122
  124. package/lib/typeTests/DBoGenerated.d.ts +0 -320
  125. package/lib/typeTests/dboTypeCheck.ts +0 -81
  126. package/lib/utils.ts +0 -15
  127. package/tests/client/hooks.spec.ts +0 -205
  128. package/tests/client/index.ts +0 -139
  129. package/tests/client/package-lock.json +0 -637
  130. package/tests/client/package.json +0 -26
  131. package/tests/client/renderReactHook.ts +0 -177
  132. package/tests/client/tsconfig.json +0 -15
  133. package/tests/client/useProstgles.spec.ts +0 -120
  134. package/tests/clientFileTests.spec.ts +0 -102
  135. package/tests/clientOnlyQueries.spec.ts +0 -667
  136. package/tests/clientRestApi.spec.ts +0 -82
  137. package/tests/config_test/DBoGenerated.d.ts +0 -407
  138. package/tests/config_test/index.html +0 -109
  139. package/tests/config_test/index.js +0 -86
  140. package/tests/config_test/index.js.map +0 -1
  141. package/tests/config_test/index.ts +0 -91
  142. package/tests/config_test/init.sql +0 -48
  143. package/tests/config_test/package.json +0 -29
  144. package/tests/config_test/tsconfig.json +0 -23
  145. package/tests/config_testDBoGenerated.d.ts +0 -407
  146. package/tests/isomorphicQueries.spec.ts +0 -1493
  147. package/tests/server/DBoGenerated.d.ts +0 -537
  148. package/tests/server/index.html +0 -73
  149. package/tests/server/index.ts +0 -289
  150. package/tests/server/init.sql +0 -224
  151. package/tests/server/package-lock.json +0 -2164
  152. package/tests/server/package.json +0 -25
  153. package/tests/server/publishTypeCheck.ts +0 -136
  154. package/tests/server/server.ts +0 -35
  155. package/tests/server/testPublish.ts +0 -147
  156. package/tests/server/testTableConfig.ts +0 -156
  157. package/tests/server/tsconfig.json +0 -22
  158. package/tests/serverOnlyQueries.spec.ts +0 -32
  159. package/tests/test.sh +0 -20
@@ -1,64 +0,0 @@
1
- import { asName } from "prostgles-types";
2
- import { pgp } from "../DboBuilder/DboBuilder";
3
- import { DB } from "../Prostgles";
4
- import { ColumnMinimalInfo, getTableColumns } from "./getColumnDefinitionQuery";
5
- import { ColConstraint, ConstraintDef, getColConstraints } from "./getConstraintDefinitionQueries";
6
-
7
- type Args = {
8
- db: DB,
9
- columnDefs: string[];
10
- tableName: string;
11
- constraintDefs?: ConstraintDef[];
12
- };
13
-
14
- export const getFutureTableSchema = async ({ columnDefs, tableName, constraintDefs = [], db }: Args): Promise<{
15
- constraints: ColConstraint[];
16
- cols: ColumnMinimalInfo[];
17
- }> => {
18
- const { TransactionMode, isolationLevel } = pgp.txMode;
19
-
20
- let constraints: ColConstraint[] = [];
21
- let cols: ColumnMinimalInfo[] = [];
22
- const ROLLBACK = "Rollback";
23
- try {
24
- const txMode = new TransactionMode({
25
- tiLevel: isolationLevel.serializable
26
- });
27
- await db.tx({ mode: txMode }, async t => {
28
-
29
- /** To prevent deadlocks we use a random table name -> Not feasible because named constraints cannot be recreated without dropping the existing ones from actual table */
30
- // const tableEsc = asName(tableName.slice(0, 12) + (await t.oneOrNone(`SELECT md5(now()::text) as md5`)).md5);
31
-
32
- const tableEsc = asName(tableName);
33
-
34
- const consQueries = constraintDefs.map(c =>
35
- `ALTER TABLE ${tableEsc} ADD ${c.name? ` CONSTRAINT ${asName(c.name)}` : ""} ${c.content};`
36
- ).join("\n");
37
-
38
- const query = `
39
- DROP TABLE IF EXISTS ${tableEsc} CASCADE;
40
- CREATE TABLE ${tableEsc} (
41
- ${columnDefs.join(",\n")}
42
- );
43
- ${consQueries}
44
- `;
45
-
46
- await t.any(query);
47
-
48
- constraints = await getColConstraints({ db: t, table: tableName });
49
- cols = await getTableColumns({ db: t, table: tableName });
50
-
51
- /** Rollback */
52
- return Promise.reject(new Error(ROLLBACK));
53
- });
54
-
55
- } catch(e: any){
56
- if(e instanceof Error && e.message === ROLLBACK) {
57
- // Ignore
58
- } else {
59
- throw e;
60
- }
61
- }
62
-
63
- return { cols, constraints };
64
- }
@@ -1,53 +0,0 @@
1
- import { DB } from "../Prostgles";
2
-
3
- type PGIndex = {
4
- schemaname: string;
5
- indexname: string;
6
- indexdef: string;
7
- escaped_identifier: string;
8
- type: string;
9
- owner: string;
10
- tablename: string;
11
- persistence: string;
12
- access_method: string;
13
- size: string;
14
- description: string | null;
15
- };
16
- export const getPGIndexes = async (db: DB, tableName: string, schema: string): Promise<PGIndex[]> => {
17
-
18
- const indexQuery = `
19
- SELECT n.nspname as schemaname,
20
- c.relname as indexname,
21
- pg_get_indexdef(c.oid) as indexdef,
22
- format('%I', c.relname) as escaped_identifier,
23
- CASE c.relkind WHEN 'r'
24
- THEN 'table' WHEN 'v'
25
- THEN 'view' WHEN 'm'
26
- THEN 'materialized view'
27
- WHEN 'i' THEN 'index'
28
- WHEN 'S' THEN 'sequence' WHEN 's' THEN 'special'
29
- WHEN 't' THEN 'TOAST table' WHEN 'f' THEN 'foreign table'
30
- WHEN 'p' THEN 'partitioned table' WHEN 'I' THEN 'partitioned index' END as "type",
31
- pg_catalog.pg_get_userbyid(c.relowner) as "owner",
32
- c2.relname as tablename,
33
- CASE c.relpersistence WHEN 'p' THEN 'permanent' WHEN 't' THEN 'temporary'
34
- WHEN 'u' THEN 'unlogged' END as "persistence",
35
- am.amname as "access_method",
36
- pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as "size",
37
- pg_catalog.obj_description(c.oid, 'pg_class') as "description"
38
- FROM pg_catalog.pg_class c
39
- LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
40
- LEFT JOIN pg_catalog.pg_am am ON am.oid = c.relam
41
- LEFT JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid
42
- LEFT JOIN pg_catalog.pg_class c2 ON i.indrelid = c2.oid
43
- WHERE c.relkind IN ('i','I','')
44
- AND n.nspname <> 'pg_catalog'
45
- AND n.nspname !~ '^pg_toast'
46
- AND n.nspname <> 'information_schema'
47
- AND pg_catalog.pg_table_is_visible(c.oid)
48
- AND c2.relname = \${tableName}
49
- AND n.nspname = \${schema}
50
- ORDER BY 1,2;
51
- `
52
- return db.any(indexQuery, { tableName, schema });
53
- };
@@ -1,129 +0,0 @@
1
- import { getKeys, asName as _asName, isObject, asName } from "prostgles-types";
2
- import { DB, DBHandlerServer } from "../Prostgles";
3
- import { validate_jsonb_schema_sql } from "../JSONBValidation/validate_jsonb_schema_sql";
4
- import { getColumnDefinitionQuery, getTableColumns } from "./getColumnDefinitionQuery";
5
- import { TableConfig } from "./TableConfig";
6
- import { getFutureTableSchema } from "./getFutureTableSchema";
7
-
8
- type Args = {
9
- db: DB;
10
- tableConf: TableConfig[string];
11
- tableName: string;
12
- tableHandler: DBHandlerServer[string] | undefined;
13
- }
14
-
15
- export const getTableColumnQueries = async ({ db, tableConf, tableName, tableHandler }: Args): Promise<undefined | {
16
- columnDefs: string[];
17
- newColumnDefs: string[];
18
- fullQuery: string;
19
- isCreate: boolean;
20
- }> => {
21
-
22
- let newColumnDefs: string[] = [];
23
- const droppedColNames: string[] = [];
24
- const alteredColQueries: string[] = [];
25
- let fullQuery = "";
26
- let isCreate = false;
27
-
28
- if ("columns" in tableConf && tableConf.columns) {
29
-
30
- const hasJSONBValidation = getKeys(tableConf.columns).some(c => {
31
- const cConf = tableConf.columns?.[c];
32
- return cConf && isObject(cConf) && (cConf.jsonbSchema || cConf.jsonbSchemaType)
33
- });
34
-
35
- /** Must install validation function */
36
- if(hasJSONBValidation){
37
- try {
38
- await db.any(validate_jsonb_schema_sql);
39
- } catch(err: any){
40
- console.error("Could not install the jsonb validation function due to error: ", err);
41
- throw err;
42
- }
43
- }
44
-
45
- const columns = getKeys(tableConf.columns).filter(c => {
46
- const colDef = tableConf.columns![c]!;
47
- /** Exclude NamedJoinColumn */
48
- return typeof colDef === "string" || !("joinDef" in colDef)
49
- }) as string[];
50
-
51
- const colDefs: { name: string; def: string }[] = [];
52
-
53
- for (const colName of columns) {
54
- const colConf = tableConf.columns![colName]!;
55
-
56
- /* Get column definition */
57
- const colDef = await getColumnDefinitionQuery({ colConf, column: colName, db, table: tableName });
58
- if(colDef){
59
- colDefs.push({ name: colName, def: colDef});
60
- }
61
- }
62
- const columnDefs = colDefs.map(c => c.def);
63
-
64
- if(!colDefs.length){
65
- return undefined;
66
- }
67
-
68
-
69
- const ALTERQ = `ALTER TABLE ${asName(tableName)}`;
70
- if (!tableHandler) {
71
- newColumnDefs.push(...colDefs.map(c => c.def));
72
-
73
- } else if (tableHandler) {
74
- const currCols = await getTableColumns({ db, table: tableName });
75
-
76
- /** Add new columns */
77
- newColumnDefs = colDefs.filter(nc => !tableHandler.columns?.some(c => nc.name === c.name)).map(c => c.def);
78
-
79
- /** Altered/Dropped columns */
80
- const { cols: futureCols } = await getFutureTableSchema({ tableName, columnDefs, constraintDefs: [], db });
81
- currCols.forEach(c => {
82
- const newCol = futureCols.find(nc => nc.column_name === c.column_name);
83
- if(!newCol){
84
- droppedColNames.push(c.column_name);
85
- } else if(newCol.nullable !== c.nullable){
86
- alteredColQueries.push(`${ALTERQ} ALTER COLUMN ${asName(c.column_name)} ${newCol.nullable? "SET" : "DROP"} NOT NULL;`)
87
- } else if(newCol.udt_name !== c.udt_name){
88
- alteredColQueries.push(`${ALTERQ} ALTER COLUMN ${asName(c.column_name)} TYPE ${newCol.udt_name} USING ${asName(c.column_name)}::${newCol.udt_name};`)
89
- } else if(newCol.column_default !== c.column_default){
90
- const colConfig = colDefs.find(cd => cd.name === c.column_name);
91
- if(["serial", "bigserial"].some(t => colConfig?.def.toLowerCase().includes(` ${t}`)) && c.column_default?.toLowerCase().includes("nextval")){
92
- /** Ignore SERIAL/BIGSERIAL <> nextval mismatch */
93
- } else {
94
- alteredColQueries.push(`${ALTERQ} ALTER COLUMN ${asName(c.column_name)} ${newCol.column_default === null? "DROP DEFAULT" : `SET DEFAULT ${newCol.column_default}`};`)
95
- }
96
- }
97
- });
98
- }
99
-
100
- if (!tableHandler || tableConf.dropIfExists || tableConf.dropIfExistsCascade) {
101
- isCreate = true;
102
- const DROPQ = `DROP TABLE IF EXISTS ${asName(tableName)}`;
103
- fullQuery = ([
104
- ...(tableConf.dropIfExists? [`${DROPQ};`] : tableConf.dropIfExistsCascade? [`${DROPQ} CASCADE;`] : []),
105
- `CREATE TABLE ${asName(tableName)} (`,
106
- columnDefs.join(", \n"),
107
- `);`
108
- ].join("\n"));
109
-
110
- } else {
111
- fullQuery = [
112
- ...droppedColNames.map(c => `${ALTERQ} DROP COLUMN ${asName(c)};`),
113
- ...newColumnDefs.map(c => `${ALTERQ} ADD COLUMN ${c};`),
114
- ...alteredColQueries,
115
- ].join("\n");
116
- }
117
-
118
- return {
119
- fullQuery,
120
- columnDefs,
121
- isCreate,
122
- newColumnDefs,
123
- }
124
- } else {
125
- return undefined;
126
- }
127
-
128
-
129
- }
@@ -1,326 +0,0 @@
1
-
2
- import { asName as _asName } from "prostgles-types";
3
- import { PubSubManager, asValue, log } from "../PubSubManager/PubSubManager";
4
- import TableConfigurator from "./TableConfig";
5
- import { getColConstraints, getConstraintDefinitionQueries } from "./getConstraintDefinitionQueries";
6
- import { getFutureTableSchema } from "./getFutureTableSchema";
7
- import { getTableColumnQueries } from "./getTableColumnQueries";
8
- import { getPGIndexes } from "./getPGIndexes";
9
-
10
- export const initTableConfig = async function (this: TableConfigurator<any>) {
11
-
12
- let changedSchema = false;
13
- const failedQueries: { query: string; error: any }[] = [];
14
- this.initialising = true;
15
- const queryHistory: string[] = [];
16
- let queries: string[] = [];
17
- const makeQuery = (q: string[]) => q.filter(v => v.trim().length).map(v => v.trim().endsWith(";") ? v : `${v};`).join("\n");
18
- const runQueries = async (_queries = queries) => {
19
- let q = makeQuery(queries);
20
- if (!_queries.some(q => q.trim().length)) {
21
- return 0;
22
- }
23
- q = `/* ${PubSubManager.EXCLUDE_QUERY_FROM_SCHEMA_WATCH_ID} */ \n\n` + q;
24
- queryHistory.push(q);
25
- this.prostgles.opts.onLog?.({ type: "debug", command: "TableConfig.runQueries.start", data: { q }, duration: -1 });
26
- const now = Date.now();
27
- await this.db.multi(q).catch(err => {
28
- log({ err, q });
29
- failedQueries.push({ query: q, error: err });
30
- return Promise.reject(err);
31
- });
32
- this.prostgles.opts.onLog?.({ type: "debug", command: "TableConfig.runQueries.end", duration: Date.now() - now, data: { q } });
33
- changedSchema = true;
34
- _queries = [];
35
- queries = [];
36
- return 1;
37
- }
38
-
39
- if (!this.prostgles.pgp) {
40
- throw "pgp missing";
41
- }
42
-
43
- const MAX_IDENTIFIER_LENGTH = +(await this.db.one("SHOW max_identifier_length;") as any).max_identifier_length;
44
- if (!Number.isFinite(MAX_IDENTIFIER_LENGTH)) throw `Could not obtain a valid max_identifier_length`;
45
- const asName = (v: string) => {
46
- if (v.length > MAX_IDENTIFIER_LENGTH - 1) {
47
- throw `The identifier name provided (${v}) is longer than the allowed limit (max_identifier_length - 1 = ${MAX_IDENTIFIER_LENGTH - 1} characters )\n Longest allowed: ${_asName(v.slice(0, MAX_IDENTIFIER_LENGTH - 1))} `
48
- }
49
-
50
- return _asName(v);
51
- }
52
-
53
- let migrations: { version: number; table: string; } | undefined;
54
- if (this.prostgles.opts.tableConfigMigrations) {
55
- const { onMigrate, version, versionTableName = "schema_version" } = this.prostgles.opts.tableConfigMigrations;
56
- await this.db.any(`
57
- /* ${PubSubManager.EXCLUDE_QUERY_FROM_SCHEMA_WATCH_ID} */
58
- CREATE TABLE IF NOT EXISTS ${asName(versionTableName)}(id NUMERIC PRIMARY KEY, table_config JSONB NOT NULL)
59
- `);
60
- migrations = { version, table: versionTableName };
61
- let latestVersion: number | undefined;
62
- try {
63
- latestVersion = Number((await this.db.oneOrNone(`SELECT MAX(id) as v FROM ${asName(versionTableName)}`)).v);
64
- } catch (e) {
65
-
66
- }
67
-
68
- if (latestVersion === version) {
69
- const isLatest = (await this.db.oneOrNone(`SELECT table_config = \${table_config} as v FROM ${asName(versionTableName)} WHERE id = \${version}`, { version, table_config: this.config })).v;
70
- if (isLatest) {
71
- return;
72
- }
73
- }
74
- if (!latestVersion || latestVersion < version) {
75
- await onMigrate({ db: this.db, oldVersion: latestVersion, getConstraints: (table, col, types) => getColConstraints({ db: this.db, table, column: col, types }) })
76
- }
77
- }
78
-
79
- /* Create lookup tables */
80
- for (const [tableNameRaw, tableConf] of Object.entries(this.config)) {
81
- const tableName = asName(tableNameRaw);
82
-
83
- if ("isLookupTable" in tableConf && Object.keys(tableConf.isLookupTable?.values).length) {
84
- const { dropIfExists = false, dropIfExistsCascade = false } = tableConf;
85
- const isDropped = dropIfExists || dropIfExistsCascade;
86
-
87
- if (dropIfExistsCascade) {
88
- queries.push(`DROP TABLE IF EXISTS ${tableName} CASCADE;`);
89
- } else if (dropIfExists) {
90
- queries.push(`DROP TABLE IF EXISTS ${tableName};`);
91
- }
92
-
93
- const rows = Object.entries(tableConf.isLookupTable?.values).map(([id, otherColumns])=> ({ id, ...otherColumns }));
94
- const lookupTableHandler = this.dbo?.[tableNameRaw];
95
- const columnNames = Object.keys(rows[0]!).filter(k => k !== "id");
96
- if (isDropped || !lookupTableHandler) {
97
- queries.push(
98
- `CREATE TABLE IF NOT EXISTS ${tableName} (
99
- id TEXT PRIMARY KEY
100
- ${columnNames.length ? (", " + columnNames.map(k => asName(k) + " TEXT ").join(", ")) : ""}
101
- );`
102
- );
103
- }
104
- if(rows.length){
105
- const existingValues: { id: any }[] = !lookupTableHandler? [] : await this.db.any(`SELECT id FROM ${tableName} WHERE id IN (${rows.map(r => asValue(r.id)).join(", ")});`);
106
- rows
107
- .filter(r => !existingValues.some(ev => ev.id === r.id))
108
- .map(row => {
109
- const allColumns = ["id", ...columnNames]
110
- const values = allColumns.map(key => (row as any)[key]);
111
- queries.push(this.prostgles.pgp!.as.format(`INSERT INTO ${tableName} (${allColumns.map(t => asName(t)).join(", ")}) ` + " VALUES (${values:csv});", { values }))
112
- });
113
- }
114
- }
115
- }
116
-
117
- if (queries.length) {
118
- await runQueries(queries);
119
- await this.prostgles.refreshDBO();
120
- }
121
-
122
- /* Create/Alter columns */
123
- for (const [tableName, tableConf] of Object.entries(this.config)) {
124
- const tableHandler = this.dbo[tableName];
125
-
126
- const ALTER_TABLE_Q = `ALTER TABLE ${asName(tableName)}`;
127
-
128
- /* isLookupTable table has already been created */
129
- const coldef = "isLookupTable" in tableConf? undefined : await getTableColumnQueries({ db: this.db, tableConf, tableHandler, tableName });
130
-
131
- if (coldef) {
132
- queries.push(coldef.fullQuery);
133
- }
134
-
135
- /** CONSTRAINTS */
136
- const constraintDefs = getConstraintDefinitionQueries({ tableName, tableConf });
137
- if (coldef?.isCreate) {
138
- queries.push(...constraintDefs?.map(c => c.alterQuery) ?? []);
139
-
140
- } else if (coldef) {
141
- const fullSchema = await getFutureTableSchema({ db: this.db, tableName, columnDefs: coldef.columnDefs, constraintDefs });
142
- const futureCons = fullSchema.constraints.map(nc => ({
143
- ...nc,
144
- isNamed: constraintDefs?.some(c => c.name === nc.name)
145
- }));
146
-
147
- /** Run this first to ensure any dropped cols drop their constraints as well */
148
- await runQueries(queries);
149
- const currCons = await getColConstraints({ db: this.db, table: tableName });
150
-
151
- /** Drop removed/modified */
152
- currCons.forEach(c => {
153
- if (!futureCons.some(nc => nc.definition === c.definition && (!nc.isNamed || nc.name === c.name))) {
154
- queries.push(`${ALTER_TABLE_Q} DROP CONSTRAINT ${asName(c.name)};`)
155
- }
156
- });
157
-
158
- /** Add missing named constraints */
159
- constraintDefs?.forEach(c => {
160
- if (c.name && !currCons.some(cc => cc.name === c.name)) {
161
- const fc = futureCons.find(nc => nc.name === c.name);
162
- if (fc) {
163
- queries.push(`${ALTER_TABLE_Q} ADD CONSTRAINT ${asName(c.name)} ${c.content};`);
164
- }
165
- }
166
- });
167
-
168
- /** Add remaining missing constraints */
169
- futureCons
170
- .filter(nc =>
171
- !currCons.some(c => c.definition === nc.definition)
172
- )
173
- .forEach(c => {
174
- queries.push(`${ALTER_TABLE_Q} ADD ${c.definition};`)
175
- });
176
- }
177
-
178
-
179
- if ("indexes" in tableConf && tableConf.indexes) {
180
- /*
181
- CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] name ] ON [ ONLY ] table_name [ USING method ]
182
- ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass [ ( opclass_parameter = value [, ... ] ) ] ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [, ...] )
183
- [ INCLUDE ( column_name [, ...] ) ]
184
- [ NULLS [ NOT ] DISTINCT ]
185
- [ WITH ( storage_parameter [= value] [, ... ] ) ]
186
- [ TABLESPACE tablespace_name ]
187
- [ WHERE predicate ]
188
- */
189
- const currIndexes = await getPGIndexes(this.db, tableName, "public");
190
- Object.entries(tableConf.indexes).forEach(([
191
- indexName,
192
- {
193
- columns,
194
- concurrently,
195
- replace,
196
- unique,
197
- using,
198
- where = ""
199
- }
200
- ]) => {
201
-
202
- if (replace || typeof replace !== "boolean" && tableConf.replaceUniqueIndexes) {
203
- queries.push(`DROP INDEX IF EXISTS ${asName(indexName)};`);
204
- }
205
- if (!currIndexes.some(idx => idx.indexname === indexName)) {
206
- queries.push([
207
- "CREATE",
208
- unique && "UNIQUE",
209
- concurrently && "CONCURRENTLY",
210
- `INDEX ${asName(indexName)} ON ${asName(tableName)}`,
211
- using && ("USING " + using),
212
- `(${columns})`,
213
- where && `WHERE ${where}`
214
- ].filter(v => v).join(" ") + ";");
215
- }
216
- });
217
- }
218
-
219
- const { triggers, dropIfExists, dropIfExistsCascade } = tableConf;
220
- if (triggers) {
221
- const isDropped = dropIfExists || dropIfExistsCascade;
222
-
223
- const existingTriggers = await this.dbo.sql!(`
224
- SELECT event_object_table
225
- ,trigger_name
226
- FROM information_schema.triggers
227
- WHERE event_object_table = \${tableName}
228
- ORDER BY event_object_table
229
- `,
230
- { tableName },
231
- { returnType: "rows" }
232
- ) as { trigger_name: string }[];
233
-
234
- // const existingTriggerFuncs = await this.dbo.sql!(`
235
- // SELECT p.oid,proname,prosrc,u.usename
236
- // FROM pg_proc p
237
- // JOIN pg_user u ON u.usesysid = p.proowner
238
- // WHERE prorettype = 2279;
239
- // `, {}, { returnType: "rows" }) as { proname: string }[];
240
-
241
- Object.entries(triggers).forEach(([triggerFuncName, trigger]) => {
242
-
243
- const funcNameParsed = asName(triggerFuncName);
244
-
245
- let addedFunc = false;
246
- const addFuncDef = () => {
247
- if (addedFunc) return;
248
- addedFunc = true;
249
- queries.push(`
250
- CREATE OR REPLACE FUNCTION ${funcNameParsed}()
251
- RETURNS trigger
252
- LANGUAGE plpgsql
253
- AS
254
- $$
255
-
256
- ${trigger.query}
257
-
258
- $$;
259
- `);
260
- }
261
-
262
- trigger.actions.forEach(action => {
263
- const triggerActionName = triggerFuncName + "_" + action;
264
-
265
- const triggerActionNameParsed = asName(triggerActionName)
266
- if (isDropped) {
267
- queries.push(`DROP TRIGGER IF EXISTS ${triggerActionNameParsed} ON ${tableName};`)
268
- }
269
-
270
- if (isDropped || !existingTriggers.some(t => t.trigger_name === triggerActionName)) {
271
- addFuncDef();
272
- const newTableName = action !== "delete" ? "NEW TABLE AS new_table" : "";
273
- const oldTableName = action !== "insert" ? "OLD TABLE AS old_table" : "";
274
- queries.push(`
275
- CREATE TRIGGER ${triggerActionNameParsed}
276
- ${trigger.type} ${action} ON ${tableName}
277
- REFERENCING ${newTableName} ${oldTableName}
278
- FOR EACH ${trigger.forEach}
279
- EXECUTE PROCEDURE ${funcNameParsed}();
280
- `);
281
- }
282
- })
283
- })
284
- }
285
- }
286
-
287
- if (queries.length) {
288
- const q = makeQuery(queries);
289
-
290
- try {
291
- await runQueries(queries);
292
- } catch (err: any) {
293
- this.initialising = false;
294
-
295
- console.error("TableConfig error: ", err);
296
- if (err.position) {
297
- const pos = +err.position;
298
- if (Number.isInteger(pos)) {
299
- return Promise.reject(err.toString() + "\n At:" + q.slice(pos - 50, pos + 50));
300
- }
301
- }
302
-
303
- return Promise.reject(err);
304
- }
305
- }
306
-
307
- if (migrations) {
308
- await this.db.any(`INSERT INTO ${migrations.table}(id, table_config) VALUES (${asValue(migrations.version)}, ${asValue(this.config)}) ON CONFLICT DO NOTHING;`)
309
- }
310
- this.initialising = false;
311
- if (changedSchema && !failedQueries.length) {
312
- if (!this.prevInitQueryHistory) {
313
- this.prevInitQueryHistory = queryHistory;
314
- } else if (this.prevInitQueryHistory.join() !== queryHistory.join()) {
315
- this.prostgles.init(this.prostgles.opts.onReady as any, { type: "TableConfig" });
316
- } else {
317
- console.error("TableConfig loop bug", queryHistory)
318
- }
319
- }
320
- if (failedQueries.length) {
321
- console.error("Table config failed queries: ", failedQueries)
322
- }
323
-
324
- await this.prostgles.refreshDBO();
325
- this.setTableOnMounts();
326
- }
package/lib/index.ts DELETED
@@ -1,13 +0,0 @@
1
- import { SessionUser } from "./Auth/AuthTypes";
2
- import { Prostgles } from "./Prostgles";
3
- import { ProstglesInitOptions } from "./ProstglesTypes";
4
-
5
- import { testDboTypes } from "./typeTests/dboTypeCheck";
6
- testDboTypes();
7
-
8
- function prostgles<S = void, SUser extends SessionUser = SessionUser>(params: ProstglesInitOptions<S, SUser>){
9
-
10
- const prgl = new Prostgles(params as any);
11
- return prgl.init(params.onReady as any, { type: "init" });
12
- }
13
- export = prostgles;