@dittowords/cli 4.3.0 → 4.4.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 (85) hide show
  1. package/.github/actions/install-node-dependencies/action.yml +24 -0
  2. package/.github/workflows/required-checks.yml +24 -0
  3. package/.sentryclirc +3 -0
  4. package/__mocks__/fs.js +2 -0
  5. package/bin/__mocks__/api.js +48 -0
  6. package/bin/__mocks__/api.js.map +1 -0
  7. package/bin/config.test.js +4 -3
  8. package/bin/config.test.js.map +1 -1
  9. package/bin/consts.js +19 -29
  10. package/bin/consts.js.map +1 -1
  11. package/bin/ditto.js +12 -4
  12. package/bin/ditto.js.map +1 -1
  13. package/bin/generate-suggestions.js +68 -58
  14. package/bin/generate-suggestions.js.map +1 -1
  15. package/bin/generate-suggestions.test.js +24 -13
  16. package/bin/generate-suggestions.test.js.map +1 -1
  17. package/bin/http/__mocks__/fetchComponentFolders.js +71 -0
  18. package/bin/http/__mocks__/fetchComponentFolders.js.map +1 -0
  19. package/bin/http/__mocks__/fetchComponents.js +73 -0
  20. package/bin/http/__mocks__/fetchComponents.js.map +1 -0
  21. package/bin/http/__mocks__/fetchVariants.js +71 -0
  22. package/bin/http/__mocks__/fetchVariants.js.map +1 -0
  23. package/bin/http/fetchComponentFolders.js +4 -4
  24. package/bin/http/fetchComponentFolders.js.map +1 -1
  25. package/bin/http/fetchComponents.js +4 -4
  26. package/bin/http/fetchComponents.js.map +1 -1
  27. package/bin/http/fetchVariants.js +6 -3
  28. package/bin/http/fetchVariants.js.map +1 -1
  29. package/bin/http/http.test.js +159 -0
  30. package/bin/http/http.test.js.map +1 -0
  31. package/bin/http/importComponents.js +9 -2
  32. package/bin/http/importComponents.js.map +1 -1
  33. package/bin/init/project.test.js +5 -28
  34. package/bin/init/project.test.js.map +1 -1
  35. package/bin/init/token.js +72 -27
  36. package/bin/init/token.js.map +1 -1
  37. package/bin/init/token.test.js +87 -9
  38. package/bin/init/token.test.js.map +1 -1
  39. package/bin/pull-lib.test.js +379 -0
  40. package/bin/pull-lib.test.js.map +1 -0
  41. package/bin/pull.js +15 -4
  42. package/bin/pull.js.map +1 -1
  43. package/bin/pull.test.js +73 -290
  44. package/bin/pull.test.js.map +1 -1
  45. package/bin/replace.js +22 -6
  46. package/bin/replace.js.map +1 -1
  47. package/bin/replace.test.js +53 -11
  48. package/bin/replace.test.js.map +1 -1
  49. package/bin/utils/determineModuleType.js +6 -7
  50. package/bin/utils/determineModuleType.js.map +1 -1
  51. package/bin/utils/determineModuleType.test.js +60 -0
  52. package/bin/utils/determineModuleType.test.js.map +1 -0
  53. package/bin/utils/getSelectedProjects.js +5 -5
  54. package/bin/utils/getSelectedProjects.js.map +1 -1
  55. package/bin/utils/quit.js +3 -3
  56. package/bin/utils/quit.js.map +1 -1
  57. package/jest.config.ts +16 -0
  58. package/lib/__mocks__/api.ts +12 -0
  59. package/lib/config.test.ts +3 -1
  60. package/lib/consts.ts +19 -17
  61. package/lib/ditto.ts +9 -1
  62. package/lib/generate-suggestions.test.ts +23 -11
  63. package/lib/generate-suggestions.ts +89 -79
  64. package/lib/http/__mocks__/fetchComponentFolders.ts +23 -0
  65. package/lib/http/__mocks__/fetchComponents.ts +24 -0
  66. package/lib/http/__mocks__/fetchVariants.ts +21 -0
  67. package/lib/http/fetchComponentFolders.ts +6 -4
  68. package/lib/http/fetchComponents.ts +5 -3
  69. package/lib/http/fetchVariants.ts +15 -4
  70. package/lib/http/http.test.ts +122 -0
  71. package/lib/http/importComponents.ts +8 -0
  72. package/lib/init/project.test.ts +4 -27
  73. package/lib/init/token.test.ts +55 -7
  74. package/lib/init/token.ts +76 -27
  75. package/lib/pull-lib.test.ts +367 -0
  76. package/lib/pull.test.ts +63 -316
  77. package/lib/pull.ts +13 -2
  78. package/lib/replace.test.ts +46 -10
  79. package/lib/replace.ts +20 -3
  80. package/lib/utils/determineModuleType.test.ts +48 -0
  81. package/lib/utils/determineModuleType.ts +4 -6
  82. package/lib/utils/getSelectedProjects.ts +3 -3
  83. package/lib/utils/quit.ts +1 -1
  84. package/package.json +4 -3
  85. package/jest.config.js +0 -6
