@postxl/generator 0.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.
Files changed (95) hide show
  1. package/README.md +3 -0
  2. package/dist/jest.config.d.ts +3 -0
  3. package/dist/src/generator.d.ts +12 -0
  4. package/dist/src/generator.js +164 -0
  5. package/dist/src/generators/enums/react.generator.d.ts +10 -0
  6. package/dist/src/generators/enums/react.generator.js +81 -0
  7. package/dist/src/generators/enums/types.generator.d.ts +10 -0
  8. package/dist/src/generators/enums/types.generator.js +18 -0
  9. package/dist/src/generators/indices/datamockmodule.generator.d.ts +9 -0
  10. package/dist/src/generators/indices/datamockmodule.generator.js +104 -0
  11. package/dist/src/generators/indices/datamodule.generator.d.ts +9 -0
  12. package/dist/src/generators/indices/datamodule.generator.js +128 -0
  13. package/dist/src/generators/indices/dataservice.generator.d.ts +9 -0
  14. package/dist/src/generators/indices/dataservice.generator.js +47 -0
  15. package/dist/src/generators/indices/repositories.generator.d.ts +9 -0
  16. package/dist/src/generators/indices/repositories.generator.js +17 -0
  17. package/dist/src/generators/indices/seed.generator.d.ts +9 -0
  18. package/dist/src/generators/indices/seed.generator.js +17 -0
  19. package/dist/src/generators/indices/stubs.generator.d.ts +9 -0
  20. package/dist/src/generators/indices/stubs.generator.js +17 -0
  21. package/dist/src/generators/indices/testdataservice.generator.d.ts +7 -0
  22. package/dist/src/generators/indices/testdataservice.generator.js +61 -0
  23. package/dist/src/generators/indices/types.generator.d.ts +10 -0
  24. package/dist/src/generators/indices/types.generator.js +21 -0
  25. package/dist/src/generators/models/react.generator/context.generator.d.ts +9 -0
  26. package/dist/src/generators/models/react.generator/context.generator.js +66 -0
  27. package/dist/src/generators/models/react.generator/index.d.ts +10 -0
  28. package/dist/src/generators/models/react.generator/index.js +32 -0
  29. package/dist/src/generators/models/react.generator/library.generator.d.ts +9 -0
  30. package/dist/src/generators/models/react.generator/library.generator.js +113 -0
  31. package/dist/src/generators/models/react.generator/lookup.generator.d.ts +9 -0
  32. package/dist/src/generators/models/react.generator/lookup.generator.js +97 -0
  33. package/dist/src/generators/models/react.generator/modals.generator.d.ts +23 -0
  34. package/dist/src/generators/models/react.generator/modals.generator.js +521 -0
  35. package/dist/src/generators/models/repository.generator.d.ts +9 -0
  36. package/dist/src/generators/models/repository.generator.js +282 -0
  37. package/dist/src/generators/models/route.generator.d.ts +16 -0
  38. package/dist/src/generators/models/route.generator.js +112 -0
  39. package/dist/src/generators/models/seed.generator.d.ts +20 -0
  40. package/dist/src/generators/models/seed.generator.js +185 -0
  41. package/dist/src/generators/models/stub.generator.d.ts +9 -0
  42. package/dist/src/generators/models/stub.generator.js +74 -0
  43. package/dist/src/generators/models/types.generator.d.ts +9 -0
  44. package/dist/src/generators/models/types.generator.js +116 -0
  45. package/dist/src/lib/attributes.d.ts +43 -0
  46. package/dist/src/lib/attributes.js +2 -0
  47. package/dist/src/lib/exports.d.ts +26 -0
  48. package/dist/src/lib/exports.js +38 -0
  49. package/dist/src/lib/imports.d.ts +35 -0
  50. package/dist/src/lib/imports.js +55 -0
  51. package/dist/src/lib/meta.d.ts +359 -0
  52. package/dist/src/lib/meta.js +195 -0
  53. package/dist/src/lib/schema/fields.d.ts +35 -0
  54. package/dist/src/lib/schema/fields.js +49 -0
  55. package/dist/src/lib/schema/schema.d.ts +275 -0
  56. package/dist/src/lib/schema/schema.js +2 -0
  57. package/dist/src/lib/schema/types.d.ts +72 -0
  58. package/dist/src/lib/schema/types.js +41 -0
  59. package/dist/src/lib/schema/zod.d.ts +8 -0
  60. package/dist/src/lib/schema/zod.js +44 -0
  61. package/dist/src/lib/serializer.d.ts +15 -0
  62. package/dist/src/lib/serializer.js +24 -0
  63. package/dist/src/lib/utils/error.d.ts +5 -0
  64. package/dist/src/lib/utils/error.js +13 -0
  65. package/dist/src/lib/utils/file.d.ts +10 -0
  66. package/dist/src/lib/utils/file.js +54 -0
  67. package/dist/src/lib/utils/logger.d.ts +11 -0
  68. package/dist/src/lib/utils/logger.js +2 -0
  69. package/dist/src/lib/utils/string.d.ts +29 -0
  70. package/dist/src/lib/utils/string.js +75 -0
  71. package/dist/src/lib/utils/types.d.ts +12 -0
  72. package/dist/src/lib/utils/types.js +2 -0
  73. package/dist/src/lib/vfs.d.ts +137 -0
  74. package/dist/src/lib/vfs.js +419 -0
  75. package/dist/src/prisma/attributes.d.ts +17 -0
  76. package/dist/src/prisma/attributes.js +80 -0
  77. package/dist/src/prisma/client-path.d.ts +7 -0
  78. package/dist/src/prisma/client-path.js +29 -0
  79. package/dist/src/prisma/parse.d.ts +12 -0
  80. package/dist/src/prisma/parse.js +276 -0
  81. package/dist/tests/attributes.test.d.ts +1 -0
  82. package/dist/tests/attributes.test.js +76 -0
  83. package/dist/tests/file.test.d.ts +1 -0
  84. package/dist/tests/file.test.js +26 -0
  85. package/dist/tests/utils/random.d.ts +3 -0
  86. package/dist/tests/utils/random.js +15 -0
  87. package/dist/tests/vfs.test.d.ts +1 -0
  88. package/dist/tests/vfs.test.js +74 -0
  89. package/dist/tsconfig.tsbuildinfo +1 -0
  90. package/jest.config.ts +18 -0
  91. package/package.json +42 -0
  92. package/tests/attributes.test.ts +91 -0
  93. package/tests/file.test.ts +32 -0
  94. package/tests/utils/random.ts +11 -0
  95. package/tests/vfs.test.ts +92 -0
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.conjugateNames = exports.commentLines = exports.pluralize = exports.toPascalCase = exports.toCamelCase = exports.uncapitalize = void 0;
4
+ /**
5
+ * Returns the same string with a lowercase first letter.
6
+ */
7
+ const uncapitalize = (str) => {
8
+ return str.charAt(0).toLowerCase() + str.slice(1);
9
+ };
10
+ exports.uncapitalize = uncapitalize;
11
+ /**
12
+ * Returns the camelCase version of the given string.
13
+ */
14
+ const toCamelCase = (str) => {
15
+ // If the string is already in camelCase format, return it unchanged
16
+ if (/^[a-z][a-zA-Z]*$/.test(str)) {
17
+ return str;
18
+ }
19
+ // Split the string into an array of words
20
+ const words = str.split(/[\s_-]+/);
21
+ // Convert the first word to lowercase and capitalize the rest
22
+ const camelCasedWords = words.map((word, index) => (index === 0 ? word.charAt(0).toLowerCase() : word.charAt(0).toUpperCase()) + word.slice(1));
23
+ // Join the words back together into a single string
24
+ const camelCasedStr = camelCasedWords.join('');
25
+ return camelCasedStr;
26
+ };
27
+ exports.toCamelCase = toCamelCase;
28
+ /**
29
+ * Returns the PascalCase version of the given string.
30
+ */
31
+ const toPascalCase = (str) => {
32
+ const s = (0, exports.toCamelCase)(str);
33
+ return s.charAt(0).toUpperCase() + s.slice(1);
34
+ };
35
+ exports.toPascalCase = toPascalCase;
36
+ /**
37
+ * Returns a pluralized version of the given string based on the count.
38
+ */
39
+ const pluralize = (s, count = 2) => {
40
+ if (count === 1)
41
+ return s;
42
+ if (s.endsWith('y') &&
43
+ !s.endsWith('ay') &&
44
+ !s.endsWith('ey') &&
45
+ !s.endsWith('iy') &&
46
+ !s.endsWith('oy') &&
47
+ !s.endsWith('uy')) {
48
+ return s.slice(0, -1) + 'ies';
49
+ }
50
+ if (s.endsWith('s')) {
51
+ return s;
52
+ }
53
+ return s + 's';
54
+ };
55
+ exports.pluralize = pluralize;
56
+ /**
57
+ * Converts each line of a string to a commented line
58
+ */
59
+ const commentLines = (lines) => {
60
+ return lines
61
+ .split('\n')
62
+ .map((l) => `// ${l}`)
63
+ .join('\n');
64
+ };
65
+ exports.commentLines = commentLines;
66
+ /**
67
+ * Provide all relevant conjugation of a name
68
+ */
69
+ const conjugateNames = (name) => ({
70
+ PascalCase: (0, exports.toPascalCase)(name),
71
+ camelCase: (0, exports.toCamelCase)(name),
72
+ pluralized: (0, exports.pluralize)(name),
73
+ uncapitalizedPlural: (0, exports.uncapitalize)((0, exports.pluralize)(name)),
74
+ });
75
+ exports.conjugateNames = conjugateNames;
@@ -0,0 +1,12 @@
1
+ type Without<T, U> = {
2
+ [P in Exclude<keyof T, keyof U>]?: never;
3
+ };
4
+ export type XOR<T, U> = T | U extends object ? (Without<T, U> & U) | (Without<U, T> & T) : T | U;
5
+ export type Exact<T, I> = T extends I ? (Exclude<keyof T, keyof I> extends never ? T : never) : never;
6
+ export type UncapitalizeObjectKeys<T> = {
7
+ [key in keyof T as Uncapitalize<key & string>]: T[key];
8
+ };
9
+ export type Prettify<T> = {
10
+ [K in keyof T]: T[K];
11
+ };
12
+ export {};
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,137 @@
1
+ import * as prettier from 'prettier';
2
+ type FileWriteError = 'EIP' | 'EISDIR';
3
+ type FileReadError = 'ENF' | 'EISDIR';
4
+ type FileStatus = 'UNCHANGED' | 'WRITTEN' | 'SKIPPED';
5
+ /**
6
+ * A utility class that helps you manage a collection of files.
7
+ */
8
+ export declare class VirtualFS {
9
+ /**
10
+ * Human readable messages for file write errors.
11
+ */
12
+ static WRITE_ERROR_MESSAGES: {
13
+ [Key in FileWriteError]: string;
14
+ };
15
+ /**
16
+ * Human readable messages for file read errors.
17
+ */
18
+ static READ_ERROR_MESSAGES: {
19
+ [Key in FileReadError]: string;
20
+ };
21
+ private _files;
22
+ constructor(files?: {
23
+ [key: string]: string;
24
+ });
25
+ /**
26
+ * Returns the chunks of the resolved path.
27
+ */
28
+ private _parse;
29
+ /**
30
+ * Writes the given contents to the given path. Path should be a relative path from the root
31
+ * of the virtual file system with no special characters.
32
+ */
33
+ write(path: string, content: string): {
34
+ ok: true;
35
+ } | {
36
+ ok: false;
37
+ path: string;
38
+ err: FileWriteError;
39
+ };
40
+ /**
41
+ * Appends given content to the file at a given path if it exists.
42
+ */
43
+ append(path: string, content: string): {
44
+ ok: true;
45
+ } | {
46
+ ok: false;
47
+ path: string;
48
+ err: FileWriteError | FileReadError;
49
+ };
50
+ /**
51
+ * Copies given files to the given path.
52
+ */
53
+ copy(files: VirtualFS, path: string): void;
54
+ /**
55
+ * Lists all files and folders in the given path.
56
+ */
57
+ list(path: string): {
58
+ kind: 'FILE' | 'FOLDER';
59
+ name: string;
60
+ }[];
61
+ /**
62
+ * Returns a dictionary of all files in the virtual file system indexed by their paths.
63
+ */
64
+ files(): {
65
+ [path: string]: string;
66
+ };
67
+ /**
68
+ * Lets you read the contents of a file in the given path.
69
+ */
70
+ read(path: string): {
71
+ ok: true;
72
+ content: string;
73
+ } | {
74
+ ok: false;
75
+ path: string;
76
+ err: FileReadError;
77
+ };
78
+ /**
79
+ * Writes files to the given path, overriding managed files and ignoring
80
+ * detached files (i.e. files that don't have a checksum value).
81
+ *
82
+ * Returns a list of paths that were written.
83
+ */
84
+ flush(relativeOutPath: string, force?: boolean): Promise<{
85
+ status: FileStatus;
86
+ path: string;
87
+ }[]>;
88
+ /**
89
+ * Writes the contents of the file to a given path. If there's already a file there,
90
+ * it checks the checksum and overrides it if the content hasn't changed.
91
+ *
92
+ * Returns `true` if the file was written, `false` if it wasn't.
93
+ */
94
+ private _safeWriteUTF8File;
95
+ /**
96
+ * Tries to read a file at a given path and surpresses the error if it fails to do so.
97
+ */
98
+ private _safeReadUTF8File;
99
+ private static CHECKSUM_PREFIX;
100
+ private static META_PREFIX;
101
+ /**
102
+ * Returns the checksum of the given content, ignoring
103
+ * the line containing the checksum if present.
104
+ */
105
+ private _calculateContentChecksum;
106
+ /**
107
+ * Adds the checksum indicator to the given content.
108
+ */
109
+ private _appendChecksumToContent;
110
+ /**
111
+ * Adds arbitrary meta information to the given content.
112
+ *
113
+ * NOTE: This only changes when the content changes regardless of the change of the meta value.
114
+ */
115
+ private _appendMetaToContent;
116
+ /**
117
+ * Extracts the checksum from the given content.
118
+ */
119
+ private _extractChecksumFromContent;
120
+ /**
121
+ * Creates a new file system from the given directory.
122
+ */
123
+ static fromDirectory(cwd: string): Promise<VirtualFS>;
124
+ /**
125
+ * Walks the file tree, calling the given function for each file.
126
+ */
127
+ walk(fn: (path: string, content: string) => void): void;
128
+ /**
129
+ * Transforms files in the file system.
130
+ */
131
+ transform(fn: (path: string, content: string) => string): void;
132
+ /**
133
+ * Formats the file system using configuration in the given directory.
134
+ */
135
+ format(options?: prettier.Options | null): void;
136
+ }
137
+ export {};
@@ -0,0 +1,419 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
+ return new (P || (P = Promise))(function (resolve, reject) {
28
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
32
+ });
33
+ };
34
+ var __asyncValues = (this && this.__asyncValues) || function (o) {
35
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
36
+ var m = o[Symbol.asyncIterator], i;
37
+ return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
38
+ function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
39
+ function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
40
+ };
41
+ var __importDefault = (this && this.__importDefault) || function (mod) {
42
+ return (mod && mod.__esModule) ? mod : { "default": mod };
43
+ };
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ exports.VirtualFS = void 0;
46
+ const crypto = __importStar(require("crypto"));
47
+ const prettier = __importStar(require("prettier"));
48
+ const nodepath = __importStar(require("path"));
49
+ const nodefs = __importStar(require("fs"));
50
+ const util_1 = require("util");
51
+ const fast_glob_1 = __importDefault(require("fast-glob"));
52
+ const error_1 = require("./utils/error");
53
+ const mkdir = (0, util_1.promisify)(nodefs.mkdir);
54
+ const writefile = (0, util_1.promisify)(nodefs.writeFile);
55
+ const readfile = (0, util_1.promisify)(nodefs.readFile);
56
+ /**
57
+ * A utility class that helps you manage a collection of files.
58
+ */
59
+ class VirtualFS {
60
+ constructor(files) {
61
+ this._files = { kind: 'FOLDER', children: {} };
62
+ if (files) {
63
+ for (const path in files) {
64
+ this.write(path, files[path]);
65
+ }
66
+ }
67
+ }
68
+ /**
69
+ * Returns the chunks of the resolved path.
70
+ */
71
+ _parse(path) {
72
+ const parts = path.split('/');
73
+ if (parts.length === 0) {
74
+ return [];
75
+ }
76
+ // Remove the first empty string if the path starts with a slash.
77
+ if (parts[0] === '' || parts[0] === '.') {
78
+ parts.shift();
79
+ }
80
+ const resolved = [];
81
+ while (parts.length > 0) {
82
+ const part = parts.shift();
83
+ if (part === '..') {
84
+ resolved.pop();
85
+ continue;
86
+ }
87
+ if (part === '.') {
88
+ continue;
89
+ }
90
+ if (part === '' && parts.length > 0) {
91
+ console.warn(`Empty subpath in path: ${path}`);
92
+ continue;
93
+ }
94
+ resolved.push(part);
95
+ }
96
+ return resolved;
97
+ }
98
+ /**
99
+ * Writes the given contents to the given path. Path should be a relative path from the root
100
+ * of the virtual file system with no special characters.
101
+ */
102
+ write(path, content) {
103
+ const parts = this._parse(path);
104
+ let folder = parts.shift();
105
+ let cwd = this._files;
106
+ while (folder != null) {
107
+ // We reached a file along the while descending the system.
108
+ if (cwd.kind === 'FILE') {
109
+ return { ok: false, path, err: 'EISDIR' };
110
+ }
111
+ if (cwd.kind === 'FOLDER') {
112
+ // We found the folder where the file should be created.
113
+ if (parts.length === 0 && folder !== '') {
114
+ cwd.children[folder] = { kind: 'FILE', content };
115
+ return { ok: true };
116
+ }
117
+ // Folder doesn't exist yet.
118
+ if (cwd.children[folder] == null) {
119
+ cwd.children[folder] = { kind: 'FOLDER', children: {} };
120
+ }
121
+ cwd = cwd.children[folder];
122
+ folder = parts.shift();
123
+ continue;
124
+ }
125
+ return { ok: false, path, err: 'EIP' };
126
+ }
127
+ return { ok: false, path, err: 'EIP' };
128
+ }
129
+ /**
130
+ * Appends given content to the file at a given path if it exists.
131
+ */
132
+ append(path, content) {
133
+ const existing = this.read(path);
134
+ if (!existing.ok) {
135
+ return existing;
136
+ }
137
+ return this.write(path, existing.content + '\n' + content);
138
+ }
139
+ /**
140
+ * Copies given files to the given path.
141
+ */
142
+ copy(files, path) {
143
+ walk(files._files, path, (path, content) => this.write(path, content));
144
+ }
145
+ /**
146
+ * Lists all files and folders in the given path.
147
+ */
148
+ list(path) {
149
+ const parts = this._parse(path);
150
+ let folder = parts.shift();
151
+ let cwd = this._files;
152
+ // Descend the tree until we reach the folder we want to list.
153
+ while (folder != null) {
154
+ // It's possible that the path ends with a slash.
155
+ if (folder === '' && parts.length === 0) {
156
+ break;
157
+ }
158
+ if (cwd.kind === 'FOLDER' && cwd.children.hasOwnProperty(folder)) {
159
+ cwd = cwd.children[folder];
160
+ folder = parts.shift();
161
+ continue;
162
+ }
163
+ return [];
164
+ }
165
+ // List items.
166
+ const items = [];
167
+ if (cwd.kind === 'FOLDER') {
168
+ for (const [name, child] of Object.entries(cwd.children)) {
169
+ items.push({ kind: child.kind, name });
170
+ }
171
+ }
172
+ return items;
173
+ }
174
+ /**
175
+ * Returns a dictionary of all files in the virtual file system indexed by their paths.
176
+ */
177
+ files() {
178
+ const fs = {};
179
+ walk(this._files, '/', (path, content) => {
180
+ fs[path] = content;
181
+ });
182
+ return fs;
183
+ }
184
+ /**
185
+ * Lets you read the contents of a file in the given path.
186
+ */
187
+ read(path) {
188
+ const parts = this._parse(path);
189
+ let folder = parts.shift();
190
+ let cwd = this._files;
191
+ while (folder != null) {
192
+ if (cwd.kind === 'FOLDER' && cwd.children.hasOwnProperty(folder)) {
193
+ cwd = cwd.children[folder];
194
+ folder = parts.shift();
195
+ continue;
196
+ }
197
+ return { ok: false, path, err: 'ENF' };
198
+ }
199
+ if (cwd.kind === 'FILE' && parts.length === 0) {
200
+ return { ok: true, content: cwd.content };
201
+ }
202
+ return { ok: false, path, err: 'ENF' };
203
+ }
204
+ /**
205
+ * Writes files to the given path, overriding managed files and ignoring
206
+ * detached files (i.e. files that don't have a checksum value).
207
+ *
208
+ * Returns a list of paths that were written.
209
+ */
210
+ flush(relativeOutPath, force = false) {
211
+ return __awaiter(this, void 0, void 0, function* () {
212
+ const targetdir = nodepath.resolve(relativeOutPath);
213
+ const tasks = Object.entries(this.files()).map(([path, content]) => __awaiter(this, void 0, void 0, function* () {
214
+ const fullPath = nodepath.join(targetdir, path);
215
+ const status = yield this._safeWriteUTF8File({ target: fullPath, content, force });
216
+ return { path, status };
217
+ }));
218
+ const entries = yield Promise.all(tasks);
219
+ return entries;
220
+ });
221
+ }
222
+ /**
223
+ * Writes the contents of the file to a given path. If there's already a file there,
224
+ * it checks the checksum and overrides it if the content hasn't changed.
225
+ *
226
+ * Returns `true` if the file was written, `false` if it wasn't.
227
+ */
228
+ _safeWriteUTF8File({ target, content, force, }) {
229
+ return __awaiter(this, void 0, void 0, function* () {
230
+ const dir = nodepath.dirname(target);
231
+ yield mkdir(dir, { recursive: true });
232
+ const checksum = this._calculateContentChecksum(content);
233
+ let status = 'WRITTEN';
234
+ const currentFileContent = yield this._safeReadUTF8File(target);
235
+ if (currentFileContent != null) {
236
+ // NOTE: If the content of the file hasn't changed, then the calculated checksum
237
+ // should match the one that's currently in the file.
238
+ const currentChecksum = this._extractChecksumFromContent(currentFileContent);
239
+ const expectedChecksum = this._calculateContentChecksum(currentFileContent);
240
+ if (currentChecksum !== expectedChecksum) {
241
+ status = 'SKIPPED';
242
+ }
243
+ else if (currentChecksum === checksum) {
244
+ // NOTE: We only check the checksum. It's possible that the content of the file changed
245
+ // in a way that doesn't affect the checksum (e.g. empty lines and spaces).
246
+ status = 'UNCHANGED';
247
+ }
248
+ }
249
+ // We manually override the status if the `force` flag is set.
250
+ if (force) {
251
+ status = 'WRITTEN';
252
+ }
253
+ if (status === 'WRITTEN') {
254
+ const contentWithDate = this._appendMetaToContent(content, `date: ${new Date().toISOString()}`);
255
+ const contentWithChecksum = this._appendChecksumToContent(contentWithDate);
256
+ yield writefile(target, contentWithChecksum, { encoding: 'utf-8' });
257
+ }
258
+ return status;
259
+ });
260
+ }
261
+ /**
262
+ * Tries to read a file at a given path and surpresses the error if it fails to do so.
263
+ */
264
+ _safeReadUTF8File(target) {
265
+ return __awaiter(this, void 0, void 0, function* () {
266
+ try {
267
+ const content = yield readfile(target, { encoding: 'utf-8' });
268
+ return content;
269
+ }
270
+ catch (err) {
271
+ return null;
272
+ }
273
+ });
274
+ }
275
+ /**
276
+ * Returns the checksum of the given content, ignoring
277
+ * the line containing the checksum if present.
278
+ */
279
+ _calculateContentChecksum(content) {
280
+ const lines = content.split('\n');
281
+ // Take the content and return SHA checksum
282
+ const hash = crypto.createHash('sha256', {});
283
+ for (let i = 0; i < lines.length; i++) {
284
+ const line = lines[i].trim();
285
+ if (lines.length === 0 || line.startsWith(VirtualFS.CHECKSUM_PREFIX) || line.startsWith(VirtualFS.META_PREFIX)) {
286
+ continue;
287
+ }
288
+ hash.update(line);
289
+ }
290
+ return hash.digest('hex');
291
+ }
292
+ /**
293
+ * Adds the checksum indicator to the given content.
294
+ */
295
+ _appendChecksumToContent(content) {
296
+ const checksum = this._calculateContentChecksum(content);
297
+ return content + '\n' + VirtualFS.CHECKSUM_PREFIX + checksum;
298
+ }
299
+ /**
300
+ * Adds arbitrary meta information to the given content.
301
+ *
302
+ * NOTE: This only changes when the content changes regardless of the change of the meta value.
303
+ */
304
+ _appendMetaToContent(content, meta) {
305
+ return content + '\n' + VirtualFS.META_PREFIX + meta;
306
+ }
307
+ /**
308
+ * Extracts the checksum from the given content.
309
+ */
310
+ _extractChecksumFromContent(content) {
311
+ const lines = content.split('\n');
312
+ for (let i = 0; i < lines.length; i++) {
313
+ if (lines[i].includes(VirtualFS.CHECKSUM_PREFIX)) {
314
+ return lines[i].replace(VirtualFS.CHECKSUM_PREFIX, '');
315
+ }
316
+ }
317
+ return null;
318
+ }
319
+ /**
320
+ * Creates a new file system from the given directory.
321
+ */
322
+ static fromDirectory(cwd) {
323
+ var _a, e_1, _b, _c;
324
+ return __awaiter(this, void 0, void 0, function* () {
325
+ const fs = new VirtualFS();
326
+ const entries = fast_glob_1.default.stream('**/*', { cwd, dot: true, onlyFiles: true });
327
+ try {
328
+ for (var _d = true, entries_1 = __asyncValues(entries), entries_1_1; entries_1_1 = yield entries_1.next(), _a = entries_1_1.done, !_a;) {
329
+ _c = entries_1_1.value;
330
+ _d = false;
331
+ try {
332
+ const entry = _c;
333
+ const content = yield readfile(nodepath.join(cwd, entry.toString()), { encoding: 'utf-8' });
334
+ fs.write(entry.toString(), content);
335
+ }
336
+ finally {
337
+ _d = true;
338
+ }
339
+ }
340
+ }
341
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
342
+ finally {
343
+ try {
344
+ if (!_d && !_a && (_b = entries_1.return)) yield _b.call(entries_1);
345
+ }
346
+ finally { if (e_1) throw e_1.error; }
347
+ }
348
+ return fs;
349
+ });
350
+ }
351
+ /**
352
+ * Walks the file tree, calling the given function for each file.
353
+ */
354
+ walk(fn) {
355
+ walk(this._files, '/', fn);
356
+ }
357
+ /**
358
+ * Transforms files in the file system.
359
+ */
360
+ transform(fn) {
361
+ this.walk((path, content) => {
362
+ this.write(path, fn(path, content));
363
+ });
364
+ }
365
+ /**
366
+ * Formats the file system using configuration in the given directory.
367
+ */
368
+ format(options = null) {
369
+ this.transform((path, content) => {
370
+ const ext = nodepath.extname(path);
371
+ let parser = undefined;
372
+ if (ext === '.js' || ext === '.jsx') {
373
+ parser = 'babel';
374
+ }
375
+ if (ext === '.ts' || ext === '.tsx') {
376
+ parser = 'typescript';
377
+ }
378
+ try {
379
+ return prettier.format(content, Object.assign(Object.assign({}, options), { parser }));
380
+ }
381
+ catch (err) {
382
+ (0, error_1.throwError)(`
383
+ ${content}\n\n
384
+ Failed to format ${path}\n\n`);
385
+ }
386
+ });
387
+ }
388
+ }
389
+ /**
390
+ * Human readable messages for file write errors.
391
+ */
392
+ VirtualFS.WRITE_ERROR_MESSAGES = {
393
+ EIP: 'Invalid path',
394
+ EISDIR: 'Is a directory',
395
+ };
396
+ /**
397
+ * Human readable messages for file read errors.
398
+ */
399
+ VirtualFS.READ_ERROR_MESSAGES = {
400
+ ENF: 'No such file or directory',
401
+ EISDIR: 'Is a directory',
402
+ };
403
+ // We add a collection of random strings that will never appear in the code otherwise.
404
+ VirtualFS.CHECKSUM_PREFIX = `// PostXL checksum (#@!):`;
405
+ VirtualFS.META_PREFIX = `// PostXL meta (#@!) `;
406
+ exports.VirtualFS = VirtualFS;
407
+ // MARK: - Utilities
408
+ /**
409
+ * Walks the file tree, calling the given function for each file, prepending the starting path.
410
+ */
411
+ function walk(tree, path, fn) {
412
+ if (tree.kind === 'FILE') {
413
+ fn(path, tree.content);
414
+ return;
415
+ }
416
+ for (const [name, child] of Object.entries(tree.children)) {
417
+ walk(child, nodepath.join(path, name), fn);
418
+ }
419
+ }
@@ -0,0 +1,17 @@
1
+ import { DMMF } from '@prisma/generator-helper';
2
+ import type { Attributes, AttributeValue, FieldAttributes, ModelAttributes } from '../lib/attributes';
3
+ /**
4
+ * Parses attributes from a given string using provided prefix.
5
+ */
6
+ export declare function parseAttributesFromDocumentation({ documentation }: {
7
+ documentation?: string;
8
+ }): Attributes;
9
+ export declare function parseArgumentToStringOrStringArray(str: string): AttributeValue;
10
+ /**
11
+ * Returns attribute information for a given model.
12
+ */
13
+ export declare function getModelAttributes(model: DMMF.Model): ModelAttributes;
14
+ /**
15
+ * Returns all attributes assigned to a field
16
+ */
17
+ export declare function getFieldAttributes(field: DMMF.Field): FieldAttributes;