graphile-presigned-url-plugin 0.10.0 → 0.11.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.
- package/download-url-field.d.ts +1 -0
- package/download-url-field.js +6 -8
- package/esm/download-url-field.d.ts +1 -0
- package/esm/download-url-field.js +7 -9
- package/esm/index.d.ts +6 -5
- package/esm/index.js +6 -5
- package/esm/plugin.d.ts +12 -8
- package/esm/plugin.js +343 -312
- package/esm/s3-signer.d.ts +9 -2
- package/esm/s3-signer.js +16 -3
- package/esm/storage-module-cache.d.ts +33 -0
- package/esm/storage-module-cache.js +45 -0
- package/index.d.ts +6 -5
- package/index.js +8 -4
- package/package.json +2 -2
- package/plugin.d.ts +12 -8
- package/plugin.js +341 -310
- package/s3-signer.d.ts +9 -2
- package/s3-signer.js +16 -2
- package/storage-module-cache.d.ts +33 -0
- package/storage-module-cache.js +47 -0
package/download-url-field.d.ts
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
* the plan() function is required for Grafast to execute the S3 signing.
|
|
20
20
|
*/
|
|
21
21
|
import type { GraphileConfig } from 'graphile-config';
|
|
22
|
+
import 'graphile-build';
|
|
22
23
|
import type { PresignedUrlPluginOptions } from './types';
|
|
23
24
|
export declare function createDownloadUrlPlugin(options: PresignedUrlPluginOptions): GraphileConfig.Plugin;
|
|
24
25
|
export default createDownloadUrlPlugin;
|
package/download-url-field.js
CHANGED
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
*/
|
|
22
22
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
23
|
exports.createDownloadUrlPlugin = createDownloadUrlPlugin;
|
|
24
|
+
require("graphile-build");
|
|
24
25
|
const grafast_1 = require("grafast");
|
|
25
26
|
const logger_1 = require("@pgpmjs/logger");
|
|
26
27
|
const s3_signer_1 = require("./s3-signer");
|
|
@@ -86,17 +87,16 @@ function createDownloadUrlPlugin(options) {
|
|
|
86
87
|
}
|
|
87
88
|
log.debug(`Adding downloadUrl field to type: ${pgCodec.name} (has @storageFiles tag)`);
|
|
88
89
|
const { graphql: { GraphQLString }, } = build;
|
|
90
|
+
const capturedCodec = pgCodec;
|
|
89
91
|
return build.extend(fields, {
|
|
90
92
|
downloadUrl: context.fieldWithHooks({ fieldName: 'downloadUrl' }, {
|
|
91
93
|
description: 'URL to download this file. For public files, returns the public URL. ' +
|
|
92
94
|
'For private files, returns a time-limited presigned URL.',
|
|
93
95
|
type: GraphQLString,
|
|
94
96
|
plan($parent) {
|
|
95
|
-
// Access file attributes from the parent PgSelectSingleStep
|
|
96
97
|
const $key = $parent.get('key');
|
|
97
98
|
const $isPublic = $parent.get('is_public');
|
|
98
99
|
const $filename = $parent.get('filename');
|
|
99
|
-
// Access GraphQL context for per-database config resolution
|
|
100
100
|
const $withPgClient = (0, grafast_1.context)().get('withPgClient');
|
|
101
101
|
const $pgSettings = (0, grafast_1.context)().get('pgSettings');
|
|
102
102
|
const $combined = (0, grafast_1.object)({
|
|
@@ -109,9 +109,8 @@ function createDownloadUrlPlugin(options) {
|
|
|
109
109
|
return (0, grafast_1.lambda)($combined, async ({ key, isPublic, filename, withPgClient, pgSettings }) => {
|
|
110
110
|
if (!key)
|
|
111
111
|
return null;
|
|
112
|
-
|
|
113
|
-
let
|
|
114
|
-
let downloadUrlExpirySeconds = 3600; // fallback default
|
|
112
|
+
let s3ForDb = resolveS3(options);
|
|
113
|
+
let downloadUrlExpirySeconds = 3600;
|
|
115
114
|
try {
|
|
116
115
|
if (withPgClient && pgSettings) {
|
|
117
116
|
const resolved = await withPgClient(null, async (pgClient) => {
|
|
@@ -121,7 +120,8 @@ function createDownloadUrlPlugin(options) {
|
|
|
121
120
|
const databaseId = dbResult.rows[0]?.id;
|
|
122
121
|
if (!databaseId)
|
|
123
122
|
return null;
|
|
124
|
-
const
|
|
123
|
+
const allConfigs = await (0, storage_module_cache_1.loadAllStorageModules)(pgClient, databaseId);
|
|
124
|
+
const config = (0, storage_module_cache_1.resolveStorageConfigFromCodec)(capturedCodec, allConfigs);
|
|
125
125
|
if (!config)
|
|
126
126
|
return null;
|
|
127
127
|
return { config, databaseId };
|
|
@@ -136,10 +136,8 @@ function createDownloadUrlPlugin(options) {
|
|
|
136
136
|
// Fall back to global config if lookup fails
|
|
137
137
|
}
|
|
138
138
|
if (isPublic && s3ForDb.publicUrlPrefix) {
|
|
139
|
-
// Public file: return direct CDN URL (per-database prefix)
|
|
140
139
|
return `${s3ForDb.publicUrlPrefix}/${key}`;
|
|
141
140
|
}
|
|
142
|
-
// Private file: generate presigned GET URL (per-database bucket)
|
|
143
141
|
return (0, s3_signer_1.generatePresignedGetUrl)(s3ForDb, key, downloadUrlExpirySeconds, filename || undefined);
|
|
144
142
|
});
|
|
145
143
|
},
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
* the plan() function is required for Grafast to execute the S3 signing.
|
|
20
20
|
*/
|
|
21
21
|
import type { GraphileConfig } from 'graphile-config';
|
|
22
|
+
import 'graphile-build';
|
|
22
23
|
import type { PresignedUrlPluginOptions } from './types';
|
|
23
24
|
export declare function createDownloadUrlPlugin(options: PresignedUrlPluginOptions): GraphileConfig.Plugin;
|
|
24
25
|
export default createDownloadUrlPlugin;
|
|
@@ -18,10 +18,11 @@
|
|
|
18
18
|
* lookups. Since downloadUrl is a computed field (not a real column),
|
|
19
19
|
* the plan() function is required for Grafast to execute the S3 signing.
|
|
20
20
|
*/
|
|
21
|
+
import 'graphile-build';
|
|
21
22
|
import { context as grafastContext, lambda, object } from 'grafast';
|
|
22
23
|
import { Logger } from '@pgpmjs/logger';
|
|
23
24
|
import { generatePresignedGetUrl } from './s3-signer';
|
|
24
|
-
import {
|
|
25
|
+
import { loadAllStorageModules, resolveStorageConfigFromCodec } from './storage-module-cache';
|
|
25
26
|
const log = new Logger('graphile-presigned-url:download-url');
|
|
26
27
|
/**
|
|
27
28
|
* Creates the downloadUrl computed field plugin.
|
|
@@ -83,17 +84,16 @@ export function createDownloadUrlPlugin(options) {
|
|
|
83
84
|
}
|
|
84
85
|
log.debug(`Adding downloadUrl field to type: ${pgCodec.name} (has @storageFiles tag)`);
|
|
85
86
|
const { graphql: { GraphQLString }, } = build;
|
|
87
|
+
const capturedCodec = pgCodec;
|
|
86
88
|
return build.extend(fields, {
|
|
87
89
|
downloadUrl: context.fieldWithHooks({ fieldName: 'downloadUrl' }, {
|
|
88
90
|
description: 'URL to download this file. For public files, returns the public URL. ' +
|
|
89
91
|
'For private files, returns a time-limited presigned URL.',
|
|
90
92
|
type: GraphQLString,
|
|
91
93
|
plan($parent) {
|
|
92
|
-
// Access file attributes from the parent PgSelectSingleStep
|
|
93
94
|
const $key = $parent.get('key');
|
|
94
95
|
const $isPublic = $parent.get('is_public');
|
|
95
96
|
const $filename = $parent.get('filename');
|
|
96
|
-
// Access GraphQL context for per-database config resolution
|
|
97
97
|
const $withPgClient = grafastContext().get('withPgClient');
|
|
98
98
|
const $pgSettings = grafastContext().get('pgSettings');
|
|
99
99
|
const $combined = object({
|
|
@@ -106,9 +106,8 @@ export function createDownloadUrlPlugin(options) {
|
|
|
106
106
|
return lambda($combined, async ({ key, isPublic, filename, withPgClient, pgSettings }) => {
|
|
107
107
|
if (!key)
|
|
108
108
|
return null;
|
|
109
|
-
|
|
110
|
-
let
|
|
111
|
-
let downloadUrlExpirySeconds = 3600; // fallback default
|
|
109
|
+
let s3ForDb = resolveS3(options);
|
|
110
|
+
let downloadUrlExpirySeconds = 3600;
|
|
112
111
|
try {
|
|
113
112
|
if (withPgClient && pgSettings) {
|
|
114
113
|
const resolved = await withPgClient(null, async (pgClient) => {
|
|
@@ -118,7 +117,8 @@ export function createDownloadUrlPlugin(options) {
|
|
|
118
117
|
const databaseId = dbResult.rows[0]?.id;
|
|
119
118
|
if (!databaseId)
|
|
120
119
|
return null;
|
|
121
|
-
const
|
|
120
|
+
const allConfigs = await loadAllStorageModules(pgClient, databaseId);
|
|
121
|
+
const config = resolveStorageConfigFromCodec(capturedCodec, allConfigs);
|
|
122
122
|
if (!config)
|
|
123
123
|
return null;
|
|
124
124
|
return { config, databaseId };
|
|
@@ -133,10 +133,8 @@ export function createDownloadUrlPlugin(options) {
|
|
|
133
133
|
// Fall back to global config if lookup fails
|
|
134
134
|
}
|
|
135
135
|
if (isPublic && s3ForDb.publicUrlPrefix) {
|
|
136
|
-
// Public file: return direct CDN URL (per-database prefix)
|
|
137
136
|
return `${s3ForDb.publicUrlPrefix}/${key}`;
|
|
138
137
|
}
|
|
139
|
-
// Private file: generate presigned GET URL (per-database bucket)
|
|
140
138
|
return generatePresignedGetUrl(s3ForDb, key, downloadUrlExpirySeconds, filename || undefined);
|
|
141
139
|
});
|
|
142
140
|
},
|
package/esm/index.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Presigned URL Plugin for PostGraphile v5
|
|
3
3
|
*
|
|
4
|
-
* Provides
|
|
5
|
-
* -
|
|
6
|
-
* -
|
|
4
|
+
* Provides per-table S3 storage middleware for PostGraphile v5:
|
|
5
|
+
* - Upload fields on @storageBuckets types (requestUploadUrl, requestBulkUploadUrls)
|
|
6
|
+
* - Delete middleware on @storageFiles tables (S3 cleanup on delete)
|
|
7
|
+
* - downloadUrl computed field on @storageFiles types
|
|
7
8
|
*
|
|
8
9
|
* @example
|
|
9
10
|
* ```typescript
|
|
@@ -28,6 +29,6 @@
|
|
|
28
29
|
export { PresignedUrlPlugin, createPresignedUrlPlugin } from './plugin';
|
|
29
30
|
export { createDownloadUrlPlugin } from './download-url-field';
|
|
30
31
|
export { PresignedUrlPreset } from './preset';
|
|
31
|
-
export { getStorageModuleConfig, getStorageModuleConfigForOwner, getBucketConfig, resolveStorageModuleByFileId, clearStorageModuleCache, clearBucketCache, isS3BucketProvisioned, markS3BucketProvisioned } from './storage-module-cache';
|
|
32
|
-
export { generatePresignedPutUrl, generatePresignedGetUrl, headObject } from './s3-signer';
|
|
32
|
+
export { getStorageModuleConfig, getStorageModuleConfigForOwner, getBucketConfig, resolveStorageModuleByFileId, loadAllStorageModules, resolveStorageConfigFromCodec, clearStorageModuleCache, clearBucketCache, isS3BucketProvisioned, markS3BucketProvisioned } from './storage-module-cache';
|
|
33
|
+
export { generatePresignedPutUrl, generatePresignedGetUrl, deleteS3Object, headObject } from './s3-signer';
|
|
33
34
|
export type { BucketConfig, StorageModuleConfig, RequestUploadUrlInput, RequestUploadUrlPayload, S3Config, S3ConfigOrGetter, PresignedUrlPluginOptions, BucketNameResolver, EnsureBucketProvisioned, } from './types';
|
package/esm/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Presigned URL Plugin for PostGraphile v5
|
|
3
3
|
*
|
|
4
|
-
* Provides
|
|
5
|
-
* -
|
|
6
|
-
* -
|
|
4
|
+
* Provides per-table S3 storage middleware for PostGraphile v5:
|
|
5
|
+
* - Upload fields on @storageBuckets types (requestUploadUrl, requestBulkUploadUrls)
|
|
6
|
+
* - Delete middleware on @storageFiles tables (S3 cleanup on delete)
|
|
7
|
+
* - downloadUrl computed field on @storageFiles types
|
|
7
8
|
*
|
|
8
9
|
* @example
|
|
9
10
|
* ```typescript
|
|
@@ -28,5 +29,5 @@
|
|
|
28
29
|
export { PresignedUrlPlugin, createPresignedUrlPlugin } from './plugin';
|
|
29
30
|
export { createDownloadUrlPlugin } from './download-url-field';
|
|
30
31
|
export { PresignedUrlPreset } from './preset';
|
|
31
|
-
export { getStorageModuleConfig, getStorageModuleConfigForOwner, getBucketConfig, resolveStorageModuleByFileId, clearStorageModuleCache, clearBucketCache, isS3BucketProvisioned, markS3BucketProvisioned } from './storage-module-cache';
|
|
32
|
-
export { generatePresignedPutUrl, generatePresignedGetUrl, headObject } from './s3-signer';
|
|
32
|
+
export { getStorageModuleConfig, getStorageModuleConfigForOwner, getBucketConfig, resolveStorageModuleByFileId, loadAllStorageModules, resolveStorageConfigFromCodec, clearStorageModuleCache, clearBucketCache, isS3BucketProvisioned, markS3BucketProvisioned } from './storage-module-cache';
|
|
33
|
+
export { generatePresignedPutUrl, generatePresignedGetUrl, deleteS3Object, headObject } from './s3-signer';
|
package/esm/plugin.d.ts
CHANGED
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Per-Table Storage Middleware Plugin for PostGraphile v5
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Hooks into PostGraphile's auto-generated CRUD mutations to add S3 operations:
|
|
5
5
|
*
|
|
6
|
-
* 1.
|
|
7
|
-
*
|
|
8
|
-
* content hash via UNIQUE(bucket_id, key) constraint.
|
|
6
|
+
* 1. Delete middleware — wraps `delete*` mutations on `@storageFiles`-tagged tables
|
|
7
|
+
* with S3 object cleanup (sync + async GC fallback via AFTER DELETE trigger).
|
|
9
8
|
*
|
|
10
|
-
* 2.
|
|
11
|
-
*
|
|
9
|
+
* 2. Upload fields — adds `requestUploadUrl` and `requestBulkUploadUrls` fields
|
|
10
|
+
* on `@storageBuckets`-tagged types, so clients upload via the typed bucket API.
|
|
12
11
|
*
|
|
13
|
-
*
|
|
12
|
+
* 3. downloadUrl — handled by download-url-field.ts (separate plugin).
|
|
13
|
+
*
|
|
14
|
+
* No global mutations — all S3 operations are scoped to the per-table types that
|
|
15
|
+
* PostGraphile already generates. Scope resolution uses the codec's schema/table
|
|
16
|
+
* name matched against cached storage module configs.
|
|
14
17
|
*/
|
|
15
18
|
import type { GraphileConfig } from 'graphile-config';
|
|
19
|
+
import 'graphile-build';
|
|
16
20
|
import type { PresignedUrlPluginOptions } from './types';
|
|
17
21
|
export declare function createPresignedUrlPlugin(options: PresignedUrlPluginOptions): GraphileConfig.Plugin;
|
|
18
22
|
export declare const PresignedUrlPlugin: typeof createPresignedUrlPlugin;
|