@@ -1 +1 @@
1
- {"version":3,"sources":["../lib/replace.test.ts"],"sourcesContent":["import fs from \"fs/promises\";\nimport { parseOptions, replaceJSXTextInFile } from \"./replace\"; // Assuming the function is exported in a separate file\n\n// Helper function to create a temporary file\nasync function createTempJSXFile(content: string): Promise<string> {\n const tempFile = \"tempFile.jsx\";\n await fs.writeFile(tempFile, content);\n return tempFile;\n}\n\n// Helper function to delete the temporary file\nasync function deleteTempFile(filePath: string): Promise<void> {\n await fs.unlink(filePath);\n}\n\ndescribe(\"parseOptions\", () => {\n test(\"should pass with valid input\", async () => {\n const tempFile = await createTempJSXFile(\"<div>Hello, world!</div>\");\n expect(() =>\n parseOptions([tempFile, \"secondString\", \"thirdString\"])\n ).not.toThrow();\n\n const result = parseOptions([tempFile, \"secondString\", \"thirdString\"]);\n expect(result).toEqual({\n filePath: tempFile,\n searchString: \"secondString\",\n replaceWith: \"thirdString\",\n });\n\n deleteTempFile(tempFile);\n });\n\n test(\"should throw error when options array does not have exactly three strings\", () => {\n expect(() => parseOptions([\"oneString\"])).toThrow(\n \"The options array must contain <file path> <search string> <replace with>.\"\n );\n expect(() => parseOptions([\"one\", \"two\"])).toThrow(\n \"The options array must contain <file path> <search string> <replace with>.\"\n );\n expect(() => parseOptions([\"one\", \"two\", \"three\", \"four\"])).toThrow(\n \"The options array must contain <file path> <search string> <replace with>.\"\n );\n });\n\n test(\"should throw error when the first string is not a valid file path\", () => {\n const invalidFilePath = \"/path/to/invalid/file.txt\";\n expect(() =>\n parseOptions([invalidFilePath, \"secondString\", \"thirdString\"])\n ).toThrow(`${invalidFilePath} is not a valid file path.`);\n });\n\n test(\"should throw error when the first string is a directory\", () => {\n const directoryPath = \".\";\n expect(() =>\n parseOptions([directoryPath, \"secondString\", \"thirdString\"])\n ).toThrow(`${directoryPath} is not a valid file path.`);\n });\n});\n\n// TODO: this is flaky\ndescribe(\"replaceJSXTextInFile\", () => {\n afterEach(async () => {\n await deleteTempFile(\"tempFile.jsx\");\n });\n\n test(\"should replace JSX text with a DittoComponent\", async () => {\n const tempFile = await createTempJSXFile(\"<div>Hello, world</div>\");\n const searchString = \"world\";\n const replaceWith = \"some-id\";\n\n await replaceJSXTextInFile(tempFile, { searchString, replaceWith }, {});\n\n const transformedCode = await fs.readFile(tempFile, \"utf-8\");\n expect(transformedCode).toContain(\n `<div>Hello, <DittoComponent componentId=\"${replaceWith}\" /></div>`\n );\n });\n\n test(\"should replace JSX text with a DittoComponent with a flag\", async () => {\n const tempFile = await createTempJSXFile(\n `<>\\n<div>Hello, world</div>\\n<div>Hello, world</div>\\n</>`\n );\n const searchString = \"world\";\n const replaceWith = \"some-id\";\n\n await replaceJSXTextInFile(\n tempFile,\n { searchString, replaceWith },\n { lineNumbers: [3] }\n );\n\n const transformedCode = await fs.readFile(tempFile, \"utf-8\");\n expect(transformedCode).toContain(\n `<>\\n <div>Hello, world</div>\\n <div>Hello, <DittoComponent componentId=\\\"some-id\\\" /></div>\\n</>;`\n );\n });\n\n test(\"should handle case-insensitive search\", async () => {\n const tempFile = await createTempJSXFile(\"<div>HeLLo, WoRlD</div>\");\n const searchString = \"world\";\n const replaceWith = \"some-id\";\n\n await replaceJSXTextInFile(tempFile, { searchString, replaceWith }, {});\n\n const transformedCode = await fs.readFile(tempFile, \"utf-8\");\n expect(transformedCode).toContain(\n `<div>HeLLo, <DittoComponent componentId=\"${replaceWith}\" /></div>`\n );\n });\n\n test(\"should not replace JSX text if searchString is not found\", async () => {\n const tempFile = await createTempJSXFile(\"<div>Hello, world!</div>\");\n const searchString = \"foobar\";\n const replaceWith = \"some-id\";\n\n await replaceJSXTextInFile(tempFile, { searchString, replaceWith }, {});\n\n const transformedCode = await fs.readFile(tempFile, \"utf-8\");\n expect(transformedCode).toContain(\"<div>Hello, world!</div>\");\n });\n});\n"],"names":["fs"],"mappings":"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","debug_id":"88bc0e18-7209-5d12-95f3-62e752160eb4"}
1
+ {"version":3,"sources":["../lib/replace.test.ts"],"sourcesContent":["import fs from \"fs\";\nimport { parseOptions, replaceJSXTextInFile } from \"./replace\"; // Assuming the function is exported in a separate file\n\njest.mock(\"fs\");\n\n// Helper function to create a temporary file\nasync function createTempJSXFile(content: string): Promise<string> {\n const tempFile = \"/tempFile.jsx\";\n await new Promise((resolve, reject) => {\n try {\n fs.writeFile(tempFile, content, resolve);\n } catch (e) {\n reject(e);\n }\n });\n return tempFile;\n}\n\n// Helper function to delete the temporary file\nasync function deleteTempFile(filePath: string): Promise<void> {\n await new Promise((resolve, reject) => {\n try {\n fs.unlink(filePath, resolve);\n } catch (e) {\n reject(e);\n }\n });\n}\n\ndescribe(\"parseOptions\", () => {\n test(\"should pass with valid input\", async () => {\n const tempFile = await createTempJSXFile(\"<div>Hello, world!</div>\");\n expect(() =>\n parseOptions([tempFile, \"secondString\", \"thirdString\"])\n ).not.toThrow();\n\n const result = parseOptions([tempFile, \"secondString\", \"thirdString\"]);\n expect(result).toEqual({\n filePath: tempFile,\n searchString: \"secondString\",\n replaceWith: \"thirdString\",\n });\n\n deleteTempFile(tempFile);\n });\n\n test(\"should throw error when options array does not have exactly three strings\", () => {\n expect(() => parseOptions([\"oneString\"])).toThrow(\n \"The options array must contain <file path> <search string> <replace with>.\"\n );\n expect(() => parseOptions([\"one\", \"two\"])).toThrow(\n \"The options array must contain <file path> <search string> <replace with>.\"\n );\n expect(() => parseOptions([\"one\", \"two\", \"three\", \"four\"])).toThrow(\n \"The options array must contain <file path> <search string> <replace with>.\"\n );\n });\n\n test(\"should throw error when the first string is not a valid file path\", () => {\n const invalidFilePath = \"/path/to/invalid/file.txt\";\n expect(() =>\n parseOptions([invalidFilePath, \"secondString\", \"thirdString\"])\n ).toThrow(`${invalidFilePath} is not a valid file path.`);\n });\n\n test(\"should throw error when the first string is a directory\", () => {\n const directoryPath = \".\";\n expect(() =>\n parseOptions([directoryPath, \"secondString\", \"thirdString\"])\n ).toThrow(`${directoryPath} is not a valid file path.`);\n });\n});\n\ndescribe(\"replaceJSXTextInFile\", () => {\n afterEach(async () => {\n await deleteTempFile(\"/tempFile.jsx\");\n });\n\n test(\"should replace JSX text with a DittoComponent\", async () => {\n const tempFile = await createTempJSXFile(\"<div>Hello, world</div>\");\n const searchString = \"world\";\n const replaceWith = \"some-id\";\n\n await replaceJSXTextInFile(tempFile, { searchString, replaceWith }, {});\n\n const transformedCode = await new Promise((resolve, reject) => {\n fs.readFile(tempFile, \"utf-8\", (error, data) => {\n if (error) {\n reject(error);\n } else {\n resolve(data);\n }\n });\n });\n expect(transformedCode).toContain(\n `<div>Hello, <DittoComponent componentId=\"${replaceWith}\" /></div>`\n );\n });\n\n test(\"should replace JSX text with a DittoComponent with a flag\", async () => {\n const tempFile = await createTempJSXFile(\n `<>\\n<div>Hello, world</div>\\n<div>Hello, world</div>\\n</>`\n );\n const searchString = \"world\";\n const replaceWith = \"some-id\";\n\n await replaceJSXTextInFile(\n tempFile,\n { searchString, replaceWith },\n { lineNumbers: [3] }\n );\n\n const transformedCode = await new Promise((resolve, reject) =>\n fs.readFile(tempFile, \"utf-8\", (error, data) => {\n if (error) reject(error);\n else resolve(data);\n })\n );\n expect(transformedCode).toContain(\n `<>\\n <div>Hello, world</div>\\n <div>Hello, <DittoComponent componentId=\\\"some-id\\\" /></div>\\n</>;`\n );\n });\n\n test(\"should handle case-insensitive search\", async () => {\n const tempFile = await createTempJSXFile(\"<div>HeLLo, WoRlD</div>\");\n const searchString = \"world\";\n const replaceWith = \"some-id\";\n\n await replaceJSXTextInFile(tempFile, { searchString, replaceWith }, {});\n\n const transformedCode = await new Promise((resolve, reject) =>\n fs.readFile(tempFile, \"utf-8\", (error, data) => {\n if (error) reject(error);\n else resolve(data);\n })\n );\n expect(transformedCode).toContain(\n `<div>HeLLo, <DittoComponent componentId=\"${replaceWith}\" /></div>`\n );\n });\n\n test(\"should not replace JSX text if searchString is not found\", async () => {\n const tempFile = await createTempJSXFile(\"<div>Hello, world!</div>\");\n const searchString = \"foobar\";\n const replaceWith = \"some-id\";\n\n await replaceJSXTextInFile(tempFile, { searchString, replaceWith }, {});\n\n const transformedCode = await new Promise((resolve, reject) =>\n fs.readFile(tempFile, \"utf-8\", (error, data) => {\n if (error) reject(error);\n else resolve(data);\n })\n );\n expect(transformedCode).toContain(\"<div>Hello, world!</div>\");\n });\n});\n"],"names":["fs"],"mappings":"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","debug_id":"8d2eb72b-d2d6-5847-b480-cd39f4da1f7e"}
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="93454caf-75d4-52db-a313-fbad56075bbe")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="6334441d-042a-5df3-9f37-7bd9fd9adae4")}catch(e){}}();
3
3
 
