@nixxie-cms/fields-encrypted 1.0.1

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/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Nixxie International DMCC
4
+ Portions Copyright (c) 2023 Thinkmill Labs Pty Ltd and contributors
5
+ (this software is derived from the KeystoneJS project, https://keystonejs.com)
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the "Software"), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in all
15
+ copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,19 @@
1
+ # @nixxie-cms/fields-encrypted
2
+
3
+ A field that is transparently encrypted at rest for Nixxie CMS. Values are encrypted with
4
+ AES-256-GCM before being written to the database and decrypted when read back through GraphQL — the
5
+ plaintext is never stored on disk.
6
+
7
+ ```ts
8
+ import { encrypted } from '@nixxie-cms/fields-encrypted'
9
+
10
+ fields: {
11
+ ssn: encrypted({ secret: process.env.FIELD_ENCRYPTION_KEY! }),
12
+ }
13
+ ```
14
+
15
+ - Keep `secret` out of source control (use an env var). Rotating it makes previously-stored values
16
+ undecryptable, so plan a re-encryption migration if you must rotate.
17
+ - The stored column holds ciphertext (`enc:v1:<iv>:<tag>:<data>`), so it is not searchable or
18
+ sortable on plaintext.
19
+ - `encrypt`, `decrypt` and `isEncrypted` helpers are also exported for migrations.
@@ -0,0 +1,7 @@
1
+ /** Encrypt a string with AES-256-GCM. Output: `enc:v1:<iv>:<tag>:<ciphertext>` (all base64). */
2
+ export declare function encrypt(plaintext: string, secret: string): string;
3
+ /** Whether a stored value looks like ciphertext produced by `encrypt`. */
4
+ export declare function isEncrypted(value: string): boolean;
5
+ /** Decrypt a value produced by `encrypt`. Returns the input unchanged if it isn't encrypted. */
6
+ export declare function decrypt(value: string, secret: string): string;
7
+ //# sourceMappingURL=crypto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"../../../src","sources":["crypto.ts"],"names":[],"mappings":"AASA,gGAAgG;AAChG,wBAAgB,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAOjE;AAED,0EAA0E;AAC1E,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAElD;AAED,gGAAgG;AAChG,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAS7D"}
@@ -0,0 +1,20 @@
1
+ import { type BaseListTypeInfo, type CommonFieldConfig, type FieldTypeFunc, type SimpleFieldTypeInfo } from '@nixxie-cms/core/types';
2
+ export type EncryptedFieldConfig<ListTypeInfo extends BaseListTypeInfo> = CommonFieldConfig<ListTypeInfo, SimpleFieldTypeInfo<'String'>> & {
3
+ /**
4
+ * Encryption secret. Data is encrypted at rest with AES-256-GCM using a key derived from this
5
+ * value. Store it outside source control (e.g. `process.env.FIELD_ENCRYPTION_KEY`). Rotating it
6
+ * makes previously-stored values undecryptable.
7
+ */
8
+ secret: string;
9
+ db?: {
10
+ isNullable?: boolean;
11
+ map?: string;
12
+ };
13
+ };
14
+ /**
15
+ * A field whose value is transparently encrypted (AES-256-GCM) before being written to the
16
+ * database and decrypted when read back through GraphQL. The plaintext never touches disk.
17
+ */
18
+ export declare function encrypted<ListTypeInfo extends BaseListTypeInfo>(config: EncryptedFieldConfig<ListTypeInfo>): FieldTypeFunc<ListTypeInfo>;
19
+ export { encrypt, decrypt, isEncrypted } from "./crypto.js";
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"../../../src","sources":["index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,mBAAmB,EAGzB,MAAM,wBAAwB,CAAA;AAG/B,MAAM,MAAM,oBAAoB,CAAC,YAAY,SAAS,gBAAgB,IAAI,iBAAiB,CACzF,YAAY,EACZ,mBAAmB,CAAC,QAAQ,CAAC,CAC9B,GAAG;IACF;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAA;IACd,EAAE,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,OAAO,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAC5C,CAAA;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,YAAY,SAAS,gBAAgB,EAC7D,MAAM,EAAE,oBAAoB,CAAC,YAAY,CAAC,GACzC,aAAa,CAAC,YAAY,CAAC,CAiD7B;AAED,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,oBAAgB"}
@@ -0,0 +1,5 @@
1
+ import type { FieldController, FieldControllerConfig, FieldProps } from '@nixxie-cms/core/types';
2
+ /** Item-page / create-modal input. The value shown is the decrypted plaintext. */
3
+ export declare function Field({ autoFocus, field, onChange, value }: FieldProps<typeof controller>): import("react/jsx-runtime").JSX.Element;
4
+ export declare function controller(config: FieldControllerConfig<Record<string, never>>): FieldController<string | null, string>;
5
+ //# sourceMappingURL=views.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"views.d.ts","sourceRoot":"../../../src","sources":["views.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,qBAAqB,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAEhG,kFAAkF;AAClF,wBAAgB,KAAK,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,2CAWzF;AAED,wBAAgB,UAAU,CACxB,MAAM,EAAE,qBAAqB,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,GACnD,eAAe,CAAC,MAAM,GAAG,IAAI,EAAE,MAAM,CAAC,CAaxC"}
@@ -0,0 +1,2 @@
1
+ export * from "./declarations/src/index.js";
2
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibml4eGllLWNtcy1maWVsZHMtZW5jcnlwdGVkLmNqcy5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi9kZWNsYXJhdGlvbnMvc3JjL2luZGV4LmQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEifQ==
@@ -0,0 +1,111 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var core = require('@nixxie-cms/core');
6
+ var types = require('@nixxie-cms/core/types');
7
+ var node_crypto = require('node:crypto');
8
+
9
+ const PREFIX = 'enc:v1:';
10
+ function deriveKey(secret) {
11
+ // Deterministic 32-byte key from the configured secret.
12
+ return node_crypto.scryptSync(secret, 'nixxie-encrypted-field', 32);
13
+ }
14
+
15
+ /** Encrypt a string with AES-256-GCM. Output: `enc:v1:<iv>:<tag>:<ciphertext>` (all base64). */
16
+ function encrypt(plaintext, secret) {
17
+ const key = deriveKey(secret);
18
+ const iv = node_crypto.randomBytes(12);
19
+ const cipher = node_crypto.createCipheriv('aes-256-gcm', key, iv);
20
+ const ciphertext = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);
21
+ const tag = cipher.getAuthTag();
22
+ return `${PREFIX}${iv.toString('base64')}:${tag.toString('base64')}:${ciphertext.toString('base64')}`;
23
+ }
24
+
25
+ /** Whether a stored value looks like ciphertext produced by `encrypt`. */
26
+ function isEncrypted(value) {
27
+ return value.startsWith(PREFIX);
28
+ }
29
+
30
+ /** Decrypt a value produced by `encrypt`. Returns the input unchanged if it isn't encrypted. */
31
+ function decrypt(value, secret) {
32
+ if (!isEncrypted(value)) return value;
33
+ const [,, ivB64, tagB64, dataB64] = value.split(':');
34
+ const key = deriveKey(secret);
35
+ const decipher = node_crypto.createDecipheriv('aes-256-gcm', key, Buffer.from(ivB64, 'base64'));
36
+ decipher.setAuthTag(Buffer.from(tagB64, 'base64'));
37
+ return Buffer.concat([decipher.update(Buffer.from(dataB64, 'base64')), decipher.final()]).toString('utf8');
38
+ }
39
+
40
+ /**
41
+ * A field whose value is transparently encrypted (AES-256-GCM) before being written to the
42
+ * database and decrypted when read back through GraphQL. The plaintext never touches disk.
43
+ */
44
+ function encrypted(config) {
45
+ if (!config.secret) {
46
+ throw new Error('@nixxie-cms/fields-encrypted: a `secret` is required');
47
+ }
48
+ const {
49
+ secret
50
+ } = config;
51
+ return () => {
52
+ var _config$db;
53
+ return types.fieldType({
54
+ kind: 'scalar',
55
+ mode: 'optional',
56
+ scalar: 'String',
57
+ map: (_config$db = config.db) === null || _config$db === void 0 ? void 0 : _config$db.map
58
+ })({
59
+ ...config,
60
+ input: {
61
+ create: {
62
+ arg: core.g.arg({
63
+ type: core.g.String
64
+ }),
65
+ resolve(val) {
66
+ if (val == null) return val;
67
+ return encrypt(val, secret);
68
+ }
69
+ },
70
+ update: {
71
+ arg: core.g.arg({
72
+ type: core.g.String
73
+ }),
74
+ resolve(val) {
75
+ if (val === undefined) return undefined;
76
+ if (val === null) return null;
77
+ return encrypt(val, secret);
78
+ }
79
+ },
80
+ orderBy: {
81
+ arg: core.g.arg({
82
+ type: types.orderDirectionEnum
83
+ })
84
+ }
85
+ },
86
+ output: core.g.field({
87
+ type: core.g.String,
88
+ resolve({
89
+ value
90
+ }) {
91
+ if (value == null) return value;
92
+ try {
93
+ return decrypt(value, secret);
94
+ } catch {
95
+ // Wrong key or corrupted data — return null rather than leaking ciphertext.
96
+ return null;
97
+ }
98
+ }
99
+ }),
100
+ views: '@nixxie-cms/fields-encrypted/views',
101
+ getAdminMeta() {
102
+ return {};
103
+ }
104
+ });
105
+ };
106
+ }
107
+
108
+ exports.decrypt = decrypt;
109
+ exports.encrypt = encrypt;
110
+ exports.encrypted = encrypted;
111
+ exports.isEncrypted = isEncrypted;
@@ -0,0 +1,104 @@
1
+ import { g } from '@nixxie-cms/core';
2
+ import { fieldType, orderDirectionEnum } from '@nixxie-cms/core/types';
3
+ import { randomBytes, createCipheriv, createDecipheriv, scryptSync } from 'node:crypto';
4
+
5
+ const PREFIX = 'enc:v1:';
6
+ function deriveKey(secret) {
7
+ // Deterministic 32-byte key from the configured secret.
8
+ return scryptSync(secret, 'nixxie-encrypted-field', 32);
9
+ }
10
+
11
+ /** Encrypt a string with AES-256-GCM. Output: `enc:v1:<iv>:<tag>:<ciphertext>` (all base64). */
12
+ function encrypt(plaintext, secret) {
13
+ const key = deriveKey(secret);
14
+ const iv = randomBytes(12);
15
+ const cipher = createCipheriv('aes-256-gcm', key, iv);
16
+ const ciphertext = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);
17
+ const tag = cipher.getAuthTag();
18
+ return `${PREFIX}${iv.toString('base64')}:${tag.toString('base64')}:${ciphertext.toString('base64')}`;
19
+ }
20
+
21
+ /** Whether a stored value looks like ciphertext produced by `encrypt`. */
22
+ function isEncrypted(value) {
23
+ return value.startsWith(PREFIX);
24
+ }
25
+
26
+ /** Decrypt a value produced by `encrypt`. Returns the input unchanged if it isn't encrypted. */
27
+ function decrypt(value, secret) {
28
+ if (!isEncrypted(value)) return value;
29
+ const [,, ivB64, tagB64, dataB64] = value.split(':');
30
+ const key = deriveKey(secret);
31
+ const decipher = createDecipheriv('aes-256-gcm', key, Buffer.from(ivB64, 'base64'));
32
+ decipher.setAuthTag(Buffer.from(tagB64, 'base64'));
33
+ return Buffer.concat([decipher.update(Buffer.from(dataB64, 'base64')), decipher.final()]).toString('utf8');
34
+ }
35
+
36
+ /**
37
+ * A field whose value is transparently encrypted (AES-256-GCM) before being written to the
38
+ * database and decrypted when read back through GraphQL. The plaintext never touches disk.
39
+ */
40
+ function encrypted(config) {
41
+ if (!config.secret) {
42
+ throw new Error('@nixxie-cms/fields-encrypted: a `secret` is required');
43
+ }
44
+ const {
45
+ secret
46
+ } = config;
47
+ return () => {
48
+ var _config$db;
49
+ return fieldType({
50
+ kind: 'scalar',
51
+ mode: 'optional',
52
+ scalar: 'String',
53
+ map: (_config$db = config.db) === null || _config$db === void 0 ? void 0 : _config$db.map
54
+ })({
55
+ ...config,
56
+ input: {
57
+ create: {
58
+ arg: g.arg({
59
+ type: g.String
60
+ }),
61
+ resolve(val) {
62
+ if (val == null) return val;
63
+ return encrypt(val, secret);
64
+ }
65
+ },
66
+ update: {
67
+ arg: g.arg({
68
+ type: g.String
69
+ }),
70
+ resolve(val) {
71
+ if (val === undefined) return undefined;
72
+ if (val === null) return null;
73
+ return encrypt(val, secret);
74
+ }
75
+ },
76
+ orderBy: {
77
+ arg: g.arg({
78
+ type: orderDirectionEnum
79
+ })
80
+ }
81
+ },
82
+ output: g.field({
83
+ type: g.String,
84
+ resolve({
85
+ value
86
+ }) {
87
+ if (value == null) return value;
88
+ try {
89
+ return decrypt(value, secret);
90
+ } catch {
91
+ // Wrong key or corrupted data — return null rather than leaking ciphertext.
92
+ return null;
93
+ }
94
+ }
95
+ }),
96
+ views: '@nixxie-cms/fields-encrypted/views',
97
+ getAdminMeta() {
98
+ return {};
99
+ }
100
+ });
101
+ };
102
+ }
103
+
104
+ export { decrypt, encrypt, encrypted, isEncrypted };
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@nixxie-cms/fields-encrypted",
3
+ "version": "1.0.1",
4
+ "license": "MIT",
5
+ "main": "dist/nixxie-cms-fields-encrypted.cjs.js",
6
+ "module": "dist/nixxie-cms-fields-encrypted.esm.js",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/nixxie-cms-fields-encrypted.cjs.js",
10
+ "module": "./dist/nixxie-cms-fields-encrypted.esm.js",
11
+ "default": "./dist/nixxie-cms-fields-encrypted.cjs.js"
12
+ },
13
+ "./views": {
14
+ "types": "./views/dist/nixxie-cms-fields-encrypted-views.cjs.js",
15
+ "module": "./views/dist/nixxie-cms-fields-encrypted-views.esm.js",
16
+ "default": "./views/dist/nixxie-cms-fields-encrypted-views.cjs.js"
17
+ },
18
+ "./package.json": "./package.json"
19
+ },
20
+ "dependencies": {
21
+ "@babel/runtime": "^7.24.7",
22
+ "@keystar/ui": "^0.7.21",
23
+ "graphql": "^16.8.1"
24
+ },
25
+ "devDependencies": {
26
+ "react": "^19.2.4",
27
+ "@nixxie-cms/core": "^1.0.1"
28
+ },
29
+ "peerDependencies": {
30
+ "@nixxie-cms/core": "^1.0.1",
31
+ "react": "^19.2.4"
32
+ },
33
+ "preconstruct": {
34
+ "entrypoints": [
35
+ "index.ts",
36
+ "views.tsx"
37
+ ]
38
+ },
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "https://github.com/nixxiecms/nixxie/tree/main/packages/fields-encrypted"
42
+ }
43
+ }
package/src/crypto.ts ADDED
@@ -0,0 +1,35 @@
1
+ import { createCipheriv, createDecipheriv, randomBytes, scryptSync } from 'node:crypto'
2
+
3
+ const PREFIX = 'enc:v1:'
4
+
5
+ function deriveKey(secret: string): Buffer {
6
+ // Deterministic 32-byte key from the configured secret.
7
+ return scryptSync(secret, 'nixxie-encrypted-field', 32)
8
+ }
9
+
10
+ /** Encrypt a string with AES-256-GCM. Output: `enc:v1:<iv>:<tag>:<ciphertext>` (all base64). */
11
+ export function encrypt(plaintext: string, secret: string): string {
12
+ const key = deriveKey(secret)
13
+ const iv = randomBytes(12)
14
+ const cipher = createCipheriv('aes-256-gcm', key, iv)
15
+ const ciphertext = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()])
16
+ const tag = cipher.getAuthTag()
17
+ return `${PREFIX}${iv.toString('base64')}:${tag.toString('base64')}:${ciphertext.toString('base64')}`
18
+ }
19
+
20
+ /** Whether a stored value looks like ciphertext produced by `encrypt`. */
21
+ export function isEncrypted(value: string): boolean {
22
+ return value.startsWith(PREFIX)
23
+ }
24
+
25
+ /** Decrypt a value produced by `encrypt`. Returns the input unchanged if it isn't encrypted. */
26
+ export function decrypt(value: string, secret: string): string {
27
+ if (!isEncrypted(value)) return value
28
+ const [, , ivB64, tagB64, dataB64] = value.split(':')
29
+ const key = deriveKey(secret)
30
+ const decipher = createDecipheriv('aes-256-gcm', key, Buffer.from(ivB64, 'base64'))
31
+ decipher.setAuthTag(Buffer.from(tagB64, 'base64'))
32
+ return Buffer.concat([decipher.update(Buffer.from(dataB64, 'base64')), decipher.final()]).toString(
33
+ 'utf8'
34
+ )
35
+ }
package/src/index.ts ADDED
@@ -0,0 +1,82 @@
1
+ import { g } from '@nixxie-cms/core'
2
+ import {
3
+ type BaseListTypeInfo,
4
+ type CommonFieldConfig,
5
+ type FieldTypeFunc,
6
+ type SimpleFieldTypeInfo,
7
+ fieldType,
8
+ orderDirectionEnum,
9
+ } from '@nixxie-cms/core/types'
10
+ import { decrypt, encrypt } from './crypto'
11
+
12
+ export type EncryptedFieldConfig<ListTypeInfo extends BaseListTypeInfo> = CommonFieldConfig<
13
+ ListTypeInfo,
14
+ SimpleFieldTypeInfo<'String'>
15
+ > & {
16
+ /**
17
+ * Encryption secret. Data is encrypted at rest with AES-256-GCM using a key derived from this
18
+ * value. Store it outside source control (e.g. `process.env.FIELD_ENCRYPTION_KEY`). Rotating it
19
+ * makes previously-stored values undecryptable.
20
+ */
21
+ secret: string
22
+ db?: { isNullable?: boolean; map?: string }
23
+ }
24
+
25
+ /**
26
+ * A field whose value is transparently encrypted (AES-256-GCM) before being written to the
27
+ * database and decrypted when read back through GraphQL. The plaintext never touches disk.
28
+ */
29
+ export function encrypted<ListTypeInfo extends BaseListTypeInfo>(
30
+ config: EncryptedFieldConfig<ListTypeInfo>
31
+ ): FieldTypeFunc<ListTypeInfo> {
32
+ if (!config.secret) {
33
+ throw new Error('@nixxie-cms/fields-encrypted: a `secret` is required')
34
+ }
35
+ const { secret } = config
36
+
37
+ return () =>
38
+ fieldType({
39
+ kind: 'scalar',
40
+ mode: 'optional',
41
+ scalar: 'String',
42
+ map: config.db?.map,
43
+ })({
44
+ ...config,
45
+ input: {
46
+ create: {
47
+ arg: g.arg({ type: g.String }),
48
+ resolve(val) {
49
+ if (val == null) return val
50
+ return encrypt(val, secret)
51
+ },
52
+ },
53
+ update: {
54
+ arg: g.arg({ type: g.String }),
55
+ resolve(val) {
56
+ if (val === undefined) return undefined
57
+ if (val === null) return null
58
+ return encrypt(val, secret)
59
+ },
60
+ },
61
+ orderBy: { arg: g.arg({ type: orderDirectionEnum }) },
62
+ },
63
+ output: g.field({
64
+ type: g.String,
65
+ resolve({ value }) {
66
+ if (value == null) return value
67
+ try {
68
+ return decrypt(value, secret)
69
+ } catch {
70
+ // Wrong key or corrupted data — return null rather than leaking ciphertext.
71
+ return null
72
+ }
73
+ },
74
+ }),
75
+ views: '@nixxie-cms/fields-encrypted/views',
76
+ getAdminMeta() {
77
+ return {}
78
+ },
79
+ })
80
+ }
81
+
82
+ export { encrypt, decrypt, isEncrypted } from './crypto'
package/src/views.tsx ADDED
@@ -0,0 +1,33 @@
1
+ import { TextField } from '@keystar/ui/text-field'
2
+ import type { FieldController, FieldControllerConfig, FieldProps } from '@nixxie-cms/core/types'
3
+
4
+ /** Item-page / create-modal input. The value shown is the decrypted plaintext. */
5
+ export function Field({ autoFocus, field, onChange, value }: FieldProps<typeof controller>) {
6
+ return (
7
+ <TextField
8
+ label={field.label}
9
+ description={field.description || undefined}
10
+ autoFocus={autoFocus}
11
+ isReadOnly={onChange === undefined}
12
+ value={value ?? ''}
13
+ onChange={onChange ? text => onChange(text === '' ? null : text) : undefined}
14
+ />
15
+ )
16
+ }
17
+
18
+ export function controller(
19
+ config: FieldControllerConfig<Record<string, never>>
20
+ ): FieldController<string | null, string> {
21
+ return {
22
+ fieldKey: config.fieldKey,
23
+ label: config.label,
24
+ description: config.description ?? '',
25
+ defaultValue: null,
26
+ deserialize: data => {
27
+ const value = data[config.fieldKey]
28
+ return typeof value === 'string' ? value : null
29
+ },
30
+ serialize: value => ({ [config.fieldKey]: value === '' ? null : value }),
31
+ graphqlSelection: config.fieldKey,
32
+ }
33
+ }
@@ -0,0 +1,2 @@
1
+ export * from "../../dist/declarations/src/views.js";
2
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibml4eGllLWNtcy1maWVsZHMtZW5jcnlwdGVkLXZpZXdzLmNqcy5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vZGlzdC9kZWNsYXJhdGlvbnMvc3JjL3ZpZXdzLmQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEifQ==
@@ -0,0 +1,43 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var textField = require('@keystar/ui/text-field');
6
+ var jsxRuntime = require('react/jsx-runtime');
7
+
8
+ /** Item-page / create-modal input. The value shown is the decrypted plaintext. */
9
+ function Field({
10
+ autoFocus,
11
+ field,
12
+ onChange,
13
+ value
14
+ }) {
15
+ return /*#__PURE__*/jsxRuntime.jsx(textField.TextField, {
16
+ label: field.label,
17
+ description: field.description || undefined,
18
+ autoFocus: autoFocus,
19
+ isReadOnly: onChange === undefined,
20
+ value: value !== null && value !== void 0 ? value : '',
21
+ onChange: onChange ? text => onChange(text === '' ? null : text) : undefined
22
+ });
23
+ }
24
+ function controller(config) {
25
+ var _config$description;
26
+ return {
27
+ fieldKey: config.fieldKey,
28
+ label: config.label,
29
+ description: (_config$description = config.description) !== null && _config$description !== void 0 ? _config$description : '',
30
+ defaultValue: null,
31
+ deserialize: data => {
32
+ const value = data[config.fieldKey];
33
+ return typeof value === 'string' ? value : null;
34
+ },
35
+ serialize: value => ({
36
+ [config.fieldKey]: value === '' ? null : value
37
+ }),
38
+ graphqlSelection: config.fieldKey
39
+ };
40
+ }
41
+
42
+ exports.Field = Field;
43
+ exports.controller = controller;
@@ -0,0 +1,38 @@
1
+ import { TextField } from '@keystar/ui/text-field';
2
+ import { jsx } from 'react/jsx-runtime';
3
+
4
+ /** Item-page / create-modal input. The value shown is the decrypted plaintext. */
5
+ function Field({
6
+ autoFocus,
7
+ field,
8
+ onChange,
9
+ value
10
+ }) {
11
+ return /*#__PURE__*/jsx(TextField, {
12
+ label: field.label,
13
+ description: field.description || undefined,
14
+ autoFocus: autoFocus,
15
+ isReadOnly: onChange === undefined,
16
+ value: value !== null && value !== void 0 ? value : '',
17
+ onChange: onChange ? text => onChange(text === '' ? null : text) : undefined
18
+ });
19
+ }
20
+ function controller(config) {
21
+ var _config$description;
22
+ return {
23
+ fieldKey: config.fieldKey,
24
+ label: config.label,
25
+ description: (_config$description = config.description) !== null && _config$description !== void 0 ? _config$description : '',
26
+ defaultValue: null,
27
+ deserialize: data => {
28
+ const value = data[config.fieldKey];
29
+ return typeof value === 'string' ? value : null;
30
+ },
31
+ serialize: value => ({
32
+ [config.fieldKey]: value === '' ? null : value
33
+ }),
34
+ graphqlSelection: config.fieldKey
35
+ };
36
+ }
37
+
38
+ export { Field, controller };
@@ -0,0 +1,4 @@
1
+ {
2
+ "main": "dist/nixxie-cms-fields-encrypted-views.cjs.js",
3
+ "module": "dist/nixxie-cms-fields-encrypted-views.esm.js"
4
+ }