prostgles-server 4.2.619 → 4.2.621

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 (105) hide show
  1. package/debug/access-profile-source.patch +14 -0
  2. package/debug/client-profile-perf.cjs +17 -0
  3. package/debug/client-publish-types-test.log +16 -0
  4. package/debug/client-schema-test.log +10 -0
  5. package/debug/client-schema-types/DBGeneratedSchema.ts +59 -0
  6. package/debug/client-typecheck.ts +11 -0
  7. package/debug/profile-perf.cjs +26 -0
  8. package/debug/prostgles-types-4.0.282.tgz +0 -0
  9. package/debug/publish-schema-test.log +16 -0
  10. package/debug/run-client-schema.cjs +3 -0
  11. package/debug/run-publish-schema.cjs +3 -0
  12. package/debug/server-lib-tests.log +28 -0
  13. package/debug/types-pack.log +162 -0
  14. package/dist/DBSchemaBuilder/DBSchemaBuilder.d.ts +6 -0
  15. package/dist/DBSchemaBuilder/DBSchemaBuilder.d.ts.map +1 -1
  16. package/dist/DBSchemaBuilder/constants.d.ts +2 -0
  17. package/dist/DBSchemaBuilder/constants.d.ts.map +1 -0
  18. package/dist/DBSchemaBuilder/constants.js +5 -0
  19. package/dist/DBSchemaBuilder/constants.js.map +1 -0
  20. package/dist/DBSchemaBuilder/getClientDBGeneratedSchemas.d.ts +9 -0
  21. package/dist/DBSchemaBuilder/getClientDBGeneratedSchemas.d.ts.map +1 -0
  22. package/dist/DBSchemaBuilder/getClientDBGeneratedSchemas.js +97 -0
  23. package/dist/DBSchemaBuilder/getClientDBGeneratedSchemas.js.map +1 -0
  24. package/dist/DBSchemaBuilder/getColumnTypescriptDefinition.js +2 -2
  25. package/dist/DBSchemaBuilder/getDBGeneratedSchema.d.ts +3 -1
  26. package/dist/DBSchemaBuilder/getDBGeneratedSchema.d.ts.map +1 -1
  27. package/dist/DBSchemaBuilder/getDBGeneratedSchema.js +7 -5
  28. package/dist/DBSchemaBuilder/getDBGeneratedSchema.js.map +1 -1
  29. package/dist/DBSchemaBuilder/getPublishSchemas.d.ts +4 -0
  30. package/dist/DBSchemaBuilder/getPublishSchemas.d.ts.map +1 -0
  31. package/dist/DBSchemaBuilder/getPublishSchemas.js +34 -0
  32. package/dist/DBSchemaBuilder/getPublishSchemas.js.map +1 -0
  33. package/dist/DboBuilder/DboBuilder.d.ts +5 -8
  34. package/dist/DboBuilder/DboBuilder.d.ts.map +1 -1
  35. package/dist/DboBuilder/DboBuilder.js +11 -14
  36. package/dist/DboBuilder/DboBuilder.js.map +1 -1
  37. package/dist/DboBuilder/TableHandler/TableHandler.d.ts +1 -1
  38. package/dist/Prostgles.d.ts +3 -2
  39. package/dist/Prostgles.d.ts.map +1 -1
  40. package/dist/Prostgles.js +9 -3
  41. package/dist/Prostgles.js.map +1 -1
  42. package/dist/PublishParser/PublishParser.d.ts +3 -2
  43. package/dist/PublishParser/PublishParser.d.ts.map +1 -1
  44. package/dist/PublishParser/PublishParser.js +16 -5
  45. package/dist/PublishParser/PublishParser.js.map +1 -1
  46. package/dist/PublishParser/defineServerFunction.d.ts +5 -3
  47. package/dist/PublishParser/defineServerFunction.d.ts.map +1 -1
  48. package/dist/PublishParser/defineServerFunction.js.map +1 -1
  49. package/dist/PublishParser/getFileTableRules.d.ts +2 -2
  50. package/dist/PublishParser/getFileTableRules.d.ts.map +1 -1
  51. package/dist/PublishParser/getFileTableRules.js +2 -2
  52. package/dist/PublishParser/getFileTableRules.js.map +1 -1
  53. package/dist/PublishParser/getPublishedTableNames.d.ts +4 -0
  54. package/dist/PublishParser/getPublishedTableNames.d.ts.map +1 -0
  55. package/dist/PublishParser/getPublishedTableNames.js +23 -0
  56. package/dist/PublishParser/getPublishedTableNames.js.map +1 -0
  57. package/dist/PublishParser/getSchemaFromPublish.d.ts.map +1 -1
  58. package/dist/PublishParser/getSchemaFromPublish.js +2 -13
  59. package/dist/PublishParser/getSchemaFromPublish.js.map +1 -1
  60. package/dist/PublishParser/publishTypesAndUtils.d.ts +13 -6
  61. package/dist/PublishParser/publishTypesAndUtils.d.ts.map +1 -1
  62. package/dist/PublishParser/publishTypesAndUtils.js.map +1 -1
  63. package/dist/PublishParser/validatePublishProfiles.d.ts +7 -0
  64. package/dist/PublishParser/validatePublishProfiles.d.ts.map +1 -0
  65. package/dist/PublishParser/validatePublishProfiles.js +27 -0
  66. package/dist/PublishParser/validatePublishProfiles.js.map +1 -0
  67. package/dist/SchemaWatch/SchemaWatch.js +1 -1
  68. package/dist/SchemaWatch/SchemaWatch.js.map +1 -1
  69. package/dist/TableHooks/TableHooks.d.ts +7 -5
  70. package/dist/TableHooks/TableHooks.d.ts.map +1 -1
  71. package/dist/WebsocketAPI/getClientHandlers.d.ts +3 -3
  72. package/dist/WebsocketAPI/getClientHandlers.d.ts.map +1 -1
  73. package/dist/WebsocketAPI/getClientHandlers.js.map +1 -1
  74. package/dist/index.d.ts +2 -2
  75. package/dist/index.d.ts.map +1 -1
  76. package/dist/initProstgles.d.ts +2 -2
  77. package/dist/initProstgles.d.ts.map +1 -1
  78. package/dist/initProstgles.js +2 -4
  79. package/dist/initProstgles.js.map +1 -1
  80. package/dist/updateConfiguration.d.ts.map +1 -1
  81. package/dist/updateConfiguration.js +6 -2
  82. package/dist/updateConfiguration.js.map +1 -1
  83. package/eslint.config.mjs +1 -1
  84. package/lib/DBSchemaBuilder/DBSchemaBuilder.ts +10 -0
  85. package/lib/DBSchemaBuilder/constants.ts +1 -0
  86. package/lib/DBSchemaBuilder/getClientDBGeneratedSchemas.ts +116 -0
  87. package/lib/DBSchemaBuilder/getColumnTypescriptDefinition.ts +2 -2
  88. package/lib/DBSchemaBuilder/getDBGeneratedSchema.ts +11 -4
  89. package/lib/DBSchemaBuilder/getPublishSchemas.ts +41 -0
  90. package/lib/DboBuilder/DboBuilder.ts +15 -22
  91. package/lib/Prostgles.ts +10 -4
  92. package/lib/PublishParser/PublishParser.ts +25 -5
  93. package/lib/PublishParser/defineServerFunction.ts +5 -3
  94. package/lib/PublishParser/getFileTableRules.ts +3 -2
  95. package/lib/PublishParser/getPublishedTableNames.ts +29 -0
  96. package/lib/PublishParser/getSchemaFromPublish.ts +2 -17
  97. package/lib/PublishParser/publishTypesAndUtils.ts +13 -5
  98. package/lib/PublishParser/validatePublishProfiles.ts +22 -0
  99. package/lib/SchemaWatch/SchemaWatch.ts +1 -1
  100. package/lib/TableHooks/TableHooks.ts +14 -7
  101. package/lib/WebsocketAPI/getClientHandlers.ts +4 -4
  102. package/lib/index.ts +2 -2
  103. package/lib/initProstgles.ts +7 -19
  104. package/lib/updateConfiguration.ts +5 -1
  105. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"updateConfiguration.js","sourceRoot":"","sources":["../lib/updateConfiguration.ts"],"names":[],"mappings":";;;AAAA,qDAAiF;AAI1E,MAAM,mBAAmB,GAAG,KAAK,EACtC,IAAe,EACf,OAA6B,EAC7B,OAAyC,EACzC,KAAY,EACZ,EAAE;IACF,IAAI,CAAC,iBAAiB,EAAE,CAAC;IACzB,MAAM,kBAAkB,GAAG,IAAA,yBAAO,EAAC,OAAO,CAAC;SACxC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACT,6DAA6D;QAC7D,IAAI,KAAK,IAAI,CAAC,IAAA,yBAAO,EAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAChD,YAAY;YACZ,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;YAC1B,OAAO,CAAC,CAAC;QACX,CAAC;QACD,OAAO;IACT,CAAC,CAAC;SACD,MAAM,CAAC,2BAAS,CAAC,CAAC;IACrB,IAAI,CAAC,kBAAkB,CAAC,MAAM,EAAE,CAAC;QAC/B,MAAM,IAAI,CAAC,WAAW,CAAC;QACvB,OAAO,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QACnC,OAAO;IACT,CAAC;IAED,IAAI,IAAA,0BAAQ,EAAC,kBAAkB,EAAE,SAAS,CAAC,EAAE,CAAC;QAC5C,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;IACD,IAAI,IAAA,0BAAQ,EAAC,kBAAkB,EAAE,QAAQ,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;IAC1B,CAAC;IACD,IAAI,IAAA,0BAAQ,EAAC,kBAAkB,EAAE,MAAM,CAAC,EAAE,CAAC;QACzC,IAAI,CAAC,eAAe,EAAE,CAAC;IACzB,CAAC;IACD,IAAI,IAAA,0BAAQ,EAAC,kBAAkB,EAAE,IAAI,CAAC,EAAE,CAAC;QACvC,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;YACvC,MAAM,CAAC,UAAU,EAAE,CAAC;QACtB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IACE,IAAA,0BAAQ,EAAC,kBAAkB,EAAE,qBAAqB,CAAC;QACnD,IAAA,0BAAQ,EAAC,kBAAkB,EAAE,+BAA+B,CAAC,EAC7D,CAAC;QACD,IAAI,CAAC,aAAa,EAAE,CAAC;IACvB,CAAC;IAED,IAAI,IAAA,yBAAO,EAAC,OAAO,CAAC;QAAE,OAAO;IAE7B,IACE,kBAAkB,CAAC,KAAK,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,UAAU,CAAC,CAAC,EAChG,CAAC;QACD,OAAO;IACT,CAAC;IAED;;;OAGG;IACH,IACE,kBAAkB,CAAC,KAAK,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,4BAAoB,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,UAAU,CAAC,CAAC,EAChG,CAAC;QACD,IAAI,CAAC,aAAa,EAAE,CAAC;IACvB,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;YACvB,IAAI,EAAE,aAAa;YACnB,OAAO;SACR,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC;AApEW,QAAA,mBAAmB,uBAoE9B;AAEF;;GAEG;AACU,QAAA,oBAAoB,GAAG;IAClC,IAAI;IACJ,MAAM;IACN,SAAS;IACT,WAAW;IACX,eAAe;IACf,oBAAoB;CACyB,CAAC;AAEhD,MAAM,oBAAoB,GAAG,CAAC,YAAY,CAA+C,CAAC"}
