@plasmicapp/cli 0.1.162

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 (162) hide show
  1. package/.eslintrc.js +61 -0
  2. package/.idea/cli.iml +11 -0
  3. package/.idea/misc.xml +6 -0
  4. package/.idea/modules.xml +8 -0
  5. package/.idea/vcs.xml +6 -0
  6. package/README +16 -0
  7. package/README.internal +46 -0
  8. package/README.md +17 -0
  9. package/build.sh +8 -0
  10. package/dist/__mocks__/api.d.ts +16 -0
  11. package/dist/__mocks__/api.js +297 -0
  12. package/dist/__tests__/code-utils-spec.d.ts +1 -0
  13. package/dist/__tests__/code-utils-spec.js +838 -0
  14. package/dist/__tests__/ftue-spec.d.ts +1 -0
  15. package/dist/__tests__/ftue-spec.js +39 -0
  16. package/dist/__tests__/project-api-token-spec.d.ts +1 -0
  17. package/dist/__tests__/project-api-token-spec.js +147 -0
  18. package/dist/__tests__/versioned-sync-spec.d.ts +1 -0
  19. package/dist/__tests__/versioned-sync-spec.js +145 -0
  20. package/dist/actions/auth.d.ts +8 -0
  21. package/dist/actions/auth.js +47 -0
  22. package/dist/actions/fix-imports.d.ts +4 -0
  23. package/dist/actions/fix-imports.js +25 -0
  24. package/dist/actions/init.d.ts +62 -0
  25. package/dist/actions/init.js +460 -0
  26. package/dist/actions/project-token.d.ts +6 -0
  27. package/dist/actions/project-token.js +42 -0
  28. package/dist/actions/sync-components.d.ts +10 -0
  29. package/dist/actions/sync-components.js +242 -0
  30. package/dist/actions/sync-global-variants.d.ts +3 -0
  31. package/dist/actions/sync-global-variants.js +89 -0
  32. package/dist/actions/sync-icons.d.ts +7 -0
  33. package/dist/actions/sync-icons.js +92 -0
  34. package/dist/actions/sync-images.d.ts +6 -0
  35. package/dist/actions/sync-images.js +137 -0
  36. package/dist/actions/sync-styles.d.ts +3 -0
  37. package/dist/actions/sync-styles.js +58 -0
  38. package/dist/actions/sync.d.ts +25 -0
  39. package/dist/actions/sync.js +417 -0
  40. package/dist/actions/upload-bundle.d.ts +15 -0
  41. package/dist/actions/upload-bundle.js +28 -0
  42. package/dist/actions/watch.d.ts +14 -0
  43. package/dist/actions/watch.js +90 -0
  44. package/dist/api.d.ts +182 -0
  45. package/dist/api.js +202 -0
  46. package/dist/deps.d.ts +2 -0
  47. package/dist/deps.js +20 -0
  48. package/dist/index.d.ts +7 -0
  49. package/dist/index.js +247 -0
  50. package/dist/lib.d.ts +10 -0
  51. package/dist/lib.js +23 -0
  52. package/dist/migrations/0.1.110-fileLocks.d.ts +2 -0
  53. package/dist/migrations/0.1.110-fileLocks.js +15 -0
  54. package/dist/migrations/0.1.143-ensureImportModuleType.d.ts +2 -0
  55. package/dist/migrations/0.1.143-ensureImportModuleType.js +12 -0
  56. package/dist/migrations/0.1.146-addReactRuntime.d.ts +2 -0
  57. package/dist/migrations/0.1.146-addReactRuntime.js +10 -0
  58. package/dist/migrations/0.1.27-migrateInit.d.ts +1 -0
  59. package/dist/migrations/0.1.27-migrateInit.js +8 -0
  60. package/dist/migrations/0.1.28-tsToTsx.d.ts +3 -0
  61. package/dist/migrations/0.1.28-tsToTsx.js +33 -0
  62. package/dist/migrations/0.1.31-ensureProjectIcons.d.ts +2 -0
  63. package/dist/migrations/0.1.31-ensureProjectIcons.js +12 -0
  64. package/dist/migrations/0.1.42-ensureVersion.d.ts +2 -0
  65. package/dist/migrations/0.1.42-ensureVersion.js +12 -0
  66. package/dist/migrations/0.1.57-ensureJsBundleThemes.d.ts +2 -0
  67. package/dist/migrations/0.1.57-ensureJsBundleThemes.js +12 -0
  68. package/dist/migrations/0.1.64-imageFiles.d.ts +2 -0
  69. package/dist/migrations/0.1.64-imageFiles.js +17 -0
  70. package/dist/migrations/0.1.95-componentType.d.ts +2 -0
  71. package/dist/migrations/0.1.95-componentType.js +16 -0
  72. package/dist/migrations/migrations.d.ts +10 -0
  73. package/dist/migrations/migrations.js +119 -0
  74. package/dist/plasmic.schema.json +463 -0
  75. package/dist/test-common/fixtures.d.ts +13 -0
  76. package/dist/test-common/fixtures.js +165 -0
  77. package/dist/tsconfig-transform.json +68 -0
  78. package/dist/utils/auth-utils.d.ts +31 -0
  79. package/dist/utils/auth-utils.js +236 -0
  80. package/dist/utils/checksum.d.ts +4 -0
  81. package/dist/utils/checksum.js +63 -0
  82. package/dist/utils/code-utils.d.ts +46 -0
  83. package/dist/utils/code-utils.js +457 -0
  84. package/dist/utils/config-utils.d.ts +271 -0
  85. package/dist/utils/config-utils.js +178 -0
  86. package/dist/utils/envdetect.d.ts +4 -0
  87. package/dist/utils/envdetect.js +42 -0
  88. package/dist/utils/error.d.ts +14 -0
  89. package/dist/utils/error.js +42 -0
  90. package/dist/utils/file-utils.d.ts +71 -0
  91. package/dist/utils/file-utils.js +433 -0
  92. package/dist/utils/get-context.d.ts +40 -0
  93. package/dist/utils/get-context.js +339 -0
  94. package/dist/utils/help.d.ts +2 -0
  95. package/dist/utils/help.js +56 -0
  96. package/dist/utils/lang-utils.d.ts +10 -0
  97. package/dist/utils/lang-utils.js +52 -0
  98. package/dist/utils/npm-utils.d.ts +28 -0
  99. package/dist/utils/npm-utils.js +215 -0
  100. package/dist/utils/prompts.d.ts +6 -0
  101. package/dist/utils/prompts.js +23 -0
  102. package/dist/utils/resolve-utils.d.ts +13 -0
  103. package/dist/utils/resolve-utils.js +198 -0
  104. package/dist/utils/semver.d.ts +34 -0
  105. package/dist/utils/semver.js +61 -0
  106. package/dist/utils/test-utils.d.ts +22 -0
  107. package/dist/utils/test-utils.js +106 -0
  108. package/dist/utils/user-utils.d.ts +7 -0
  109. package/dist/utils/user-utils.js +48 -0
  110. package/jest.config.js +6 -0
  111. package/package.json +80 -0
  112. package/src/__mocks__/api.ts +394 -0
  113. package/src/__tests__/code-utils-spec.ts +881 -0
  114. package/src/__tests__/ftue-spec.ts +43 -0
  115. package/src/__tests__/project-api-token-spec.ts +208 -0
  116. package/src/__tests__/versioned-sync-spec.ts +176 -0
  117. package/src/actions/auth.ts +43 -0
  118. package/src/actions/fix-imports.ts +13 -0
  119. package/src/actions/init.ts +638 -0
  120. package/src/actions/project-token.ts +36 -0
  121. package/src/actions/sync-components.ts +405 -0
  122. package/src/actions/sync-global-variants.ts +129 -0
  123. package/src/actions/sync-icons.ts +135 -0
  124. package/src/actions/sync-images.ts +191 -0
  125. package/src/actions/sync-styles.ts +71 -0
  126. package/src/actions/sync.ts +747 -0
  127. package/src/actions/upload-bundle.ts +38 -0
  128. package/src/actions/watch.ts +95 -0
  129. package/src/api.ts +407 -0
  130. package/src/deps.ts +18 -0
  131. package/src/index.ts +300 -0
  132. package/src/lib.ts +10 -0
  133. package/src/migrations/0.1.110-fileLocks.ts +16 -0
  134. package/src/migrations/0.1.146-addReactRuntime.ts +8 -0
  135. package/src/migrations/0.1.27-migrateInit.ts +4 -0
  136. package/src/migrations/0.1.28-tsToTsx.ts +37 -0
  137. package/src/migrations/0.1.31-ensureProjectIcons.ts +10 -0
  138. package/src/migrations/0.1.42-ensureVersion.ts +10 -0
  139. package/src/migrations/0.1.57-ensureJsBundleThemes.ts +10 -0
  140. package/src/migrations/0.1.64-imageFiles.ts +15 -0
  141. package/src/migrations/0.1.95-componentType.ts +14 -0
  142. package/src/migrations/migrations.ts +147 -0
  143. package/src/test-common/fixtures.ts +178 -0
  144. package/src/utils/auth-utils.ts +276 -0
  145. package/src/utils/checksum.ts +106 -0
  146. package/src/utils/code-utils.ts +656 -0
  147. package/src/utils/config-utils.ts +551 -0
  148. package/src/utils/envdetect.ts +39 -0
  149. package/src/utils/error.ts +36 -0
  150. package/src/utils/file-utils.ts +526 -0
  151. package/src/utils/get-context.ts +451 -0
  152. package/src/utils/help.ts +75 -0
  153. package/src/utils/lang-utils.ts +52 -0
  154. package/src/utils/npm-utils.ts +223 -0
  155. package/src/utils/prompts.ts +22 -0
  156. package/src/utils/resolve-utils.ts +245 -0
  157. package/src/utils/semver.ts +67 -0
  158. package/src/utils/test-utils.ts +116 -0
  159. package/src/utils/user-utils.ts +37 -0
  160. package/testData/fixImports_plasmic.json +66 -0
  161. package/tsconfig-transform.json +68 -0
  162. package/tsconfig.json +67 -0
