generated from 8iq/nodejs-hackathon-boilerplate-starter-kit
-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(keystone): DOMA-10804 LargeText field is added in keystone
- Loading branch information
1 parent
5c8090d
commit 23c285d
Showing
8 changed files
with
168 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
const { Text } = require('@keystonejs/fields') | ||
|
||
class LargeTextImplementation extends Text.implementation { | ||
constructor (path, { | ||
adapter, | ||
}) { | ||
super(...arguments) | ||
this.fileAdapter = adapter | ||
} | ||
} | ||
|
||
module.exports = { | ||
LargeTextImplementation, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
# LargeText | ||
|
||
The `LargeText` field simplifies the storage of large text data by abstracting the implementation of cloud storage usage. | ||
|
||
## Basic Usage | ||
|
||
Simply add the `LargeText` field type and a file adapter, and your text data will be stored in cloud storage. This helps avoid storing large datasets directly in the database. You can use it just like a common `Text` field in your code. | ||
|
||
```js | ||
const fileAdapter = new FileAdapter('LOG_FILE_NAME') | ||
|
||
keystone.createList('Log', { | ||
fields: { | ||
xmlLog: { | ||
type: 'LargeText', | ||
adapter: fileAdapter, | ||
}, | ||
}, | ||
}); | ||
``` | ||
|
||
# GraphQL | ||
|
||
The `LargeText` field behaves like a standard string (`Text` field). During create/update operations, the input value is saved to cloud storage, and only a reference to the saved file is stored in the database. For read operations, the saved file is downloaded from cloud storage, and its contents are provided as a string. | ||
|
||
# Storage | ||
|
||
The text value is stored as a file in the cloud, while the database only holds a reference (link) to the source file. | ||
|
||
# Configuration | ||
|
||
You will need to configure a file adapter to work with cloud storage. Example: | ||
|
||
```js | ||
const fileAdapter = new FileAdapter('LOG_FILE_NAME') | ||
``` | ||
|
||
or | ||
|
||
```js | ||
const fileAdapter = new FileAdapter('LOG_FILE_NAME', false, false, { bucket: 'BUCKET_FOR_LOGS'}) | ||
``` | ||
|
||
Ensure your cloud storage configuration is properly set up and accessible for file storage. | ||
|
||
# Notes | ||
|
||
- The `LargeText` field is ideal for storing large logs, parsed values, or other text data that may exceed the typical size limits of database fields. | ||
- The text is stored as a file in cloud storage, reducing the load on the database while still providing easy access to the data. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
const { Text } = require('@keystonejs/fields') | ||
const cuid = require('cuid') | ||
const isNil = require('lodash/isNil') | ||
|
||
const { bufferToStream, readFileFromStream, getObjectStream } = require('@open-condo/keystone/file') | ||
|
||
const CommonInterface = superclass => class extends superclass { | ||
|
||
constructor () { | ||
super(...arguments) | ||
if (!this.config.adapter) { | ||
throw new Error('LargeText field cannot be used without a file adapter') | ||
} | ||
this.fileAdapter = this.config.adapter | ||
} | ||
|
||
setupHooks ({ addPreSaveHook, addPostReadHook }) { | ||
|
||
addPreSaveHook(async item => { | ||
const fieldIsDefined = !isNil(item) && !isNil(item[this.path]) | ||
if (fieldIsDefined) { | ||
const stream = bufferToStream(item[this.path]) | ||
//TODO: need to think about name | ||
const originalFilename = `${new Date().toISOString()}` | ||
const mimetype = 'text/plain' | ||
const encoding = 'utf8' | ||
|
||
const { | ||
id, | ||
filename, | ||
_meta, | ||
} = await this.fileAdapter.save({ | ||
stream, | ||
filename: originalFilename, | ||
mimetype, | ||
encoding, | ||
id: cuid(), | ||
}) | ||
item[this.path] = JSON.stringify( | ||
{ | ||
id, | ||
filename, | ||
originalFilename, | ||
mimetype, | ||
encoding, | ||
_meta, | ||
} | ||
) | ||
} | ||
return item | ||
}) | ||
|
||
addPostReadHook(async item => { | ||
if (item[this.path]) { | ||
item[this.path] = (await readFileFromStream(await getObjectStream(item[this.path], this.fileAdapter))).toString() | ||
} | ||
|
||
return item | ||
}) | ||
} | ||
|
||
addToTableSchema (table) { | ||
const column = table.jsonb(this.path) | ||
column.isMultiline = true | ||
} | ||
} | ||
|
||
class LargeTextKnexFieldAdapter extends CommonInterface(Text.adapters.knex) {} | ||
class LargeTextMongooseFieldAdapter extends CommonInterface(Text.adapters.mongoose) {} | ||
class LargeTextPrismaFieldAdapter extends CommonInterface(Text.adapters.prisma) {} | ||
|
||
module.exports = { | ||
mongoose: LargeTextKnexFieldAdapter, | ||
knex: LargeTextMongooseFieldAdapter, | ||
prisma: LargeTextPrismaFieldAdapter, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
const { Text } = require('@keystonejs/fields') | ||
|
||
const LargeTextAdapters = require('./adapters') | ||
const { LargeTextImplementation } = require('./Implementation') | ||
|
||
module.exports = { | ||
type: 'LargeText', | ||
implementation: LargeTextImplementation, | ||
views: { | ||
...Text.views, | ||
Controller: require.resolve('./views/Controller'), | ||
}, | ||
adapters: LargeTextAdapters, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import FieldController from '@keystonejs/fields/Controller' | ||
|
||
export default class LargeTextController extends FieldController { | ||
getFilterTypes = () => [] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters