@genoacms/adapter-gcp 0.1.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2 @@
1
+ declare const _default: Config;
2
+ export default _default;
package/dist/config.js ADDED
@@ -0,0 +1,2 @@
1
+ import { config } from '@genoacms/cloudabstraction';
2
+ export default config;
@@ -0,0 +1,7 @@
1
+ import type { database as databaseT } from '@genoacms/cloudabstraction';
2
+ declare const createDocument: databaseT.createDocument;
3
+ declare const getCollection: databaseT.getCollection;
4
+ declare const getDocument: databaseT.getDocument;
5
+ declare const updateDocument: databaseT.updateDocument;
6
+ declare const deleteDocument: databaseT.deleteDocument;
7
+ export { createDocument, getDocument, getCollection, updateDocument, deleteDocument };
@@ -0,0 +1,38 @@
1
+ import { Firestore } from '@google-cloud/firestore';
2
+ import config from '../../config.js';
3
+ const firestore = new Firestore({
4
+ credentials: config.database.credentials,
5
+ databaseId: config.database.databaseId,
6
+ projectId: config.database.projectId
7
+ });
8
+ const createDocument = async (reference, data) => {
9
+ const document = await firestore.collection(reference.name).add(data);
10
+ return {
11
+ collection: reference,
12
+ id: document.id
13
+ };
14
+ };
15
+ const getCollection = async ({ name, schema }) => {
16
+ const collection = await firestore.collection(name).get();
17
+ const documents = [];
18
+ collection.forEach(document => {
19
+ const documentData = {};
20
+ Object.keys(schema.properties).forEach(key => {
21
+ documentData[key] = document.get(key);
22
+ });
23
+ documents.push(document.data());
24
+ });
25
+ return documents;
26
+ };
27
+ const getDocument = async ({ collection, id }) => {
28
+ const document = await firestore.collection(collection.name).doc(id).get();
29
+ return document.data();
30
+ };
31
+ const updateDocument = async (reference, document) => {
32
+ await firestore.collection(reference.collection.name).doc(reference.id).update(document);
33
+ return reference;
34
+ };
35
+ const deleteDocument = async (reference) => {
36
+ await firestore.collection(reference.collection.name).doc(reference.id).delete();
37
+ };
38
+ export { createDocument, getDocument, getCollection, updateDocument, deleteDocument };
@@ -0,0 +1,7 @@
1
+ import type { storage as storageT } from '@genoacms/cloudabstraction';
2
+ declare const getObject: storageT.getObject;
3
+ declare const uploadObject: storageT.uploadObject;
4
+ declare const deleteObject: storageT.deleteObject;
5
+ declare const listDirectory: storageT.listDirectory;
6
+ declare const createDirectory: storageT.createDirectory;
7
+ export { getObject, uploadObject, deleteObject, listDirectory, createDirectory };
@@ -0,0 +1,49 @@
1
+ import { Storage } from '@google-cloud/storage';
2
+ import config from '../../config.js';
3
+ const storage = new Storage({
4
+ credentials: config.storage.credentials
5
+ });
6
+ const getBucket = (name) => {
7
+ if (!config.storage.buckets.includes(name))
8
+ throw new Error('bucket-unregistered');
9
+ const bucket = storage.bucket(name);
10
+ return bucket;
11
+ };
12
+ const getObject = async ({ bucket, name }) => {
13
+ const bucketInstance = getBucket(bucket);
14
+ const file = bucketInstance.file(name);
15
+ return {
16
+ data: file.createReadStream()
17
+ };
18
+ };
19
+ const uploadObject = async ({ bucket, name }, stream) => {
20
+ const bucketInstance = getBucket(bucket);
21
+ const file = bucketInstance.file(name);
22
+ await file.save(stream);
23
+ };
24
+ const deleteObject = async ({ bucket, name }) => {
25
+ const bucketInstance = getBucket(bucket);
26
+ const file = bucketInstance.file(name);
27
+ await file.delete();
28
+ };
29
+ const listDirectory = async ({ bucket, name }, listingParams = {}) => {
30
+ const bucketInstance = getBucket(bucket);
31
+ const [files] = await bucketInstance.getFiles({
32
+ prefix: name,
33
+ maxResults: listingParams?.limit,
34
+ startOffset: listingParams?.startAfter
35
+ });
36
+ return files.map((file) => {
37
+ return {
38
+ name: file.name,
39
+ size: file.metadata.size,
40
+ lastModified: new Date(file.metadata.updated)
41
+ };
42
+ });
43
+ };
44
+ const createDirectory = async ({ bucket, name }) => {
45
+ const bucketInstance = getBucket(bucket);
46
+ const file = bucketInstance.file(`${name}/.folderPlaceholder`);
47
+ await file.save('');
48
+ };
49
+ export { getObject, uploadObject, deleteObject, listDirectory, createDirectory };
package/package.json CHANGED
@@ -1,8 +1,7 @@
1
1
  {
2
2
  "name": "@genoacms/adapter-gcp",
3
- "version": "0.1.1",
3
+ "version": "0.3.0",
4
4
  "description": "Implementation of abstraction layer of GenoaCMS for GCP",
5
- "main": "index.js",
6
5
  "repository": {
7
6
  "type": "git",
8
7
  "url": "git+https://github.com/GenoaCMS/adapter-gcp.git"
@@ -18,7 +17,7 @@
18
17
  "homepage": "https://github.com/GenoaCMS/adapter-gcp#readme",
19
18
  "type": "module",
20
19
  "dependencies": {
21
- "@genoacms/cloudabstraction": "^0.1.7",
20
+ "@genoacms/cloudabstraction": "^0.3.2",
22
21
  "@google-cloud/firestore": "^7.1.0",
23
22
  "@google-cloud/storage": "^7.4.0"
24
23
  },
@@ -30,7 +29,8 @@
30
29
  "eslint-plugin-n": "^16.2.0",
31
30
  "eslint-plugin-promise": "^6.1.1",
32
31
  "rimraf": "^5.0.5",
33
- "typescript": "^5.2.2"
32
+ "typescript": "^5.2.2",
33
+ "vitest": "^1.0.4"
34
34
  },
35
35
  "files": [
36
36
  "src",
@@ -51,6 +51,9 @@
51
51
  }
52
52
  },