4
4
  var __create = Object.create;
5
5
  var __defProp = Object.defineProperty;
@@ -35,15 +35,14 @@ __export(determineModuleType_exports, {
35
35
  module.exports = __toCommonJS(determineModuleType_exports);
36
36
  var fs = __toESM(require("fs"));
37
37
  var path = __toESM(require("path"));
38
- function determineModuleType() {
39
- const value = getRawTypeFromPackageJson();
38
+ function determineModuleType(currentDir = process.cwd()) {
39
+ const value = getRawTypeFromPackageJson(currentDir);
40
40
  return getTypeOrDefault(value);
41
41
  }
42
- function getRawTypeFromPackageJson() {
42
+ function getRawTypeFromPackageJson(currentDir) {
43
43
  if (process.env.DITTO_MODULE_TYPE) {
44
44
  return process.env.DITTO_MODULE_TYPE;
45
45
  }
46
- let currentDir = process.cwd();
47
46
  while (currentDir) {
48
47
  const packageJsonPath = path.join(currentDir, "package.json");
49
48
  if (fs.existsSync(packageJsonPath)) {
@@ -58,7 +57,7 @@ function getRawTypeFromPackageJson() {
58
57
  return null;
59
58
  }
60
59
  if (currentDir === "/") {
61
- return null;
60
+ break;
62
61
  }
63
62
  currentDir = path.dirname(currentDir);
64
63
  }
@@ -77,4 +76,4 @@ function getTypeOrDefault(value) {
77
76
  });
78
77
  //# sourceMappingURL=determineModuleType.js.map
79
78
 
80
- //# debugId=93454caf-75d4-52db-a313-fbad56075bbe
79
+ //# debugId=6334441d-042a-5df3-9f37-7bd9fd9adae4
@@ -1 +1 @@
1
- {"version":3,"sources":["../../lib/utils/determineModuleType.ts"],"sourcesContent":["import * as fs from \"fs\";\nimport * as path from \"path\";\n\nexport type ModuleType = \"commonjs\" | \"module\";\n\n/**\n * Looks for a `package.json` file starting in the current working directory and traversing upwards\n * until it finds one or reaches root.\n * @returns \"commonjs\" or \"module\", defaulting to \"module\" if no `package.json` is found or if the found\n * file does not include a `type` property.\n */\nexport function determineModuleType() {\n const value = getRawTypeFromPackageJson();\n return getTypeOrDefault(value);\n}\n\nfunction getRawTypeFromPackageJson() {\n if (process.env.DITTO_MODULE_TYPE) {\n return process.env.DITTO_MODULE_TYPE;\n }\n\n let currentDir: string | null = process.cwd(); // Get the current working directory\n\n while (currentDir) {\n const packageJsonPath = path.join(currentDir, \"package.json\");\n if (fs.existsSync(packageJsonPath)) {\n const packageJsonContents = fs.readFileSync(packageJsonPath, \"utf8\");\n try {\n const packageData: { type?: string } = JSON.parse(packageJsonContents);\n if (packageData?.type) {\n return packageData.type;\n }\n } catch {}\n\n return null;\n }\n\n if (currentDir === \"/\") {\n return null;\n }\n\n // Move up a directory and continue the search\n currentDir = path.dirname(currentDir);\n }\n\n // No package.json\n return null;\n}\n\nfunction getTypeOrDefault(value: string | null): ModuleType {\n const valueLower = value?.toLowerCase() || \"\";\n if (valueLower === \"commonjs\" || valueLower === \"module\") {\n return valueLower;\n }\n\n return \"commonjs\";\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAoB;AACpB,WAAsB;AAUf,SAAS,sBAAsB;AACpC,QAAM,QAAQ,0BAA0B;AACxC,SAAO,iBAAiB,KAAK;AAC/B;AAEA,SAAS,4BAA4B;AACnC,MAAI,QAAQ,IAAI,mBAAmB;AACjC,WAAO,QAAQ,IAAI;AAAA,EACrB;AAEA,MAAI,aAA4B,QAAQ,IAAI;AAE5C,SAAO,YAAY;AACjB,UAAM,kBAAkB,KAAK,KAAK,YAAY,cAAc;AAC5D,QAAI,GAAG,WAAW,eAAe,GAAG;AAClC,YAAM,sBAAsB,GAAG,aAAa,iBAAiB,MAAM;AACnE,UAAI;AACF,cAAM,cAAiC,KAAK,MAAM,mBAAmB;AACrE,YAAI,2CAAa,MAAM;AACrB,iBAAO,YAAY;AAAA,QACrB;AAAA,MACF,SAAQ;AAAA,MAAC;AAET,aAAO;AAAA,IACT;AAEA,QAAI,eAAe,KAAK;AACtB,aAAO;AAAA,IACT;AAGA,iBAAa,KAAK,QAAQ,UAAU;AAAA,EACtC;AAGA,SAAO;AACT;AAEA,SAAS,iBAAiB,OAAkC;AAC1D,QAAM,cAAa,+BAAO,kBAAiB;AAC3C,MAAI,eAAe,cAAc,eAAe,UAAU;AACxD,WAAO;AAAA,EACT;AAEA,SAAO;AACT","debug_id":"93454caf-75d4-52db-a313-fbad56075bbe"}
1
+ {"version":3,"sources":["../../lib/utils/determineModuleType.ts"],"sourcesContent":["import * as fs from \"fs\";\nimport * as path from \"path\";\n\nexport type ModuleType = \"commonjs\" | \"module\";\n\n/**\n * Looks for a `package.json` file starting in the current working directory and traversing upwards\n * until it finds one or reaches root.\n * @returns \"commonjs\" or \"module\", defaulting to \"module\" if no `package.json` is found or if the found\n * file does not include a `type` property.\n */\nexport function determineModuleType(currentDir: string | null = process.cwd()) {\n const value = getRawTypeFromPackageJson(currentDir);\n return getTypeOrDefault(value);\n}\n\nfunction getRawTypeFromPackageJson(currentDir: string | null) {\n if (process.env.DITTO_MODULE_TYPE) {\n return process.env.DITTO_MODULE_TYPE;\n }\n\n while (currentDir) {\n const packageJsonPath = path.join(currentDir, \"package.json\");\n if (fs.existsSync(packageJsonPath)) {\n const packageJsonContents = fs.readFileSync(packageJsonPath, \"utf8\");\n try {\n const packageData: { type?: string } = JSON.parse(packageJsonContents);\n if (packageData?.type) {\n return packageData.type;\n }\n } catch {}\n\n return null;\n }\n\n if (currentDir === \"/\") {\n break;\n }\n\n // Move up a directory and continue the search\n currentDir = path.dirname(currentDir);\n }\n\n // No package.json\n return null;\n}\n\nfunction getTypeOrDefault(value: string | null): ModuleType {\n const valueLower = value?.toLowerCase() || \"\";\n if (valueLower === \"commonjs\" || valueLower === \"module\") {\n return valueLower;\n }\n\n return \"commonjs\";\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAoB;AACpB,WAAsB;AAUf,SAAS,oBAAoB,aAA4B,QAAQ,IAAI,GAAG;AAC7E,QAAM,QAAQ,0BAA0B,UAAU;AAClD,SAAO,iBAAiB,KAAK;AAC/B;AAEA,SAAS,0BAA0B,YAA2B;AAC5D,MAAI,QAAQ,IAAI,mBAAmB;AACjC,WAAO,QAAQ,IAAI;AAAA,EACrB;AAEA,SAAO,YAAY;AACjB,UAAM,kBAAkB,KAAK,KAAK,YAAY,cAAc;AAC5D,QAAI,GAAG,WAAW,eAAe,GAAG;AAClC,YAAM,sBAAsB,GAAG,aAAa,iBAAiB,MAAM;AACnE,UAAI;AACF,cAAM,cAAiC,KAAK,MAAM,mBAAmB;AACrE,YAAI,2CAAa,MAAM;AACrB,iBAAO,YAAY;AAAA,QACrB;AAAA,MACF,SAAQ;AAAA,MAAC;AAET,aAAO;AAAA,IACT;AAEA,QAAI,eAAe,KAAK;AACtB;AAAA,IACF;AAGA,iBAAa,KAAK,QAAQ,UAAU;AAAA,EACtC;AAGA,SAAO;AACT;AAEA,SAAS,iBAAiB,OAAkC;AAC1D,QAAM,cAAa,+BAAO,kBAAiB;AAC3C,MAAI,eAAe,cAAc,eAAe,UAAU;AACxD,WAAO;AAAA,EACT;AAEA,SAAO;AACT","debug_id":"6334441d-042a-5df3-9f37-7bd9fd9adae4"}
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="31410f07-eaa0-59b5-a32b-1c709affaf87")}catch(e){}}();
3
+
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
8
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
9
+ var __spreadValues = (a, b) => {
10
+ for (var prop in b || (b = {}))
11
+ if (__hasOwnProp.call(b, prop))
12
+ __defNormalProp(a, prop, b[prop]);
13
+ if (__getOwnPropSymbols)
14
+ for (var prop of __getOwnPropSymbols(b)) {
15
+ if (__propIsEnum.call(b, prop))
16
+ __defNormalProp(a, prop, b[prop]);
17
+ }
18
+ return a;
19
+ };
20
+ var import_determineModuleType = require("./determineModuleType");
21
+ var import_memfs = require("memfs");
22
+ const defaultEnv = process.env;
23
+ jest.mock("fs");
24
+ beforeEach(() => {
25
+ import_memfs.vol.reset();
26
+ process.env = __spreadValues({}, defaultEnv);
27
+ });
28
+ test("'commonjs' if no package.json found", () => {
29
+ expect((0, import_determineModuleType.determineModuleType)()).toBe("commonjs");
30
+ });
31
+ test("'commonjs' if package.json found but no `type` property", () => {
32
+ import_memfs.vol.fromJSON({ "package.json": JSON.stringify({}) }, process.cwd());
33
+ expect((0, import_determineModuleType.determineModuleType)()).toBe("commonjs");
34
+ });
35
+ test("'commonjs' if package.json found and `type` property is 'commonjs'", () => {
36
+ import_memfs.vol.fromJSON({ "package.json": JSON.stringify({ type: "commonjs" }) });
37
+ expect((0, import_determineModuleType.determineModuleType)()).toBe("commonjs");
38
+ });
39
+ test("'commonjs' if package.json found and `type` property is invalid", () => {
40
+ import_memfs.vol.fromJSON({ "package.json": JSON.stringify({ type: "invalid-type" }) });
41
+ expect((0, import_determineModuleType.determineModuleType)()).toBe("commonjs");
42
+ });
43
+ test("'module' if package.json found and `type` property is 'module'", () => {
44
+ import_memfs.vol.fromJSON({ "package.json": JSON.stringify({ type: "module" }) });
45
+ expect((0, import_determineModuleType.determineModuleType)()).toBe("module");
46
+ });
47
+ test("finds package.json in parent directories", () => {
48
+ import_memfs.vol.fromJSON({
49
+ "/some/nested/dir/test.txt": "",
50
+ "/package.json": JSON.stringify({ type: "module" })
51
+ });
52
+ expect((0, import_determineModuleType.determineModuleType)("/some/nested/dir")).toBe("module");
53
+ });
54
+ test("supports explicit specification of module type via environment variable", () => {
55
+ process.env.DITTO_MODULE_TYPE = "module";
56
+ expect((0, import_determineModuleType.determineModuleType)()).toBe("module");
57
+ });
58
+ //# sourceMappingURL=determineModuleType.test.js.map
59
+
60
+ //# debugId=31410f07-eaa0-59b5-a32b-1c709affaf87
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../lib/utils/determineModuleType.test.ts"],"sourcesContent":["import { determineModuleType } from \"./determineModuleType\";\nimport { vol } from \"memfs\";\n\nconst defaultEnv = process.env;\n\njest.mock(\"fs\");\n\nbeforeEach(() => {\n vol.reset();\n process.env = { ...defaultEnv };\n});\n\ntest(\"'commonjs' if no package.json found\", () => {\n expect(determineModuleType()).toBe(\"commonjs\");\n});\n\ntest(\"'commonjs' if package.json found but no `type` property\", () => {\n vol.fromJSON({ \"package.json\": JSON.stringify({}) }, process.cwd());\n expect(determineModuleType()).toBe(\"commonjs\");\n});\n\ntest(\"'commonjs' if package.json found and `type` property is 'commonjs'\", () => {\n vol.fromJSON({ \"package.json\": JSON.stringify({ type: \"commonjs\" }) });\n expect(determineModuleType()).toBe(\"commonjs\");\n});\n\ntest(\"'commonjs' if package.json found and `type` property is invalid\", () => {\n vol.fromJSON({ \"package.json\": JSON.stringify({ type: \"invalid-type\" }) });\n expect(determineModuleType()).toBe(\"commonjs\");\n});\n\ntest(\"'module' if package.json found and `type` property is 'module'\", () => {\n vol.fromJSON({ \"package.json\": JSON.stringify({ type: \"module\" }) });\n expect(determineModuleType()).toBe(\"module\");\n});\n\ntest(\"finds package.json in parent directories\", () => {\n vol.fromJSON({\n \"/some/nested/dir/test.txt\": \"\",\n \"/package.json\": JSON.stringify({ type: \"module\" }),\n });\n expect(determineModuleType(\"/some/nested/dir\")).toBe(\"module\");\n});\n\ntest(\"supports explicit specification of module type via environment variable\", () => {\n process.env.DITTO_MODULE_TYPE = \"module\";\n expect(determineModuleType()).toBe(\"module\");\n});\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;AAAA,iCAAoC;AACpC,mBAAoB;AAEpB,MAAM,aAAa,QAAQ;AAE3B,KAAK,KAAK,IAAI;AAEd,WAAW,MAAM;AACf,mBAAI,MAAM;AACV,UAAQ,MAAM,mBAAK;AACrB,CAAC;AAED,KAAK,uCAAuC,MAAM;AAChD,aAAO,gDAAoB,CAAC,EAAE,KAAK,UAAU;AAC/C,CAAC;AAED,KAAK,2DAA2D,MAAM;AACpE,mBAAI,SAAS,EAAE,gBAAgB,KAAK,UAAU,CAAC,CAAC,EAAE,GAAG,QAAQ,IAAI,CAAC;AAClE,aAAO,gDAAoB,CAAC,EAAE,KAAK,UAAU;AAC/C,CAAC;AAED,KAAK,sEAAsE,MAAM;AAC/E,mBAAI,SAAS,EAAE,gBAAgB,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC,EAAE,CAAC;AACrE,aAAO,gDAAoB,CAAC,EAAE,KAAK,UAAU;AAC/C,CAAC;AAED,KAAK,mEAAmE,MAAM;AAC5E,mBAAI,SAAS,EAAE,gBAAgB,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC,EAAE,CAAC;AACzE,aAAO,gDAAoB,CAAC,EAAE,KAAK,UAAU;AAC/C,CAAC;AAED,KAAK,kEAAkE,MAAM;AAC3E,mBAAI,SAAS,EAAE,gBAAgB,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC,EAAE,CAAC;AACnE,aAAO,gDAAoB,CAAC,EAAE,KAAK,QAAQ;AAC7C,CAAC;AAED,KAAK,4CAA4C,MAAM;AACrD,mBAAI,SAAS;AAAA,IACX,6BAA6B;AAAA,IAC7B,iBAAiB,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AAAA,EACpD,CAAC;AACD,aAAO,gDAAoB,kBAAkB,CAAC,EAAE,KAAK,QAAQ;AAC/D,CAAC;AAED,KAAK,2EAA2E,MAAM;AACpF,UAAQ,IAAI,oBAAoB;AAChC,aAAO,gDAAoB,CAAC,EAAE,KAAK,QAAQ;AAC7C,CAAC","debug_id":"31410f07-eaa0-59b5-a32b-1c709affaf87"}
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="3231592f-fedc-5607-aa4c-eae91957e0ed")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="ca926dda-44e3-512a-b95e-05b445329a2e")}catch(e){}}();
3
3
 
