@constructive-io/graphql-server 2.14.8 → 2.15.0

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 (219) hide show
  1. package/codegen/orm/client.d.ts +55 -0
  2. package/codegen/orm/client.js +75 -0
  3. package/codegen/orm/index.d.ts +632 -0
  4. package/codegen/orm/index.js +182 -0
  5. package/codegen/orm/input-types.d.ts +13248 -0
  6. package/codegen/orm/input-types.js +7 -0
  7. package/codegen/orm/models/api.d.ts +42 -0
  8. package/codegen/orm/models/api.js +77 -0
  9. package/codegen/orm/models/apiExtension.d.ts +42 -0
  10. package/codegen/orm/models/apiExtension.js +77 -0
  11. package/codegen/orm/models/apiModule.d.ts +42 -0
  12. package/codegen/orm/models/apiModule.js +77 -0
  13. package/codegen/orm/models/apiSchema.d.ts +42 -0
  14. package/codegen/orm/models/apiSchema.js +77 -0
  15. package/codegen/orm/models/app.d.ts +42 -0
  16. package/codegen/orm/models/app.js +77 -0
  17. package/codegen/orm/models/checkConstraint.d.ts +42 -0
  18. package/codegen/orm/models/checkConstraint.js +77 -0
  19. package/codegen/orm/models/connectedAccountsModule.d.ts +42 -0
  20. package/codegen/orm/models/connectedAccountsModule.js +77 -0
  21. package/codegen/orm/models/cryptoAddressesModule.d.ts +42 -0
  22. package/codegen/orm/models/cryptoAddressesModule.js +77 -0
  23. package/codegen/orm/models/cryptoAuthModule.d.ts +42 -0
  24. package/codegen/orm/models/cryptoAuthModule.js +77 -0
  25. package/codegen/orm/models/database.d.ts +42 -0
  26. package/codegen/orm/models/database.js +77 -0
  27. package/codegen/orm/models/databaseExtension.d.ts +42 -0
  28. package/codegen/orm/models/databaseExtension.js +77 -0
  29. package/codegen/orm/models/databaseProvision.d.ts +42 -0
  30. package/codegen/orm/models/databaseProvision.js +77 -0
  31. package/codegen/orm/models/defaultIdsModule.d.ts +42 -0
  32. package/codegen/orm/models/defaultIdsModule.js +77 -0
  33. package/codegen/orm/models/denormalizedTableField.d.ts +42 -0
  34. package/codegen/orm/models/denormalizedTableField.js +77 -0
  35. package/codegen/orm/models/domain.d.ts +42 -0
  36. package/codegen/orm/models/domain.js +77 -0
  37. package/codegen/orm/models/emailsModule.d.ts +42 -0
  38. package/codegen/orm/models/emailsModule.js +77 -0
  39. package/codegen/orm/models/encryptedSecretsModule.d.ts +42 -0
  40. package/codegen/orm/models/encryptedSecretsModule.js +77 -0
  41. package/codegen/orm/models/extension.d.ts +42 -0
  42. package/codegen/orm/models/extension.js +77 -0
  43. package/codegen/orm/models/field.d.ts +42 -0
  44. package/codegen/orm/models/field.js +77 -0
  45. package/codegen/orm/models/fieldModule.d.ts +42 -0
  46. package/codegen/orm/models/fieldModule.js +77 -0
  47. package/codegen/orm/models/foreignKeyConstraint.d.ts +42 -0
  48. package/codegen/orm/models/foreignKeyConstraint.js +77 -0
  49. package/codegen/orm/models/fullTextSearch.d.ts +42 -0
  50. package/codegen/orm/models/fullTextSearch.js +77 -0
  51. package/codegen/orm/models/hierarchyModule.d.ts +42 -0
  52. package/codegen/orm/models/hierarchyModule.js +77 -0
  53. package/codegen/orm/models/index.d.ts +64 -0
  54. package/codegen/orm/models/index.js +127 -0
  55. package/codegen/orm/models/indexModel.d.ts +42 -0
  56. package/codegen/orm/models/indexModel.js +77 -0
  57. package/codegen/orm/models/invitesModule.d.ts +42 -0
  58. package/codegen/orm/models/invitesModule.js +77 -0
  59. package/codegen/orm/models/levelsModule.d.ts +42 -0
  60. package/codegen/orm/models/levelsModule.js +77 -0
  61. package/codegen/orm/models/limitFunction.d.ts +42 -0
  62. package/codegen/orm/models/limitFunction.js +77 -0
  63. package/codegen/orm/models/limitsModule.d.ts +42 -0
  64. package/codegen/orm/models/limitsModule.js +77 -0
  65. package/codegen/orm/models/membershipTypesModule.d.ts +42 -0
  66. package/codegen/orm/models/membershipTypesModule.js +77 -0
  67. package/codegen/orm/models/membershipsModule.d.ts +42 -0
  68. package/codegen/orm/models/membershipsModule.js +77 -0
  69. package/codegen/orm/models/module.d.ts +42 -0
  70. package/codegen/orm/models/module.js +77 -0
  71. package/codegen/orm/models/moduleDefinition.d.ts +42 -0
  72. package/codegen/orm/models/moduleDefinition.js +77 -0
  73. package/codegen/orm/models/moduleField.d.ts +42 -0
  74. package/codegen/orm/models/moduleField.js +77 -0
  75. package/codegen/orm/models/moduleInputRecord.d.ts +42 -0
  76. package/codegen/orm/models/moduleInputRecord.js +77 -0
  77. package/codegen/orm/models/moduleOutput.d.ts +42 -0
  78. package/codegen/orm/models/moduleOutput.js +77 -0
  79. package/codegen/orm/models/permissionsModule.d.ts +42 -0
  80. package/codegen/orm/models/permissionsModule.js +77 -0
  81. package/codegen/orm/models/phoneNumbersModule.d.ts +42 -0
  82. package/codegen/orm/models/phoneNumbersModule.js +77 -0
  83. package/codegen/orm/models/policy.d.ts +42 -0
  84. package/codegen/orm/models/policy.js +77 -0
  85. package/codegen/orm/models/primaryKeyConstraint.d.ts +42 -0
  86. package/codegen/orm/models/primaryKeyConstraint.js +77 -0
  87. package/codegen/orm/models/procedure.d.ts +42 -0
  88. package/codegen/orm/models/procedure.js +77 -0
  89. package/codegen/orm/models/profilesModule.d.ts +42 -0
  90. package/codegen/orm/models/profilesModule.js +77 -0
  91. package/codegen/orm/models/rlsFunction.d.ts +42 -0
  92. package/codegen/orm/models/rlsFunction.js +77 -0
  93. package/codegen/orm/models/rlsModule.d.ts +42 -0
  94. package/codegen/orm/models/rlsModule.js +77 -0
  95. package/codegen/orm/models/schema.d.ts +42 -0
  96. package/codegen/orm/models/schema.js +77 -0
  97. package/codegen/orm/models/schemaGrant.d.ts +42 -0
  98. package/codegen/orm/models/schemaGrant.js +77 -0
  99. package/codegen/orm/models/secretsModule.d.ts +42 -0
  100. package/codegen/orm/models/secretsModule.js +77 -0
  101. package/codegen/orm/models/site.d.ts +42 -0
  102. package/codegen/orm/models/site.js +77 -0
  103. package/codegen/orm/models/siteMetadatum.d.ts +42 -0
  104. package/codegen/orm/models/siteMetadatum.js +77 -0
  105. package/codegen/orm/models/siteModule.d.ts +42 -0
  106. package/codegen/orm/models/siteModule.js +77 -0
  107. package/codegen/orm/models/siteTheme.d.ts +42 -0
  108. package/codegen/orm/models/siteTheme.js +77 -0
  109. package/codegen/orm/models/table.d.ts +42 -0
  110. package/codegen/orm/models/table.js +77 -0
  111. package/codegen/orm/models/tableGrant.d.ts +42 -0
  112. package/codegen/orm/models/tableGrant.js +77 -0
  113. package/codegen/orm/models/tokensModule.d.ts +42 -0
  114. package/codegen/orm/models/tokensModule.js +77 -0
  115. package/codegen/orm/models/trigger.d.ts +42 -0
  116. package/codegen/orm/models/trigger.js +77 -0
  117. package/codegen/orm/models/triggerFunction.d.ts +42 -0
  118. package/codegen/orm/models/triggerFunction.js +77 -0
  119. package/codegen/orm/models/uniqueConstraint.d.ts +42 -0
  120. package/codegen/orm/models/uniqueConstraint.js +77 -0
  121. package/codegen/orm/models/userAuthModule.d.ts +42 -0
  122. package/codegen/orm/models/userAuthModule.js +77 -0
  123. package/codegen/orm/models/usersModule.d.ts +42 -0
  124. package/codegen/orm/models/usersModule.js +77 -0
  125. package/codegen/orm/models/uuidModule.d.ts +42 -0
  126. package/codegen/orm/models/uuidModule.js +77 -0
  127. package/codegen/orm/mutation/index.d.ts +531 -0
  128. package/codegen/orm/mutation/index.js +596 -0
  129. package/codegen/orm/query/index.d.ts +274 -0
  130. package/codegen/orm/query/index.js +290 -0
  131. package/codegen/orm/query-builder.d.ts +80 -0
  132. package/codegen/orm/query-builder.js +249 -0
  133. package/codegen/orm/select-types.d.ts +50 -0
  134. package/codegen/orm/select-types.js +7 -0
  135. package/codegen/orm/types.d.ts +6 -0
  136. package/codegen/orm/types.js +23 -0
  137. package/esm/codegen/orm/client.js +70 -0
  138. package/esm/codegen/orm/index.js +162 -0
  139. package/esm/codegen/orm/input-types.js +6 -0
  140. package/esm/codegen/orm/models/api.js +73 -0
  141. package/esm/codegen/orm/models/apiExtension.js +73 -0
  142. package/esm/codegen/orm/models/apiModule.js +73 -0
  143. package/esm/codegen/orm/models/apiSchema.js +73 -0
  144. package/esm/codegen/orm/models/app.js +73 -0
  145. package/esm/codegen/orm/models/checkConstraint.js +73 -0
  146. package/esm/codegen/orm/models/connectedAccountsModule.js +73 -0
  147. package/esm/codegen/orm/models/cryptoAddressesModule.js +73 -0
  148. package/esm/codegen/orm/models/cryptoAuthModule.js +73 -0
  149. package/esm/codegen/orm/models/database.js +73 -0
  150. package/esm/codegen/orm/models/databaseExtension.js +73 -0
  151. package/esm/codegen/orm/models/databaseProvision.js +73 -0
  152. package/esm/codegen/orm/models/defaultIdsModule.js +73 -0
  153. package/esm/codegen/orm/models/denormalizedTableField.js +73 -0
  154. package/esm/codegen/orm/models/domain.js +73 -0
  155. package/esm/codegen/orm/models/emailsModule.js +73 -0
  156. package/esm/codegen/orm/models/encryptedSecretsModule.js +73 -0
  157. package/esm/codegen/orm/models/extension.js +73 -0
  158. package/esm/codegen/orm/models/field.js +73 -0
  159. package/esm/codegen/orm/models/fieldModule.js +73 -0
  160. package/esm/codegen/orm/models/foreignKeyConstraint.js +73 -0
  161. package/esm/codegen/orm/models/fullTextSearch.js +73 -0
  162. package/esm/codegen/orm/models/hierarchyModule.js +73 -0
  163. package/esm/codegen/orm/models/index.js +64 -0
  164. package/esm/codegen/orm/models/indexModel.js +73 -0
  165. package/esm/codegen/orm/models/invitesModule.js +73 -0
  166. package/esm/codegen/orm/models/levelsModule.js +73 -0
  167. package/esm/codegen/orm/models/limitFunction.js +73 -0
  168. package/esm/codegen/orm/models/limitsModule.js +73 -0
  169. package/esm/codegen/orm/models/membershipTypesModule.js +73 -0
  170. package/esm/codegen/orm/models/membershipsModule.js +73 -0
  171. package/esm/codegen/orm/models/module.js +73 -0
  172. package/esm/codegen/orm/models/moduleDefinition.js +73 -0
  173. package/esm/codegen/orm/models/moduleField.js +73 -0
  174. package/esm/codegen/orm/models/moduleInputRecord.js +73 -0
  175. package/esm/codegen/orm/models/moduleOutput.js +73 -0
  176. package/esm/codegen/orm/models/permissionsModule.js +73 -0
  177. package/esm/codegen/orm/models/phoneNumbersModule.js +73 -0
  178. package/esm/codegen/orm/models/policy.js +73 -0
  179. package/esm/codegen/orm/models/primaryKeyConstraint.js +73 -0
  180. package/esm/codegen/orm/models/procedure.js +73 -0
  181. package/esm/codegen/orm/models/profilesModule.js +73 -0
  182. package/esm/codegen/orm/models/rlsFunction.js +73 -0
  183. package/esm/codegen/orm/models/rlsModule.js +73 -0
  184. package/esm/codegen/orm/models/schema.js +73 -0
  185. package/esm/codegen/orm/models/schemaGrant.js +73 -0
  186. package/esm/codegen/orm/models/secretsModule.js +73 -0
  187. package/esm/codegen/orm/models/site.js +73 -0
  188. package/esm/codegen/orm/models/siteMetadatum.js +73 -0
  189. package/esm/codegen/orm/models/siteModule.js +73 -0
  190. package/esm/codegen/orm/models/siteTheme.js +73 -0
  191. package/esm/codegen/orm/models/table.js +73 -0
  192. package/esm/codegen/orm/models/tableGrant.js +73 -0
  193. package/esm/codegen/orm/models/tokensModule.js +73 -0
  194. package/esm/codegen/orm/models/trigger.js +73 -0
  195. package/esm/codegen/orm/models/triggerFunction.js +73 -0
  196. package/esm/codegen/orm/models/uniqueConstraint.js +73 -0
  197. package/esm/codegen/orm/models/userAuthModule.js +73 -0
  198. package/esm/codegen/orm/models/usersModule.js +73 -0
  199. package/esm/codegen/orm/models/uuidModule.js +73 -0
  200. package/esm/codegen/orm/mutation/index.js +593 -0
  201. package/esm/codegen/orm/query/index.js +287 -0
  202. package/esm/codegen/orm/query-builder.js +238 -0
  203. package/esm/codegen/orm/select-types.js +6 -0
  204. package/esm/codegen/orm/types.js +7 -0
  205. package/esm/middleware/api.js +10 -9
  206. package/esm/middleware/gql.js +118 -123
  207. package/esm/middleware/graphile.js +19 -3
  208. package/esm/scripts/codegen-schema.js +71 -0
  209. package/esm/server.js +21 -0
  210. package/middleware/api.js +9 -8
  211. package/middleware/gql.d.ts +25 -5
  212. package/middleware/gql.js +122 -127
  213. package/middleware/graphile.js +19 -3
  214. package/middleware/types.d.ts +1 -0
  215. package/package.json +15 -11
  216. package/scripts/codegen-schema.d.ts +1 -0
  217. package/scripts/codegen-schema.js +76 -0
  218. package/server.js +21 -0
  219. package/types.d.ts +2 -2