1
+ {"version":3,"file":"updateConfiguration.js","sourceRoot":"","sources":["../lib/updateConfiguration.ts"],"names":[],"mappings":"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"}
package/eslint.config.mjs CHANGED
@@ -3,7 +3,7 @@ import tseslint from "typescript-eslint";
3
3
 
4
4
  export default tseslint.config(
5
5
  {
6
- ignores: ["node_modules", "dist", "examples", "**/*.d.ts", "tests", "docs"],
6
+ ignores: ["node_modules", "dist", "debug", "examples", "**/*.d.ts", "tests", "docs"],
7
7
  },
8
8
  eslint.configs.recommended,
9
9
  tseslint.configs.recommendedTypeChecked,
@@ -27,6 +27,16 @@ export type DBOFullyTyped<
27
27
  > = DBTableHandlersFromSchema<Schema> &
28
28
  DBHandlerServerWithTx<DBTableHandlersFromSchema<Schema>, WithTransactions>;
29
29
 
30
+ /** Publish-aware server wrappers for client requests; transactions and isView are unavailable. */
31
+ export type DBOFullyTypedClient<Schema = void> =
32
+ Schema extends DBSchema ?
33
+ {
34
+ [TName in keyof Schema]:
35
+ | TableHandler<Schema[TName]["columns"], Schema, TName>
36
+ | (Schema[TName] extends { optional: true } ? undefined : never);
37
+ }
38
+ : Record<string, Partial<TableHandler>>;
39
+
30
40
  export type PublishFullyTyped<Schema = void> =
31
41
  Schema extends DBSchema ?
32
42
  {
@@ -0,0 +1 @@
1
+ export const DB_GENERATED_SCHEMA_NAME = "DBGeneratedSchema";
@@ -0,0 +1,116 @@
1
+ import { DB_GENERATED_SCHEMA_NAME } from "./constants";
2
+ import type { DBSchemaTable, TableSchema } from "prostgles-types";
3
+ import type { TableConfig } from "../TableConfig/TableConfigTypes";
4
+
5
+ /** Permissions compiled from publish profiles at startup. */
6
+ export type ClientSchemaProfiles = Record<string, { tableSchema: DBSchemaTable[] }>;
7
+
8
+ export const getClientDBGeneratedSchemas = (
9
+ profiles: ClientSchemaProfiles,
10
+ tables: TableSchema[],
11
+ config: TableConfig | undefined,
12
+ ): string => {
13
+ const entries = Object.entries(profiles).sort(([a], [b]) => a.localeCompare(b));
14
+ if (!entries.length) return "";
15
+ for (const [name, schema] of entries) {
16
+ validateClientSchemaName(name);
17
+ for (const table of schema.tableSchema) {
18
+ const base = tables.find((t) => t.name === table.name);
19
+ if (!base || table.columns.some((c) => !base.columns.some((b) => b.name === c.name))) {
20
+ throw new Error(`Cannot generate ${name}: unknown table or column in ${table.name}.`);
21
+ }
22
+ }
23
+ }
24
+
25
+ const generate = (name: string, schemas: ClientSchemaProfiles[string][]) => {
26
+ const definitions = tables
27
+ .slice()
28
+ .sort((a, b) => a.name.localeCompare(b.name))
29
+ .flatMap((table) => {
30
+ const published = schemas.map((s) => s.tableSchema.find((t) => t.name === table.name));
31
+ if (!published.some(Boolean)) return [];
32
+ const inserting = published.filter((t) => t?.publishInfo.insert);
33
+ const tableType = `${DB_GENERATED_SCHEMA_NAME}[${JSON.stringify(table.name)}]`;
34
+ const required: string[] = [];
35
+ const optional: string[] = [];
36
+ const excluded: string[] = [];
37
+ for (const column of table.columns.slice().sort((a, b) => a.name.localeCompare(b.name))) {
38
+ const writable = inserting.map(
39
+ (t) => !!t?.columns.find((c) => c.name === column.name)?.insert,
40
+ );
41
+ if (!writable.some(Boolean)) {
42
+ excluded.push(`${JSON.stringify(column.name)}?: never`);
43
+ } else if (
44
+ !writable.every(Boolean) ||
45
+ config?.[table.name]?.syncConfig?.synced_field === column.name
46
+ ) {
47
+ optional.push(column.name);
48
+ } else {
49
+ required.push(column.name);
50
+ }
51
+ }
52
+ const input =
53
+ !inserting.length ? "never" : (
54
+ [
55
+ required.length ? `Pick<${tableType}["columns"], ${keys(required)}>` : "",
56
+ optional.length ? `Partial<Pick<${tableType}["columns"], ${keys(optional)}>>` : "",
57
+ excluded.length ? `{ ${excluded.join("; ")} }` : "",
58
+ ]
59
+ .filter(Boolean)
60
+ .join(" & ") || "Record<string, never>"
61
+ );
62
+ const updating = published.filter((t) => t?.publishInfo.update);
63
+ const updateAllowed = table.columns
64
+ .filter((column) =>
65
+ updating.some((t) => t?.columns.some((c) => c.name === column.name && c.update)),
66
+ )
67
+ .map((column) => column.name)
68
+ .sort();
69
+ const updateExcluded = table.columns
70
+ .filter((column) => !updateAllowed.includes(column.name))
71
+ .map((column) => `${JSON.stringify(column.name)}?: never`)
72
+ .sort();
73
+ const updateInput =
74
+ !updating.length ? "never" : (
75
+ [
76
+ updateAllowed.length ?
77
+ `Partial<import("prostgles-types").UpsertDataToPGCast<Pick<${tableType}["columns"], ${keys(updateAllowed)}>>>`
78
+ : "",
79
+ updateExcluded.length ? `{ ${updateExcluded.join("; ")} }` : "",
80
+ ]
81
+ .filter(Boolean)
82
+ .join(" & ") || "Record<string, never>"
83
+ );
84
+ const optionalTable = published.every(Boolean) ? "" : " optional: true;";
85
+ return [
86
+ ` ${JSON.stringify(table.name)}: ${tableType} & { insertColumns: ${input}; updateColumns: ${updateInput};${optionalTable} };`,
87
+ ];
88
+ });
89
+ return `export type ${name} = {\n${definitions.join("\n")}\n};`;
90
+ };
91
+
92
+ return [
93
+ "/** Publish access profiles. Row types retain the database schema; runtime permissions still apply. */",
94
+ ...entries.map(([name, schema]) => generate(name, [schema])),
95
+ "/** Permissive write inputs across all supplied profiles; tables missing from a profile are optional. */",
96
+ generate(
97
+ "ClientDBSchema",
98
+ entries.map(([, schema]) => schema),
99
+ ),
100
+ ].join("\n\n");
101
+ };
102
+
103
+ const keys = (names: string[]) => names.map((name) => JSON.stringify(name)).join(" | ");
104
+ const reservedNames = new Set([
105
+ DB_GENERATED_SCHEMA_NAME,
106
+ "DBSchema",
107
+ "DBSchemaForInsert",
108
+ "ClientDBSchema",
109
+ ]);
110
+
111
+ export const validateClientSchemaName = (name: string) => {
112
+ // Requiring a Schema suffix also avoids TypeScript keywords and primitive type names.
113
+ if (!/^[A-Za-z_$][\w$]*Schema$/.test(name) || reservedNames.has(name)) {
114
+ throw new Error(`Invalid client schema name: ${name}. Use a unique name ending in Schema.`);
115
+ }
116
+ };
@@ -25,8 +25,8 @@ export const getColumnTypescriptDefinition = ({
25
25
  column: TableSchema["columns"][number];
26
26
  }) => {
27
27
  /**
28
- * Columns that are nullable or have default values can be ommitted from an insert
29
- * Non nullable columns with default values cannot containt null values in an insert so they must contain a valid value or be omitted
28
+ * Columns that are nullable or have default values can be omitted from an insert
29
+ * Non nullable columns with default values cannot contain null values in an insert so they must contain a valid value or be omitted
30
30
  */
31
31
 
32
32
  const dataType = getDataType({
@@ -1,15 +1,22 @@
1
+ import { DB_GENERATED_SCHEMA_NAME } from "./constants";
1
2
  import { isDefined, isEmpty, type TableSchema } from "prostgles-types";
2
3
  import type { TableConfig } from "../TableConfig/TableConfigTypes";
3
4
  import { escapeTSNames } from "../utils/utils";
4
5
  import { getColumnTypescriptDefinition } from "./getColumnTypescriptDefinition";
5
6
  import { fromEntries } from "../PublishParser/applyScopeToTableRules";
7
+ import {
8
+ getClientDBGeneratedSchemas,
9
+ type ClientSchemaProfiles,
10
+ } from "./getClientDBGeneratedSchemas";
6
11
 
7
12
  export const getDBGeneratedSchema = ({
8
13
  config,
9
14
  tablesOrViews,
15
+ clientSchemas,
10
16
  }: {
11
17
  config: TableConfig | undefined;
12
18
  tablesOrViews: TableSchema[];
19
+ clientSchemas?: ClientSchemaProfiles;
13
20
  }): string => {
14
21
  const tables: string[] = [];
15
22
 
@@ -61,7 +68,7 @@ export const getDBGeneratedSchema = ({
61
68
  };\n `);
62
69
  });
63
70
  return `
64
- export type DBGeneratedSchema = {
71
+ export type ${DB_GENERATED_SCHEMA_NAME} = {
65
72
  ${tables.join("")}
66
73
  }
67
74
 
@@ -69,14 +76,14 @@ export type DBGeneratedSchema = {
69
76
  * Data types as expected when selecting from the database
70
77
  * */
71
78
  export type DBSchema = {
72
- [K in keyof DBGeneratedSchema]: Required<DBGeneratedSchema[K]["columns"]>;
79
+ [K in keyof ${DB_GENERATED_SCHEMA_NAME}]: Required<${DB_GENERATED_SCHEMA_NAME}[K]["columns"]>;
73
80
  };
74
81
 
75
82
  /**
76
83
  * Data types as expected when inserting into the database (optional fields might be nullable/with defaults)
77
84
  * */
78
85
  export type DBSchemaForInsert = {
79
- [K in keyof DBGeneratedSchema]: DBGeneratedSchema[K]["columns"];
80
- };
86
+ [K in keyof ${DB_GENERATED_SCHEMA_NAME}]: ${DB_GENERATED_SCHEMA_NAME}[K]["columns"];
87
+ };${clientSchemas ? "\n" + getClientDBGeneratedSchemas(clientSchemas, tablesOrViews, config) : ""}
81
88
  `;
82
89
  };
@@ -0,0 +1,41 @@
1
+ import { getRawColumns } from "../DboBuilder/getColumns";
2
+ import { getRawInfo } from "../DboBuilder/ViewHandler/getRawInfo";
3
+ import { getPublishedTableNames } from "../PublishParser/getPublishedTableNames";
4
+ import type { PublishObject, PublishParser } from "../PublishParser/PublishParser";
5
+ import type { ClientSchemaProfiles } from "./getClientDBGeneratedSchemas";
6
+
7
+ export const getPublishSchemas = async (
8
+ publishParser: PublishParser,
9
+ ): Promise<ClientSchemaProfiles | undefined> => {
10
+ if (!Array.isArray(publishParser.publish)) {
11
+ return;
12
+ }
13
+ const entries = publishParser.publish;
14
+ const profiles: ClientSchemaProfiles = Object.fromEntries(
15
+ entries.map(({ name }) => [name, { tableSchema: [] }]),
16
+ );
17
+ const { tablesOrViews = [] } = publishParser.prostgles.dboBuilder;
18
+ for (const { name, publish } of entries) {
19
+ const publishObject: PublishObject =
20
+ publish === "*" ?
21
+ Object.fromEntries(tablesOrViews.map((table) => [table.name, "*"]))
22
+ : (publish ?? {});
23
+ const tableNames = getPublishedTableNames(publishParser, publishObject);
24
+ for (const tableName of tableNames) {
25
+ const rules = await publishParser.getTableRules(
26
+ { tableName, clientReq: undefined },
27
+ undefined,
28
+ undefined,
29
+ publishObject,
30
+ );
31
+ if (!rules || !Object.values(rules).some(Boolean)) continue;
32
+ const table = publishParser.dbo[tableName]!;
33
+ profiles[name]!.tableSchema.push({
34
+ ...getRawInfo.call(table, undefined, rules),
35
+ name: tableName,
36
+ columns: await getRawColumns.call(table, undefined, undefined, rules),
37
+ });
38
+ }
39
+ }
40
+ return profiles;
41
+ };
@@ -35,6 +35,7 @@ import { prepareShortestJoinPaths } from "./joins/prepareShortestJoinPaths";
35
35
  import { cacheDBTypes, runSQL } from "./runSql/runSQL";
36
36
  import { getDetailedFieldInfo, type getDbTypes } from "./runSql/runSqlUtils";
37
37
  import { getTablesForSchemaPostgresSQL } from "./schema/getTablesForSchemaPostgresSQL";
38
+ import { getPublishSchemas } from "../DBSchemaBuilder/getPublishSchemas";
38
39
 
39
40
  export * from "./DboBuilderTypes";
40
41
  export * from "./dboBuilderUtils";
@@ -208,8 +209,8 @@ export class DboBuilder {
208
209
  return this.shortestJoinPaths;
209
210
  }
210
211
 
211
- prepareShortestJoinPaths = async () => {
212
- const { joins, shortestJoinPaths, joinGraph } = await prepareShortestJoinPaths(this);
212
+ prepareShortestJoinPaths = () => {
213
+ const { joins, shortestJoinPaths, joinGraph } = prepareShortestJoinPaths(this);
213
214
  this.joinGraph = joinGraph;
214
215
  this.joins = joins;
215
216
  this.shortestJoinPaths = shortestJoinPaths;
@@ -276,7 +277,7 @@ export class DboBuilder {
276
277
  this.prostgles.dbForSchema!,
277
278
  this.prostgles.opts.schemaFilter,
278
279
  );
279
- await this.prepareShortestJoinPaths();
280
+ this.prepareShortestJoinPaths();
280
281
 
281
282
  this.dbo = {};
282
283
  this.tablesOrViews.map((tov) => {
@@ -349,7 +350,7 @@ export class DboBuilder {
349
350
  }
350
351
  return this.tablesOrViews;
351
352
  };
352
- getTsDefinitions = <DDL extends string | undefined = undefined>({
353
+ getTsDefinitions = async ({
353
354
  excludeFunctions,
354
355
  extraTables = [],
355
356
  ddlWithRollback,
@@ -362,12 +363,13 @@ export class DboBuilder {
362
363
  * This is useful for generating an updated TypeScript schema after running a migration SQL file, for example.
363
364
  * Note that this will be run within a transaction that is rolled back, so it SHOULD not affect the actual database schema.
364
365
  */
365
- ddlWithRollback?: DDL;
366
- } = {}): DDL extends string ? Promise<{ tsSchema: string; tablesOrViews: TableSchema[] }>
367
- : { tsSchema: string; tablesOrViews: TableSchema[] } => {
366
+ ddlWithRollback?: string;
367
+ } = {}): Promise<{ tsSchema: string; tablesOrViews: TableSchema[] }> => {
368
+ const clientSchemas = this.publishParser && (await getPublishSchemas(this.publishParser));
368
369
  const getSchema = (tablesOrViews: TableSchema[]) => {
369
370
  const tableTsDefinitions = getDBGeneratedSchema({
370
371
  config: this.prostgles.mergedTableConfig.tableConfig,
372
+ clientSchemas,
371
373
  tablesOrViews: [
372
374
  ...tablesOrViews,
373
375
  ...extraTables.filter(
@@ -386,26 +388,17 @@ export class DboBuilder {
386
388
  return { tsSchema, tablesOrViews };
387
389
  };
388
390
  if (ddlWithRollback) {
389
- return new Promise<{ tsSchema: string; tablesOrViews: TableSchema[] }>((resolve, reject) => {
390
- getTablesForSchemaPostgresSQL(this, {
391
- schemaFilter: this.prostgles.opts.schemaFilter,
392
- ddlWithRollback,
393
- })
394
- .then((res) => {
395
- const tablesOrViews = res.result;
396
- resolve(getSchema(tablesOrViews));
397
- })
398
- .catch(reject);
399
- }) as DDL extends string ? Promise<{ tsSchema: string; tablesOrViews: TableSchema[] }>
400
- : { tsSchema: string; tablesOrViews: TableSchema[] };
391
+ const { result } = await getTablesForSchemaPostgresSQL(this, {
392
+ schemaFilter: this.prostgles.opts.schemaFilter,
393
+ ddlWithRollback,
394
+ });
395
+ return getSchema(result);
401
396
  }
402
397
  const tablesOrViews = this.tablesOrViews;
403
398
  if (!tablesOrViews) {
404
399
  throw new Error("Unexpected error: tablesOrViews is undefined");
405
400
  }
406
- return getSchema(tablesOrViews) as DDL extends string ?
407
- Promise<{ tsSchema: string; tablesOrViews: TableSchema[] }>
408
- : { tsSchema: string; tablesOrViews: TableSchema[] };
401
+ return getSchema(tablesOrViews);
409
402
  };
410
403
 
411
404
  getShortestJoinPath = (
package/lib/Prostgles.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { DB_GENERATED_SCHEMA_NAME } from "./DBSchemaBuilder/constants";
1
2
  import type pgPromise from "pg-promise";
2
3
  import { AuthHandler } from "./Auth/AuthHandler";
3
4
  import type { SessionUser } from "./Auth/AuthTypes";
@@ -21,7 +22,7 @@ export { applyTableConfig } from "./TableConfig/applyTableConfig";
21
22
 
22
23
  import { CHANNELS, tryCatchV2 } from "prostgles-types";
23
24
  import type { DBEventsManager } from "./DBEventsManager";
24
- import type { PublishParser } from "./PublishParser/PublishParser";
25
+ import { PublishParser } from "./PublishParser/PublishParser";
25
26
  import { pushSocketSchema } from "./WebsocketAPI/pushSocketSchema";
26
27
 
27
28
  export type DB = pgPromise.IDatabase<{}, pg.IClient>;
@@ -229,7 +230,7 @@ export class Prostgles {
229
230
  }
230
231
 
231
232
  getTSFileName() {
232
- const fileName = "DBGeneratedSchema.ts";
233
+ const fileName = `${DB_GENERATED_SCHEMA_NAME}.ts`;
233
234
  const _dir = this.opts.tsGeneratedTypesDir || "";
234
235
  const dir = _dir.endsWith("/") ? _dir : `${_dir}/`;
235
236
  const fullPath = dir + fileName;
@@ -240,10 +241,10 @@ export class Prostgles {
240
241
  * Will write the Schema Typescript definitions to file (tsGeneratedTypesDir)
241
242
  * force is used for hotReloadMode to trigger a restart
242
243
  */
243
- writeDBSchema(force = false) {
244
+ async writeDBSchema(force = false) {
244
245
  if (this.opts.tsGeneratedTypesDir) {
246
+ const { tsSchema: fileContent } = await this.dboBuilder.getTsDefinitions();
245
247
  const { fullPath, fileName } = this.getTSFileName();
246
- const { tsSchema: fileContent } = this.dboBuilder.getTsDefinitions();
247
248
  fs.mkdirSync(dirname(fullPath), { recursive: true });
248
249
 
249
250
  const existingContent =
@@ -348,6 +349,11 @@ export class Prostgles {
348
349
  this.restApi = this.opts.restApi && new RestApi({ prostgles: this, ...this.opts.restApi });
349
350
  };
350
351
 
352
+ initPublishParser = () => {
353
+ this.publishParser = new PublishParser(this);
354
+ this.dboBuilder.publishParser = this.publishParser;
355
+ };
356
+
351
357
  initAuthHandler = () => {
352
358
  this.authHandler.destroy();
353
359
  this.authHandler = new AuthHandler(this);
@@ -25,9 +25,12 @@ import {
25
25
  type PermissionScope,
26
26
  type PublishObject,
27
27
  } from "./publishTypesAndUtils";
28
+ import { validatePublishProfiles } from "./validatePublishProfiles";
28
29
 
29
30
  export class PublishParser {
30
- publish: ProstglesInitOptions<void, SessionUser, any>["publish"];
31
+ publish:
32
+ | Exclude<ProstglesInitOptions<void, SessionUser, any>["publish"], unknown[]>
33
+ | ReturnType<typeof validatePublishProfiles>;
31
34
  publishRawSQL?: any;
32
35
  dbo: DBHandlerServer;
33
36
  db: DB;
@@ -35,7 +38,8 @@ export class PublishParser {
35
38
 
36
39
  constructor(prostgles: Prostgles) {
37
40
  this.prostgles = prostgles;
38
- this.publish = prostgles.opts.publish;
41
+ const { publish } = prostgles.opts;
42
+ this.publish = Array.isArray(publish) ? validatePublishProfiles(publish) : publish;
39
43
 
40
44
  // eslint-disable-next-line @typescript-eslint/unbound-method
41
45
  this.publishRawSQL = prostgles.opts.publishRawSQL;
@@ -119,7 +123,7 @@ export class PublishParser {
119
123
  const { clientDb } = await publishParams.getClientDBHandlers(undefined);
120
124
  const { clientInfo, clientReq, tables } = publishParams;
121
125
  const restrictedCtx: RestrictedFunctionContext<void, SessionUser, unknown> = {
122
- dbo: clientDb as unknown as DBOFullyTyped<void>,
126
+ dbo: clientDb,
123
127
  user,
124
128
  clientInfo,
125
129
  clientReq,
@@ -146,7 +150,17 @@ export class PublishParser {
146
150
  clientInfo: AuthResultWithSID | undefined,
147
151
  ): Promise<PublishObject | undefined> {
148
152
  const publishParams = await this.getPublishParams(clientReq, clientInfo);
149
- const publish = await applyParamsIfFunc(this.publish, publishParams);
153
+
154
+ const publish = await (() => {
155
+ if (Array.isArray(this.publish)) {
156
+ const { user } = publishParams;
157
+ if (!user) return undefined;
158
+ return this.publish.find((publishRule) => publishRule.userTypes.includes(user.type))
159
+ ?.publish;
160
+ }
161
+
162
+ return applyParamsIfFunc(this.publish, publishParams);
163
+ })();
150
164
 
151
165
  if (publish === "*") {
152
166
  const publish: PublishObject = {};
@@ -271,13 +285,18 @@ export class PublishParser {
271
285
  args: DboTable,
272
286
  clientInfo: AuthResultWithSID | undefined,
273
287
  scope: PermissionScope | undefined,
288
+ overriddenPublish?: PublishObject,
274
289
  ): Promise<ParsedTableRule | undefined> {
275
290
  const { tableName } = args;
276
291
  const tableHandler = this.dbo[tableName];
277
292
  if (!tableHandler) {
278
293
  throw "INTERNAL ERROR: table handler not found for " + args.tableName;
279
294
  }
280
- const fileTablePublishRules = await this.getTableRulesWithoutFileTable(args, clientInfo);
295
+ const fileTablePublishRules = await this.getTableRulesWithoutFileTable(
296
+ args,
297
+ clientInfo,
298
+ overriddenPublish,
299
+ );
281
300
  if (this.dbo[args.tableName]?.is_media) {
282
301
  const { rules: fileTableRules } = await getFileTableRules.bind(this)(
283
302
  args.tableName,
@@ -285,6 +304,7 @@ export class PublishParser {
285
304
  args.clientReq,
286
305
  clientInfo,
287
306
  scope,
307
+ overriddenPublish,
288
308
  );
289
309
  return applyScopeToTableRules(
290
310
  tableName,
@@ -8,7 +8,7 @@ import type {
8
8
  SQLHandler,
9
9
  } from "prostgles-types";
10
10
  import type { SessionUser } from "../Auth/AuthTypes";
11
- import type { DBOFullyTyped } from "../DBSchemaBuilder/DBSchemaBuilder";
11
+ import type { DBOFullyTyped, DBOFullyTypedClient } from "../DBSchemaBuilder/DBSchemaBuilder";
12
12
  import type { DB } from "../initProstgles";
13
13
  import type { PublishParams } from "./publishTypesAndUtils";
14
14
 
@@ -17,7 +17,6 @@ type FunctionContextBase<S, SUser extends SessionUser, Context> = Pick<
17
17
  "tables" | "clientReq" | "clientInfo"
18
18
  > & {
19
19
  context: Context;
20
- dbo: DBOFullyTyped<S>;
21
20
  user: S extends DBSchema ?
22
21
  S["users"]["columns"] extends AnyObject ?
23
22
  Required<S["users"]["columns"]>
@@ -29,13 +28,16 @@ export type RestrictedFunctionContext<
29
28
  S = void,
30
29
  SUser extends SessionUser = SessionUser,
31
30
  Context = undefined,
32
- > = FunctionContextBase<S, SUser, Context>;
31
+ > = FunctionContextBase<S, SUser, Context> & {
32
+ dbo: DBOFullyTypedClient<S>;
33
+ };
33
34
 
34
35
  export type UnrestrictedFunctionContext<
35
36
  S = void,
36
37
  SUser extends SessionUser = SessionUser,
37
38
  Context = undefined,
38
39
  > = FunctionContextBase<S, SUser, Context> & {
40
+ dbo: DBOFullyTyped<S>;
39
41
  db: DB;
40
42
  sql: SQLHandler;
41
43
  getClientDBHandlers: PublishParams<S, SUser>["getClientDBHandlers"];
@@ -3,7 +3,7 @@ import { includes, isDefined } from "prostgles-types";
3
3
  import type { AuthClientRequest, AuthResultWithSID } from "../Auth/AuthTypes";
4
4
  import { parseFieldFilter } from "../DboBuilder/ViewHandler/parseFieldFilter";
5
5
  import type { PublishParser } from "./PublishParser";
6
- import type { ParsedPublishTable, UpdateRule } from "./publishTypesAndUtils";
6
+ import type { ParsedPublishTable, PublishObject, UpdateRule } from "./publishTypesAndUtils";
7
7
  import type { LocalParams } from "../DboBuilder/DboBuilder";
8
8
 
9
9
  /**
@@ -21,6 +21,7 @@ export async function getFileTableRules(
21
21
  clientReq: AuthClientRequest | undefined,
22
22
  clientInfo: AuthResultWithSID | undefined,
23
23
  scope: LocalParams["scope"],
24
+ overriddenPublish?: PublishObject,
24
25
  ) {
25
26
  const forcedDeleteFilters: FullFilter<AnyObject, void>[] = [];
26
27
  const forcedSelectFilters: FullFilter<AnyObject, void>[] = [];
@@ -42,7 +43,7 @@ export async function getFileTableRules(
42
43
  .filter(isDefined);
43
44
  if (referencedColumns?.length) {
44
45
  for (const { tableName, fileColumns, allColumns } of referencedColumns) {
45
- const tableRules = await this.getTableRules({ clientReq, tableName }, clientInfo, scope);
46
+ const tableRules = await this.getTableRules({ clientReq, tableName }, clientInfo, scope, overriddenPublish);
46
47
  if (tableRules) {
47
48
  fileColumns.map((column) => {
48
49
  const path = [{ table: tableName, on: [{ id: column }] }];
@@ -0,0 +1,29 @@
1
+ import type { PublishParser } from "./PublishParser";
2
+ import { type PublishObject } from "./PublishParser";
3
+
4
+ export const getPublishedTableNames = (
5
+ publishParserInstance: PublishParser,
6
+ publishObject: PublishObject,
7
+ ) => {
8
+ const txKey = !publishParserInstance.prostgles.opts.transactions ? "" : "tx";
9
+ const tableNames = Object.keys(publishObject).filter((k) => !txKey || txKey !== k);
10
+
11
+ /**
12
+ * Add file table to the list of published tables if it's referenced by other published tables.
13
+ * Access to the file table is controlled through the publish rules of the tables referencing it.
14
+ */
15
+ const fileTableName = publishParserInstance.prostgles.opts.fileTable?.tableName;
16
+ if (
17
+ fileTableName &&
18
+ publishParserInstance.dbo[fileTableName]?.is_media &&
19
+ !tableNames.includes(fileTableName)
20
+ ) {
21
+ const isReferenced = publishParserInstance.prostgles.dboBuilder.tablesOrViews?.some((t) =>
22
+ t.columns.some((c) => c.references?.some((r) => r.ftable === fileTableName)),
23
+ );
24
+ if (isReferenced) {
25
+ tableNames.unshift(fileTableName);
26
+ }
27
+ }
28
+ return tableNames;
29
+ };
@@ -4,6 +4,7 @@ import type { AuthClientRequest, AuthResultWithSID } from "../Auth/AuthTypes";
4
4
  import type { PublishParser } from "./PublishParser";
5
5
  import { type PermissionScope, type PublishObject } from "./PublishParser";
6
6
  import { getDBSchemaTable } from "./getDBSchemaTable";
7
+ import { getPublishedTableNames } from "./getPublishedTableNames";
7
8
 
8
9
  type Args = AuthClientRequest & {
9
10
  userData: AuthResultWithSID | undefined;
@@ -19,8 +20,6 @@ export async function getSchemaFromPublish(
19
20
  const tableSchemaErrors: TableSchemaErrors = {};
20
21
  const tables: DBSchemaTable[] = [];
21
22
 
22
- const txKey = !this.prostgles.opts.transactions ? "" : "tx";
23
-
24
23
  try {
25
24
  /* Publish tables and views based on socket */
26
25
  const clientInfo =
@@ -39,21 +38,7 @@ export async function getSchemaFromPublish(
39
38
  if (!publish || !Object.keys(publish).length) {
40
39
  return { tables, tableSchemaErrors };
41
40
  }
42
- const tableNames = Object.keys(publish).filter((k) => !txKey || txKey !== k);
43
-
44
- /**
45
- * Add file table to the list of published tables if it's referenced by other published tables.
46
- * Access to the file table is controlled through the publish rules of the tables referencing it.
47
- */
48
- const fileTableName = this.prostgles.opts.fileTable?.tableName;
49
- if (fileTableName && this.dbo[fileTableName]?.is_media && !tableNames.includes(fileTableName)) {
50
- const isReferenced = this.prostgles.dboBuilder.tablesOrViews?.some((t) =>
51
- t.columns.some((c) => c.references?.some((r) => r.ftable === fileTableName)),
52
- );
53
- if (isReferenced) {
54
- tableNames.unshift(fileTableName);
55
- }
56
- }
41
+ const tableNames = getPublishedTableNames(this, publish);
57
42
 
58
43
  await Promise.all(
59
44
  tableNames.map(async (tableName) => {
@@ -62,7 +62,7 @@ export type ValidateBeforeRowArgsCommon<R = AnyObject, DBX = DBHandlerServer> =
62
62
  data: Partial<R>;
63
63
  filter: AnyObject | undefined;
64
64
  };
65
- export type ValidateRowArgsCommon<R = AnyObject, DBX = DBHandlerServer> = {
65
+ export type ValidateRowArgsCommon<R = AnyObject, DBX = DBHandlerServer, InputDataType = R> = {
66
66
  row: R;
67
67
  dbx: DBX;
68
68
  tx: pgPromise.ITask<{}> | DB;
@@ -73,11 +73,12 @@ export type ValidateRowArgsCommon<R = AnyObject, DBX = DBHandlerServer> = {
73
73
  }
74
74
  | {
75
75
  command: "insert";
76
- data: R;
76
+ /** The whole input, including all rows for a bulk insert. */
77
+ data: Partial<InputDataType> | Partial<InputDataType>[];
77
78
  }
78
79
  | {
79
80
  command: "update";
80
- data: Partial<R>;
81
+ data: Partial<InputDataType>;
81
82
  }
82
83
  );
83
84
 
@@ -113,14 +114,14 @@ export type TransactionCallbacks<DBO = DBHandlerServer> = {
113
114
  onRollback: OnCommit<DBO>;
114
115
  };
115
116
 
116
- export type AfterEachTsTrigger<R, DBX, Context = undefined> = {
117
+ export type AfterEachTsTrigger<R, DBX, Context = undefined, InputDataType = R> = {
117
118
  commands: Partial<Record<"insert" | "update" | "delete", 1>>;
118
119
  /**
119
120
  * Will only run this trigger if the insert/update provides non null values for these fields.
120
121
  */
121
122
  changedFields?: (keyof R)[];
122
123
  validate: (
123
- params: ValidateRowArgsCommon<R, DBX> &
124
+ params: ValidateRowArgsCommon<R, DBX, InputDataType> &
124
125
  TransactionCallbacks<DBX> & {
125
126
  localParams: undefined | LocalParams;
126
127
  context: Context;
@@ -556,6 +557,13 @@ export type ParsedPublishTables = {
556
557
 
557
558
  type PublishAllOrNothingRoot = Exclude<PublishAllOrNothing, boolean>;
558
559
  export type PublishedResult<Schema = void> = PublishAllOrNothingRoot | PublishFullyTyped<Schema>;
560
+ export type PublishProfile<Schema = void> = {
561
+ /** Exported schema type name; defaults to Publish1Schema, Publish2Schema, etc. */
562
+ name?: string;
563
+ userTypes: string[];
564
+ publish: PublishedResult<Schema>;
565
+ };
559
566
  export type Publish<Schema = void, SUser extends SessionUser = SessionUser> =
567
+ | PublishProfile<Schema>[]
560
568
  | PublishedResult<Schema>
561
569
  | ((params: PublishParams<Schema, SUser>) => Awaitable<PublishedResult<Schema>>);