4
4
  var __create = Object.create;
5
5
  var __defProp = Object.defineProperty;
@@ -35,7 +35,7 @@ __export(getSelectedProjects_exports, {
35
35
  });
36
36
  module.exports = __toCommonJS(getSelectedProjects_exports);
37
37
  var import_js_yaml = __toESM(require("js-yaml"));
38
- var import_consts = require("../consts");
38
+ var import_consts = __toESM(require("../consts"));
39
39
  var import_config = __toESM(require("../config"));
40
40
  function jsonIsConfigYAML(json) {
41
41
  return typeof json === "object";
@@ -55,8 +55,8 @@ function yamlToJson(_yaml) {
55
55
  }
56
56
  }
57
57
  }
58
- const getSelectedProjects = (configFile = import_consts.PROJECT_CONFIG_FILE) => import_config.default.parseSourceInformation(configFile).validProjects;
59
- const getIsUsingComponents = (configFile = import_consts.PROJECT_CONFIG_FILE) => import_config.default.parseSourceInformation(configFile).shouldFetchComponentLibrary;
58
+ const getSelectedProjects = (configFile = import_consts.default.PROJECT_CONFIG_FILE) => import_config.default.parseSourceInformation(configFile).validProjects;
59
+ const getIsUsingComponents = (configFile = import_consts.default.PROJECT_CONFIG_FILE) => import_config.default.parseSourceInformation(configFile).shouldFetchComponentLibrary;
60
60
  // Annotate the CommonJS export names for ESM import in node:
61
61
  0 && (module.exports = {
62
62
  getIsUsingComponents,
@@ -64,4 +64,4 @@ const getIsUsingComponents = (configFile = import_consts.PROJECT_CONFIG_FILE) =>
64
64
  });
65
65
  //# sourceMappingURL=getSelectedProjects.js.map
66
66
 
67
- //# debugId=3231592f-fedc-5607-aa4c-eae91957e0ed
67
+ //# debugId=ca926dda-44e3-512a-b95e-05b445329a2e
@@ -1 +1 @@
1
- {"version":3,"sources":["../../lib/utils/getSelectedProjects.ts"],"sourcesContent":["import fs from \"fs\";\nimport yaml, { YAMLException } from \"js-yaml\";\n\nimport { PROJECT_CONFIG_FILE } from \"../consts\";\nimport { ConfigYAML, Project } from \"../types\";\nimport Config, { DEFAULT_CONFIG_JSON } from \"../config\";\n\nfunction jsonIsConfigYAML(json: unknown): json is ConfigYAML {\n return typeof json === \"object\";\n}\n\nfunction yamlToJson(_yaml: string): ConfigYAML | null {\n try {\n let configYaml = yaml.load(_yaml);\n if (!jsonIsConfigYAML(configYaml)) {\n return {};\n }\n return configYaml;\n } catch (e) {\n if (e instanceof YAMLException) {\n return null;\n } else {\n throw e;\n }\n }\n}\n\n/**\n * Returns an array containing all valid projects ({ id, name })\n * currently contained in the project config file.\n */\nexport const getSelectedProjects = (configFile = PROJECT_CONFIG_FILE) =>\n Config.parseSourceInformation(configFile).validProjects;\n\nexport const getIsUsingComponents = (configFile = PROJECT_CONFIG_FILE) =>\n Config.parseSourceInformation(configFile).shouldFetchComponentLibrary;\n"],"names":["yaml","Config"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,qBAAoC;AAEpC,oBAAoC;AAEpC,oBAA4C;AAE5C,SAAS,iBAAiB,MAAmC;AAC3D,SAAO,OAAO,SAAS;AACzB;AAEA,SAAS,WAAW,OAAkC;AACpD,MAAI;AACF,QAAI,aAAa,eAAAA,QAAK,KAAK,KAAK;AAChC,QAAI,CAAC,iBAAiB,UAAU,GAAG;AACjC,aAAO,CAAC;AAAA,IACV;AACA,WAAO;AAAA,EACT,SAAS,GAAG;AACV,QAAI,aAAa,8BAAe;AAC9B,aAAO;AAAA,IACT,OAAO;AACL,YAAM;AAAA,IACR;AAAA,EACF;AACF;AAMO,MAAM,sBAAsB,CAAC,aAAa,sCAC/C,cAAAC,QAAO,uBAAuB,UAAU,EAAE;AAErC,MAAM,uBAAuB,CAAC,aAAa,sCAChD,cAAAA,QAAO,uBAAuB,UAAU,EAAE","debug_id":"3231592f-fedc-5607-aa4c-eae91957e0ed"}
1
+ {"version":3,"sources":["../../lib/utils/getSelectedProjects.ts"],"sourcesContent":["import fs from \"fs\";\nimport yaml, { YAMLException } from \"js-yaml\";\n\nimport consts from \"../consts\";\nimport { ConfigYAML, Project } from \"../types\";\nimport Config, { DEFAULT_CONFIG_JSON } from \"../config\";\n\nfunction jsonIsConfigYAML(json: unknown): json is ConfigYAML {\n return typeof json === \"object\";\n}\n\nfunction yamlToJson(_yaml: string): ConfigYAML | null {\n try {\n let configYaml = yaml.load(_yaml);\n if (!jsonIsConfigYAML(configYaml)) {\n return {};\n }\n return configYaml;\n } catch (e) {\n if (e instanceof YAMLException) {\n return null;\n } else {\n throw e;\n }\n }\n}\n\n/**\n * Returns an array containing all valid projects ({ id, name })\n * currently contained in the project config file.\n */\nexport const getSelectedProjects = (configFile = consts.PROJECT_CONFIG_FILE) =>\n Config.parseSourceInformation(configFile).validProjects;\n\nexport const getIsUsingComponents = (configFile = consts.PROJECT_CONFIG_FILE) =>\n Config.parseSourceInformation(configFile).shouldFetchComponentLibrary;\n"],"names":["yaml","consts","Config"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,qBAAoC;AAEpC,oBAAmB;AAEnB,oBAA4C;AAE5C,SAAS,iBAAiB,MAAmC;AAC3D,SAAO,OAAO,SAAS;AACzB;AAEA,SAAS,WAAW,OAAkC;AACpD,MAAI;AACF,QAAI,aAAa,eAAAA,QAAK,KAAK,KAAK;AAChC,QAAI,CAAC,iBAAiB,UAAU,GAAG;AACjC,aAAO,CAAC;AAAA,IACV;AACA,WAAO;AAAA,EACT,SAAS,GAAG;AACV,QAAI,aAAa,8BAAe;AAC9B,aAAO;AAAA,IACT,OAAO;AACL,YAAM;AAAA,IACR;AAAA,EACF;AACF;AAMO,MAAM,sBAAsB,CAAC,aAAa,cAAAC,QAAO,wBACtD,cAAAC,QAAO,uBAAuB,UAAU,EAAE;AAErC,MAAM,uBAAuB,CAAC,aAAa,cAAAD,QAAO,wBACvD,cAAAC,QAAO,uBAAuB,UAAU,EAAE","debug_id":"ca926dda-44e3-512a-b95e-05b445329a2e"}
package/bin/utils/quit.js CHANGED
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="4e7dfedc-459a-5b77-bc0f-5524b331ec6d")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},n=(new Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="79239749-0258-5746-9b26-d5a38d1e3f33")}catch(e){}}();
3
3
 