53
53
  "scripts": {
54
- "build": "rimraf dist && tsc"
54
+ "build": "rimraf dist && tsc",
55
+ "test:all": "npm run build && vitest --silent=false --config node_modules/@genoacms/cloudabstraction/test/vitest.config.js --run node_modules/@genoacms/cloudabstraction/test/all.test.js",
56
+ "test:database": "npm run build && vitest --silent=false --config node_modules/@genoacms/cloudabstraction/test/vitest.config.js --run node_modules/@genoacms/cloudabstraction/test/database.test.js",
57
+ "test:storage": "npm run build && vitest --silent=false --config node_modules/@genoacms/cloudabstraction/test/vitest.config.js --run node_modules/@genoacms/cloudabstraction/test/storage.test.js"
55
58
  }
56
59
  }
package/src/config.ts ADDED
@@ -0,0 +1,4 @@
1
+ import type Config from './genoa.config.js'
2
+ import { config } from '@genoacms/cloudabstraction'
3
+
4
+ export default config satisfies Config
@@ -0,0 +1,30 @@
1
+ import type Config from '@genoacms/cloudabstraction/src/genoa.config.js'
2
+
3
+ interface Credentials {
4
+ type: string
5
+ 'project_id': string
6
+ 'private_key_id': string
7
+ 'private_key': string
8
+ 'client_email': string
9
+ 'client_id': string
10
+ 'auth_uri': string
11
+ 'token_uri': string
12
+ 'auth_provider_x509_cert_url': string
13
+ 'client_x509_cert_url': string
14
+ 'universe_domain': string
15
+ }
16
+
17
+ interface DatabaseConfig {
18
+ credentials: Credentials
19
+ databaseId: string
20
+ region: string
21
+ }
22
+
23
+ interface StorageConfig {
24
+ credentials: Credentials
25
+ buckets: string[]
26
+ }
27
+
28
+ interface ConfigGCP extends Config<object, DatabaseConfig, StorageConfig> {}
29
+
30
+ export default Config
@@ -0,0 +1,53 @@
1
+ import { Firestore } from '@google-cloud/firestore'
2
+ import config from '../../config.js'
3
+ import type { database as databaseT } from '@genoacms/cloudabstraction'
4
+
5
+ const firestore = new Firestore({
6
+ credentials: config.database.credentials,
7
+ databaseId: config.database.databaseId,
8
+ projectId: config.database.projectId
9
+ })
10
+
11
+ const createDocument: databaseT.createDocument = async (reference, data) => {
12
+ const document = await firestore.collection(reference.name).add(data)
13
+ return {
14
+ collection: reference,
15
+ id: document.id
16
+ }
17
+ }
18
+
19
+ const getCollection: databaseT.getCollection = async ({ name, schema }) => {
20
+ const collection = await firestore.collection(name).get()
21
+ const documents: Array<databaseT.Document<typeof schema>> = []
22
+ collection.forEach(document => {
23
+ const documentData: databaseT.Document<typeof schema> = {}
24
+ Object.keys(schema.properties).forEach(key => {
25
+ documentData[key] = document.get(key)
26
+ })
27
+
28
+ documents.push(document.data())
29
+ })
30
+ return documents
31
+ }
32
+
33
+ const getDocument: databaseT.getDocument = async ({ collection, id }) => {
34
+ const document = await firestore.collection(collection.name).doc(id).get()
35
+ return document.data() as any
36
+ }
37
+
38
+ const updateDocument: databaseT.updateDocument = async (reference, document) => {
39
+ await firestore.collection(reference.collection.name).doc(reference.id).update(document)
40
+ return reference
41
+ }
42
+
43
+ const deleteDocument: databaseT.deleteDocument = async (reference) => {
44
+ await firestore.collection(reference.collection.name).doc(reference.id).delete()
45
+ }
46
+
47
+ export {
48
+ createDocument,
49
+ getDocument,
50
+ getCollection,
51
+ updateDocument,
52
+ deleteDocument
53
+ }
@@ -1,31 +1,66 @@
1
1
  import type {
2
2
  storage as storageT
3
3
  } from '@genoacms/cloudabstraction'
