@haustle/notion-orm 0.0.42 → 0.0.44

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.
@@ -1,421 +0,0 @@
1
- import {
2
- DatabaseObjectResponse,
3
- GetDatabaseResponse,
4
- } from "@notionhq/client/build/src/api-endpoints";
5
- import * as ts from "typescript";
6
- import fs from "fs";
7
- import path from "path";
8
- import { DATABASES_DIR } from "./index";
9
- import { NotionColumnTypes } from "queryTypes";
10
-
11
- type propNameToColumnNameType = Record<
12
- string,
13
- { columnName: string; type: NotionColumnTypes }
14
- >;
15
-
16
- /*
17
- Responsible for generating `.ts` files
18
- */
19
- export async function createTypescriptFileForDatabase(
20
- dbResponse: GetDatabaseResponse
21
- ) {
22
- const {
23
- id: databaseId,
24
- properties,
25
- title,
26
- } = dbResponse as DatabaseObjectResponse;
27
- const propNameToColumnName: propNameToColumnNameType = {};
28
- const databaseName = title[0].plain_text;
29
- const databaseClassName = camelize(databaseName).replace(/[^a-zA-Z0-9]/g, "");
30
-
31
- const databaseColumnTypeProps: ts.TypeElement[] = [];
32
-
33
- // Looping through each column of database
34
- Object.values(properties).forEach((value) => {
35
- const { type: columnType, name: columnName } = value;
36
-
37
- // Taking the column name and camelizing it for typescript use
38
- const camelizedColumnName = camelize(columnName);
39
-
40
- // Creating map of column name to the column's name in the database's typescript type
41
- propNameToColumnName[camelizedColumnName] = {
42
- columnName,
43
- type: columnType,
44
- };
45
-
46
- if (
47
- columnType === "title" ||
48
- columnType === "rich_text" ||
49
- columnType === "email" ||
50
- columnType === "phone_number"
51
- ) {
52
- // add text column to collection type
53
- databaseColumnTypeProps.push(
54
- createTextProperty({
55
- name: camelizedColumnName,
56
- isTitle: columnType === "title",
57
- })
58
- );
59
- } else if (columnType === "number") {
60
- // add number column to collection type
61
- databaseColumnTypeProps.push(createNumberProperty(camelizedColumnName));
62
- } else if (columnType === "url") {
63
- // add url column to collection type
64
- databaseColumnTypeProps.push(
65
- createTextProperty({ name: camelizedColumnName, isTitle: false })
66
- );
67
- } else if (columnType === "date") {
68
- // add Date column to collection type
69
- databaseColumnTypeProps.push(createDateProperty(camelizedColumnName));
70
- } else if (
71
- columnType === "select" ||
72
- columnType === "status" ||
73
- columnType === "multi_select"
74
- ) {
75
- // @ts-ignore
76
- const options = value[columnType].options.map((x) => x.name);
77
- databaseColumnTypeProps.push(
78
- createMultiOptionProp({
79
- name: camelizedColumnName,
80
- options,
81
- isArray: columnType === "multi_select", // Union or Union Array
82
- })
83
- );
84
- }
85
- });
86
-
87
- // Object type that represents the database schema
88
- const DatabaseSchemaType = ts.factory.createTypeAliasDeclaration(
89
- undefined,
90
- ts.factory.createIdentifier("DatabaseSchemaType"),
91
- undefined,
92
- ts.factory.createTypeLiteralNode(databaseColumnTypeProps)
93
- );
94
-
95
- // Top level non-nested variable, functions, types for database files
96
- const TsNodesForDatabaseFile = ts.factory.createNodeArray([
97
- createDatabaseActionsClassImport(),
98
- createDatabaseIdVariable(databaseId),
99
- DatabaseSchemaType,
100
- createColumnNameToColumnProperties(propNameToColumnName),
101
- createColumnNameToColumnType(),
102
- createDatabaseClassExport({ databaseName: databaseClassName }),
103
- ]);
104
-
105
- const sourceFile = ts.createSourceFile(
106
- "",
107
- "",
108
- ts.ScriptTarget.ESNext,
109
- true,
110
- ts.ScriptKind.TS
111
- );
112
- const printer = ts.createPrinter();
113
-
114
- const typescriptCodeToString = printer.printList(
115
- ts.ListFormat.MultiLine,
116
- TsNodesForDatabaseFile,
117
- sourceFile
118
- );
119
- const transpileToJavaScript = ts.transpile(typescriptCodeToString, {
120
- module: ts.ModuleKind.None,
121
- target: ts.ScriptTarget.ESNext,
122
- });
123
-
124
- // Create databases output folder
125
- if (!fs.existsSync(DATABASES_DIR)) {
126
- fs.mkdirSync(DATABASES_DIR);
127
- }
128
-
129
- // Create TypeScript and JavaScript files
130
- fs.writeFileSync(
131
- path.resolve(DATABASES_DIR, `${databaseClassName}.ts`),
132
- typescriptCodeToString
133
- );
134
- fs.writeFileSync(
135
- path.resolve(DATABASES_DIR, `${databaseClassName}.js`),
136
- transpileToJavaScript
137
- );
138
-
139
- return { databaseName, databaseClassName, databaseId };
140
- }
141
-
142
- // generate text property
143
- function createTextProperty(args: { name: string; isTitle: boolean }) {
144
- const { name, isTitle } = args;
145
- const text = ts.factory.createPropertySignature(
146
- undefined,
147
- ts.factory.createIdentifier(name),
148
- !isTitle ? ts.factory.createToken(ts.SyntaxKind.QuestionToken) : undefined,
149
- ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)
150
- );
151
- return text;
152
- }
153
-
154
- /**
155
- * Generate number property to go inside a type
156
- * name: number
157
- */
158
- function createNumberProperty(name: string) {
159
- const number = ts.factory.createPropertySignature(
160
- undefined,
161
- ts.factory.createIdentifier(name),
162
- ts.factory.createToken(ts.SyntaxKind.QuestionToken),
163
- ts.factory.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword)
164
- );
165
- return number;
166
- }
167
-
168
- /**
169
- * For selects and multi-select collection properties
170
- * array = true for multi-select
171
- */
172
- function createMultiOptionProp(args: {
173
- name: string;
174
- options: string[];
175
- isArray: boolean;
176
- }) {
177
- const { isArray, name, options } = args;
178
- return ts.factory.createPropertySignature(
179
- undefined,
180
- ts.factory.createIdentifier(name),
181
- ts.factory.createToken(ts.SyntaxKind.QuestionToken),
182
- isArray
183
- ? ts.factory.createArrayTypeNode(
184
- ts.factory.createParenthesizedType(
185
- ts.factory.createUnionTypeNode([
186
- ...options.map((option) =>
187
- ts.factory.createLiteralTypeNode(
188
- ts.factory.createStringLiteral(option)
189
- )
190
- ),
191
- createOtherStringProp(),
192
- ])
193
- )
194
- )
195
- : ts.factory.createUnionTypeNode([
196
- ...options.map((option) =>
197
- ts.factory.createLiteralTypeNode(
198
- ts.factory.createStringLiteral(option)
199
- )
200
- ),
201
- createOtherStringProp(),
202
- ])
203
- );
204
- }
205
-
206
- // string & {}. Allows users to pass in values
207
- function createOtherStringProp() {
208
- return ts.factory.createIntersectionTypeNode([
209
- ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
210
- ts.factory.createTypeLiteralNode([]),
211
- ]);
212
- }
213
-
214
- function createDateProperty(name: string) {
215
- return ts.factory.createPropertySignature(
216
- undefined,
217
- ts.factory.createIdentifier(name),
218
- ts.factory.createToken(ts.SyntaxKind.QuestionToken),
219
- ts.factory.createTypeLiteralNode([
220
- ts.factory.createPropertySignature(
221
- undefined,
222
- ts.factory.createIdentifier("start"),
223
- undefined,
224
- ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)
225
- ),
226
- ts.factory.createPropertySignature(
227
- undefined,
228
- ts.factory.createIdentifier("end"),
229
- ts.factory.createToken(ts.SyntaxKind.QuestionToken),
230
- ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)
231
- ),
232
- ])
233
- );
234
- }
235
-
236
- // Generate database Id variable
237
- // const databaseId = <database-id>
238
- function createDatabaseIdVariable(databaseId: string) {
239
- return ts.factory.createVariableStatement(
240
- undefined,
241
- ts.factory.createVariableDeclarationList(
242
- [
243
- ts.factory.createVariableDeclaration(
244
- ts.factory.createIdentifier("databaseId"),
245
- undefined,
246
- undefined,
247
- ts.factory.createStringLiteral(databaseId)
248
- ),
249
- ],
250
- ts.NodeFlags.Const
251
- )
252
- );
253
- }
254
-
255
- /**
256
- * Instead of refering to the column names 1:1 such as "Book Rating", we transform them to
257
- * camelcase (eg. bookRating). So we need to keep track of the original name and the type
258
- * for when we construct request for API
259
- *
260
- * Example
261
- *
262
- * const columnNameToColumnProperties = {
263
- *
264
- * "bookRating": {
265
- * columnName: "Book Rating",
266
- * type: "select"
267
- * },
268
- * "genre": {
269
- * columnName: "Genre",
270
- * type: "multi_select"
271
- * }
272
- *
273
- * }
274
- */
275
- function createColumnNameToColumnProperties(colMap: propNameToColumnNameType) {
276
- return ts.factory.createVariableDeclarationList(
277
- [
278
- ts.factory.createVariableDeclaration(
279
- ts.factory.createIdentifier("columnNameToColumnProperties"),
280
- undefined,
281
- undefined,
282
- ts.factory.createAsExpression(
283
- ts.factory.createObjectLiteralExpression(
284
- [
285
- ...Object.entries(colMap).map(([propName, value]) =>
286
- ts.factory.createPropertyAssignment(
287
- ts.factory.createStringLiteral(propName),
288
- ts.factory.createObjectLiteralExpression(
289
- [
290
- ts.factory.createPropertyAssignment(
291
- ts.factory.createIdentifier("columnName"),
292
- ts.factory.createStringLiteral(value.columnName)
293
- ),
294
- ts.factory.createPropertyAssignment(
295
- ts.factory.createIdentifier("type"),
296
- ts.factory.createStringLiteral(value.type)
297
- ),
298
- ],
299
- true
300
- )
301
- )
302
- ),
303
- ],
304
- true
305
- ),
306
- ts.factory.createTypeReferenceNode(
307
- ts.factory.createIdentifier("const"),
308
- undefined
309
- )
310
- )
311
- ),
312
- ],
313
- ts.NodeFlags.Const
314
- );
315
- }
316
-
317
- function createColumnNameToColumnType() {
318
- return ts.factory.createTypeAliasDeclaration(
319
- undefined,
320
- ts.factory.createIdentifier("ColumnNameToColumnType"),
321
- undefined,
322
- ts.factory.createMappedTypeNode(
323
- undefined,
324
- ts.factory.createTypeParameterDeclaration(
325
- undefined,
326
- ts.factory.createIdentifier("Property"),
327
- ts.factory.createTypeOperatorNode(
328
- ts.SyntaxKind.KeyOfKeyword,
329
- ts.factory.createTypeQueryNode(
330
- ts.factory.createIdentifier("columnNameToColumnProperties"),
331
- undefined
332
- )
333
- ),
334
- undefined
335
- ),
336
- undefined,
337
- undefined,
338
- ts.factory.createIndexedAccessTypeNode(
339
- ts.factory.createIndexedAccessTypeNode(
340
- ts.factory.createTypeQueryNode(
341
- ts.factory.createIdentifier("columnNameToColumnProperties"),
342
- undefined
343
- ),
344
- ts.factory.createTypeReferenceNode(
345
- ts.factory.createIdentifier("Property"),
346
- undefined
347
- )
348
- ),
349
- ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral("type"))
350
- ),
351
- undefined
352
- /* unknown */
353
- )
354
- );
355
- }
356
-
357
- // Need to import the database class used to execute database actions (adding + querying)
358
- function createDatabaseActionsClassImport() {
359
- return ts.factory.createImportDeclaration(
360
- undefined,
361
- ts.factory.createImportClause(
362
- false,
363
- undefined,
364
- ts.factory.createNamedImports([
365
- ts.factory.createImportSpecifier(
366
- false,
367
- undefined,
368
- ts.factory.createIdentifier("DatabaseActions")
369
- ),
370
- ])
371
- ),
372
- ts.factory.createStringLiteral("../src/DatabaseActions"),
373
- undefined
374
- );
375
- }
376
-
377
- /**
378
- * Create export statement for the database class
379
- * export const <databaseName> = new DatabaseActions<DatabaseSchemaType>(datbaseId, columnNameToColumnProperties)
380
- */
381
- function createDatabaseClassExport(args: { databaseName: string }) {
382
- const { databaseName } = args;
383
- return ts.factory.createVariableStatement(
384
- [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
385
- ts.factory.createVariableDeclarationList(
386
- [
387
- ts.factory.createVariableDeclaration(
388
- ts.factory.createIdentifier(databaseName),
389
- undefined,
390
- undefined,
391
- ts.factory.createNewExpression(
392
- ts.factory.createIdentifier("DatabaseActions"),
393
- [
394
- ts.factory.createTypeReferenceNode(
395
- ts.factory.createIdentifier("DatabaseSchemaType"),
396
- undefined
397
- ),
398
- ts.factory.createTypeReferenceNode(
399
- ts.factory.createIdentifier("ColumnNameToColumnType"),
400
- undefined
401
- ),
402
- ],
403
- [
404
- ts.factory.createIdentifier("databaseId"),
405
- ts.factory.createIdentifier("columnNameToColumnProperties"),
406
- ]
407
- )
408
- ),
409
- ],
410
- ts.NodeFlags.Const
411
- )
412
- );
413
- }
414
-
415
- // for a type's property name
416
- function camelize(str: string) {
417
- return str.replace(/(?:^\w|[A-Z]|\b\w|\s+)/g, function (match, index) {
418
- if (+match === 0) return ""; // or if (/\s+/.test(match)) for white spaces
419
- return index === 0 ? match.toLowerCase() : match.toUpperCase();
420
- });
421
- }
package/src/cli.ts DELETED
@@ -1,40 +0,0 @@
1
- #! /usr/bin/env node
2
-
3
- import fs from "fs";
4
- import { createDatabaseTypes } from "./index";
5
- import path from "path";
6
-
7
- async function main() {
8
- const args = process.argv.slice(2);
9
-
10
- if (args.length === 1 && args[0] === "generate") {
11
- const projDir = process.cwd();
12
-
13
- const notionConfigDirJS = fs.existsSync(
14
- path.join(projDir, "notion.config.js")
15
- );
16
- const notionConfigDirTS = fs.existsSync(
17
- path.join(projDir, "notion.config.ts")
18
- );
19
-
20
- console.log(path.join(projDir, "notion.config"));
21
- if (notionConfigDirJS || notionConfigDirTS) {
22
- const config = require(path.join(projDir, "notion.config"));
23
-
24
- const { databaseNames } = await createDatabaseTypes(config);
25
- if (databaseNames.length < 0) {
26
- console.log("generated no types");
27
- } else {
28
- console.log("Generated types for the following Database's: ");
29
- for (let x = 0; x < databaseNames.length; x++) {
30
- console.log(`${x}. ${databaseNames[x]}`);
31
- }
32
- }
33
- } else {
34
- console.error("Could not find file `notion.config.ts` in root");
35
- process.exit(1);
36
- }
37
- }
38
- }
39
-
40
- main();
package/src/index.ts DELETED
@@ -1,136 +0,0 @@
1
- /**
2
- * Responsible for consuming notion.config.js
3
- */
4
-
5
- import { Client } from "@notionhq/client";
6
- import { GetDatabaseResponse } from "@notionhq/client/build/src/api-endpoints";
7
- import { createTypescriptFileForDatabase } from "./GenerateTypes";
8
- import * as ts from "typescript";
9
- import fs from "fs";
10
- import path from "path";
11
-
12
- export const DATABASES_DIR = path.join(__dirname, "../../build", "databases");
13
-
14
- export type NotionConfigType = {
15
- auth: string;
16
- databaseIds: string[];
17
- };
18
-
19
- export const createDatabaseTypes = async (args: NotionConfigType) => {
20
- const { auth, databaseIds } = args;
21
-
22
- // Making sure the user is passing valid arguments
23
- if (!auth) {
24
- console.error("Please pass a valid Notion Integration Key");
25
- process.exit(1);
26
- }
27
-
28
- if (databaseIds.length < 0) {
29
- console.error("Please pass some database Ids");
30
- process.exit(1);
31
- }
32
-
33
- // Initialize client
34
- const NotionClient = new Client({
35
- auth: auth,
36
- });
37
-
38
- const databaseNames: string[] = [];
39
- const databaseClassExportStatements: ts.ExportDeclaration[] = [];
40
-
41
- // Remove the previous databases, so they can call get updated
42
- fs.rmdir(DATABASES_DIR, () =>
43
- console.log("Deleting current database types...")
44
- );
45
-
46
- for (const database_id of databaseIds) {
47
- let dbOjbect: GetDatabaseResponse;
48
-
49
- try {
50
- // Get the database schema
51
- dbOjbect = await NotionClient.databases.retrieve({
52
- database_id,
53
- });
54
-
55
- // Create typescript file based on schema
56
- const { databaseClassName, databaseId, databaseName } =
57
- await createTypescriptFileForDatabase(dbOjbect);
58
-
59
- databaseNames.push(databaseName);
60
- databaseClassExportStatements.push(
61
- databaseExportStatement({
62
- databaseClassName,
63
- })
64
- );
65
- } catch (e) {
66
- console.error(e);
67
- return { databaseNames: [] };
68
- }
69
- }
70
-
71
- // Create a file that exports all databases
72
- createDatabaseBarrelFile({
73
- databaseClassExportStatements,
74
- });
75
- return { databaseNames };
76
- };
77
-
78
- // Create the export statement for database file file
79
- // export { databaseName } from "./databaseName"
80
- function databaseExportStatement(args: { databaseClassName: string }) {
81
- const { databaseClassName } = args;
82
- return ts.factory.createExportDeclaration(
83
- undefined,
84
- false,
85
- ts.factory.createNamedExports([
86
- ts.factory.createExportSpecifier(
87
- false,
88
- undefined,
89
- ts.factory.createIdentifier(databaseClassName)
90
- ),
91
- ]),
92
- ts.factory.createStringLiteral(`./${databaseClassName}`),
93
- undefined
94
- );
95
- }
96
-
97
- // Creates file that import all generated notion database Ids
98
- function createDatabaseBarrelFile(args: {
99
- databaseClassExportStatements: ts.Node[];
100
- }) {
101
- const { databaseClassExportStatements } = args;
102
- const nodes = ts.factory.createNodeArray(databaseClassExportStatements);
103
- const sourceFile = ts.createSourceFile(
104
- "placeholder.ts",
105
- "",
106
- ts.ScriptTarget.ESNext,
107
- true,
108
- ts.ScriptKind.TS
109
- );
110
- const printer = ts.createPrinter();
111
-
112
- const typescriptCodeToString = printer.printList(
113
- ts.ListFormat.MultiLine,
114
- nodes,
115
- sourceFile
116
- );
117
-
118
- const transpileToJavaScript = ts.transpile(typescriptCodeToString, {
119
- module: ts.ModuleKind.None,
120
- target: ts.ScriptTarget.ES2015,
121
- });
122
-
123
- if (!fs.existsSync(DATABASES_DIR)) {
124
- fs.mkdirSync(DATABASES_DIR);
125
- }
126
-
127
- // Create TypeScript and JavaScript file
128
- fs.writeFileSync(
129
- path.resolve(DATABASES_DIR, "index.ts"),
130
- typescriptCodeToString
131
- );
132
- fs.writeFileSync(
133
- path.resolve(DATABASES_DIR, "index.js"),
134
- transpileToJavaScript
135
- );
136
- }