4
4
  var __defProp = Object.defineProperty;
5
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -28,7 +28,7 @@ function quit(message, exitCode = 2) {
28
28
  console.log(`
29
29
  ${message}
30
30
  `);
31
- process.exitCode = exitCode;
31
+ process.exit(exitCode);
32
32
  }
33
33
  // Annotate the CommonJS export names for ESM import in node:
34
34
  0 && (module.exports = {
@@ -36,4 +36,4 @@ ${message}
36
36
  });
37
37
  //# sourceMappingURL=quit.js.map
38
38
 
39
- //# debugId=4e7dfedc-459a-5b77-bc0f-5524b331ec6d
39
+ //# debugId=79239749-0258-5746-9b26-d5a38d1e3f33
@@ -1 +1 @@
1
- {"version":3,"sources":["../../lib/utils/quit.ts"],"sourcesContent":["export function quit(message: string | null, exitCode = 2) {\n if (message) console.log(`\\n${message}\\n`);\n process.exitCode = exitCode;\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAO,SAAS,KAAK,SAAwB,WAAW,GAAG;AACzD,MAAI;AAAS,YAAQ,IAAI;AAAA,EAAK,OAAO;AAAA,CAAI;AACzC,UAAQ,WAAW;AACrB","debug_id":"4e7dfedc-459a-5b77-bc0f-5524b331ec6d"}
1
+ {"version":3,"sources":["../../lib/utils/quit.ts"],"sourcesContent":["export function quit(message: string | null, exitCode = 2) {\n if (message) console.log(`\\n${message}\\n`);\n process.exit(exitCode);\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAO,SAAS,KAAK,SAAwB,WAAW,GAAG;AACzD,MAAI;AAAS,YAAQ,IAAI;AAAA,EAAK,OAAO;AAAA,CAAI;AACzC,UAAQ,KAAK,QAAQ;AACvB","debug_id":"79239749-0258-5746-9b26-d5a38d1e3f33"}
package/jest.config.ts ADDED
@@ -0,0 +1,16 @@
1
+ import type { Config } from "jest";
2
+
3
+ const config: Config = {
4
+ transformIgnorePatterns: [],
5
+ maxWorkers: 1,
6
+ verbose: true,
7
+ testPathIgnorePatterns: [
8
+ "<rootDir>/node_modules/",
9
+ "<rootDir>/dist/",
10
+ "<rootDir>/bin/",
11
+ ],
12
+ watchPathIgnorePatterns: ["<rootDir>/.testing/", "<rootDir>/testing/"],
13
+ collectCoverageFrom: ["lib/**/*.{js,jsx,ts,tsx}"],
14
+ };
15
+
16
+ export default config;
@@ -0,0 +1,12 @@
1
+ import axios from "axios";
2
+ import { jest } from "@jest/globals";
3
+
4
+ jest.mock("axios");
5
+
6
+ // by returning the mocked module directly, we can mock responses in tests
7
+ // like `axios.get.mockResolvedValue()`; otherwise, we'd be unable to mock
8
+ // responses because `createApiClient` would be returning an axios instance
9
+ // unaffected by mocks applied to the `axios` module itself.
10
+ export function createApiClient(_token?: string) {
11
+ return axios;
12
+ }
@@ -5,7 +5,9 @@ import tempy from "tempy";
5
5
  import yaml from "js-yaml";
6
6
  import config from "./config";
7
7
 
8
- const fakeHomedir = fs.mkdtempSync(path.join(__dirname, "../testing/tmp"));
8
+ jest.mock("fs");
9
+
10
+ const fakeHomedir = fs.mkdtempSync("/config-testing");
9
11
 
10
12
  describe("Config File", () => {
11
13
  const expectedConfigDir = path.join(fakeHomedir, ".config");
package/lib/consts.ts CHANGED
@@ -1,20 +1,22 @@
1
1
  import { homedir } from "os";
2
2
  import path from "path";
3
3
 
4
- export const API_HOST =
5
- process.env.DITTO_API_HOST || "https://api.dittowords.com";
6
- export const CONFIG_FILE =
7
- process.env.DITTO_CONFIG_FILE || path.join(homedir(), ".config", "ditto");
8
- export const PROJECT_CONFIG_FILE = path.normalize(
9
- path.join("ditto", "config.yml")
10
- );
11
- export const TEXT_DIR = process.env.DITTO_TEXT_DIR || "ditto";
12
- export const TEXT_FILE = path.normalize(path.join(TEXT_DIR, "text.json"));
13
-
14
- export default {
15
- API_HOST,
16
- CONFIG_FILE,
17
- PROJECT_CONFIG_FILE,
18
- TEXT_DIR,
19
- TEXT_FILE,
20
- };
4
+ export default new (class {
5
+ get API_HOST() {
6
+ return process.env.DITTO_API_HOST || "https://api.dittowords.com";
7
+ }
8
+ get CONFIG_FILE() {
9
+ return (
10
+ process.env.DITTO_CONFIG_FILE || path.join(homedir(), ".config", "ditto")
11
+ );
12
+ }
13
+ get PROJECT_CONFIG_FILE() {
14
+ return path.normalize(path.join("ditto", "config.yml"));
15
+ }
16
+ get TEXT_DIR() {
17
+ return process.env.DITTO_TEXT_DIR || "ditto";
18
+ }
19
+ get TEXT_FILE() {
20
+ return path.normalize(path.join(this.TEXT_DIR, "text.json"));
21
+ }
22
+ })();
package/lib/ditto.ts CHANGED
@@ -63,6 +63,11 @@ const COMMANDS: CommandConfig<Command>[] = [
63
63
  {
64
64
  name: "pull",
65
65
  description: "Sync copy from Ditto into the current working directory",
66
+ flags: {
67
+ "--sample-data": {
68
+ description: "Include sample data. Currently only supports variants.",
69
+ },
70
+ },
66
71
  },
67
72
  {
68
73
  name: "project",
@@ -210,7 +215,10 @@ const executeCommand = async (
210
215
  switch (command) {
211
216
  case "none":
212
217
  case "pull": {
213
- return pull({ meta: processMetaOption(meta) });
218
+ return pull({
219
+ meta: processMetaOption(meta),
220
+ includeSampleData: options.sampleData || false,
221
+ });
214
222
  }
215
223
  case "project":
216
224
  case "project add": {
@@ -1,17 +1,31 @@
1
- import fs from "fs/promises";
1
+ import fs from "fs";
2
2
  import path from "path";
3
3
  import { findComponentsInJSXFiles } from "./generate-suggestions";
4
4
 
5
+ jest.mock("fs");
6
+
5
7
  describe("findTextInJSXFiles", () => {
6
8
  async function createTempFile(filename: string, content: string) {
7
- const filePath = path.join(".", filename);
8
- await fs.writeFile(filePath, content);
9
+ const filePath = path.join("/", filename);
10
+ await new Promise((resolve, reject) => {
11
+ try {
12
+ fs.writeFile(filePath, content, () => resolve(null));
13
+ } catch (e) {
14
+ reject(e);
15
+ }
16
+ });
9
17
  return filePath;
10
18
  }
11
19
 
12
20
  async function deleteTempFile(filename: string) {
13
- const filePath = path.join(".", filename);
14
- await fs.unlink(filePath);
21
+ const filePath = path.join("/", filename);
22
+ await new Promise((resolve, reject) => {
23
+ try {
24
+ fs.unlink(filePath, resolve);
25
+ } catch (e) {
26
+ reject(e);
27
+ }
28
+ });
15
29
  }
16
30
 
17
31
  it("should return an empty obj when no files are found", async () => {
@@ -74,7 +88,7 @@ describe("findTextInJSXFiles", () => {
74
88
  };
75
89
 
76
90
  const result = await findComponentsInJSXFiles({
77
- directory: ".",
91
+ directory: "/",
78
92
  components: {
79
93
  "search-string": {
80
94
  name: "Search String",
@@ -119,8 +133,7 @@ describe("findTextInJSXFiles", () => {
119
133
  };
120
134
 
121
135
  const result = await findComponentsInJSXFiles({
122
- directory: ".",
123
- files: ["file1.jsx"],
136
+ files: ["/file1.jsx"],
124
137
  components: {
125
138
  "search-string": {
126
139
  name: "Search String",
@@ -134,9 +147,8 @@ describe("findTextInJSXFiles", () => {
134
147
  expect(result).toEqual(expectedResult);
135
148
 
136
149
  try {
137
- const result2 = await findComponentsInJSXFiles({
138
- directory: ".",
139
- files: ["file2.jsx"],
150
+ await findComponentsInJSXFiles({
151
+ files: ["/file2.jsx"],
140
152
  components: {
141
153
  "search-string": {
142
154
  name: "Search String",
@@ -1,4 +1,4 @@
1
- import fs from "fs-extra";
1
+ import fs from "fs";
2
2
  import glob from "glob";
3
3
  import { parse } from "@babel/parser";
4
4
  import traverse from "@babel/traverse";
@@ -43,11 +43,14 @@ async function generateSuggestions(flags: {
43
43
  console.log(JSON.stringify(results, null, 2));
44
44
  }
45
45
 
46
- async function findComponentsInJSXFiles(params: {
47
- directory: string;
48
- files?: string[];
49
- components: FetchComponentResponse;
50
- }): Promise<{ [apiId: string]: Result }> {
46
+ async function findComponentsInJSXFiles(
47
+ params: (
48
+ | { directory: string; files?: string[] }
49
+ | { files: string[]; directory?: string }
50
+ ) & {
51
+ components: FetchComponentResponse;
52
+ }
53
+ ): Promise<{ [apiId: string]: Result }> {
51
54
  const result: { [apiId: string]: Result } = {};
52
55
  const files =
53
56
  params.files ||
@@ -57,83 +60,90 @@ async function findComponentsInJSXFiles(params: {
57
60
 
58
61
  const promises: Promise<any>[] = [];
59
62
 
60
- for (const file of files) {
61
- promises.push(
62
- fs.readFile(file, "utf-8").then((code) => {
63
- const ast = parse(code, {
64
- sourceType: "module",
65
- plugins: ["jsx", "typescript"],
66
- });
67
-
68
- traverse(ast, {
69
- JSXText(path) {
70
- for (const [compApiId, component] of Object.entries(
71
- params.components,
72
- )) {
73
- // If we haven't seen this component before, add it to the result
74
- if (!result[compApiId]) {
75
- result[compApiId] = {
76
- apiId: compApiId,
77
- ...component,
78
- occurrences: {},
79
- };
80
- }
63
+ async function handleFile(file: string) {
64
+ const code = await new Promise<string>((resolve, reject) =>
65
+ fs.readFile(file, "utf-8", (err, data) => {
66
+ if (err) {
67
+ reject(err);
68
+ } else {
69
+ resolve(data);
70
+ }
71
+ })
72
+ );
73
+
74
+ const ast = parse(code, {
75
+ sourceType: "module",
76
+ plugins: ["jsx", "typescript"],
77
+ });
81
78
 
82
- if (
83
- // Skip white space lines
84
- !/^\s*$/.test(path.node.value) &&
85
- !/^\s*$/.test(component.text) &&
86
- path.node.value.includes(component.text)
87
- ) {
88
- // Escape all special characters from the text so we can use it in a regex
89
- const escapedText = component.text.replace(
90
- /[.*+?^${}()|[\]\\]/g,
91
- "\\$&",
92
- );
93
- const regex = new RegExp(escapedText, "g");
94
- let match;
95
- while ((match = regex.exec(path.node.value)) !== null) {
96
- const lines = path.node.value
97
- .slice(0, match.index)
98
- .split("\n");
99
-
100
- if (!path.node.loc) {
101
- continue;
102
- }
103
-
104
- const lineNumber =
105
- path.node.loc.start.line + lines.length - 1;
106
-
107
- const codeLines = code.split("\n");
108
- const line = codeLines[lineNumber - 1];
109
- const preview = replaceAt(
110
- line,
111
- match.index,
112
- component.text,
113
- `${component.text}`,
114
- );
115
-
116
- // Initialize the occurrences array if it doesn't exist
117
- if (!result[compApiId]["occurrences"][file]) {
118
- result[compApiId]["occurrences"][file] = [];
119
- }
120
-
121
- result[compApiId]["occurrences"][file].push({
122
- lineNumber,
123
- preview,
124
- });
125
- }
79
+ traverse(ast, {
80
+ JSXText(path) {
81
+ for (const [compApiId, component] of Object.entries(
82
+ params.components
83
+ )) {
84
+ // If we haven't seen this component before, add it to the result
85
+ if (!result[compApiId]) {
86
+ result[compApiId] = {
87
+ apiId: compApiId,
88
+ ...component,
89
+ occurrences: {},
90
+ };
91
+ }
92
+
93
+ if (
94
+ // Skip white space lines
95
+ !/^\s*$/.test(path.node.value) &&
96
+ !/^\s*$/.test(component.text) &&
97
+ path.node.value.includes(component.text)
98
+ ) {
99
+ // Escape all special characters from the text so we can use it in a regex
100
+ const escapedText = component.text.replace(
101
+ /[.*+?^${}()|[\]\\]/g,
102
+ "\\$&"
103
+ );
104
+ const regex = new RegExp(escapedText, "g");
105
+ let match;
106
+ while ((match = regex.exec(path.node.value)) !== null) {
107
+ const lines = path.node.value.slice(0, match.index).split("\n");
108
+
109
+ if (!path.node.loc) {
110
+ continue;
126
111
  }
127
112
 
128
- // Remove from result if no occurrences were found
129
- if (Object.keys(result[compApiId]["occurrences"]).length === 0) {
130
- delete result[compApiId];
113
+ const lineNumber = path.node.loc.start.line + lines.length - 1;
114
+
115
+ const codeLines = code.split("\n");
116
+ const line = codeLines[lineNumber - 1];
117
+ const preview = replaceAt(
118
+ line,
119
+ match.index,
120
+ component.text,
121
+ `${component.text}`
122
+ );
123
+
124
+ // Initialize the occurrences array if it doesn't exist
125
+ if (!result[compApiId]["occurrences"][file]) {
126
+ result[compApiId]["occurrences"][file] = [];
131
127
  }
128
+
129
+ result[compApiId]["occurrences"][file].push({
130
+ lineNumber,
131
+ preview,
132
+ });
132
133
  }
133
- },
134
- });
135
- }),
136
- );
134
+ }
135
+
136
+ // Remove from result if no occurrences were found
137
+ if (Object.keys(result[compApiId]["occurrences"]).length === 0) {
138
+ delete result[compApiId];
139
+ }
140
+ }
141
+ },
142
+ });
143
+ }
144
+
145
+ for (const file of files) {
146
+ promises.push(handleFile(file));
137
147
  }
138
148
 
139
149
  await Promise.all(promises);
@@ -145,7 +155,7 @@ function replaceAt(
145
155
  str: string,
146
156
  index: number,
147
157
  searchString: string,
148
- replacement: string,
158
+ replacement: string
149
159
  ) {
150
160
  return (
151
161
  str.substring(0, index) +