package/middleware/gql.js CHANGED
@@ -1,131 +1,126 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.ListOfAllDomainsOfDb = exports.ApiByNameQuery = exports.ApiQuery = void 0;
7
- const graphql_tag_1 = __importDefault(require("graphql-tag"));
8
- // DO NOT CHANGE TO domainBySubdomainAndDomain(domain: $domain, subdomain: $subdomain)
9
- // condition is the way to handle since it will pass in null properly
10
- // e.g. subdomain.domain or domain both work
11
- exports.ApiQuery = (0, graphql_tag_1.default) `
12
- query ApiRoot($domain: String!, $subdomain: String) {
13
- domains(condition: { domain: $domain, subdomain: $subdomain }) {
14
- nodes {
15
- api {
16
- databaseId
17
- dbname
18
- roleName
19
- anonRole
20
- isPublic
21
- schemaNamesFromExt: apiExtensions {
22
- nodes {
23
- schemaName
24
- }
25
- }
26
- schemaNames: schemataByApiSchemaApiIdAndSchemaId {
27
- nodes {
28
- schemaName
29
- }
30
- }
31
- rlsModule {
32
- privateSchema {
33
- schemaName
34
- }
35
- authenticateStrict
36
- authenticate
37
- currentRole
38
- currentRoleId
39
- }
40
- database {
41
- sites {
42
- nodes {
43
- domains {
44
- nodes {
45
- subdomain
46
- domain
47
- }
48
- }
49
- }
50
- }
51
- } # for now keep this for patches
52
- apiModules {
53
- nodes {
54
- name
55
- data
56
- }
57
- }
58
- }
59
- }
60
- }
61
- }
62
- `;
63
- exports.ApiByNameQuery = (0, graphql_tag_1.default) `
64
- query ApiByName($name: String!, $databaseId: UUID!) {
65
- api: apiByDatabaseIdAndName(name: $name, databaseId: $databaseId) {
66
- databaseId
67
- dbname
68
- roleName
69
- anonRole
70
- isPublic
71
- schemaNamesFromExt: apiExtensions {
72
- nodes {
73
- schemaName
74
- }
75
- }
76
- schemaNames: schemataByApiSchemaApiIdAndSchemaId {
77
- nodes {
78
- schemaName
79
- }
80
- }
81
- rlsModule {
82
- privateSchema {
83
- schemaName
84
- }
85
- authenticate
86
- authenticateStrict
87
- currentRole
88
- currentRoleId
89
- }
90
- database {
91
- sites {
92
- nodes {
93
- domains {
94
- nodes {
95
- subdomain
96
- domain
97
- }
98
- }
99
- }
100
- }
101
- } # for now keep this for patches
102
- apiModules {
103
- nodes {
104
- name
105
- data
106
- }
107
- }
3
+ exports.buildListApis = exports.buildApiByDatabaseIdAndName = exports.buildDomainLookup = void 0;
4
+ const query_builder_1 = require("../codegen/orm/query-builder");
5
+ const apiSelect = {
6
+ databaseId: true,
7
+ dbname: true,
8
+ roleName: true,
9
+ anonRole: true,
10
+ isPublic: true,
11
+ domains: {
12
+ select: {
13
+ subdomain: true,
14
+ domain: true,
15
+ },
16
+ connection: true,
17
+ },
18
+ apiExtensions: {
19
+ select: { schemaName: true },
20
+ connection: true,
21
+ },
22
+ schemasByApiSchemaApiIdAndSchemaId: {
23
+ select: { schemaName: true },
24
+ connection: true,
25
+ },
26
+ rlsModule: {
27
+ select: {
28
+ privateSchema: { select: { schemaName: true } },
29
+ authenticateStrict: true,
30
+ authenticate: true,
31
+ currentRole: true,
32
+ currentRoleId: true,
33
+ },
34
+ },
35
+ database: {
36
+ select: {
37
+ sites: {
38
+ select: {
39
+ domains: {
40
+ select: { subdomain: true, domain: true },
41
+ connection: true,
42
+ },
43
+ },
44
+ connection: true,
45
+ },
46
+ },
47
+ },
48
+ apiModules: {
49
+ select: { name: true, data: true },
50
+ connection: true,
51
+ },
52
+ };
53
+ const domainSelect = {
54
+ domain: true,
55
+ subdomain: true,
56
+ api: { select: apiSelect },
57
+ };
58
+ const apisSelect = {
59
+ id: true,
60
+ databaseId: true,
61
+ name: true,
62
+ dbname: true,
63
+ roleName: true,
64
+ anonRole: true,
65
+ isPublic: true,
66
+ domains: {
67
+ select: { domain: true, subdomain: true },
68
+ connection: true,
69
+ },
70
+ database: {
71
+ select: {
72
+ sites: {
73
+ select: {
74
+ domains: {
75
+ select: { domain: true, subdomain: true },
76
+ connection: true,
77
+ },
78
+ },
79
+ connection: true,
80
+ },
81
+ },
82
+ },
83
+ };
84
+ /**
85
+ * Build query for domain lookup with optional subdomain
86
+ * This uses domains connection instead of domainBySubdomainAndDomain
87
+ * because we need to handle null subdomain with condition filter
88
+ */
89
+ const buildDomainLookup = (vars) => {
90
+ const where = {
91
+ domain: { equalTo: vars.domain },
92
+ };
93
+ if (vars.subdomain === null || vars.subdomain === undefined) {
94
+ where.subdomain = { isNull: true };
108
95
  }
109
- }
110
- `;
111
- exports.ListOfAllDomainsOfDb = (0, graphql_tag_1.default) `
112
- query ListApisByDatabaseId {
113
- apis {
114
- nodes {
115
- id
116
- databaseId
117
- name
118
- dbname
119
- roleName
120
- anonRole
121
- isPublic
122
- domains {
123
- nodes {
124
- domain
125
- subdomain
126
- }
127
- }
128
- }
96
+ else {
97
+ where.subdomain = { equalTo: vars.subdomain };
129
98
  }
130
- }
131
- `;
99
+ return (0, query_builder_1.buildFindFirstDocument)('DomainLookup', 'domains', domainSelect, { where }, 'DomainFilter');
100
+ };
101
+ exports.buildDomainLookup = buildDomainLookup;
102
+ /**
103
+ * Build query for API lookup by database ID and name
104
+ * Uses the generated apiByDatabaseIdAndName custom query
105
+ */
106
+ const buildApiByDatabaseIdAndName = (vars) => {
107
+ // Import buildCustomDocument locally to avoid circular dependency
108
+ const { buildCustomDocument } = require('../codegen/orm/query-builder');
109
+ return buildCustomDocument('query', 'ApiByDatabaseIdAndName', 'apiByDatabaseIdAndName', apiSelect, vars, [
110
+ { name: 'databaseId', type: 'UUID!' },
111
+ { name: 'name', type: 'String!' },
112
+ ]);
113
+ };
114
+ exports.buildApiByDatabaseIdAndName = buildApiByDatabaseIdAndName;
115
+ /**
116
+ * Build query to list all APIs
117
+ */
118
+ const buildListApis = () => {
119
+ // Import buildCustomDocument locally to avoid circular dependency
120
+ const { buildCustomDocument } = require('../codegen/orm/query-builder');
121
+ return buildCustomDocument('query', 'ListApisByDatabaseId', 'apis', {
122
+ select: apisSelect,
123
+ connection: true,
124
+ }, undefined, []);
125
+ };
126
+ exports.buildListApis = buildListApis;
@@ -4,28 +4,37 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.graphile = void 0;
7
+ const logger_1 = require("@pgpmjs/logger");
7
8
  const graphile_cache_1 = require("graphile-cache");
