@genoacms/adapter-gcp 0.7.1 → 0.7.9

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.
@@ -1,4 +1,4 @@
1
- import { handler } from './build/handler.js'
1
+ import { handler } from './node_modules/@genoacms/core/build/index.js'
2
2
 
3
3
  function genoacms (req, res) {
4
4
  handler(req, res, undefined)
@@ -1,13 +1,14 @@
1
1
  import config from '../../config.js';
2
2
  import { ProjectsClient } from '@google-cloud/resource-manager';
3
- const authorizationConfig = config.authorization.providers.find((provider) => provider.name === 'gcp');
3
+ const PROVIDER_NAME = '@genoacms/adapter-gcp/authorization';
4
+ const authorizationConfig = config.authorization.providers.find((provider) => provider.name === PROVIDER_NAME);
4
5
  if (!authorizationConfig)
5
6
  throw new Error('authorization-provider-not-found');
7
+ const projectId = authorizationConfig.projectId;
6
8
  const resourceManager = new ProjectsClient({
7
- projectId: config.authorization.projectId,
8
- credentials: config.authorization.credentials
9
+ projectId,
10
+ credentials: authorizationConfig.credentials
9
11
  });
10
- const projectId = config.authorization.projectId;
11
12
  const isEmailAdmins = async (email) => {
12
13
  const resource = `projects/${projectId}`;
13
14
  const role = resource + '/roles/genoacms';
@@ -1,6 +1,7 @@
1
1
  import config from '../../config.js';
2
2
  import { Firestore } from '@google-cloud/firestore';
3
- const firestoreConfig = config.database.providers.find((provider) => provider.name === 'firestore');
3
+ const PROVIDER_NAME = '@genoacms/adapter-gcp/database';
4
+ const firestoreConfig = config.database.providers.find((provider) => provider.name === PROVIDER_NAME);
4
5
  if (!firestoreConfig)
5
6
  throw new Error('firestore-provider-not-found');
6
7
  const firestore = new Firestore({
@@ -22,7 +22,7 @@ async function createZip(source, injectPaths, ignorePaths, out) {
22
22
  reject(err);
23
23
  });
24
24
  archive.pipe(output);
25
- archive.glob(source, { ignore: ignorePaths });
25
+ archive.glob(source, { ignore: ignorePaths, follow: true });
26
26
  for (const path of injectPaths) {
27
27
  archive.file(path, { name: basename(path) });
28
28
  }
@@ -74,7 +74,7 @@ async function deployFunction(functionName, storageSource) {
74
74
  serviceConfig: {
75
75
  minInstanceCount: 0,
76
76
  maxInstanceCount: 1,
77
- ingressSettings: 1,
77
+ ingressSettings: 1, // ALLOW_ALL
78
78
  environmentVariables: {
79
79
  NODE_ENV: 'production'
80
80
  }
@@ -92,17 +92,20 @@ async function deployFunction(functionName, storageSource) {
92
92
  }
93
93
  async function deploy() {
94
94
  const buildDirectoryPath = '**';
95
- const buildArchivePath = resolve(currentDir, '../../../deployment/build.zip');
95
+ const buildArchivePath = resolve(currentDir, '../../../../../../.genoacms/build.zip');
96
96
  const functionEntryScriptPath = resolve(currentDir, '../../../deployment/snippets/index.js');
97
+ const builderScriptPath = resolve(currentDir, '../../../deployment/snippets/build.js');
97
98
  const ignoreArchivePaths = [
98
99
  'node_modules/**',
99
100
  '.git/**',
100
101
  '.github/**',
101
102
  '.gitignore',
103
+ '.genoacms/**',
102
104
  'build/**'
103
105
  ];
104
106
  const injectArchivePaths = [
105
- functionEntryScriptPath
107
+ functionEntryScriptPath,
108
+ builderScriptPath
106
109
  ];
107
110
  await createZip(buildDirectoryPath, injectArchivePaths, ignoreArchivePaths, buildArchivePath);
108
111
  const functionStorageSource = await uploadSource(buildArchivePath);
@@ -3,7 +3,10 @@ declare const getObject: Adapter['getObject'];
3
3
  declare const getPublicURL: Adapter['getPublicURL'];
4
4
  declare const getSignedURL: Adapter['getSignedURL'];
5
5
  declare const uploadObject: Adapter['uploadObject'];
6
+ declare const moveObject: Adapter['moveObject'];
6
7
  declare const deleteObject: Adapter['deleteObject'];
7
8
  declare const listDirectory: Adapter['listDirectory'];
8
9
  declare const createDirectory: Adapter['createDirectory'];
9
- export { getObject, getPublicURL, getSignedURL, uploadObject, deleteObject, listDirectory, createDirectory };
10
+ declare const deleteDirectory: Adapter['deleteDirectory'];
11
+ declare const moveDirectory: Adapter['moveDirectory'];
12
+ export { getObject, getPublicURL, getSignedURL, uploadObject, moveObject, deleteObject, listDirectory, createDirectory, deleteDirectory, moveDirectory };
@@ -1,5 +1,4 @@
1
1
  import { getBucket } from './storage.js';
2
- import { join } from 'path';
3
2
  const getObject = async ({ bucket, name }) => {
4
3
  const bucketInstance = getBucket(bucket);
5
4
  const file = bucketInstance.file(name);
@@ -26,6 +25,11 @@ const uploadObject = async ({ bucket, name }, stream, options) => {
26
25
  const file = bucketInstance.file(name);
27
26
  await file.save(stream, options);
28
27
  };
28
+ const moveObject = async ({ bucket, name }, newName) => {
29
+ const bucketInstance = getBucket(bucket);
30
+ const file = bucketInstance.file(name);
31
+ await file.move(newName);
32
+ };
29
33
  const deleteObject = async ({ bucket, name }) => {
30
34
  const bucketInstance = getBucket(bucket);
31
35
  const file = bucketInstance.file(name);
@@ -35,7 +39,7 @@ const listDirectory = async ({ bucket, name }, listingParams = {}) => {
35
39
  const bucketInstance = getBucket(bucket);
36
40
  const options = {
37
41
  autoPaginate: false,
38
- prefix: join(name, '/'),
42
+ prefix: name,
39
43
  maxResults: listingParams?.limit,
40
44
  startOffset: listingParams?.startAfter,
41
45
  delimiter: '/'
@@ -43,7 +47,7 @@ const listDirectory = async ({ bucket, name }, listingParams = {}) => {
43
47
  let [files, , apiResponse] = (await bucketInstance.getFiles(options));
44
48
  files = files.filter((file) => !file.name.endsWith('.folderPlaceholder'));
45
49
  return {
46
- files: files.map((file) => {
50
+ files: files.filter(f => f.name !== name).map((file) => {
47
51
  return {
48
52
  name: file.name,
49
53
  // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
@@ -51,7 +55,13 @@ const listDirectory = async ({ bucket, name }, listingParams = {}) => {
51
55
  lastModified: new Date(file.metadata.updated)
52
56
  };
53
57
  }),
54
- directories: (apiResponse?.prefixes ?? []).filter((item) => item !== name)
58
+ directories: (apiResponse?.prefixes ?? []).filter((item) => item !== name).map(i => {
59
+ const object = {
60
+ bucket,
61
+ name: i
62
+ };
63
+ return object;
64
+ })
55
65
  };
56
66
  };
57
67
  const createDirectory = async ({ bucket, name }) => {
@@ -59,4 +69,19 @@ const createDirectory = async ({ bucket, name }) => {
59
69
  const file = bucketInstance.file(`${name}/.folderPlaceholder`);
60
70
  await file.save('');
61
71
  };
62
- export { getObject, getPublicURL, getSignedURL, uploadObject, deleteObject, listDirectory, createDirectory };
72
+ const deleteDirectory = async ({ bucket, name }) => {
73
+ const bucketInstance = getBucket(bucket);
74
+ const [files] = await bucketInstance.getFiles({ prefix: name });
75
+ const deletePromises = files.map(async (file) => await file.delete());
76
+ await Promise.all(deletePromises);
77
+ };
78
+ const moveDirectory = async ({ bucket, name }, newName) => {
79
+ const bucketInstance = getBucket(bucket);
80
+ const [files] = await bucketInstance.getFiles({ prefix: name });
81
+ const movePromises = files.map(async (file) => {
82
+ const newFileName = file.name.replace(name, newName);
83
+ await file.move(newFileName);
84
+ });
85
+ await Promise.all(movePromises);
86
+ };
87
+ export { getObject, getPublicURL, getSignedURL, uploadObject, moveObject, deleteObject, listDirectory, createDirectory, deleteDirectory, moveDirectory };
@@ -1,13 +1,18 @@
1
1
  import config from '../../config.js';
2
2
  import { Storage } from '@google-cloud/storage';
3
- const storageConfig = config.storage.providers.find((provider) => provider.name === 'gcs');
3
+ const PROVIDER_NAME = '@genoacms/adapter-gcp/storage';
4
+ const storageConfig = config.storage.providers.find((provider) => provider.name === PROVIDER_NAME);
4
5
  if (!storageConfig)
5
6
  throw new Error('storage-provider-not-found');
6
7
  const storage = new Storage({
7
- credentials: config.storage.credentials
8
+ credentials: storageConfig.credentials
8
9
  });
10
+ const hasBucket = (name) => {
11
+ const has = config.storage.buckets.find((bucket) => bucket.name === name && bucket.providerName === PROVIDER_NAME);
12
+ return !!has;
13
+ };
9
14
  const getBucket = (name) => {
10
- if (!config.storage.buckets.includes(name))
15
+ if (!hasBucket(name))
11
16
  throw new Error('bucket-unregistered');
12
17
  const bucket = storage.bucket(name);
13
18
  return bucket;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@genoacms/adapter-gcp",
3
- "version": "0.7.1",
3
+ "version": "0.7.9",
4
4
  "type": "module",
5
5
  "description": "Implementation of abstraction layer of GenoaCMS for GCP",
6
6
  "repository": {
@@ -20,7 +20,7 @@
20
20
  "provenance": true
21
21
  },
22
22
  "dependencies": {
23
- "@genoacms/cloudabstraction": "^0.7.1",
23
+ "@genoacms/cloudabstraction": "^0.7.9",
24
24
  "@google-cloud/firestore": "^7.1.0",
25
25
  "@google-cloud/functions": "^3.4.0",
26
26
  "@google-cloud/resource-manager": "^5.1.0",
@@ -2,13 +2,14 @@ import type { Adapter, AuthorizationProvider } from '@genoacms/cloudabstraction/
2
2
  import config from '../../config.js'
3
3
  import { ProjectsClient } from '@google-cloud/resource-manager'
4
4
 
5
- const authorizationConfig = config.authorization.providers.find((provider: AuthorizationProvider) => provider.name === 'gcp')
5
+ const PROVIDER_NAME = '@genoacms/adapter-gcp/authorization'
6
+ const authorizationConfig = config.authorization.providers.find((provider: AuthorizationProvider) => provider.name === PROVIDER_NAME)
6
7
  if (!authorizationConfig) throw new Error('authorization-provider-not-found')
8
+ const projectId = authorizationConfig.projectId
7
9
  const resourceManager = new ProjectsClient({
8
- projectId: config.authorization.projectId,
9
- credentials: config.authorization.credentials
10
+ projectId,
11
+ credentials: authorizationConfig.credentials
10
12
  })
11
- const projectId = config.authorization.projectId
12
13
 
13
14
  const isEmailAdmins: Adapter.isEmailAdmins = async (email: string) => {
14
15
  const resource = `projects/${projectId}`
@@ -10,7 +10,8 @@ import type {
10
10
  import config from '../../config.js'
11
11
  import { Firestore } from '@google-cloud/firestore'
12
12
 
13
- const firestoreConfig = config.database.providers.find((provider: DatabaseProvider) => provider.name === 'firestore')
13
+ const PROVIDER_NAME = '@genoacms/adapter-gcp/database'
14
+ const firestoreConfig = config.database.providers.find((provider: DatabaseProvider) => provider.name === PROVIDER_NAME)
14
15
  if (!firestoreConfig) throw new Error('firestore-provider-not-found')
15
16
  const firestore = new Firestore({
16
17
  credentials: firestoreConfig.credentials,
@@ -30,7 +30,7 @@ async function createZip (source: string, injectPaths: string[], ignorePaths: st
30
30
  })
31
31
 
32
32
  archive.pipe(output)
33
- archive.glob(source, { ignore: ignorePaths })
33
+ archive.glob(source, { ignore: ignorePaths, follow: true })
34
34
  for (const path of injectPaths) {
35
35
  archive.file(path, { name: basename(path) })
36
36
  }
@@ -100,17 +100,20 @@ async function deployFunction (functionName: string, storageSource: IStorageSour
100
100
 
101
101
  async function deploy (): Promise<void> {
102
102
  const buildDirectoryPath = '**'
103
- const buildArchivePath = resolve(currentDir, '../../../deployment/build.zip')
103
+ const buildArchivePath = resolve(currentDir, '../../../../../../.genoacms/build.zip')
104
104
  const functionEntryScriptPath = resolve(currentDir, '../../../deployment/snippets/index.js')
105
+ const builderScriptPath = resolve(currentDir, '../../../deployment/snippets/build.js')
105
106
  const ignoreArchivePaths = [
106
107
  'node_modules/**',
107
108
  '.git/**',
108
109
  '.github/**',
109
110
  '.gitignore',
111
+ '.genoacms/**',
110
112
  'build/**'
111
113
  ]
112
114
  const injectArchivePaths = [
113
- functionEntryScriptPath
115
+ functionEntryScriptPath,
116
+ builderScriptPath
114
117
  ]
115
118
  await createZip(buildDirectoryPath, injectArchivePaths, ignoreArchivePaths, buildArchivePath)
116
119
  const functionStorageSource = await uploadSource(buildArchivePath)
@@ -1,10 +1,10 @@
1
1
  import type {
2
2
  Adapter,
3
+ ObjectReference,
3
4
  StorageObject
4
5
  } from '@genoacms/cloudabstraction/storage'
5
6
  import { type File } from '@google-cloud/storage'
6
7
  import { getBucket } from './storage.js'
7
- import { join } from 'path'
8
8
 
9
9
  const getObject: Adapter['getObject'] = async ({ bucket, name }) => {
10
10
  const bucketInstance = getBucket(bucket)
@@ -37,6 +37,12 @@ const uploadObject: Adapter['uploadObject'] = async ({ bucket, name }, stream, o
37
37
  await file.save(stream, options)
38
38
  }
39
39
 
40
+ const moveObject: Adapter['moveObject'] = async ({ bucket, name }, newName) => {
41
+ const bucketInstance = getBucket(bucket)
42
+ const file = bucketInstance.file(name)
43
+ await file.move(newName)
44
+ }
45
+
40
46
  const deleteObject: Adapter['deleteObject'] = async ({ bucket, name }) => {
41
47
  const bucketInstance = getBucket(bucket)
42
48
  const file = bucketInstance.file(name)
@@ -47,7 +53,7 @@ const listDirectory: Adapter['listDirectory'] = async ({ bucket, name }, listing
47
53
  const bucketInstance = getBucket(bucket)
48
54
  const options = {
49
55
  autoPaginate: false,
50
- prefix: join(name, '/'),
56
+ prefix: name,
51
57
  maxResults: listingParams?.limit,
52
58
  startOffset: listingParams?.startAfter,
53
59
  delimiter: '/'
@@ -58,7 +64,7 @@ const listDirectory: Adapter['listDirectory'] = async ({ bucket, name }, listing
58
64
  files = files.filter((file) => !file.name.endsWith('.folderPlaceholder'))
59
65
 
60
66
  return {
61
- files: files.map((file) => {
67
+ files: files.filter(f => f.name !== name).map((file) => {
62
68
  return {
63
69
  name: file.name,
64
70
  // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
@@ -66,7 +72,13 @@ const listDirectory: Adapter['listDirectory'] = async ({ bucket, name }, listing
66
72
  lastModified: new Date(file.metadata.updated as string)
67
73
  } satisfies StorageObject
68
74
  }),
69
- directories: (apiResponse?.prefixes ?? []).filter((item) => item !== name)
75
+ directories: (apiResponse?.prefixes ?? []).filter((item) => item !== name).map(i => {
76
+ const object: ObjectReference = {
77
+ bucket,
78
+ name: i
79
+ }
80
+ return object
81
+ })
70
82
  }
71
83
  }
72
84
 
@@ -76,12 +88,32 @@ const createDirectory: Adapter['createDirectory'] = async ({ bucket, name }) =>
76
88
  await file.save('')
77
89
  }
78
90
 
91
+ const deleteDirectory: Adapter['deleteDirectory'] = async ({ bucket, name }) => {
92
+ const bucketInstance = getBucket(bucket)
93
+ const [files] = await bucketInstance.getFiles({ prefix: name })
94
+ const deletePromises = files.map(async (file) => await file.delete())
95
+ await Promise.all(deletePromises)
96
+ }
97
+
98
+ const moveDirectory: Adapter['moveDirectory'] = async ({ bucket, name }, newName) => {
99
+ const bucketInstance = getBucket(bucket)
100
+ const [files] = await bucketInstance.getFiles({ prefix: name })
101
+ const movePromises = files.map(async (file) => {
102
+ const newFileName = file.name.replace(name, newName)
103
+ await file.move(newFileName)
104
+ })
105
+ await Promise.all(movePromises)
106
+ }
107
+
79
108
  export {
80
109
  getObject,
81
110
  getPublicURL,
82
111
  getSignedURL,
83
112
  uploadObject,
113
+ moveObject,
84
114
  deleteObject,
85
115
  listDirectory,
86
- createDirectory
116
+ createDirectory,
117
+ deleteDirectory,
118
+ moveDirectory
87
119
  }
@@ -1,15 +1,21 @@
1
1
  import config from '../../config.js'
2
2
  import { type Bucket, Storage } from '@google-cloud/storage'
3
- import type { StorageProvider } from '@genoacms/cloudabstraction/storage'
3
+ import type { StorageProvider, BucketInit } from '@genoacms/cloudabstraction/storage'
4
4
 
5
- const storageConfig = config.storage.providers.find((provider: StorageProvider) => provider.name === 'gcs')
5
+ const PROVIDER_NAME = '@genoacms/adapter-gcp/storage'
6
+ const storageConfig = config.storage.providers.find((provider: StorageProvider) => provider.name === PROVIDER_NAME)
6
7
  if (!storageConfig) throw new Error('storage-provider-not-found')
7
8
  const storage = new Storage({
8
- credentials: config.storage.credentials
9
+ credentials: storageConfig.credentials
9
10
  })
10
11
 
12
+ const hasBucket = (name: string): boolean => {
13
+ const has = config.storage.buckets.find((bucket: BucketInit) => bucket.name === name && bucket.providerName === PROVIDER_NAME)
14
+ return !!has
15
+ }
16
+
11
17
  const getBucket = (name: string): Bucket => {
12
- if (!config.storage.buckets.includes(name)) throw new Error('bucket-unregistered')
18
+ if (!hasBucket(name)) throw new Error('bucket-unregistered')
13
19
  const bucket = storage.bucket(name)
14
20
  return bucket
15
21
  }