-
Notifications
You must be signed in to change notification settings - Fork 5
/
generate-collections.js
123 lines (88 loc) · 3.08 KB
/
generate-collections.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
const { readdir, writeFile } = require('fs/promises');
const { join } = require('path');
const COLLECTIONS_INPUT = join(__dirname, '/census-index/collections');
const COLLECTIONS_OUTPUT = join(__dirname, '/src/rest/collections');
void run();
async function run() {
const files = await readdir(COLLECTIONS_INPUT);
const collections = [];
await Promise.all(
files.map(async file => {
const { collection, conditions, format, resolve } = require(join(
COLLECTIONS_INPUT,
file,
));
const typeName = collection.replaceAll(/(?:^|_)([a-z0-9])/g, (_, s) =>
s.toUpperCase(),
);
const partialPaths = getPaths(format, (key, paths) => {
if (!paths) return [key];
return [key, ...paths.map(path => `${key}.${path}`)];
});
const paths = getPaths(format, (key, paths) => {
if (!paths) return [key];
return paths.map(path => `${key}.${path}`);
});
let collectionType = '';
// Start type
collectionType += `export type ${typeName} = {`;
// Collection name
collectionType += `collection: '${collection}',`;
// Format
collectionType += `format: ${buildFormat(format)},`;
// Paths
collectionType += `paths: ${paths.map(path => `'${path}'`).join(' | ')},`;
// Partial paths
collectionType += `partialPaths: ${partialPaths
.map(path => `'${path}'`)
.join(' | ')},`;
// Conditions
collectionType += `conditions: {${Object.entries(conditions)
.map(
([key, cond]) =>
`${formatKey(key)}: ${
Array.isArray(cond) ? cond.map(c => `'${c}'`).join(' | ') : cond
}`,
)
.join(',')}},`;
// Resolve
if (resolve)
collectionType += `resolve: ${Object.keys(resolve)
.map(key => `'${key}'`)
.join(' | ')},`;
// Close type
collectionType += `};\n`;
const path = join(COLLECTIONS_OUTPUT, `${typeName}.ts`);
await writeFile(path, collectionType);
collections.push(typeName);
console.log(`${file} => ${typeName}`);
}),
);
let index = '';
// Import all collections
index += collections
.map(typeName => `import {${typeName}} from './${typeName}';`)
.join('\n');
index += '\n\n';
// Create collections type
index += `export type Collections = ${collections.join(' | ')};`;
await writeFile(join(COLLECTIONS_OUTPUT, 'index.ts'), index);
}
function formatKey(key) {
if (key.endsWith('?')) return `'${key.slice(0, -1)}'?`;
return `'${key}'`;
}
function buildFormat(format) {
if (typeof format == 'string') return 'string';
if (Array.isArray(format)) return `${buildFormat(format[0])}[]`;
return `{${Object.entries(format)
.map(([k, v]) => `'${k}': ${buildFormat(v)}`)
.join(',')}}`;
}
function getPaths(something, reducer) {
if (typeof something == 'string') return null;
if (Array.isArray(something)) return getPaths(something[0], reducer);
return Object.entries(something)
.map(([key, something]) => reducer(key, getPaths(something, reducer)))
.flat();
}