8
9
  const graphile_settings_1 = require("graphile-settings");
9
10
  const pg_cache_1 = require("pg-cache");
10
11
  const postgraphile_1 = require("postgraphile");
11
12
  require("./types"); // for Request type
12
13
  const PublicKeySignature_1 = __importDefault(require("../plugins/PublicKeySignature"));
14
+ const log = new logger_1.Logger('graphile');
15
+ const reqLabel = (req) => req.requestId ? `[${req.requestId}]` : '[req]';
13
16
  const graphile = (opts) => {
14
17
  return async (req, res, next) => {
18
+ const label = reqLabel(req);
15
19
  try {
16
20
  const api = req.api;
17
21
  if (!api) {
22
+ log.error(`${label} Missing API info`);
18
23
  return res.status(500).send('Missing API info');
19
24
  }
20
25
  const key = req.svc_key;
21
26
  if (!key) {
27
+ log.error(`${label} Missing service cache key`);
22
28
  return res.status(500).send('Missing service cache key');
23
29
  }
24
30
  const { dbname, anonRole, roleName, schema } = api;
25
- if (graphile_cache_1.graphileCache.has(key)) {
26
- const { handler } = graphile_cache_1.graphileCache.get(key);
27
- return handler(req, res, next);
31
+ const schemaLabel = schema?.join(',') || 'unknown';
32
+ const cached = graphile_cache_1.graphileCache.get(key);
33
+ if (cached) {
34
+ log.debug(`${label} PostGraphile cache hit key=${key} db=${dbname} schemas=${schemaLabel}`);
35
+ return cached.handler(req, res, next);
28
36
  }
37
+ log.debug(`${label} PostGraphile cache miss key=${key} db=${dbname} schemas=${schemaLabel}`);
29
38
  const options = (0, graphile_settings_1.getGraphileSettings)({
30
39
  ...opts,
31
40
  graphile: {
@@ -35,12 +44,14 @@ const graphile = (opts) => {
35
44
  });
36
45
  const pubkey_challenge = api.apiModules.find((mod) => mod.name === 'pubkey_challenge');
37
46
  if (pubkey_challenge && pubkey_challenge.data) {
47
+ log.info(`${label} Enabling PublicKeySignature plugin for ${dbname}`);
38
48
  options.appendPlugins.push((0, PublicKeySignature_1.default)(pubkey_challenge.data));
39
49
  }
40
50
  options.appendPlugins = options.appendPlugins ?? [];
41
51
  options.appendPlugins.push(...opts.graphile.appendPlugins);
42
52
  options.pgSettings = async function pgSettings(request) {
43
53
  const gqlReq = request;
54
+ const settingsLabel = reqLabel(gqlReq);
44
55
  const context = {
45
56
  [`jwt.claims.database_id`]: gqlReq.databaseId,
46
57
  [`jwt.claims.ip_address`]: gqlReq.clientIp,
@@ -52,6 +63,7 @@ const graphile = (opts) => {
52
63
  context['jwt.claims.user_agent'] = gqlReq.get('User-Agent');
53
64
  }
54
65
  if (gqlReq?.token?.user_id) {
66
+ log.debug(`${settingsLabel} pgSettings role=${roleName} db=${gqlReq.databaseId} ip=${gqlReq.clientIp}`);
55
67
  return {
56
68
  role: roleName,
57
69
  [`jwt.claims.token_id`]: gqlReq.token.id,
@@ -59,6 +71,7 @@ const graphile = (opts) => {
59
71
  ...context,
60
72
  };
61
73
  }
74
+ log.debug(`${settingsLabel} pgSettings role=${anonRole} db=${gqlReq.databaseId} ip=${gqlReq.clientIp}`);
62
75
  return { role: anonRole, ...context };
63
76
  };
64
77
  options.graphqlRoute = '/graphql';
@@ -71,6 +84,7 @@ const graphile = (opts) => {
71
84
  ...options,
72
85
  ...opts.graphile.overrideSettings,
73
86
  };
87
+ log.info(`${label} Building PostGraphile handler key=${key} db=${dbname} schemas=${schemaLabel} role=${roleName} anon=${anonRole}`);
74
88
  const pgPool = (0, pg_cache_1.getPgPool)({
75
89
  ...opts.pg,
76
90
  database: dbname,
@@ -81,9 +95,11 @@ const graphile = (opts) => {
81
95
  pgPoolKey: dbname,
82
96
  handler,
83
97
  });
98
+ log.info(`${label} Cached PostGraphile handler key=${key} db=${dbname}`);
84
99
  return handler(req, res, next);
85
100
  }
86
101
  catch (e) {
102
+ log.error(`${label} PostGraphile middleware error`, e);
87
103
  return res.status(500).send(e.message);
88
104
  }
89
105
  };
@@ -27,6 +27,7 @@ declare global {
27
27
  svc_key?: string;
28
28
  clientIp?: string;
29
29
  databaseId?: string;
30
+ requestId?: string;
30
31
  token?: ConstructiveAPIToken;
31
32
  }
32
33
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@constructive-io/graphql-server",
3
- "version": "2.14.8",
3
+ "version": "2.15.0",
4
4
  "author": "Constructive <developers@constructive.io>",
5
5
  "description": "Constructive GraphQL Server",
6
6
  "main": "index.js",
@@ -29,7 +29,9 @@
29
29
  "lint": "eslint . --fix",
30
30
  "test": "jest --passWithNoTests",
31
31
  "test:watch": "jest --watch",
32
- "bucket:create": "ts-node src/scripts/create-bucket.ts"
32
+ "bucket:create": "ts-node src/scripts/create-bucket.ts",
33
+ "codegen:schema": "ts-node src/scripts/codegen-schema.ts",
34
+ "codegen": "npm run codegen:schema && graphql-codegen generate-orm --schema codegen/schema.graphql --output src/codegen/orm"
33
35
  },
34
36
  "keywords": [
35
37
  "server",
@@ -52,15 +54,15 @@
52
54
  "express": "^5.2.1",
53
55
  "graphile-build": "^4.14.1",
54
56
  "graphile-cache": "^1.6.14",
55
- "graphile-i18n": "^0.4.7",
56
- "graphile-meta-schema": "^0.5.7",
57
- "graphile-plugin-connection-filter": "^2.6.7",
58
- "graphile-plugin-connection-filter-postgis": "^1.3.7",
59
- "graphile-plugin-fulltext-filter": "^2.3.7",
57
+ "graphile-i18n": "^0.4.8",
58
+ "graphile-meta-schema": "^0.5.8",
59
+ "graphile-plugin-connection-filter": "^2.6.8",
60
+ "graphile-plugin-connection-filter-postgis": "^1.3.8",
61
+ "graphile-plugin-fulltext-filter": "^2.3.8",
60
62
  "graphile-query": "^2.4.7",
61
- "graphile-search-plugin": "^0.4.8",
62
- "graphile-settings": "^2.12.8",
63
- "graphile-simple-inflector": "^0.4.8",
63
+ "graphile-search-plugin": "^0.4.9",
64
+ "graphile-settings": "^2.12.9",
65
+ "graphile-simple-inflector": "^0.4.9",
64
66
  "graphile-utils": "^4.14.1",
65
67
  "graphql": "15.10.1",
66
68
  "graphql-tag": "2.12.6",
@@ -74,14 +76,16 @@
74
76
  },
75
77
  "devDependencies": {
76
78
  "@aws-sdk/client-s3": "^3.958.0",
79
+ "@constructive-io/graphql-codegen": "2.23.2",
77
80
  "@types/cors": "^2.8.17",
78
81
  "@types/express": "^5.0.6",
79
82
  "@types/graphql-upload": "^8.0.12",
80
83
  "@types/pg": "^8.16.0",
81
84
  "@types/request-ip": "^0.0.41",
85
+ "graphile-test": "2.13.8",
82
86
  "makage": "^0.1.10",
83
87
  "nodemon": "^3.1.10",
84
88
  "ts-node": "^10.9.2"
85
89
  },
86
- "gitHead": "8ba31ce871a6fec054ee6ea5627f44d69c635828"
90
+ "gitHead": "eff12e839462a1d5435f04318db1f44fc141e235"
87
91
  }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const graphql_env_1 = require("@constructive-io/graphql-env");
7
+ const logger_1 = require("@pgpmjs/logger");
8
+ const graphile_settings_1 = require("graphile-settings");
9
+ const pg_cache_1 = require("pg-cache");
10
+ const graphile_query_1 = require("graphile-query");
11
+ const graphql_1 = require("graphql");
12
+ const node_fs_1 = require("node:fs");
13
+ const node_path_1 = __importDefault(require("node:path"));
14
+ const log = new logger_1.Logger('codegen-schema');
15
+ const getSchemaOutputPath = () => process.env.CODEGEN_SCHEMA_OUT ??
16
+ node_path_1.default.resolve(__dirname, '../../codegen/schema.graphql');
17
+ (async () => {
18
+ try {
19
+ const opts = (0, graphql_env_1.getEnvOptions)();
20
+ const apiOpts = opts.api || {};
21
+ const metaSchemas = Array.isArray(apiOpts.metaSchemas)
22
+ ? apiOpts.metaSchemas
23
+ : [];
24
+ let schemas;
25
+ let usingFallback = false;
26
+ const dbName = process.env.CODEGEN_DATABASE || process.env.PGDATABASE || 'constructive';
27
+ const pgConfig = { ...opts.pg, database: dbName };
28
+ log.info(`Target database for codegen: ${dbName}`);
29
+ if (metaSchemas.length) {
30
+ schemas = metaSchemas;
31
+ log.info(`Using meta schemas: ${schemas.join(', ')}`);
32
+ const pool = (0, pg_cache_1.getPgPool)(pgConfig);
33
+ const checkResult = await pool.query(`SELECT schema_name FROM information_schema.schemata
34
+ WHERE schema_name = ANY($1::text[])
35
+ ORDER BY schema_name`, [schemas]);
36
+ const foundSchemas = checkResult.rows.map((r) => r.schema_name);
37
+ const missing = schemas.filter((s) => !foundSchemas.includes(s));
38
+ if (missing.length > 0) {
39
+ log.warn(`Missing schemas: ${missing.join(', ')}. Falling back to 'public'.`);
40
+ schemas = ['public'];
41
+ usingFallback = true;
42
+ }
43
+ }
44
+ else {
45
+ schemas = ['public'];
46
+ log.info('No meta schemas configured, using: public');
47
+ usingFallback = true;
48
+ }
49
+ if (usingFallback) {
50
+ log.warn('Schema will be generated from public schema only. To generate full meta schema, ensure meta tables exist.');
51
+ }
52
+ const settings = (0, graphile_settings_1.getGraphileSettings)({
53
+ ...opts,
54
+ pg: pgConfig,
55
+ graphile: {
56
+ ...opts.graphile,
57
+ schema: schemas,
58
+ },
59
+ });
60
+ const pool = (0, pg_cache_1.getPgPool)(pgConfig);
61
+ log.debug(`Connecting to database: ${dbName}`);
62
+ log.debug(`Connecting to host: ${opts.pg?.host || '(default)'}`);
63
+ const dbInfo = await pool.query('SELECT current_database() AS current_database, current_user AS current_user');
64
+ log.info(`Connected to database: ${dbInfo.rows[0]?.current_database} as user: ${dbInfo.rows[0]?.current_user}`);
65
+ const graphqlSchema = await (0, graphile_query_1.getSchema)(pool, settings);
66
+ const sdl = (0, graphql_1.printSchema)(graphqlSchema);
67
+ const outputPath = getSchemaOutputPath();
68
+ await node_fs_1.promises.mkdir(node_path_1.default.dirname(outputPath), { recursive: true });
69
+ await node_fs_1.promises.writeFile(outputPath, sdl, 'utf8');
70
+ log.success(`Schema written to ${outputPath}`);
71
+ }
72
+ catch (error) {
73
+ log.error('Failed to write schema', error?.stack || error);
74
+ process.exitCode = 1;
75
+ }
76
+ })();
package/server.js CHANGED
@@ -8,6 +8,7 @@ const graphql_env_1 = require("@constructive-io/graphql-env");
8
8
  const logger_1 = require("@pgpmjs/logger");
9
9
  const server_utils_1 = require("@pgpmjs/server-utils");
10
10
  const url_domains_1 = require("@constructive-io/url-domains");
11
+ const crypto_1 = require("crypto");
11
12
  const express_1 = __importDefault(require("express"));
12
13
  // @ts-ignore
13
14
  const graphql_upload_1 = __importDefault(require("graphql-upload"));
@@ -35,6 +36,25 @@ class Server {
35
36
  const app = (0, express_1.default)();
36
37
  const api = (0, api_1.createApiMiddleware)(opts);
37
38
  const authenticate = (0, auth_1.createAuthenticateMiddleware)(opts);
39
+ const requestLogger = (req, res, next) => {
40
+ const headerRequestId = req.header('x-request-id');
41
+ const reqId = headerRequestId || (0, crypto_1.randomUUID)();
42
+ const start = process.hrtime.bigint();
43
+ req.requestId = reqId;
44
+ const host = req.hostname || req.headers.host || 'unknown';
45
+ const ip = req.clientIp || req.ip;
46
+ log.debug(`[${reqId}] -> ${req.method} ${req.originalUrl} host=${host} ip=${ip}`);
47
+ res.on('finish', () => {
48
+ const durationMs = Number(process.hrtime.bigint() - start) / 1e6;
49
+ const apiInfo = req.api
50
+ ? `db=${req.api.dbname} schemas=${req.api.schema?.join(',') || 'none'}`
51
+ : 'api=unresolved';
52
+ const authInfo = req.token ? 'auth=token' : 'auth=anon';
53
+ const svcInfo = req.svc_key ? `svc=${req.svc_key}` : 'svc=unset';
54
+ log.debug(`[${reqId}] <- ${res.statusCode} ${req.method} ${req.originalUrl} (${durationMs.toFixed(1)} ms) ${apiInfo} ${svcInfo} ${authInfo}`);
55
+ });
56
+ next();
57
+ };
38
58
  // Log startup config in dev mode
39
59
  if (isDev()) {
40
60
  log.debug(`Database: ${opts.pg?.database}@${opts.pg?.host}:${opts.pg?.port}`);
@@ -57,6 +77,7 @@ class Server {
57
77
  app.use(graphql_upload_1.default.graphqlUploadExpress());
58
78
  app.use((0, url_domains_1.middleware)());
59
79
  app.use(request_ip_1.default.mw());
80
+ app.use(requestLogger);
60
81
  app.use(api);
61
82
  app.use(authenticate);
62
83
  app.use((0, graphile_1.graphile)(opts));
package/types.d.ts CHANGED
@@ -58,8 +58,8 @@ export interface OldApiStructure {
58
58
  dbname: string;
59
59
  anonRole: string;
60
60
  roleName: string;
61
- schemaNames: SchemaNodes;
62
- schemaNamesFromExt: SchemaNodes;
61
+ schemasByApiSchemaApiIdAndSchemaId: SchemaNodes;
62
+ apiExtensions: SchemaNodes;
63
63
  apiModules: ApiModuleNodes;
64
64
  rlsModule?: RlsModule;
65
65
  database?: Database;