graphile-settings 4.18.9 → 4.19.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.
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Bucket provisioner resolver for the Constructive bucket provisioner plugin.
3
+ *
4
+ * Reads CDN/S3 configuration from the standard env system
5
+ * (getEnvOptions -> pgpmDefaults + config files + env vars) and lazily
6
+ * returns a StorageConnectionConfig on first use.
7
+ *
8
+ * Follows the same lazy-init pattern as presigned-url-resolver.ts.
9
+ */
10
+ import type { StorageConnectionConfig } from 'graphile-bucket-provisioner-plugin';
11
+ /**
12
+ * Lazily initialize and return the StorageConnectionConfig for the
13
+ * bucket provisioner plugin.
14
+ *
15
+ * Reads CDN config on first call via getEnvOptions() (which already merges
16
+ * pgpmDefaults -> config file -> env vars) and caches the result.
17
+ * Same CDN config source as presigned-url-resolver.ts.
18
+ */
19
+ export declare function getBucketProvisionerConnection(): StorageConnectionConfig;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ /**
3
+ * Bucket provisioner resolver for the Constructive bucket provisioner plugin.
4
+ *
5
+ * Reads CDN/S3 configuration from the standard env system
6
+ * (getEnvOptions -> pgpmDefaults + config files + env vars) and lazily
7
+ * returns a StorageConnectionConfig on first use.
8
+ *
9
+ * Follows the same lazy-init pattern as presigned-url-resolver.ts.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.getBucketProvisionerConnection = getBucketProvisionerConnection;
13
+ const graphql_env_1 = require("@constructive-io/graphql-env");
14
+ const logger_1 = require("@pgpmjs/logger");
15
+ const log = new logger_1.Logger('bucket-provisioner-resolver');
16
+ let connectionConfig = null;
17
+ /**
18
+ * Lazily initialize and return the StorageConnectionConfig for the
19
+ * bucket provisioner plugin.
20
+ *
21
+ * Reads CDN config on first call via getEnvOptions() (which already merges
22
+ * pgpmDefaults -> config file -> env vars) and caches the result.
23
+ * Same CDN config source as presigned-url-resolver.ts.
24
+ */
25
+ function getBucketProvisionerConnection() {
26
+ if (connectionConfig)
27
+ return connectionConfig;
28
+ const { cdn } = (0, graphql_env_1.getEnvOptions)();
29
+ // cdn is guaranteed populated — pgpmDefaults provides all CDN fields
30
+ const { provider, awsRegion, awsAccessKey, awsSecretKey, endpoint } = cdn;
31
+ log.info(`[bucket-provisioner-resolver] Initializing: provider=${provider} endpoint=${endpoint}`);
32
+ connectionConfig = {
33
+ provider: provider || 'minio',
34
+ region: awsRegion || 'us-east-1',
35
+ accessKeyId: awsAccessKey,
36
+ secretAccessKey: awsSecretKey,
37
+ ...(endpoint ? { endpoint, forcePathStyle: true } : {}),
38
+ };
39
+ return connectionConfig;
40
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Bucket provisioner resolver for the Constructive bucket provisioner plugin.
3
+ *
4
+ * Reads CDN/S3 configuration from the standard env system
5
+ * (getEnvOptions -> pgpmDefaults + config files + env vars) and lazily
6
+ * returns a StorageConnectionConfig on first use.
7
+ *
8
+ * Follows the same lazy-init pattern as presigned-url-resolver.ts.
9
+ */
10
+ import type { StorageConnectionConfig } from 'graphile-bucket-provisioner-plugin';
11
+ /**
12
+ * Lazily initialize and return the StorageConnectionConfig for the
13
+ * bucket provisioner plugin.
14
+ *
15
+ * Reads CDN config on first call via getEnvOptions() (which already merges
16
+ * pgpmDefaults -> config file -> env vars) and caches the result.
17
+ * Same CDN config source as presigned-url-resolver.ts.
18
+ */
19
+ export declare function getBucketProvisionerConnection(): StorageConnectionConfig;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Bucket provisioner resolver for the Constructive bucket provisioner plugin.
3
+ *
4
+ * Reads CDN/S3 configuration from the standard env system
5
+ * (getEnvOptions -> pgpmDefaults + config files + env vars) and lazily
6
+ * returns a StorageConnectionConfig on first use.
7
+ *
8
+ * Follows the same lazy-init pattern as presigned-url-resolver.ts.
9
+ */
10
+ import { getEnvOptions } from '@constructive-io/graphql-env';
11
+ import { Logger } from '@pgpmjs/logger';
12
+ const log = new Logger('bucket-provisioner-resolver');
13
+ let connectionConfig = null;
14
+ /**
15
+ * Lazily initialize and return the StorageConnectionConfig for the
16
+ * bucket provisioner plugin.
17
+ *
18
+ * Reads CDN config on first call via getEnvOptions() (which already merges
19
+ * pgpmDefaults -> config file -> env vars) and caches the result.
20
+ * Same CDN config source as presigned-url-resolver.ts.
21
+ */
22
+ export function getBucketProvisionerConnection() {
23
+ if (connectionConfig)
24
+ return connectionConfig;
25
+ const { cdn } = getEnvOptions();
26
+ // cdn is guaranteed populated — pgpmDefaults provides all CDN fields
27
+ const { provider, awsRegion, awsAccessKey, awsSecretKey, endpoint } = cdn;
28
+ log.info(`[bucket-provisioner-resolver] Initializing: provider=${provider} endpoint=${endpoint}`);
29
+ connectionConfig = {
30
+ provider: provider || 'minio',
31
+ region: awsRegion || 'us-east-1',
32
+ accessKeyId: awsAccessKey,
33
+ secretAccessKey: awsSecretKey,
34
+ ...(endpoint ? { endpoint, forcePathStyle: true } : {}),
35
+ };
36
+ return connectionConfig;
37
+ }
package/esm/index.d.ts CHANGED
@@ -34,3 +34,5 @@ export * from './plugins/index';
34
34
  export * from './presets/index';
35
35
  export { makePgService };
36
36
  export { streamToStorage } from './upload-resolver';
37
+ export { getPresignedUrlS3Config } from './presigned-url-resolver';
38
+ export { getBucketProvisionerConnection } from './bucket-provisioner-resolver';
package/esm/index.js CHANGED
@@ -50,3 +50,7 @@ export * from './presets/index';
50
50
  export { makePgService };
51
51
  // Upload utilities
52
52
  export { streamToStorage } from './upload-resolver';
53
+ // Presigned URL utilities
54
+ export { getPresignedUrlS3Config } from './presigned-url-resolver';
55
+ // Bucket provisioner utilities
56
+ export { getBucketProvisionerConnection } from './bucket-provisioner-resolver';
@@ -41,7 +41,7 @@ export function buildUniqueConstraints(codec, attributes, uniques, context) {
41
41
  export function buildForeignKeyConstraints(codec, attributes, relations, context) {
42
42
  const constraints = [];
43
43
  for (const [relationName, relation] of Object.entries(relations)) {
44
- if (relation.isReferencee !== false)
44
+ if (relation.isReferencee)
45
45
  continue;
46
46
  const remoteCodec = relation.remoteResource?.codec;
47
47
  const remoteAttributes = remoteCodec?.attributes || {};
@@ -8,7 +8,9 @@ function isRecord(value) {
8
8
  export function buildBelongsToRelations(codec, attributes, uniques, relations, context) {
9
9
  const belongsTo = [];
10
10
  for (const [relationName, relation] of Object.entries(relations)) {
11
- if (relation.isReferencee !== false)
11
+ // PostGraphile only sets isReferencee when true (reverse FK);
12
+ // forward relations have isReferencee undefined, not false.
13
+ if (relation.isReferencee)
12
14
  continue;
13
15
  const localAttributes = relation.localAttributes || [];
14
16
  const isUnique = uniques.some((unique) => sameAttributes(unique.attributes, localAttributes));
@@ -19,7 +19,7 @@ function buildTableMeta(resource, schemaName, context) {
19
19
  }
20
20
  }
21
21
  for (const relation of Object.values(relations)) {
22
- if (relation.isReferencee !== false)
22
+ if (relation.isReferencee)
23
23
  continue;
24
24
  for (const attrName of relation.localAttributes || [])
25
25
  fkAttrNames.add(attrName);
@@ -17,6 +17,9 @@ import type { GraphileConfig } from 'graphile-config';
17
17
  * - PostGIS support (geometry/geography types, GeoJSON scalar — auto-detects PostGIS extension)
18
18
  * - PostGIS connection filter operators (spatial filtering on geometry/geography columns)
19
19
  * - Upload plugin (file upload to S3/MinIO for image, upload, attachment domain columns)
20
+ * - Presigned URL plugin (requestUploadUrl, confirmUpload mutations + downloadUrl computed field)
21
+ * - Bucket provisioner plugin (auto-provisions S3 buckets on @storageBuckets table mutations,
22
+ * CORS management, provisionBucket mutation for manual/retry)
20
23
  * - SQL expression validator (validates @sqlExpression columns in mutations)
21
24
  * - PG type mappings (maps custom types like email, url to GraphQL scalars)
22
25
  * - pgvector search (auto-discovers vector columns: filter fields, distance computed fields,
@@ -3,8 +3,12 @@ import { MinimalPreset, InflektPreset, ConflictDetectorPreset, InflectorLoggerPr
3
3
  import { UnifiedSearchPreset, createMatchesOperatorFactory, createTrgmOperatorFactories } from 'graphile-search';
4
4
  import { GraphilePostgisPreset, createPostgisOperatorFactory } from 'graphile-postgis';
5
5
  import { UploadPreset } from 'graphile-upload-plugin';
6
+ import { PresignedUrlPreset } from 'graphile-presigned-url-plugin';
7
+ import { BucketProvisionerPreset } from 'graphile-bucket-provisioner-plugin';
6
8
  import { SqlExpressionValidatorPreset } from 'graphile-sql-expression-validator';
7
9
  import { constructiveUploadFieldDefinitions } from '../upload-resolver';
10
+ import { getPresignedUrlS3Config } from '../presigned-url-resolver';
11
+ import { getBucketProvisionerConnection } from '../bucket-provisioner-resolver';
8
12
  /**
9
13
  * Constructive PostGraphile v5 Preset
10
14
  *
@@ -23,6 +27,9 @@ import { constructiveUploadFieldDefinitions } from '../upload-resolver';
23
27
  * - PostGIS support (geometry/geography types, GeoJSON scalar — auto-detects PostGIS extension)
24
28
  * - PostGIS connection filter operators (spatial filtering on geometry/geography columns)
25
29
  * - Upload plugin (file upload to S3/MinIO for image, upload, attachment domain columns)
30
+ * - Presigned URL plugin (requestUploadUrl, confirmUpload mutations + downloadUrl computed field)
31
+ * - Bucket provisioner plugin (auto-provisions S3 buckets on @storageBuckets table mutations,
32
+ * CORS management, provisionBucket mutation for manual/retry)
26
33
  * - SQL expression validator (validates @sqlExpression columns in mutations)
27
34
  * - PG type mappings (maps custom types like email, url to GraphQL scalars)
28
35
  * - pgvector search (auto-discovers vector columns: filter fields, distance computed fields,
@@ -70,6 +77,11 @@ export const ConstructivePreset = {
70
77
  uploadFieldDefinitions: constructiveUploadFieldDefinitions,
71
78
  maxFileSize: 10 * 1024 * 1024, // 10MB
72
79
  }),
80
+ PresignedUrlPreset({ s3: getPresignedUrlS3Config }),
81
+ BucketProvisionerPreset({
82
+ connection: getBucketProvisionerConnection,
83
+ allowedOrigins: ['http://localhost:3000'],
84
+ }),
73
85
  SqlExpressionValidatorPreset(),
74
86
  PgTypeMappingsPreset,
75
87
  RequiredInputPreset,
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Presigned URL resolver for the Constructive presigned URL plugin.
3
+ *
4
+ * Reads CDN/S3 configuration from the standard env system
5
+ * (getEnvOptions → pgpmDefaults + config files + env vars) and lazily
6
+ * initializes an S3Client on first use.
7
+ *
8
+ * Follows the same lazy-init pattern as upload-resolver.ts.
9
+ */
10
+ import type { S3Config } from 'graphile-presigned-url-plugin';
11
+ /**
12
+ * Lazily initialize and return the S3Config for the presigned URL plugin.
13
+ *
14
+ * Reads CDN config on first call via getEnvOptions() (which already merges
15
+ * pgpmDefaults → config file → env vars), creates an S3Client, and caches
16
+ * the result. Same CDN config as upload-resolver.ts.
17
+ */
18
+ export declare function getPresignedUrlS3Config(): S3Config;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Presigned URL resolver for the Constructive presigned URL plugin.
3
+ *
4
+ * Reads CDN/S3 configuration from the standard env system
5
+ * (getEnvOptions → pgpmDefaults + config files + env vars) and lazily
6
+ * initializes an S3Client on first use.
7
+ *
8
+ * Follows the same lazy-init pattern as upload-resolver.ts.
9
+ */
10
+ import { S3Client } from '@aws-sdk/client-s3';
11
+ import { getEnvOptions } from '@constructive-io/graphql-env';
12
+ import { Logger } from '@pgpmjs/logger';
13
+ const log = new Logger('presigned-url-resolver');
14
+ let s3Config = null;
15
+ /**
16
+ * Lazily initialize and return the S3Config for the presigned URL plugin.
17
+ *
18
+ * Reads CDN config on first call via getEnvOptions() (which already merges
19
+ * pgpmDefaults → config file → env vars), creates an S3Client, and caches
20
+ * the result. Same CDN config as upload-resolver.ts.
21
+ */
22
+ export function getPresignedUrlS3Config() {
23
+ if (s3Config)
24
+ return s3Config;
25
+ const { cdn } = getEnvOptions();
26
+ // cdn is guaranteed populated — pgpmDefaults provides all CDN fields
27
+ const { bucketName, awsRegion, awsAccessKey, awsSecretKey, endpoint, publicUrlPrefix } = cdn;
28
+ log.info(`[presigned-url-resolver] Initializing: bucket=${bucketName} endpoint=${endpoint}`);
29
+ const client = new S3Client({
30
+ region: awsRegion,
31
+ credentials: { accessKeyId: awsAccessKey, secretAccessKey: awsSecretKey },
32
+ ...(endpoint ? { endpoint, forcePathStyle: true } : {}),
33
+ });
34
+ s3Config = {
35
+ client,
36
+ bucket: bucketName,
37
+ region: awsRegion,
38
+ publicUrlPrefix,
39
+ ...(endpoint ? { endpoint, forcePathStyle: true } : {}),
40
+ };
41
+ return s3Config;
42
+ }
@@ -13,7 +13,7 @@
13
13
  * AWS_REGION - AWS region (default: 'us-east-1')
14
14
  * AWS_ACCESS_KEY - access key (default: 'minioadmin')
15
15
  * AWS_SECRET_KEY - secret key (default: 'minioadmin')
16
- * MINIO_ENDPOINT - MinIO endpoint (default: 'http://localhost:9000')
16
+ * CDN_ENDPOINT - S3-compatible endpoint (default: 'http://localhost:9000')
17
17
  */
18
18
  import type { Readable } from 'stream';
19
19
  import type { UploadFieldDefinition } from 'graphile-upload-plugin';
@@ -13,7 +13,7 @@
13
13
  * AWS_REGION - AWS region (default: 'us-east-1')
14
14
  * AWS_ACCESS_KEY - access key (default: 'minioadmin')
15
15
  * AWS_SECRET_KEY - secret key (default: 'minioadmin')
16
- * MINIO_ENDPOINT - MinIO endpoint (default: 'http://localhost:9000')
16
+ * CDN_ENDPOINT - S3-compatible endpoint (default: 'http://localhost:9000')
17
17
  */
18
18
  import Streamer from '@constructive-io/s3-streamer';
19
19
  import uploadNames from '@constructive-io/upload-names';
@@ -34,7 +34,7 @@ function getStreamer() {
34
34
  const awsRegion = cdn.awsRegion || 'us-east-1';
35
35
  const awsAccessKey = cdn.awsAccessKey || 'minioadmin';
36
36
  const awsSecretKey = cdn.awsSecretKey || 'minioadmin';
37
- const minioEndpoint = cdn.minioEndpoint || 'http://localhost:9000';
37
+ const endpoint = cdn.endpoint || 'http://localhost:9000';
38
38
  if (process.env.NODE_ENV === 'production') {
39
39
  if (!cdn.awsAccessKey || !cdn.awsSecretKey) {
40
40
  log.warn('[upload-resolver] WARNING: Using default credentials in production.');
@@ -46,7 +46,7 @@ function getStreamer() {
46
46
  awsRegion,
47
47
  awsSecretKey,
48
48
  awsAccessKey,
49
- minioEndpoint,
49
+ endpoint,
50
50
  provider,
51
51
  });
52
52
  return streamer;
package/index.d.ts CHANGED
@@ -34,3 +34,5 @@ export * from './plugins/index';
34
34
  export * from './presets/index';
35
35
  export { makePgService };
36
36
  export { streamToStorage } from './upload-resolver';
37
+ export { getPresignedUrlS3Config } from './presigned-url-resolver';
38
+ export { getBucketProvisionerConnection } from './bucket-provisioner-resolver';
package/index.js CHANGED
@@ -42,7 +42,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
42
42
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
43
43
  };
44
44
  Object.defineProperty(exports, "__esModule", { value: true });
45
- exports.streamToStorage = exports.makePgService = exports.ConstructivePreset = void 0;
45
+ exports.getBucketProvisionerConnection = exports.getPresignedUrlS3Config = exports.streamToStorage = exports.makePgService = exports.ConstructivePreset = void 0;
46
46
  const pg_1 = require("postgraphile/adaptors/pg");
47
47
  Object.defineProperty(exports, "makePgService", { enumerable: true, get: function () { return pg_1.makePgService; } });
48
48
  // Import modules for type augmentation
@@ -65,3 +65,9 @@ __exportStar(require("./presets/index"), exports);
65
65
  // Upload utilities
66
66
  var upload_resolver_1 = require("./upload-resolver");
67
67
  Object.defineProperty(exports, "streamToStorage", { enumerable: true, get: function () { return upload_resolver_1.streamToStorage; } });
68
+ // Presigned URL utilities
69
+ var presigned_url_resolver_1 = require("./presigned-url-resolver");
70
+ Object.defineProperty(exports, "getPresignedUrlS3Config", { enumerable: true, get: function () { return presigned_url_resolver_1.getPresignedUrlS3Config; } });
71
+ // Bucket provisioner utilities
72
+ var bucket_provisioner_resolver_1 = require("./bucket-provisioner-resolver");
73
+ Object.defineProperty(exports, "getBucketProvisionerConnection", { enumerable: true, get: function () { return bucket_provisioner_resolver_1.getBucketProvisionerConnection; } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "graphile-settings",
3
- "version": "4.18.9",
3
+ "version": "4.19.0",
4
4
  "author": "Constructive <developers@constructive.io>",
5
5
  "description": "graphile settings",
6
6
  "main": "index.js",
@@ -29,26 +29,29 @@
29
29
  "test:watch": "jest --watch"
30
30
  },
31
31
  "dependencies": {
32
- "@constructive-io/graphql-env": "^3.5.3",
33
- "@constructive-io/graphql-types": "^3.4.3",
34
- "@constructive-io/s3-streamer": "^2.17.3",
32
+ "@aws-sdk/client-s3": "^3.1009.0",
33
+ "@constructive-io/graphql-env": "^3.5.4",
34
+ "@constructive-io/graphql-types": "^3.4.4",
35
+ "@constructive-io/s3-streamer": "^2.17.4",
35
36
  "@constructive-io/upload-names": "^2.10.2",
36
37
  "@dataplan/json": "1.0.0",
37
38
  "@dataplan/pg": "1.0.0",
38
39
  "@graphile-contrib/pg-many-to-many": "2.0.0-rc.2",
39
40
  "@pgpmjs/logger": "^2.5.2",
40
- "@pgpmjs/types": "^2.20.3",
41
+ "@pgpmjs/types": "^2.21.0",
41
42
  "@pgsql/quotes": "^17.1.0",
42
43
  "cors": "^2.8.6",
43
44
  "express": "^5.2.1",
44
45
  "grafast": "1.0.0",
45
46
  "grafserv": "1.0.0",
47
+ "graphile-bucket-provisioner-plugin": "0.2.0",
46
48
  "graphile-build": "5.0.0",
47
49
  "graphile-build-pg": "5.0.0",
48
50
  "graphile-config": "1.0.0",
49
- "graphile-connection-filter": "^1.3.7",
50
- "graphile-postgis": "^2.9.9",
51
- "graphile-search": "^1.5.9",
51
+ "graphile-connection-filter": "^1.3.8",
52
+ "graphile-postgis": "^2.9.10",
53
+ "graphile-presigned-url-plugin": "^0.3.0",
54
+ "graphile-search": "^1.5.10",
52
55
  "graphile-sql-expression-validator": "^2.6.2",
53
56
  "graphile-upload-plugin": "^2.5.2",
54
57
  "graphile-utils": "5.0.0",
@@ -67,10 +70,10 @@
67
70
  "@types/express": "^5.0.6",
68
71
  "@types/pg": "^8.18.0",
69
72
  "@types/request-ip": "^0.0.41",
70
- "graphile-test": "^4.7.7",
73
+ "graphile-test": "^4.7.8",
71
74
  "makage": "^0.3.0",
72
75
  "nodemon": "^3.1.14",
73
- "pgsql-test": "^4.7.7",
76
+ "pgsql-test": "^4.7.8",
74
77
  "ts-node": "^10.9.2"
75
78
  },
76
79
  "keywords": [
@@ -80,5 +83,5 @@
80
83
  "constructive",
81
84
  "graphql"
82
85
  ],
83
- "gitHead": "b0b6f07955974ab896a058a69196eaf4bb445feb"
86
+ "gitHead": "fe60f7b81252eea53dce227bb581d5ae2ef0ec36"
84
87
  }
@@ -48,7 +48,7 @@ function buildUniqueConstraints(codec, attributes, uniques, context) {
48
48
  function buildForeignKeyConstraints(codec, attributes, relations, context) {
49
49
  const constraints = [];
50
50
  for (const [relationName, relation] of Object.entries(relations)) {
51
- if (relation.isReferencee !== false)
51
+ if (relation.isReferencee)
52
52
  continue;
53
53
  const remoteCodec = relation.remoteResource?.codec;
54
54
  const remoteAttributes = remoteCodec?.attributes || {};
@@ -13,7 +13,9 @@ function isRecord(value) {
13
13
  function buildBelongsToRelations(codec, attributes, uniques, relations, context) {
14
14
  const belongsTo = [];
15
15
  for (const [relationName, relation] of Object.entries(relations)) {
16
- if (relation.isReferencee !== false)
16
+ // PostGraphile only sets isReferencee when true (reverse FK);
17
+ // forward relations have isReferencee undefined, not false.
18
+ if (relation.isReferencee)
17
19
  continue;
18
20
  const localAttributes = relation.localAttributes || [];
19
21
  const isUnique = uniques.some((unique) => (0, table_resource_utils_1.sameAttributes)(unique.attributes, localAttributes));
@@ -22,7 +22,7 @@ function buildTableMeta(resource, schemaName, context) {
22
22
  }
23
23
  }
24
24
  for (const relation of Object.values(relations)) {
25
- if (relation.isReferencee !== false)
25
+ if (relation.isReferencee)
26
26
  continue;
27
27
  for (const attrName of relation.localAttributes || [])
28
28
  fkAttrNames.add(attrName);
@@ -17,6 +17,9 @@ import type { GraphileConfig } from 'graphile-config';
17
17
  * - PostGIS support (geometry/geography types, GeoJSON scalar — auto-detects PostGIS extension)
18
18
  * - PostGIS connection filter operators (spatial filtering on geometry/geography columns)
19
19
  * - Upload plugin (file upload to S3/MinIO for image, upload, attachment domain columns)
20
+ * - Presigned URL plugin (requestUploadUrl, confirmUpload mutations + downloadUrl computed field)
21
+ * - Bucket provisioner plugin (auto-provisions S3 buckets on @storageBuckets table mutations,
22
+ * CORS management, provisionBucket mutation for manual/retry)
20
23
  * - SQL expression validator (validates @sqlExpression columns in mutations)
21
24
  * - PG type mappings (maps custom types like email, url to GraphQL scalars)
22
25
  * - pgvector search (auto-discovers vector columns: filter fields, distance computed fields,
@@ -6,8 +6,12 @@ const plugins_1 = require("../plugins");
6
6
  const graphile_search_1 = require("graphile-search");
7
7
  const graphile_postgis_1 = require("graphile-postgis");
8
8
  const graphile_upload_plugin_1 = require("graphile-upload-plugin");
9
+ const graphile_presigned_url_plugin_1 = require("graphile-presigned-url-plugin");
10
+ const graphile_bucket_provisioner_plugin_1 = require("graphile-bucket-provisioner-plugin");
9
11
  const graphile_sql_expression_validator_1 = require("graphile-sql-expression-validator");
10
12
  const upload_resolver_1 = require("../upload-resolver");
13
+ const presigned_url_resolver_1 = require("../presigned-url-resolver");
14
+ const bucket_provisioner_resolver_1 = require("../bucket-provisioner-resolver");
11
15
  /**
12
16
  * Constructive PostGraphile v5 Preset
13
17
  *
@@ -26,6 +30,9 @@ const upload_resolver_1 = require("../upload-resolver");
26
30
  * - PostGIS support (geometry/geography types, GeoJSON scalar — auto-detects PostGIS extension)
27
31
  * - PostGIS connection filter operators (spatial filtering on geometry/geography columns)
28
32
  * - Upload plugin (file upload to S3/MinIO for image, upload, attachment domain columns)
33
+ * - Presigned URL plugin (requestUploadUrl, confirmUpload mutations + downloadUrl computed field)
34
+ * - Bucket provisioner plugin (auto-provisions S3 buckets on @storageBuckets table mutations,
35
+ * CORS management, provisionBucket mutation for manual/retry)
29
36
  * - SQL expression validator (validates @sqlExpression columns in mutations)
30
37
  * - PG type mappings (maps custom types like email, url to GraphQL scalars)
31
38
  * - pgvector search (auto-discovers vector columns: filter fields, distance computed fields,
@@ -73,6 +80,11 @@ exports.ConstructivePreset = {
73
80
  uploadFieldDefinitions: upload_resolver_1.constructiveUploadFieldDefinitions,
74
81
  maxFileSize: 10 * 1024 * 1024, // 10MB
75
82
  }),
83
+ (0, graphile_presigned_url_plugin_1.PresignedUrlPreset)({ s3: presigned_url_resolver_1.getPresignedUrlS3Config }),
84
+ (0, graphile_bucket_provisioner_plugin_1.BucketProvisionerPreset)({
85
+ connection: bucket_provisioner_resolver_1.getBucketProvisionerConnection,
86
+ allowedOrigins: ['http://localhost:3000'],
87
+ }),
76
88
  (0, graphile_sql_expression_validator_1.SqlExpressionValidatorPreset)(),
77
89
  plugins_1.PgTypeMappingsPreset,
78
90
  plugins_1.RequiredInputPreset,
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Presigned URL resolver for the Constructive presigned URL plugin.
3
+ *
4
+ * Reads CDN/S3 configuration from the standard env system
5
+ * (getEnvOptions → pgpmDefaults + config files + env vars) and lazily
6
+ * initializes an S3Client on first use.
7
+ *
8
+ * Follows the same lazy-init pattern as upload-resolver.ts.
9
+ */
10
+ import type { S3Config } from 'graphile-presigned-url-plugin';
11
+ /**
12
+ * Lazily initialize and return the S3Config for the presigned URL plugin.
13
+ *
14
+ * Reads CDN config on first call via getEnvOptions() (which already merges
15
+ * pgpmDefaults → config file → env vars), creates an S3Client, and caches
16
+ * the result. Same CDN config as upload-resolver.ts.
17
+ */
18
+ export declare function getPresignedUrlS3Config(): S3Config;
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ /**
3
+ * Presigned URL resolver for the Constructive presigned URL plugin.
4
+ *
5
+ * Reads CDN/S3 configuration from the standard env system
6
+ * (getEnvOptions → pgpmDefaults + config files + env vars) and lazily
7
+ * initializes an S3Client on first use.
8
+ *
9
+ * Follows the same lazy-init pattern as upload-resolver.ts.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.getPresignedUrlS3Config = getPresignedUrlS3Config;
13
+ const client_s3_1 = require("@aws-sdk/client-s3");
14
+ const graphql_env_1 = require("@constructive-io/graphql-env");
15
+ const logger_1 = require("@pgpmjs/logger");
16
+ const log = new logger_1.Logger('presigned-url-resolver');
17
+ let s3Config = null;
18
+ /**
19
+ * Lazily initialize and return the S3Config for the presigned URL plugin.
20
+ *
21
+ * Reads CDN config on first call via getEnvOptions() (which already merges
22
+ * pgpmDefaults → config file → env vars), creates an S3Client, and caches
23
+ * the result. Same CDN config as upload-resolver.ts.
24
+ */
25
+ function getPresignedUrlS3Config() {
26
+ if (s3Config)
27
+ return s3Config;
28
+ const { cdn } = (0, graphql_env_1.getEnvOptions)();
29
+ // cdn is guaranteed populated — pgpmDefaults provides all CDN fields
30
+ const { bucketName, awsRegion, awsAccessKey, awsSecretKey, endpoint, publicUrlPrefix } = cdn;
31
+ log.info(`[presigned-url-resolver] Initializing: bucket=${bucketName} endpoint=${endpoint}`);
32
+ const client = new client_s3_1.S3Client({
33
+ region: awsRegion,
34
+ credentials: { accessKeyId: awsAccessKey, secretAccessKey: awsSecretKey },
35
+ ...(endpoint ? { endpoint, forcePathStyle: true } : {}),
36
+ });
37
+ s3Config = {
38
+ client,
39
+ bucket: bucketName,
40
+ region: awsRegion,
41
+ publicUrlPrefix,
42
+ ...(endpoint ? { endpoint, forcePathStyle: true } : {}),
43
+ };
44
+ return s3Config;
45
+ }
@@ -13,7 +13,7 @@
13
13
  * AWS_REGION - AWS region (default: 'us-east-1')
14
14
  * AWS_ACCESS_KEY - access key (default: 'minioadmin')
15
15
  * AWS_SECRET_KEY - secret key (default: 'minioadmin')
16
- * MINIO_ENDPOINT - MinIO endpoint (default: 'http://localhost:9000')
16
+ * CDN_ENDPOINT - S3-compatible endpoint (default: 'http://localhost:9000')
17
17
  */
18
18
  import type { Readable } from 'stream';
19
19
  import type { UploadFieldDefinition } from 'graphile-upload-plugin';
@@ -14,7 +14,7 @@
14
14
  * AWS_REGION - AWS region (default: 'us-east-1')
15
15
  * AWS_ACCESS_KEY - access key (default: 'minioadmin')
16
16
  * AWS_SECRET_KEY - secret key (default: 'minioadmin')
17
- * MINIO_ENDPOINT - MinIO endpoint (default: 'http://localhost:9000')
17
+ * CDN_ENDPOINT - S3-compatible endpoint (default: 'http://localhost:9000')
18
18
  */
19
19
  var __importDefault = (this && this.__importDefault) || function (mod) {
20
20
  return (mod && mod.__esModule) ? mod : { "default": mod };
@@ -41,7 +41,7 @@ function getStreamer() {
41
41
  const awsRegion = cdn.awsRegion || 'us-east-1';
42
42
  const awsAccessKey = cdn.awsAccessKey || 'minioadmin';
43
43
  const awsSecretKey = cdn.awsSecretKey || 'minioadmin';
44
- const minioEndpoint = cdn.minioEndpoint || 'http://localhost:9000';
44
+ const endpoint = cdn.endpoint || 'http://localhost:9000';
45
45
  if (process.env.NODE_ENV === 'production') {
46
46
  if (!cdn.awsAccessKey || !cdn.awsSecretKey) {
47
47
  log.warn('[upload-resolver] WARNING: Using default credentials in production.');
@@ -53,7 +53,7 @@ function getStreamer() {
53
53
  awsRegion,
54
54
  awsSecretKey,
55
55
  awsAccessKey,
56
- minioEndpoint,
56
+ endpoint,
57
57
  provider,
58
58
  });
59
59
  return streamer;