@postxl/generator 0.74.2 → 1.0.3

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 (189) hide show
  1. package/LICENSE +50 -0
  2. package/README.md +79 -1
  3. package/dist/generator-manager.class.d.ts +59 -0
  4. package/dist/generator-manager.class.js +221 -0
  5. package/dist/generator.class.d.ts +90 -0
  6. package/dist/generator.class.js +32 -0
  7. package/dist/generator.context.d.ts +174 -0
  8. package/dist/generator.context.js +125 -0
  9. package/dist/helpers/branded.types.d.ts +149 -0
  10. package/dist/helpers/branded.types.js +111 -0
  11. package/dist/helpers/config-builder.class.d.ts +27 -0
  12. package/dist/helpers/config-builder.class.js +54 -0
  13. package/dist/helpers/import-generator.class.d.ts +70 -0
  14. package/dist/helpers/import-generator.class.js +166 -0
  15. package/dist/helpers/importable.types.d.ts +52 -0
  16. package/dist/helpers/importable.types.js +15 -0
  17. package/dist/helpers/index-generator.class.d.ts +10 -0
  18. package/dist/helpers/index-generator.class.js +46 -0
  19. package/dist/helpers/index.d.ts +8 -0
  20. package/dist/helpers/index.js +24 -0
  21. package/dist/helpers/package-json.generator.d.ts +56 -0
  22. package/dist/helpers/package-json.generator.js +36 -0
  23. package/dist/helpers/tsconfig.generator.d.ts +1 -0
  24. package/dist/helpers/tsconfig.generator.js +14 -0
  25. package/dist/helpers/verify-context.d.ts +4 -0
  26. package/dist/helpers/verify-context.js +23 -0
  27. package/dist/index.d.ts +5 -0
  28. package/dist/index.js +21 -0
  29. package/dist/utils/checksum.d.ts +10 -0
  30. package/dist/utils/checksum.js +132 -0
  31. package/dist/utils/fs-utils.d.ts +34 -0
  32. package/dist/utils/fs-utils.js +126 -0
  33. package/dist/utils/index.d.ts +10 -0
  34. package/dist/utils/index.js +26 -0
  35. package/dist/utils/jsdoc.d.ts +12 -0
  36. package/dist/utils/jsdoc.js +37 -0
  37. package/dist/utils/lint.d.ts +46 -0
  38. package/dist/utils/lint.js +154 -0
  39. package/dist/utils/lockfile.d.ts +7 -0
  40. package/dist/utils/lockfile.js +80 -0
  41. package/dist/utils/logger.class.d.ts +25 -0
  42. package/dist/utils/logger.class.js +55 -0
  43. package/dist/utils/merge-conflict.d.ts +55 -0
  44. package/dist/utils/merge-conflict.js +264 -0
  45. package/dist/utils/path.d.ts +52 -0
  46. package/dist/utils/path.js +183 -0
  47. package/dist/utils/prettier-config.d.ts +2 -0
  48. package/dist/utils/prettier-config.js +13 -0
  49. package/dist/utils/prettier.d.ts +5 -0
  50. package/dist/utils/prettier.js +67 -0
  51. package/dist/utils/prettier.skiptest.d.ts +1 -0
  52. package/dist/utils/prettier.skiptest.js +22 -0
  53. package/dist/utils/promise.d.ts +2 -0
  54. package/dist/utils/promise.js +10 -0
  55. package/dist/utils/string-functions.d.ts +9 -0
  56. package/dist/utils/string-functions.js +23 -0
  57. package/dist/utils/sync-log-result.d.ts +9 -0
  58. package/dist/utils/sync-log-result.js +90 -0
  59. package/dist/utils/sync.d.ts +143 -0
  60. package/dist/utils/sync.js +325 -0
  61. package/dist/utils/template.d.ts +66 -0
  62. package/dist/utils/template.js +159 -0
  63. package/dist/utils/vfs.class.d.ts +115 -0
  64. package/dist/utils/vfs.class.js +239 -0
  65. package/dist/utils/zip.d.ts +13 -0
  66. package/dist/utils/zip.js +40 -0
  67. package/package.json +53 -31
  68. package/dist/generator.d.ts +0 -13
  69. package/dist/generator.js +0 -455
  70. package/dist/generators/enums/react.generator.d.ts +0 -10
  71. package/dist/generators/enums/react.generator.js +0 -110
  72. package/dist/generators/enums/types.generator.d.ts +0 -10
  73. package/dist/generators/enums/types.generator.js +0 -39
  74. package/dist/generators/indices/data/module.generator.d.ts +0 -9
  75. package/dist/generators/indices/data/module.generator.js +0 -60
  76. package/dist/generators/indices/data/service.generator.d.ts +0 -9
  77. package/dist/generators/indices/data/service.generator.js +0 -249
  78. package/dist/generators/indices/data/types.generator.d.ts +0 -9
  79. package/dist/generators/indices/data/types.generator.js +0 -49
  80. package/dist/generators/indices/dispatcher-service.generator.d.ts +0 -9
  81. package/dist/generators/indices/dispatcher-service.generator.js +0 -107
  82. package/dist/generators/indices/export/class.generator.d.ts +0 -9
  83. package/dist/generators/indices/export/class.generator.js +0 -140
  84. package/dist/generators/indices/export/encoder.generator.d.ts +0 -9
  85. package/dist/generators/indices/export/encoder.generator.js +0 -50
  86. package/dist/generators/indices/import/convert-functions.generator.d.ts +0 -9
  87. package/dist/generators/indices/import/convert-functions.generator.js +0 -509
  88. package/dist/generators/indices/import/decoder.generator.d.ts +0 -9
  89. package/dist/generators/indices/import/decoder.generator.js +0 -40
  90. package/dist/generators/indices/import/service.generator.d.ts +0 -9
  91. package/dist/generators/indices/import/service.generator.js +0 -573
  92. package/dist/generators/indices/import/types.generator.d.ts +0 -9
  93. package/dist/generators/indices/import/types.generator.js +0 -242
  94. package/dist/generators/indices/repositories.generator.d.ts +0 -9
  95. package/dist/generators/indices/repositories.generator.js +0 -25
  96. package/dist/generators/indices/routes.generator.d.ts +0 -9
  97. package/dist/generators/indices/routes.generator.js +0 -29
  98. package/dist/generators/indices/seed-migration.generator.d.ts +0 -9
  99. package/dist/generators/indices/seed-migration.generator.js +0 -36
  100. package/dist/generators/indices/seed-template.generator.d.ts +0 -9
  101. package/dist/generators/indices/seed-template.generator.js +0 -80
  102. package/dist/generators/indices/testids.generator.d.ts +0 -7
  103. package/dist/generators/indices/testids.generator.js +0 -71
  104. package/dist/generators/indices/types.generator.d.ts +0 -10
  105. package/dist/generators/indices/types.generator.js +0 -35
  106. package/dist/generators/indices/update/actiontypes.generator.d.ts +0 -9
  107. package/dist/generators/indices/update/actiontypes.generator.js +0 -49
  108. package/dist/generators/indices/update/module.generator.d.ts +0 -9
  109. package/dist/generators/indices/update/module.generator.js +0 -41
  110. package/dist/generators/indices/update/service.generator.d.ts +0 -9
  111. package/dist/generators/indices/update/service.generator.js +0 -34
  112. package/dist/generators/indices/view/module.generator.d.ts +0 -9
  113. package/dist/generators/indices/view/module.generator.js +0 -39
  114. package/dist/generators/indices/view/service.generator.d.ts +0 -9
  115. package/dist/generators/indices/view/service.generator.js +0 -34
  116. package/dist/generators/models/admin.page.generator.d.ts +0 -7
  117. package/dist/generators/models/admin.page.generator.js +0 -74
  118. package/dist/generators/models/export/encoder.generator.d.ts +0 -9
  119. package/dist/generators/models/export/encoder.generator.js +0 -51
  120. package/dist/generators/models/import/decoder.generator.d.ts +0 -9
  121. package/dist/generators/models/import/decoder.generator.js +0 -148
  122. package/dist/generators/models/react/context.generator.d.ts +0 -9
  123. package/dist/generators/models/react/context.generator.js +0 -71
  124. package/dist/generators/models/react/index.d.ts +0 -10
  125. package/dist/generators/models/react/index.js +0 -31
  126. package/dist/generators/models/react/library.generator.d.ts +0 -10
  127. package/dist/generators/models/react/library.generator.js +0 -94
  128. package/dist/generators/models/react/lookup.generator.d.ts +0 -9
  129. package/dist/generators/models/react/lookup.generator.js +0 -175
  130. package/dist/generators/models/react/modals.generator.d.ts +0 -23
  131. package/dist/generators/models/react/modals.generator.js +0 -710
  132. package/dist/generators/models/repository.generator.d.ts +0 -9
  133. package/dist/generators/models/repository.generator.js +0 -955
  134. package/dist/generators/models/route.generator.d.ts +0 -9
  135. package/dist/generators/models/route.generator.js +0 -92
  136. package/dist/generators/models/seed.generator.d.ts +0 -21
  137. package/dist/generators/models/seed.generator.js +0 -285
  138. package/dist/generators/models/stub.generator.d.ts +0 -9
  139. package/dist/generators/models/stub.generator.js +0 -92
  140. package/dist/generators/models/types.generator.d.ts +0 -9
  141. package/dist/generators/models/types.generator.js +0 -125
  142. package/dist/generators/models/update/service.generator.d.ts +0 -10
  143. package/dist/generators/models/update/service.generator.js +0 -302
  144. package/dist/generators/models/view/service.generator.d.ts +0 -10
  145. package/dist/generators/models/view/service.generator.js +0 -239
  146. package/dist/lib/attributes.d.ts +0 -114
  147. package/dist/lib/attributes.js +0 -2
  148. package/dist/lib/exports.d.ts +0 -45
  149. package/dist/lib/exports.js +0 -90
  150. package/dist/lib/imports.d.ts +0 -65
  151. package/dist/lib/imports.js +0 -114
  152. package/dist/lib/meta.d.ts +0 -1191
  153. package/dist/lib/meta.js +0 -434
  154. package/dist/lib/schema/fields.d.ts +0 -46
  155. package/dist/lib/schema/fields.js +0 -62
  156. package/dist/lib/schema/schema.d.ts +0 -466
  157. package/dist/lib/schema/schema.js +0 -18
  158. package/dist/lib/schema/types.d.ts +0 -201
  159. package/dist/lib/schema/types.js +0 -112
  160. package/dist/lib/serializer.d.ts +0 -15
  161. package/dist/lib/serializer.js +0 -24
  162. package/dist/lib/test-id-collector.d.ts +0 -42
  163. package/dist/lib/test-id-collector.js +0 -53
  164. package/dist/lib/types.d.ts +0 -7
  165. package/dist/lib/types.js +0 -13
  166. package/dist/lib/typescript.d.ts +0 -5
  167. package/dist/lib/typescript.js +0 -22
  168. package/dist/lib/utils/ast.d.ts +0 -29
  169. package/dist/lib/utils/ast.js +0 -23
  170. package/dist/lib/utils/error.d.ts +0 -17
  171. package/dist/lib/utils/error.js +0 -52
  172. package/dist/lib/utils/file.d.ts +0 -10
  173. package/dist/lib/utils/file.js +0 -56
  174. package/dist/lib/utils/jsdoc.d.ts +0 -9
  175. package/dist/lib/utils/jsdoc.js +0 -37
  176. package/dist/lib/utils/logger.d.ts +0 -17
  177. package/dist/lib/utils/logger.js +0 -12
  178. package/dist/lib/utils/string.d.ts +0 -40
  179. package/dist/lib/utils/string.js +0 -187
  180. package/dist/lib/utils/types.d.ts +0 -12
  181. package/dist/lib/utils/types.js +0 -2
  182. package/dist/lib/zod.d.ts +0 -8
  183. package/dist/lib/zod.js +0 -60
  184. package/dist/prisma/attributes.d.ts +0 -21
  185. package/dist/prisma/attributes.js +0 -175
  186. package/dist/prisma/client-path.d.ts +0 -7
  187. package/dist/prisma/client-path.js +0 -29
  188. package/dist/prisma/parse.d.ts +0 -12
  189. package/dist/prisma/parse.js +0 -452