@@ -0,0 +1,526 @@
1
+ import fs from "fs";
2
+ import glob from "glob";
3
+ import L from "lodash";
4
+ import path from "upath";
5
+ import { ProjectMetaBundle } from "../api";
6
+ import { logger } from "../deps";
7
+ import { HandledError } from "../utils/error";
8
+ import { isLocalModulePath } from "./code-utils";
9
+ import {
10
+ ComponentConfig,
11
+ CONFIG_FILE_NAME,
12
+ PlasmicContext,
13
+ ProjectConfig,
14
+ updateConfig,
15
+ } from "./config-utils";
16
+ import { ensureString } from "./lang-utils";
17
+ import { confirmWithUser } from "./user-utils";
18
+
19
+ export function stripExtension(filename: string, removeComposedPath = false) {
20
+ const ext = removeComposedPath
21
+ ? filename.substring(filename.indexOf("."))
22
+ : path.extname(filename);
23
+ if (!ext || filename === ext) {
24
+ return filename;
25
+ }
26
+ return filename.substring(0, filename.lastIndexOf(ext));
27
+ }
28
+
29
+ export async function writeFileContentRaw(
30
+ filePath: string,
31
+ content: string | Buffer,
32
+ opts?: { force?: boolean; yes?: boolean }
33
+ ) {
34
+ opts = opts || {};
35
+ if (existsBuffered(filePath) && !opts.force) {
36
+ const overwrite = await confirmWithUser(
37
+ `File ${filePath} already exists. Do you want to overwrite?`,
38
+ opts.yes
39
+ );
40
+ if (!overwrite) {
41
+ throw new HandledError(
42
+ `Cannot write to ${filePath}; file already exists.`
43
+ );
44
+ }
45
+ }
46
+
47
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
48
+
49
+ writeFileText(filePath, content);
50
+ }
51
+
52
+ export function defaultResourcePath(
53
+ context: PlasmicContext,
54
+ project: ProjectConfig | ProjectMetaBundle | string,
55
+ ...subpaths: string[]
56
+ ) {
57
+ const projectName = L.isString(project) ? project : project.projectName;
58
+ return path.join(
59
+ context.config.defaultPlasmicDir,
60
+ L.snakeCase(projectName),
61
+ ...subpaths
62
+ );
63
+ }
64
+
65
+ export function defaultPublicResourcePath(
66
+ context: PlasmicContext,
67
+ project: ProjectConfig,
68
+ ...subpaths: string[]
69
+ ) {
70
+ return path.join(
71
+ context.config.images.publicDir,
72
+ "plasmic",
73
+ L.snakeCase(project.projectName),
74
+ ...subpaths
75
+ );
76
+ }
77
+
78
+ export function defaultPagePath(context: PlasmicContext, fileName: string) {
79
+ if (context.config.platform === "nextjs") {
80
+ return path.join(context.config.nextjsConfig?.pagesDir || "", fileName);
81
+ }
82
+ if (context.config.platform === "gatsby") {
83
+ return path.join(context.config.gatsbyConfig?.pagesDir || "", fileName);
84
+ }
85
+ return fileName;
86
+ }
87
+
88
+ export async function writeFileContent(
89
+ context: PlasmicContext,
90
+ srcDirFilePath: string,
91
+ content: string | Buffer,
92
+ opts: { force?: boolean } = {}
93
+ ) {
94
+ const path = makeFilePath(context, srcDirFilePath);
95
+ await writeFileContentRaw(path, content, {
96
+ yes: context.cliArgs.yes,
97
+ ...opts,
98
+ });
99
+ }
100
+
101
+ export function readFileContent(
102
+ context: PlasmicContext,
103
+ srcDirFilePath: string
104
+ ) {
105
+ const path = makeFilePath(context, srcDirFilePath);
106
+ return readFileText(path);
107
+ }
108
+
109
+ export function deleteFile(context: PlasmicContext, srcDirFilePath: string) {
110
+ const path = makeFilePath(context, srcDirFilePath);
111
+ deleteFileBuffered(path);
112
+ }
113
+
114
+ export function fileExists(context: PlasmicContext, srcDirFilePath: string) {
115
+ return existsBuffered(makeFilePath(context, srcDirFilePath));
116
+ }
117
+
118
+ export function makeFilePath(context: PlasmicContext, filePath: string) {
119
+ return path.isAbsolute(filePath)
120
+ ? filePath
121
+ : path.join(context.absoluteSrcDir, filePath);
122
+ }
123
+
124
+ export function renameFile(
125
+ context: PlasmicContext,
126
+ oldPath: string,
127
+ newPath: string
128
+ ) {
129
+ renameFileBuffered(
130
+ makeFilePath(context, oldPath),
131
+ makeFilePath(context, newPath)
132
+ );
133
+ }
134
+
135
+ /**
136
+ * Returns absolute paths of all Plasmic managed files found, grouped by each basename
137
+ * for example:
138
+ * {
139
+ * "file.txt": [ "/path1/file.txt", "/path2.txt" ]
140
+ * ...
141
+ * }
142
+ * @param {PlasmicContext} context
143
+ * @returns {Record<string, string[]>}
144
+ **/
145
+ export function buildBaseNameToFiles(
146
+ context: PlasmicContext
147
+ ): Record<string, string[]> {
148
+ const srcDir = context.absoluteSrcDir;
149
+ const scriptFileExt = context.config.code.lang === "ts" ? "tsx" : "jsx";
150
+ const allFiles = glob.sync(`${srcDir}/**/*.+(ts|css|${scriptFileExt}|json)`, {
151
+ ignore: [`${srcDir}/**/node_modules/**/*`],
152
+ });
153
+ return L.groupBy(allFiles, (f) => path.basename(f));
154
+ }
155
+
156
+ /**
157
+ * Tries to find the file at `srcDir/expectedPath`. If it's not there, tries to detect if it has
158
+ * been moved to a different location. Returns the found location relative to the `srcDir`.
159
+ *
160
+ * If `expectedPath` doesn't exist, but there's more than one file of that name in `baseNameToFiles`, then
161
+ * error and quit. If no file of that name can be found, `expectedPath` is returned.
162
+ */
163
+ export function findSrcDirPath(
164
+ absoluteSrcDir: string,
165
+ expectedPath: string,
166
+ baseNameToFiles: Record<string, string[]>
167
+ ): string {
168
+ if (!path.isAbsolute(absoluteSrcDir)) {
169
+ throw new HandledError("Cannot find srcDir. Please check plasmic.json.");
170
+ }
171
+
172
+ const fileName = path.basename(expectedPath);
173
+ if (existsBuffered(path.join(absoluteSrcDir, expectedPath))) {
174
+ return expectedPath;
175
+ } else if (!(fileName in baseNameToFiles)) {
176
+ return expectedPath;
177
+ } else if (baseNameToFiles[fileName].length === 1) {
178
+ // There's only one file of the same name, so maybe we've been moved there?
179
+ const newPath = path.relative(absoluteSrcDir, baseNameToFiles[fileName][0]);
180
+ logger.info(`\tDetected file moved from ${expectedPath} to ${newPath}`);
181
+ return newPath;
182
+ } else {
183
+ throw new HandledError(
184
+ `Cannot find expected file at ${expectedPath}, and found multiple possible matching files ${baseNameToFiles[fileName]}. Please update plasmic.config with the real location for ${fileName}.`
185
+ );
186
+ }
187
+ }
188
+
189
+ /**
190
+ * Finds the full path to the first file satisfying `pred` in `dir`. If
191
+ * `opts.traverseParents` is set to true, then will also look in ancestor
192
+ * directories until the plasmic.json file is found. If none is found,
193
+ * returns undefined.
194
+ */
195
+ export function findFile(
196
+ dir: string,
197
+ pred: (name: string) => boolean,
198
+ opts: {
199
+ traverseParents?: boolean;
200
+ }
201
+ ): string | undefined {
202
+ const files = fs.readdirSync(dir);
203
+ const found = files.find((f) => pred(f));
204
+ if (found) {
205
+ return path.join(dir, found);
206
+ }
207
+ if (!opts.traverseParents) {
208
+ return undefined;
209
+ }
210
+ const parent = path.dirname(dir);
211
+ if (parent === dir) {
212
+ // We've hit the root dir already
213
+ return undefined;
214
+ }
215
+ return findFile(path.dirname(dir), pred, opts);
216
+ }
217
+
218
+ type BundleKeyPair = {
219
+ bundle: Record<string, any>;
220
+ key: string;
221
+ };
222
+
223
+ /**
224
+ * Parses a configuration and returns file/dir paths in it (in the format
225
+ * BundleKeyPair to allow the caller to change these paths).
226
+ */
227
+ function getAllPaths(context: PlasmicContext): BundleKeyPair[] {
228
+ const config = context.config;
229
+
230
+ const pairs: BundleKeyPair[] = [];
231
+ const pushPath = (bundle: Record<string, any>, key: string) => {
232
+ pairs.push({ bundle, key });
233
+ };
234
+
235
+ const pushComponent = (comp: ComponentConfig) => {
236
+ pushPath(comp, "renderModuleFilePath");
237
+ pushPath(comp, "cssFilePath");
238
+ if (isLocalModulePath(comp.importSpec.modulePath)) {
239
+ pushPath(comp.importSpec, "modulePath");
240
+ }
241
+ };
242
+
243
+ const pushProject = (proj: ProjectConfig) => {
244
+ pushPath(proj, "cssFilePath");
245
+ for (const component of proj.components) {
246
+ pushComponent(component);
247
+ }
248
+ for (const icon of proj.icons) {
249
+ pushPath(icon, "moduleFilePath");
250
+ }
251
+ for (const image of proj.images) {
252
+ pushPath(image, "filePath");
253
+ }
254
+ };
255
+
256
+ for (const project of config.projects) {
257
+ pushProject(project);
258
+ }
259
+
260
+ for (const bundle of config.globalVariants.variantGroups) {
261
+ pushPath(bundle, "contextFilePath");
262
+ }
263
+
264
+ pushPath(config.tokens, "tokensFilePath");
265
+ pushPath(config.style, "defaultStyleCssFilePath");
266
+
267
+ pushPath(config, "defaultPlasmicDir");
268
+ if (config.images.publicDir) {
269
+ pushPath(config.images, "publicDir");
270
+ }
271
+ if (config.gatsbyConfig) {
272
+ pushPath(config.gatsbyConfig, "pagesDir");
273
+ }
274
+ if (config.nextjsConfig) {
275
+ pushPath(config.nextjsConfig, "pagesDir");
276
+ }
277
+
278
+ return pairs;
279
+ }
280
+
281
+ /**
282
+ * Fixes all src-relative file paths in PlasmicConfig by detecting file
283
+ * movement on disk.
284
+ */
285
+ export async function fixAllFilePaths(context: PlasmicContext, baseDir: string) {
286
+ const baseNameToFiles = buildBaseNameToFiles(context);
287
+ let changed = false;
288
+
289
+ const paths = getAllPaths(context);
290
+ for (const { bundle, key } of paths) {
291
+ const known = bundle[key];
292
+ // Check null and undefined
293
+ if (known == null) {
294
+ throw new HandledError(
295
+ `"${key} is required, but missing in ${CONFIG_FILE_NAME}. Please restore the file or delete from ${CONFIG_FILE_NAME} and run plasmic sync: ${bundle}"`
296
+ );
297
+ }
298
+ // Check falsey values (e.g. "")
299
+ if (!known) {
300
+ continue;
301
+ }
302
+ const found = findSrcDirPath(
303
+ context.absoluteSrcDir,
304
+ known,
305
+ baseNameToFiles
306
+ );
307
+ if (known !== found) {
308
+ bundle[key] = found;
309
+ changed = true;
310
+ }
311
+ }
312
+
313
+ if (changed) {
314
+ await updateConfig(context, context.config, baseDir);
315
+ }
316
+ }
317
+
318
+ /**
319
+ * Throws an error if some file in PlasmicConfig is not inside the root
320
+ * directory (i.e., the directory containing plasmic.json).
321
+ */
322
+ export function assertAllPathsInRootDir(context: PlasmicContext) {
323
+ // Do not run this check when running in PlasmicLoader environment
324
+ if (process.env.PLASMIC_LOADER) {
325
+ return;
326
+ }
327
+
328
+ if (!context.absoluteSrcDir.startsWith(context.rootDir)) {
329
+ throw new HandledError(
330
+ `"srcDir" in ${CONFIG_FILE_NAME} is outside of ${context.rootDir}`
331
+ );
332
+ }
333
+
334
+ const paths = getAllPaths(context);
335
+ for (const { bundle, key } of paths) {
336
+ const relPath = bundle[key];
337
+ if (!relPath) {
338
+ continue;
339
+ }
340
+
341
+ const absPath = path.resolve(context.absoluteSrcDir, relPath);
342
+ if (!absPath.startsWith(context.rootDir)) {
343
+ throw new HandledError(
344
+ `The path "${relPath}" in ${CONFIG_FILE_NAME} is outside of ${context.rootDir}`
345
+ );
346
+ }
347
+ }
348
+ }
349
+
350
+ /** Whether we're currently recording to the buffer. */
351
+ let buffering = false;
352
+
353
+ interface BufferCreateFile {
354
+ type: "create";
355
+ content: string | Buffer;
356
+ }
357
+ interface BufferRenameFile {
358
+ type: "rename";
359
+ newPath: string;
360
+ }
361
+ interface BufferDeleteFile {
362
+ type: "delete";
363
+ }
364
+
365
+ /** List of buffer actions. */
366
+ const buffer = new Map<
367
+ string,
368
+ BufferCreateFile | BufferRenameFile | BufferDeleteFile
369
+ >();
370
+ const renamedFiles = new Map<string, string>();
371
+
372
+ /**
373
+ * This turns on buffering of file writes/reads.
374
+ *
375
+ * This is useful for reducing the extent to which our file updates are scattered over time, which can cause webpack
376
+ * dev server to trip up.
377
+ *
378
+ * This also has the side benefit of making our CLI commands more atomic, in case of failure partway through a sync.
379
+ */
380
+ export async function withBufferedFs(f: () => Promise<void>) {
381
+ buffering = true;
382
+ buffer.clear();
383
+ renamedFiles.clear();
384
+ try {
385
+ await f();
386
+ for (const [filePath, action] of buffer.entries()) {
387
+ switch (action.type) {
388
+ case "create":
389
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
390
+ // eslint-disable-next-line no-restricted-properties
391
+ fs.writeFileSync(filePath, action.content);
392
+ break;
393
+ case "rename":
394
+ fs.mkdirSync(path.dirname(action.newPath), { recursive: true });
395
+ // eslint-disable-next-line no-restricted-properties
396
+ fs.renameSync(filePath, action.newPath);
397
+ break;
398
+ case "delete":
399
+ // eslint-disable-next-line no-restricted-properties
400
+ fs.unlinkSync(filePath);
401
+ break;
402
+ }
403
+ }
404
+ } finally {
405
+ buffering = false;
406
+ }
407
+ }
408
+
409
+ export function writeFileText(path: string, content: string | Buffer) {
410
+ if (buffering) {
411
+ buffer.set(path, { type: "create", content });
412
+ } else {
413
+ // eslint-disable-next-line no-restricted-properties
414
+ fs.writeFileSync(path, content, "utf8");
415
+ }
416
+ }
417
+
418
+ export function readFileText(path: string): string {
419
+ if (buffering) {
420
+ const action = buffer.get(path);
421
+ if (action) {
422
+ switch (action.type) {
423
+ case "create":
424
+ return ensureString(action.content);
425
+ case "rename":
426
+ return readFileText(action.newPath);
427
+ case "delete":
428
+ throw new HandledError("File does not exists");
429
+ }
430
+ }
431
+ }
432
+
433
+ // eslint-disable-next-line no-restricted-properties
434
+ return fs.readFileSync(path, "utf8");
435
+ }
436
+
437
+ export function renameFileBuffered(oldPath: string, newPath: string) {
438
+ if (oldPath === newPath) {
439
+ return;
440
+ }
441
+
442
+ if (buffering) {
443
+ if (!existsBuffered(oldPath)) {
444
+ throw new HandledError("File does not exists");
445
+ }
446
+
447
+ const action = buffer.get(oldPath);
448
+
449
+ if (action) {
450
+ switch (action.type) {
451
+ case "create":
452
+ buffer.set(newPath, action);
453
+ buffer.delete(oldPath);
454
+ break;
455
+ case "rename":
456
+ throw new HandledError("File does not exists");
457
+ case "delete":
458
+ throw new HandledError("File does not exists");
459
+ }
460
+ }
461
+
462
+ const renamedFile = renamedFiles.get(oldPath);
463
+ if (renamedFile !== undefined) {
464
+ oldPath = renamedFile;
465
+ }
466
+
467
+ buffer.set(oldPath, { type: "rename", newPath });
468
+ renamedFiles.set(newPath, oldPath);
469
+ } else {
470
+ fs.mkdirSync(path.dirname(newPath), { recursive: true });
471
+ // eslint-disable-next-line no-restricted-properties
472
+ fs.renameSync(oldPath, newPath);
473
+ }
474
+ }
475
+
476
+ export function deleteFileBuffered(path: string) {
477
+ if (buffering) {
478
+ if (!existsBuffered(path)) {
479
+ throw new HandledError("File does not exists");
480
+ }
481
+
482
+ const action = buffer.get(path);
483
+
484
+ if (action) {
485
+ switch (action.type) {
486
+ case "create":
487
+ buffer.delete(path);
488
+ break;
489
+ case "rename":
490
+ throw new HandledError("File does not exists");
491
+ case "delete":
492
+ throw new HandledError("File does not exists");
493
+ }
494
+ } else {
495
+ buffer.set(path, { type: "delete" });
496
+ }
497
+
498
+ renamedFiles.delete(path);
499
+ } else {
500
+ // eslint-disable-next-line no-restricted-properties
501
+ fs.unlinkSync(path);
502
+ }
503
+ }
504
+
505
+ export function existsBuffered(path: string): boolean {
506
+ if (buffering) {
507
+ if (renamedFiles.has(path)) {
508
+ return true;
509
+ }
510
+
511
+ const action = buffer.get(path);
512
+ if (action) {
513
+ switch (action.type) {
514
+ case "create":
515
+ return true;
516
+ case "rename":
517
+ return false;
518
+ case "delete":
519
+ return false;
520
+ }
521
+ }
522
+ }
523
+
524
+ // eslint-disable-next-line no-restricted-properties
525
+ return fs.existsSync(path);
526
+ }