Skip to content

Commit fe76ae1

Browse files
add field transform (#83)
* add field transform * Update README.md Co-authored-by: Tony <tonyketcham@gmail.com> * comments * fix type name * comments * formatting * add prepare script * remove prepare script * undo toLowerCase Co-authored-by: Tony <tonyketcham@gmail.com>
1 parent 5aa1c07 commit fe76ae1

File tree

14 files changed

+270
-12
lines changed

14 files changed

+270
-12
lines changed

packages/core/src/errors.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { outdent } from './utils/outdent';
2+
3+
export class IllegalFieldNameError extends Error {
4+
constructor(illegalSequence: string) {
5+
super();
6+
this.message = outdent`
7+
The sequence "${illegalSequence}" is reserved and not allowed in field names
8+
Either:
9+
- remove all instances of "${illegalSequence}" in the names of fields in your content
10+
- add a fieldNameTransform function to your flatbread.config.js to translate to something else
11+
Example:
12+
{
13+
...,
14+
fieldNameTransform: (value) => value.replaceAll("${illegalSequence}",'-')
15+
}
16+
`;
17+
}
18+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { defaultsDeep, merge } from 'lodash-es';
2+
import { LoadedFlatbreadConfig } from '../types';
3+
import { getFieldOverrides } from '../utils/fieldOverrides';
4+
import transformKeys from '../utils/transformKeys';
5+
6+
interface GenerateCollectionArgs<T> {
7+
collection: string;
8+
nodes: T[];
9+
config: LoadedFlatbreadConfig;
10+
preknownSchemaFragments: Record<string, any[]>;
11+
}
12+
13+
export function generateCollection<T>({
14+
collection,
15+
preknownSchemaFragments,
16+
config,
17+
nodes,
18+
}: GenerateCollectionArgs<T>) {
19+
return transformKeys(
20+
defaultsDeep(
21+
{},
22+
getFieldOverrides(collection, config),
23+
...nodes.map((node) => merge({}, node, preknownSchemaFragments))
24+
),
25+
config.fieldNameTransform
26+
);
27+
}

packages/core/src/generators/schema.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
import { schemaComposer } from 'graphql-compose';
22
import { composeWithJson } from 'graphql-compose-json';
3-
import { cloneDeep, defaultsDeep, merge } from 'lodash-es';
3+
import { cloneDeep, merge } from 'lodash-es';
44
import plur from 'plur';
55
import { VFile } from 'vfile';
6+
import { cacheSchema, checkCacheForSchema } from '../cache/cache';
67
import {
78
generateArgsForAllItemQuery,
89
generateArgsForManyItemQuery,
910
generateArgsForSingleItemQuery,
1011
} from '../generators/arguments';
1112
import resolveQueryArgs from '../resolvers/arguments';
12-
import { cacheSchema, checkCacheForSchema } from '../cache/cache';
1313
import {
1414
ConfigResult,
1515
EntryNode,
1616
LoadedFlatbreadConfig,
1717
Transformer,
1818
} from '../types';
1919
import { map } from '../utils/map';
20-
import { getFieldOverrides } from '../utils/fieldOverrides';
20+
import { generateCollection } from './generateCollection';
2121

2222
interface RootQueries {
2323
maybeReturnsSingleItem: string[];
@@ -69,11 +69,12 @@ export async function generateSchema(
6969
collection,
7070
composeWithJson(
7171
collection,
72-
defaultsDeep(
73-
{},
74-
getFieldOverrides(collection, config),
75-
...nodes.map((node) => merge({}, node, preknownSchemaFragments))
76-
),
72+
generateCollection({
73+
collection,
74+
nodes,
75+
config,
76+
preknownSchemaFragments,
77+
}),
7778
{ schemaComposer }
7879
),
7980
])

packages/core/src/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,14 @@ export interface FlatbreadConfig {
2424
source: Source;
2525
transformer?: Transformer | Transformer[];
2626
content: Content;
27+
fieldNameTransform?: (field: string) => string;
2728
}
2829

2930
export interface LoadedFlatbreadConfig {
3031
source: Source;
3132
transformer: Transformer[];
3233
content: Content;
34+
fieldNameTransform: (field: string) => string;
3335
loaded: {
3436
extensions: string[];
3537
};
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/**
2+
* camelCase string
3+
* @param field: string
4+
* @returns camelCaseString
5+
*/
6+
export default function camelCase(field: string) {
7+
return String(field).replace(/\s(\w)/g, (_, m) => m.toUpperCase());
8+
}

packages/core/src/utils/initializeConfig.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { cloneDeep } from 'lodash-es';
22
import { FlatbreadConfig, LoadedFlatbreadConfig, Transformer } from '../types';
33
import { toArray } from './arrayUtils';
4+
import camelCase from './camelCase';
45

56
/**
67
* Processes a config object and returns a normalized version of it.
@@ -11,7 +12,8 @@ export function initializeConfig(
1112
const config = cloneDeep(rawConfig);
1213
const transformer = toArray(config.transformer ?? []);
1314

14-
const newConfig = {
15+
return {
16+
fieldNameTransform: camelCase,
1517
...config,
1618
transformer,
1719
loaded: {
@@ -20,6 +22,4 @@ export function initializeConfig(
2022
.flat(),
2123
},
2224
};
23-
24-
return newConfig;
2525
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export function isObject<K extends string | number | symbol, T>(
2+
value: unknown
3+
): value is Record<K, T> {
4+
return (
5+
!!value && typeof value === 'object' && value.constructor.name === 'Object'
6+
);
7+
}

packages/core/src/utils/outdent.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* when used as a template literal tag will remove the indentation that exists from the code block indentation
3+
*
4+
*/
5+
6+
export function outdent(
7+
strings: TemplateStringsArray,
8+
...values: string[]
9+
): string {
10+
const result = strings
11+
.map((s, i) => s + (values[i] ?? ''))
12+
.join('')
13+
.trim();
14+
const matches = Array.from(result.matchAll(/\n(\s+)/gs));
15+
const minimumIndent =
16+
matches.map((match) => match[1]).sort((a, b) => a.length - b.length)?.[0]
17+
?.length ?? 0;
18+
const replacer = new RegExp(`\\n\\s{${minimumIndent}}`, 'g');
19+
20+
return result.replace(replacer, '\n');
21+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import test from 'ava';
2+
import { outdent } from '../outdent';
3+
4+
test('basic outdent', (t) => {
5+
const result = outdent`This
6+
is
7+
a
8+
test you
9+
this should still be indented`;
10+
11+
t.is(
12+
result,
13+
`This
14+
is
15+
a
16+
test you
17+
this should still be indented`
18+
);
19+
});
20+
21+
test('it still interpolates data', (t) => {
22+
const p = 'animal';
23+
const result = outdent`This
24+
is
25+
a
26+
test you ${p}
27+
this should still be indented`;
28+
29+
t.is(
30+
result,
31+
`This
32+
is
33+
a
34+
test you animal
35+
this should still be indented`
36+
);
37+
});
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Snapshot report for `packages/core/src/utils/tests/transformKeys.test.ts`
2+
3+
The actual snapshot is saved in `transformKeys.test.ts.snap`.
4+
5+
Generated by [AVA](https://avajs.dev).
6+
7+
## it throws an error on illegal field names
8+
9+
> Snapshot 1
10+
11+
`The sequence "[]" is reserved and not allowed in field names␊
12+
Either:␊
13+
- remove all instances of "[]" in the names of fields in your content␊
14+
- add a fieldTransform function to your flatbread.config.js to translate to something else␊
15+
Example:␊
16+
{␊
17+
...,␊
18+
fieldTransform: (value) => value.replaceAll("[]",'-')␊
19+
}`

0 commit comments

Comments
 (0)