4
- import { Storage } from '@google-cloud/storage'
5
- import { config } from '@genoacms/cloudabstraction'
4
+ import { type Bucket, Storage } from '@google-cloud/storage'
5
+ import config from '../../config.js'
6
6
 
7
7
  const storage = new Storage({
8
- // @ts-expect-error: TODO: type this adapter
9
- credentials: config.adapter.gcp.credentials
8
+ credentials: config.storage.credentials
10
9
  })
11
- // @ts-expect-error: TODO: type this adapter
12
- const bucket = storage.bucket(config.adapter.gcp.storage.bucket)
13
10
 
14
- const listDirectory: storageT.listDirectory = async ({ limit, prefix }) => {
15
- const [files] = await bucket.getFiles({
16
- prefix,
17
- maxResults: limit
11
+ const getBucket = (name: string): Bucket => {
12
+ if (!config.storage.buckets.includes(name)) throw new Error('bucket-unregistered')
13
+ const bucket = storage.bucket(name)
14
+ return bucket
15
+ }
16
+
17
+ const getObject: storageT.getObject = async ({ bucket, name }) => {
18
+ const bucketInstance = getBucket(bucket)
19
+ const file = bucketInstance.file(name)
20
+
21
+ return {
22
+ data: file.createReadStream()
23
+ }
24
+ }
25
+
26
+ const uploadObject: storageT.uploadObject = async ({ bucket, name }, stream) => {
27
+ const bucketInstance = getBucket(bucket)
28
+ const file = bucketInstance.file(name)
29
+ await file.save(stream)
30
+ }
31
+
32
+ const deleteObject: storageT.deleteObject = async ({ bucket, name }) => {
33
+ const bucketInstance = getBucket(bucket)
34
+ const file = bucketInstance.file(name)
35
+ await file.delete()
36
+ }
37
+
38
+ const listDirectory: storageT.listDirectory = async ({ bucket, name }, listingParams = {}) => {
39
+ const bucketInstance = getBucket(bucket)
40
+ const [files] = await bucketInstance.getFiles({
41
+ prefix: name,
42
+ maxResults: listingParams?.limit,
43
+ startOffset: listingParams?.startAfter
18
44
  })
19
45
  return files.map((file) => {
20
46
  return {
21
47
  name: file.name,
22
- size: file.metadata.size,
23
- // @ts-expect-error: Handle this
24
- lastModified: new Date(file.metadata.updated)
25
- } as storageT.StorageObject
48
+ size: file.metadata.size as number,
49
+ lastModified: new Date(file.metadata.updated as string)
50
+ } satisfies storageT.StorageObject
26
51
  })
27
52
  }
28
53
 
54
+ const createDirectory: storageT.createDirectory = async ({ bucket, name }) => {
55
+ const bucketInstance = getBucket(bucket)
56
+ const file = bucketInstance.file(`${name}/.folderPlaceholder`)
57
+ await file.save('')
58
+ }
59
+
29
60
  export {
30
- listDirectory
61
+ getObject,
62
+ uploadObject,
63
+ deleteObject,
64
+ listDirectory,
65
+ createDirectory
31
66
  }
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1,3 +0,0 @@
1
- import type { storage as storageT } from '@genoacms/cloudabstraction';
2
- declare const listDirectory: storageT.listDirectory;
3
- export { listDirectory };
@@ -1,23 +0,0 @@
1
- import { Storage } from '@google-cloud/storage';
2
- import { config } from '@genoacms/cloudabstraction';
3
- const storage = new Storage({
4
- // @ts-expect-error: TODO: type this adapter
5
- credentials: config.adapter.gcp.credentials
6
- });
7
- // @ts-expect-error: TODO: type this adapter
8
- const bucket = storage.bucket(config.adapter.gcp.storage.bucket);
9
- const listDirectory = async ({ limit, prefix }) => {
10
- const [files] = await bucket.getFiles({
11
- prefix,
12
- maxResults: limit
13
- });
14
- return files.map((file) => {
15
- return {
16
- name: file.name,
17
- size: file.metadata.size,
18
- // @ts-expect-error: Handle this
19
- lastModified: new Date(file.metadata.updated)
20
- };
21
- });
22
- };
23
- export { listDirectory };
File without changes
File without changes