@@ -0,0 +1,132 @@
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 () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.zChecksum = void 0;
40
+ exports.calculateChecksum = calculateChecksum;
41
+ const crypto = __importStar(require("node:crypto"));
42
+ const zod_1 = __importDefault(require("zod"));
43
+ const zip_1 = require("./zip");
44
+ exports.zChecksum = zod_1.default.string().brand('PXL.Checksum');
45
+ /**
46
+ * Converts a given scalar to a branded checksum type.
47
+ *
48
+ * IMPORTANT: This function does not calculate the checksum!
49
+ */
50
+ const toBrandedChecksum = (input) => exports.zChecksum.parse(input);
51
+ /**
52
+ * Returns the checksum of the given file
53
+ */
54
+ async function calculateChecksum(content) {
55
+ if (Buffer.isBuffer(content)) {
56
+ if (isBufferZip(content)) {
57
+ return await calculateZipFileChecksum(content);
58
+ }
59
+ return calculateBinaryContentChecksum(content);
60
+ }
61
+ return calculateUTF8ContentChecksum(content);
62
+ }
63
+ function calculateUTF8ContentChecksum(content) {
64
+ const normalized = content
65
+ .replace(/\r\n/g, '\n') // Normalize Windows line endings to Unix
66
+ .replace(/\n\r/g, '\n') // Normalize Mac line endings to Unix
67
+ .replace(/\r/g, '\n') // Normalize Mac line endings to Unix
68
+ .replace(/\uFEFF/g, ''); // Remove BOM
69
+ const hash = crypto.createHash('sha256', {});
70
+ hash.update(normalized);
71
+ return toBrandedChecksum(hash.digest('hex'));
72
+ }
73
+ function calculateBinaryContentChecksum(content) {
74
+ const hash = crypto.createHash('sha256', {});
75
+ hash.update(content);
76
+ return toBrandedChecksum(hash.digest('hex'));
77
+ }
78
+ /**
79
+ * Checks if a given buffer represents a zip file.
80
+ *
81
+ * Zip files start with a specific signature (magic numbers) -
82
+ * (0x50, 0x4b) followed by 0x03 0x04 or
83
+ * (0x50, 0x4b) followed by 0x05 0x06 (empty archive) or
84
+ * (0x50, 0x4b) followed by 0x07 0x08 (spanned archive).
85
+ *
86
+ * See https://en.wikipedia.org/wiki/Zip_(file_format)#File_headers
87
+ * More details: See https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT
88
+ * in section 4.3.7 (Local file header)
89
+ * By checking the beginning of the buffer against these signatures, we can infer whether it represents a zip file or not.
90
+ */
91
+ function isBufferZip(buffer) {
92
+ if (buffer.length < 4) {
93
+ return false;
94
+ }
95
+ const header = buffer.subarray(0, 4);
96
+ return (header[0] === 0x50 &&
97
+ header[1] === 0x4b &&
98
+ ((header[2] === 0x03 && header[3] === 0x04) ||
99
+ (header[2] === 0x05 && header[3] === 0x06) ||
100
+ (header[2] === 0x07 && header[3] === 0x08)));
101
+ }
102
+ /**
103
+ * Calculates the checksum of the given zip file, ignoring the metadata.
104
+ * This also ignores Excel specific files (core.xml) as they contain the creation date.
105
+ *
106
+ * Details:
107
+ * Zip files contain a central directory which contains a list of all files
108
+ * This includes metadata including the file creation time, which means that
109
+ * the checksum of a zip file can change even if the contents of the files
110
+ * inside the zip file have not changed.
111
+ * To avoid this, we calculate the checksum of the contents of the files inside
112
+ * the zip file, ignoring the metadata.
113
+ */
114
+ async function calculateZipFileChecksum(content) {
115
+ const hash = crypto.createHash('sha256', {});
116
+ const zip = await (0, zip_1.loadZip)(content);
117
+ const fileNames = Object.keys(zip.files);
118
+ for (const fileName of fileNames) {
119
+ // in case filename is core.xml, we skip it as it is a part of an Excel file
120
+ // and contains the creation date - which results in a different checksum
121
+ // even if the contents of the file have not changed
122
+ if (fileName.endsWith('core.xml')) {
123
+ continue;
124
+ }
125
+ const file = zip.file(fileName);
126
+ if (file) {
127
+ const fileContent = await file.async('nodebuffer');
128
+ hash.update(fileContent);
129
+ }
130
+ }
131
+ return toBrandedChecksum(hash.digest('hex'));
132
+ }
@@ -0,0 +1,34 @@
1
+ import { Result } from '@postxl/utils';
2
+ import * as Path from './path';
3
+ export type FileContent = string | Buffer;
4
+ export declare function isBuffer(x: FileContent): x is Buffer;
5
+ /**
6
+ * List of files that are read as text.
7
+ */
8
+ export declare const textExtensions: string[];
9
+ type ReadFileError = {
10
+ type: 'ReadFileError';
11
+ message: string;
12
+ error: Error;
13
+ };
14
+ /**
15
+ * Reads the content from the given path.
16
+ *
17
+ * If the file is text, it will be read as UTF-8 and converted to a string.
18
+ * Otherwise, it will be read as binary.
19
+ */
20
+ export declare function readFile(path: Path.PosixPath): Promise<Result<FileContent, ReadFileError>>;
21
+ export type WriteFileError = {
22
+ type: 'WriteFileError';
23
+ message: string;
24
+ error: Error;
25
+ };
26
+ export declare function writeFile(filePath: Path.PosixPath, content: FileContent): Promise<Result<void, WriteFileError>>;
27
+ export type FileErrorTypes = 'ReadFileError' | 'WriteFileError' | 'DeleteFileError';
28
+ export type DeleteFileError = {
29
+ type: 'DeleteFileError';
30
+ message: string;
31
+ error: Error;
32
+ };
33
+ export declare function deleteFile(filePath: Path.PosixPath): Promise<Result<void, DeleteFileError>>;
34
+ export {};
@@ -0,0 +1,126 @@
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 () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.textExtensions = void 0;
37
+ exports.isBuffer = isBuffer;
38
+ exports.readFile = readFile;
39
+ exports.writeFile = writeFile;
40
+ exports.deleteFile = deleteFile;
41
+ const fs = __importStar(require("fs/promises"));
42
+ const path_1 = require("path");
43
+ const isbinaryfile_1 = require("isbinaryfile");
44
+ const utils_1 = require("@postxl/utils");
45
+ function isBuffer(x) {
46
+ return Buffer.isBuffer(x);
47
+ }
48
+ /**
49
+ * List of files that are read as text.
50
+ */
51
+ exports.textExtensions = [
52
+ '.json',
53
+ '.js',
54
+ '.ts',
55
+ '.tsx',
56
+ '.jsx',
57
+ '.html',
58
+ '.css',
59
+ '.md',
60
+ '.txt',
61
+ '.prisma',
62
+ '.yaml',
63
+ '.yml',
64
+ '.graphql',
65
+ '.gql',
66
+ '.mdx',
67
+ '.toml',
68
+ '.xml',
69
+ '.svg',
70
+ '.nvmrc',
71
+ '.npmignore',
72
+ '.gitignore',
73
+ '.sql',
74
+ '.sh',
75
+ '.env',
76
+ '.env.example',
77
+ ];
78
+ async function isFileText(path) {
79
+ const isTextExtension = exports.textExtensions.some((x) => path.endsWith(x));
80
+ if (isTextExtension) {
81
+ return true;
82
+ }
83
+ try {
84
+ return !(await (0, isbinaryfile_1.isBinaryFile)(path, 256));
85
+ }
86
+ catch {
87
+ return false;
88
+ }
89
+ }
90
+ /**
91
+ * Reads the content from the given path.
92
+ *
93
+ * If the file is text, it will be read as UTF-8 and converted to a string.
94
+ * Otherwise, it will be read as binary.
95
+ */
96
+ async function readFile(path) {
97
+ return utils_1.Result.fromPromise(async () => {
98
+ if (await isFileText(path)) {
99
+ const content = await fs.readFile(path, { encoding: 'utf-8' });
100
+ return content.toString();
101
+ }
102
+ else {
103
+ return fs.readFile(path);
104
+ }
105
+ }, (error) => ({ type: 'ReadFileError', message: `Error reading "${path}"!`, error }));
106
+ }
107
+ async function writeFile(filePath, content) {
108
+ return utils_1.Result.fromPromise(async () => {
109
+ await fs.mkdir((0, path_1.dirname)(filePath), { recursive: true });
110
+ if (typeof content === 'string') {
111
+ await fs.writeFile(filePath, content);
112
+ }
113
+ else {
114
+ await fs.writeFile(filePath, new Uint8Array(content));
115
+ }
116
+ // Set executable permission for shell scripts
117
+ if (filePath.endsWith('.sh')) {
118
+ await fs.chmod(filePath, 0o755);
119
+ }
120
+ }, (error) => ({ type: 'WriteFileError', message: `Error writing "${filePath}"!`, error }));
121
+ }
122
+ async function deleteFile(filePath) {
123
+ return utils_1.Result.fromPromise(async () => {
124
+ return fs.unlink(filePath);
125
+ }, (error) => ({ type: 'DeleteFileError', message: `Error deleting "${filePath}"!`, error }));
126
+ }
@@ -0,0 +1,10 @@
1
+ export * from './jsdoc';
2
+ export * from './lint';
3
+ export * from './path';
4
+ export * from './promise';
5
+ export * from './prettier';
6
+ export * from './string-functions';
7
+ export * from './sync';
8
+ export * from './sync-log-result';
9
+ export * from './template';
10
+ export * from './vfs.class';
@@ -0,0 +1,26 @@
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./jsdoc"), exports);
18
+ __exportStar(require("./lint"), exports);
19
+ __exportStar(require("./path"), exports);
20
+ __exportStar(require("./promise"), exports);
21
+ __exportStar(require("./prettier"), exports);
22
+ __exportStar(require("./string-functions"), exports);
23
+ __exportStar(require("./sync"), exports);
24
+ __exportStar(require("./sync-log-result"), exports);
25
+ __exportStar(require("./template"), exports);
26
+ __exportStar(require("./vfs.class"), exports);
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Returns a string of JSDoc comments from an array of lines.
3
+ */
4
+ export declare function toJsDocComment(comments: string | string[] | undefined): string;
5
+ /**
6
+ * Adds a JSDoc comment to the beginning of a code string.
7
+ * If `comments` is blank, the code is returned as-is.
8
+ *
9
+ * This is a small convenience function that wraps `toJsDocComment` and
10
+ * handles the case where `comments` is blank.
11
+ */
12
+ export declare function addJsDocComment(code: string, comments: string | string[] | undefined): string;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toJsDocComment = toJsDocComment;
4
+ exports.addJsDocComment = addJsDocComment;
5
+ /**
6
+ * Returns a string of JSDoc comments from an array of lines.
7
+ */
8
+ function toJsDocComment(comments) {
9
+ if (!comments || comments.length === 0) {
10
+ return '';
11
+ }
12
+ if (typeof comments === 'string') {
13
+ comments = comments.split('\n');
14
+ }
15
+ if (comments.length === 1 && comments[0].trim() === '') {
16
+ return '';
17
+ }
18
+ return `/**
19
+ ${comments
20
+ //
21
+ .map((c) => ` * ${c.trim()}`.trimEnd())
22
+ .join('\n')}\n */`;
23
+ }
24
+ /**
25
+ * Adds a JSDoc comment to the beginning of a code string.
26
+ * If `comments` is blank, the code is returned as-is.
27
+ *
28
+ * This is a small convenience function that wraps `toJsDocComment` and
29
+ * handles the case where `comments` is blank.
30
+ */
31
+ function addJsDocComment(code, comments) {
32
+ const comment = toJsDocComment(comments);
33
+ if (comment === '') {
34
+ return code;
35
+ }
36
+ return `${comment}\n${code}`;
37
+ }
@@ -0,0 +1,46 @@
1
+ import { Linter } from 'eslint';
2
+ import { Logger } from './logger.class';
3
+ import { PosixPath } from './path';
4
+ import { VirtualFileSystem } from './vfs.class';
5
+ type FileLintResult = {
6
+ errorCount: number;
7
+ warningCount: number;
8
+ fixableCount: number;
9
+ messages: Linter.LintMessage[];
10
+ };
11
+ type LintResults = {
12
+ totalErrorCount: number;
13
+ totalWarningCount: number;
14
+ totalFixableCount: number;
15
+ fileResults: Map<PosixPath, FileLintResult>;
16
+ };
17
+ export type LintOptions = {
18
+ /**
19
+ * If true, the linter will skip attempt to fix the errors.
20
+ *
21
+ * Default: false
22
+ */
23
+ noFix: boolean;
24
+ /**
25
+ * If true, linting will be skipped
26
+ *
27
+ * Default: false
28
+ */
29
+ skipLint: boolean;
30
+ /**
31
+ * If true, the linter will not print any messages to the logger.
32
+ *
33
+ * Default: false
34
+ */
35
+ quiet: boolean;
36
+ /**
37
+ * If true, the linter will print verbose messages to the logger.
38
+ *
39
+ * Default: false
40
+ */
41
+ verbose: boolean;
42
+ logger?: Logger;
43
+ };
44
+ export declare function lint(vfs: VirtualFileSystem, options?: Partial<LintOptions>): Promise<LintResults>;
45
+ export declare function logLintResults(results: LintResults, options?: Partial<LintOptions>): void;
46
+ export {};
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.lint = lint;
4
+ exports.logLintResults = logLintResults;
5
+ const path_1 = require("path");
6
+ const process_1 = require("process");
7
+ const eslint_1 = require("eslint");
8
+ const utils_1 = require("@postxl/utils");
9
+ const fs_utils_1 = require("./fs-utils");
10
+ const logger_class_1 = require("./logger.class");
11
+ const defaultOptions = {
12
+ noFix: false,
13
+ skipLint: false,
14
+ quiet: false,
15
+ verbose: false,
16
+ logger: new logger_class_1.Logger(),
17
+ };
18
+ function ignoreMessage(message) {
19
+ // For performance reasons (and also to lower complexity), we do not use the TS Language Service.
20
+ // Therefore, some linting rules cannot be applied at generate time and only pop up after generation.
21
+ // When we purposefully add an eslint-disable directive, eslint normally removes it as it
22
+ // considers it unused. We however want to keep it - the below check ensures that it remains.
23
+ // Not the cleanest solution, but cannot think of a better one at the moment. ¯\_(ツ)_/¯
24
+ if (message.message.startsWith("Unused eslint-disable directive (no problems were reported from '@typescript-eslint/")) {
25
+ return true;
26
+ }
27
+ return false;
28
+ }
29
+ async function lint(vfs, options = {}) {
30
+ const opts = { ...defaultOptions, ...options };
31
+ const logger = opts.logger ?? new logger_class_1.Logger();
32
+ const results = {
33
+ totalErrorCount: 0,
34
+ totalWarningCount: 0,
35
+ totalFixableCount: 0,
36
+ fileResults: new Map(),
37
+ };
38
+ if (opts.skipLint) {
39
+ return results;
40
+ }
41
+ const linter = new eslint_1.ESLint({
42
+ cwd: (0, path_1.join)((0, process_1.cwd)(), '../..'),
43
+ fix: opts.noFix ? false : (m) => !ignoreMessage(m),
44
+ warnIgnored: false,
45
+ });
46
+ await vfs.transform(async ({ path, content }) => {
47
+ const { content: newContent, stats: result } = await lintFile({ path, content, linter, fix: !opts.noFix, logger });
48
+ results.fileResults.set(path, result);
49
+ results.totalErrorCount += result.errorCount;
50
+ results.totalWarningCount += result.warningCount;
51
+ results.totalFixableCount += result.fixableCount;
52
+ return newContent;
53
+ });
54
+ return results;
55
+ }
56
+ async function lintFile({ path, content, linter, logger, }) {
57
+ const stats = {
58
+ errorCount: 0,
59
+ warningCount: 0,
60
+ fixableCount: 0,
61
+ messages: [],
62
+ };
63
+ if ((0, fs_utils_1.isBuffer)(content)) {
64
+ return { content, stats };
65
+ }
66
+ const fileExtension = (0, path_1.extname)(path);
67
+ if (fileExtension !== '.js' && fileExtension !== '.jsx' && fileExtension !== '.ts' && fileExtension !== '.tsx') {
68
+ return { content, stats };
69
+ }
70
+ try {
71
+ const results = await linter.lintText(content, { filePath: (0, path_1.join)((0, process_1.cwd)(), 'vfs', path) });
72
+ return extractResult({ results, stats, content });
73
+ }
74
+ catch (err) {
75
+ logger.error(`${content}\n\nFailed to lint ${path}\n\n`);
76
+ throw err;
77
+ }
78
+ }
79
+ function extractResult({ results, stats, content, }) {
80
+ const [result] = results;
81
+ if (!result) {
82
+ return { content, stats };
83
+ }
84
+ for (const message of result.messages) {
85
+ if (ignoreMessage(message)) {
86
+ continue;
87
+ }
88
+ stats.messages.push(message);
89
+ if (message.fatal) {
90
+ stats.errorCount++;
91
+ }
92
+ else if (message.fix) {
93
+ stats.fixableCount++;
94
+ }
95
+ else if (message.severity === 2) {
96
+ stats.errorCount++;
97
+ }
98
+ else if (message.severity === 1) {
99
+ stats.warningCount++;
100
+ }
101
+ }
102
+ return { content: result.output ?? content, stats };
103
+ }
104
+ function logLintResults(results, options = {}) {
105
+ const logger = options.logger ?? new logger_class_1.Logger();
106
+ if (options.quiet) {
107
+ return;
108
+ }
109
+ if (results.totalErrorCount === 0 && results.totalWarningCount === 0 && results.totalFixableCount === 0) {
110
+ if (!options.verbose) {
111
+ return;
112
+ }
113
+ if (results.fileResults.size === 0) {
114
+ logger.log((0, utils_1.bold)((0, utils_1.green)('No files linted!')));
115
+ return;
116
+ }
117
+ const count = results.fileResults.size;
118
+ logger.log((0, utils_1.bold)((0, utils_1.green)(`Successfully linted ${count} ${(0, utils_1.pluralize)('file', count)}!`)));
119
+ return;
120
+ }
121
+ for (const [path, result] of results.fileResults) {
122
+ logLintFileResult({ result, path, logger });
123
+ }
124
+ }
125
+ function logLintFileResult({ result, path, logger }) {
126
+ if (result.errorCount === 0 && result.warningCount === 0 && result.fixableCount === 0) {
127
+ return;
128
+ }
129
+ let fileColor = utils_1.gray;
130
+ let fileSummary = '';
131
+ if (result.errorCount > 0) {
132
+ fileColor = utils_1.red;
133
+ fileSummary = (0, utils_1.red)(`${result.errorCount} errors`);
134
+ }
135
+ else if (result.warningCount > 0) {
136
+ fileColor = utils_1.yellow;
137
+ if (fileSummary.length > 0) {
138
+ fileSummary += ', ';
139
+ }
140
+ fileSummary += (0, utils_1.yellow)(`${result.warningCount} warnings`);
141
+ }
142
+ else if (result.fixableCount > 0) {
143
+ fileColor = utils_1.green;
144
+ if (fileSummary.length > 0) {
145
+ fileSummary += ', ';
146
+ }
147
+ fileSummary += (0, utils_1.green)(`${result.fixableCount} fixable`);
148
+ }
149
+ for (const message of result.messages) {
150
+ const position = message.line ? `${message.line}:${message.column} ` : '';
151
+ fileSummary += `\n ${position}${message.message}`;
152
+ }
153
+ logger.log(`${fileColor(path)}: ${fileSummary}`);
154
+ }
@@ -0,0 +1,7 @@
1
+ import { z } from 'zod';
2
+ import { VirtualFileSystem } from './vfs.class';
3
+ declare const zLockFile: z.ZodEffects<z.ZodRecord<z.ZodBranded<z.ZodString, "PXL.PosixPath">, z.ZodBranded<z.ZodString, "PXL.Checksum">>, Map<string & z.BRAND<"PXL.PosixPath">, string & z.BRAND<"PXL.Checksum">>, Record<string, string>>;
4
+ type LockFile = z.infer<typeof zLockFile>;
5
+ export declare function writeLockFile(lockFilePath: string, vfs: VirtualFileSystem): Promise<void>;
6
+ export declare function readLockFile(lockFilePath: string): Promise<LockFile | undefined>;
7
+ export {};
@@ -0,0 +1,80 @@
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 () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.writeLockFile = writeLockFile;
37
+ exports.readLockFile = readLockFile;
38
+ const fs = __importStar(require("fs/promises"));
39
+ const zod_1 = require("zod");
40
+ const checksum_1 = require("./checksum");
41
+ const path_1 = require("./path");
42
+ const zLockFile = zod_1.z
43
+ .record(path_1.zPosixPath, checksum_1.zChecksum)
44
+ .transform((val) => new Map(Object.entries(val).filter((entry) => entry[1] !== undefined)));
45
+ async function writeLockFile(lockFilePath, vfs) {
46
+ const newLockFileMap = await vfsToLockFile(vfs);
47
+ // If VFS has a file pattern filter, merge with existing lock file to preserve non-filtered entries
48
+ if (vfs.filePattern) {
49
+ const existingLockFile = await readLockFile(lockFilePath);
50
+ if (existingLockFile) {
51
+ // Keep all entries from existing lock file that don't match the current filter
52
+ for (const [filePath, checksum] of existingLockFile) {
53
+ if (!vfs.matchesPattern(filePath) && !newLockFileMap.has(filePath)) {
54
+ newLockFileMap.set(filePath, checksum);
55
+ }
56
+ }
57
+ }
58
+ }
59
+ const sortedEntries = Array.from(newLockFileMap.entries()).sort((a, b) => String(a[0]).localeCompare(String(b[0])));
60
+ await fs.writeFile(lockFilePath, JSON.stringify(Object.fromEntries(sortedEntries), null, 2));
61
+ }
62
+ async function vfsToLockFile(vfs) {
63
+ const lockFile = new Map();
64
+ for (const fileName of vfs.fileNames) {
65
+ const content = vfs.get(fileName);
66
+ if (content) {
67
+ lockFile.set(fileName, await (0, checksum_1.calculateChecksum)(content));
68
+ }
69
+ }
70
+ return lockFile;
71
+ }
72
+ async function readLockFile(lockFilePath) {
73
+ try {
74
+ const lockFile = zLockFile.parse(JSON.parse(await fs.readFile(lockFilePath, 'utf8')));
75
+ return lockFile;
76
+ }
77
+ catch {
78
+ return undefined;
79
+ }
80
+ }