@intlayer/chokidar 3.3.4 → 3.3.5

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.
@@ -50,7 +50,13 @@ const fetchDistantDictionaries = async (options) => {
50
50
  const distantDictionariesKeys = options.dictionaryKeys;
51
51
  const limit = (0, import_p_limit.default)(5);
52
52
  const processDictionary = async (dictionaryKey) => {
53
- import_log.logger.updateStatus(dictionaryKey, "distant", { status: "fetching" });
53
+ import_log.logger.updateStatus([
54
+ {
55
+ dictionaryKey,
56
+ type: "distant",
57
+ status: { status: "fetching" }
58
+ }
59
+ ]);
54
60
  try {
55
61
  const getDictionaryResult = await intlayerAPI.dictionary.getDictionary(
56
62
  dictionaryKey,
@@ -63,19 +69,27 @@ const fetchDistantDictionaries = async (options) => {
63
69
  if (!distantDictionary) {
64
70
  throw new Error(`Dictionary ${dictionaryKey} not found on remote`);
65
71
  }
66
- import_log.logger.updateStatus(dictionaryKey, "distant", { status: "imported" });
72
+ import_log.logger.updateStatus([
73
+ { dictionaryKey, type: "distant", status: { status: "imported" } }
74
+ ]);
67
75
  return distantDictionary;
68
76
  } catch (error) {
69
- import_log.logger.updateStatus(dictionaryKey, "distant", {
70
- status: "error",
71
- error,
72
- errorMessage: `${options?.logPrefix ?? ""}Error fetching dictionary ${dictionaryKey}: ${error}`
73
- });
77
+ import_log.logger.updateStatus([
78
+ {
79
+ dictionaryKey,
80
+ type: "distant",
81
+ status: {
82
+ status: "error",
83
+ error,
84
+ errorMessage: `${options?.logPrefix ?? ""}Error fetching dictionary ${dictionaryKey}: ${error}`
85
+ }
86
+ }
87
+ ]);
74
88
  return void 0;
75
89
  }
76
90
  };
77
91
  const fetchPromises = distantDictionariesKeys.map(
78
- (dictionaryKey) => limit(() => processDictionary(dictionaryKey))
92
+ (dictionaryKey) => limit(async () => await processDictionary(dictionaryKey))
79
93
  );
80
94
  const result = await Promise.all(fetchPromises);
81
95
  const statuses = import_log.logger.getStatuses();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/fetchDistantDictionaries.ts"],"sourcesContent":["// @ts-ignore @intlayer/backend not build yet\nimport { type DictionaryAPI } from '@intlayer/backend';\nimport { getConfiguration } from '@intlayer/config';\n// @ts-ignore @intlayer/design-system not build yet\nimport { getIntlayerAPI } from '@intlayer/design-system/libs';\nimport pLimit from 'p-limit';\nimport { logger } from './log';\n\ntype FetchDistantDictionariesOptions = {\n dictionaryKeys: string[];\n newDictionariesPath?: string;\n logPrefix?: string;\n};\n\n/**\n * Fetch distant dictionaries and update the logger with their statuses.\n */\nexport const fetchDistantDictionaries = async (\n options: FetchDistantDictionariesOptions\n): Promise<DictionaryAPI[]> => {\n try {\n const config = getConfiguration();\n const { clientId, clientSecret } = config.editor;\n const intlayerAPI = getIntlayerAPI(undefined, config);\n\n if (!clientId || !clientSecret) {\n throw new Error(\n 'Missing OAuth2 client ID or client secret. To get access token go to https://intlayer.org/dashboard/project.'\n );\n }\n\n const oAuth2TokenResult = await intlayerAPI.auth.getOAuth2AccessToken();\n\n const oAuth2AccessToken = oAuth2TokenResult.data?.accessToken;\n\n const distantDictionariesKeys = options.dictionaryKeys;\n\n // Process dictionaries in parallel with a concurrency limit\n const limit = pLimit(5); // Adjust the limit as needed\n\n const processDictionary = async (\n dictionaryKey: string\n ): Promise<DictionaryAPI | undefined> => {\n logger.updateStatus(dictionaryKey, 'distant', { status: 'fetching' });\n\n try {\n // Fetch the dictionary\n const getDictionaryResult = await intlayerAPI.dictionary.getDictionary(\n dictionaryKey,\n undefined,\n {\n headers: { Authorization: `Bearer ${oAuth2AccessToken}` },\n }\n );\n\n const distantDictionary = getDictionaryResult.data;\n\n if (!distantDictionary) {\n throw new Error(`Dictionary ${dictionaryKey} not found on remote`);\n }\n\n logger.updateStatus(dictionaryKey, 'distant', { status: 'imported' });\n\n return distantDictionary;\n } catch (error) {\n logger.updateStatus(dictionaryKey, 'distant', {\n status: 'error',\n error: error as Error,\n errorMessage: `${options?.logPrefix ?? ''}Error fetching dictionary ${dictionaryKey}: ${error}`,\n });\n return undefined;\n }\n };\n\n const fetchPromises = distantDictionariesKeys.map((dictionaryKey) =>\n limit(() => processDictionary(dictionaryKey))\n );\n\n const result = await Promise.all(fetchPromises);\n\n // Output any error messages\n const statuses = logger.getStatuses();\n for (const statusObj of statuses) {\n const currentState = statusObj.state.find((s) => s.type === 'distant');\n if (currentState && currentState.errorMessage) {\n console.error(currentState.errorMessage);\n }\n }\n\n // Remove undefined values\n const filteredResult = result.filter(\n (dict): dict is DictionaryAPI => dict !== undefined\n );\n\n return filteredResult;\n } catch (error) {\n console.error(error);\n return [];\n }\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,oBAAiC;AAEjC,kBAA+B;AAC/B,qBAAmB;AACnB,iBAAuB;AAWhB,MAAM,2BAA2B,OACtC,YAC6B;AAC7B,MAAI;AACF,UAAM,aAAS,gCAAiB;AAChC,UAAM,EAAE,UAAU,aAAa,IAAI,OAAO;AAC1C,UAAM,kBAAc,4BAAe,QAAW,MAAM;AAEpD,QAAI,CAAC,YAAY,CAAC,cAAc;AAC9B,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,oBAAoB,MAAM,YAAY,KAAK,qBAAqB;AAEtE,UAAM,oBAAoB,kBAAkB,MAAM;AAElD,UAAM,0BAA0B,QAAQ;AAGxC,UAAM,YAAQ,eAAAA,SAAO,CAAC;AAEtB,UAAM,oBAAoB,OACxB,kBACuC;AACvC,wBAAO,aAAa,eAAe,WAAW,EAAE,QAAQ,WAAW,CAAC;AAEpE,UAAI;AAEF,cAAM,sBAAsB,MAAM,YAAY,WAAW;AAAA,UACvD;AAAA,UACA;AAAA,UACA;AAAA,YACE,SAAS,EAAE,eAAe,UAAU,iBAAiB,GAAG;AAAA,UAC1D;AAAA,QACF;AAEA,cAAM,oBAAoB,oBAAoB;AAE9C,YAAI,CAAC,mBAAmB;AACtB,gBAAM,IAAI,MAAM,cAAc,aAAa,sBAAsB;AAAA,QACnE;AAEA,0BAAO,aAAa,eAAe,WAAW,EAAE,QAAQ,WAAW,CAAC;AAEpE,eAAO;AAAA,MACT,SAAS,OAAO;AACd,0BAAO,aAAa,eAAe,WAAW;AAAA,UAC5C,QAAQ;AAAA,UACR;AAAA,UACA,cAAc,GAAG,SAAS,aAAa,EAAE,6BAA6B,aAAa,KAAK,KAAK;AAAA,QAC/F,CAAC;AACD,eAAO;AAAA,MACT;AAAA,IACF;AAEA,UAAM,gBAAgB,wBAAwB;AAAA,MAAI,CAAC,kBACjD,MAAM,MAAM,kBAAkB,aAAa,CAAC;AAAA,IAC9C;AAEA,UAAM,SAAS,MAAM,QAAQ,IAAI,aAAa;AAG9C,UAAM,WAAW,kBAAO,YAAY;AACpC,eAAW,aAAa,UAAU;AAChC,YAAM,eAAe,UAAU,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,SAAS;AACrE,UAAI,gBAAgB,aAAa,cAAc;AAC7C,gBAAQ,MAAM,aAAa,YAAY;AAAA,MACzC;AAAA,IACF;AAGA,UAAM,iBAAiB,OAAO;AAAA,MAC5B,CAAC,SAAgC,SAAS;AAAA,IAC5C;AAEA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ,MAAM,KAAK;AACnB,WAAO,CAAC;AAAA,EACV;AACF;","names":["pLimit"]}
1
+ {"version":3,"sources":["../../src/fetchDistantDictionaries.ts"],"sourcesContent":["// @ts-ignore @intlayer/backend not build yet\nimport { type DictionaryAPI } from '@intlayer/backend';\nimport { getConfiguration } from '@intlayer/config';\n// @ts-ignore @intlayer/design-system not build yet\nimport { getIntlayerAPI } from '@intlayer/design-system/libs';\nimport pLimit from 'p-limit';\nimport { logger } from './log';\n\ntype FetchDistantDictionariesOptions = {\n dictionaryKeys: string[];\n newDictionariesPath?: string;\n logPrefix?: string;\n};\n\n/**\n * Fetch distant dictionaries and update the logger with their statuses.\n */\nexport const fetchDistantDictionaries = async (\n options: FetchDistantDictionariesOptions\n): Promise<DictionaryAPI[]> => {\n try {\n const config = getConfiguration();\n const { clientId, clientSecret } = config.editor;\n const intlayerAPI = getIntlayerAPI(undefined, config);\n\n if (!clientId || !clientSecret) {\n throw new Error(\n 'Missing OAuth2 client ID or client secret. To get access token go to https://intlayer.org/dashboard/project.'\n );\n }\n\n const oAuth2TokenResult = await intlayerAPI.auth.getOAuth2AccessToken();\n\n const oAuth2AccessToken = oAuth2TokenResult.data?.accessToken;\n\n const distantDictionariesKeys = options.dictionaryKeys;\n\n // Process dictionaries in parallel with a concurrency limit\n const limit = pLimit(5); // Adjust the limit as needed\n\n const processDictionary = async (\n dictionaryKey: string\n ): Promise<DictionaryAPI | undefined> => {\n logger.updateStatus([\n {\n dictionaryKey,\n type: 'distant',\n status: { status: 'fetching' },\n },\n ]);\n\n try {\n // Fetch the dictionary\n const getDictionaryResult = await intlayerAPI.dictionary.getDictionary(\n dictionaryKey,\n undefined,\n {\n headers: { Authorization: `Bearer ${oAuth2AccessToken}` },\n }\n );\n\n const distantDictionary = getDictionaryResult.data;\n\n if (!distantDictionary) {\n throw new Error(`Dictionary ${dictionaryKey} not found on remote`);\n }\n\n logger.updateStatus([\n { dictionaryKey, type: 'distant', status: { status: 'imported' } },\n ]);\n\n return distantDictionary;\n } catch (error) {\n logger.updateStatus([\n {\n dictionaryKey,\n type: 'distant',\n status: {\n status: 'error',\n error: error as Error,\n errorMessage: `${options?.logPrefix ?? ''}Error fetching dictionary ${dictionaryKey}: ${error}`,\n },\n },\n ]);\n return undefined;\n }\n };\n\n const fetchPromises = distantDictionariesKeys.map((dictionaryKey) =>\n limit(async () => await processDictionary(dictionaryKey))\n );\n\n const result = await Promise.all(fetchPromises);\n\n // Output any error messages\n const statuses = logger.getStatuses();\n for (const statusObj of statuses) {\n const currentState = statusObj.state.find((s) => s.type === 'distant');\n if (currentState && currentState.errorMessage) {\n console.error(currentState.errorMessage);\n }\n }\n\n // Remove undefined values\n const filteredResult = result.filter(\n (dict): dict is DictionaryAPI => dict !== undefined\n );\n\n return filteredResult;\n } catch (error) {\n console.error(error);\n return [];\n }\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,oBAAiC;AAEjC,kBAA+B;AAC/B,qBAAmB;AACnB,iBAAuB;AAWhB,MAAM,2BAA2B,OACtC,YAC6B;AAC7B,MAAI;AACF,UAAM,aAAS,gCAAiB;AAChC,UAAM,EAAE,UAAU,aAAa,IAAI,OAAO;AAC1C,UAAM,kBAAc,4BAAe,QAAW,MAAM;AAEpD,QAAI,CAAC,YAAY,CAAC,cAAc;AAC9B,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,oBAAoB,MAAM,YAAY,KAAK,qBAAqB;AAEtE,UAAM,oBAAoB,kBAAkB,MAAM;AAElD,UAAM,0BAA0B,QAAQ;AAGxC,UAAM,YAAQ,eAAAA,SAAO,CAAC;AAEtB,UAAM,oBAAoB,OACxB,kBACuC;AACvC,wBAAO,aAAa;AAAA,QAClB;AAAA,UACE;AAAA,UACA,MAAM;AAAA,UACN,QAAQ,EAAE,QAAQ,WAAW;AAAA,QAC/B;AAAA,MACF,CAAC;AAED,UAAI;AAEF,cAAM,sBAAsB,MAAM,YAAY,WAAW;AAAA,UACvD;AAAA,UACA;AAAA,UACA;AAAA,YACE,SAAS,EAAE,eAAe,UAAU,iBAAiB,GAAG;AAAA,UAC1D;AAAA,QACF;AAEA,cAAM,oBAAoB,oBAAoB;AAE9C,YAAI,CAAC,mBAAmB;AACtB,gBAAM,IAAI,MAAM,cAAc,aAAa,sBAAsB;AAAA,QACnE;AAEA,0BAAO,aAAa;AAAA,UAClB,EAAE,eAAe,MAAM,WAAW,QAAQ,EAAE,QAAQ,WAAW,EAAE;AAAA,QACnE,CAAC;AAED,eAAO;AAAA,MACT,SAAS,OAAO;AACd,0BAAO,aAAa;AAAA,UAClB;AAAA,YACE;AAAA,YACA,MAAM;AAAA,YACN,QAAQ;AAAA,cACN,QAAQ;AAAA,cACR;AAAA,cACA,cAAc,GAAG,SAAS,aAAa,EAAE,6BAA6B,aAAa,KAAK,KAAK;AAAA,YAC/F;AAAA,UACF;AAAA,QACF,CAAC;AACD,eAAO;AAAA,MACT;AAAA,IACF;AAEA,UAAM,gBAAgB,wBAAwB;AAAA,MAAI,CAAC,kBACjD,MAAM,YAAY,MAAM,kBAAkB,aAAa,CAAC;AAAA,IAC1D;AAEA,UAAM,SAAS,MAAM,QAAQ,IAAI,aAAa;AAG9C,UAAM,WAAW,kBAAO,YAAY;AACpC,eAAW,aAAa,UAAU;AAChC,YAAM,eAAe,UAAU,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,SAAS;AACrE,UAAI,gBAAgB,aAAa,cAAc;AAC7C,gBAAQ,MAAM,aAAa,YAAY;AAAA,MACzC;AAAA,IACF;AAGA,UAAM,iBAAiB,OAAO;AAAA,MAC5B,CAAC,SAAgC,SAAS;AAAA,IAC5C;AAEA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ,MAAM,KAAK;AACnB,WAAO,CAAC;AAAA,EACV;AACF;","names":["pLimit"]}
@@ -48,9 +48,13 @@ const loadDictionaries = async (contentDeclarationsPaths) => {
48
48
  const localDictionaries = await (0, import_loadContentDeclaration.loadContentDeclarations)(files);
49
49
  const localDictionaryKeys = localDictionaries.map((dict) => dict.key);
50
50
  import_log.logger.init(localDictionaryKeys, []);
51
- for (const dict of localDictionaries) {
52
- import_log.logger.updateStatus(dict.key, "local", { status: "built" });
53
- }
51
+ import_log.logger.updateStatus(
52
+ localDictionaries.map((dict) => ({
53
+ dictionaryKey: dict.key,
54
+ type: "local",
55
+ status: { status: "built" }
56
+ }))
57
+ );
54
58
  let distantDictionaries = [];
55
59
  let distantDictionaryKeys = [];
56
60
  let mergedDictionaries = localDictionaries;
@@ -71,7 +75,7 @@ const loadDictionaries = async (contentDeclarationsPaths) => {
71
75
  arrayMerge: (0, import_mergeDictionaries.mergeByKey)("key")
72
76
  });
73
77
  }
74
- } catch (error) {
78
+ } catch (_error) {
75
79
  console.error("Error during fetching distant dictionaries");
76
80
  }
77
81
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/loadDictionaries/loadDictionaries.ts"],"sourcesContent":["// @ts-ignore @intlayer/backend not build yet\nimport { type DictionaryAPI } from '@intlayer/backend';\nimport { getConfiguration } from '@intlayer/config';\nimport { Dictionary } from '@intlayer/core';\nimport merge from 'deepmerge';\nimport { fetchDistantDictionaryKeys } from '../fetchDistantDictionaryKeys';\nimport { logger } from '../log';\nimport { mergeByKey } from '../mergeDictionaries';\nimport { sortAlphabetically } from '../utils';\nimport { loadContentDeclarations } from './loadContentDeclaration';\nimport { loadDistantDictionaries } from './loadDistantDictionaries';\n\nconst LOG_PREFIX = '[intlayer] ';\n\nexport const loadDictionaries = async (\n contentDeclarationsPaths: string[] | string\n): Promise<Dictionary[]> => {\n try {\n const { editor } = getConfiguration();\n\n console.info(`${LOG_PREFIX}Dictionaries:`);\n\n const files = Array.isArray(contentDeclarationsPaths)\n ? contentDeclarationsPaths\n : [contentDeclarationsPaths];\n\n const localDictionaries: Dictionary[] =\n await loadContentDeclarations(files);\n const localDictionaryKeys = localDictionaries.map((dict) => dict.key);\n\n // Initialize the logger with both local and distant dictionaries\n logger.init(localDictionaryKeys, []);\n\n // Update logger statuses for local dictionaries\n for (const dict of localDictionaries) {\n logger.updateStatus(dict.key, 'local', { status: 'built' });\n }\n\n let distantDictionaries: DictionaryAPI[] = [];\n let distantDictionaryKeys: string[] = [];\n let mergedDictionaries = localDictionaries;\n\n if (editor.clientId && editor.clientSecret) {\n try {\n // Fetch distant dictionary keys\n distantDictionaryKeys = await fetchDistantDictionaryKeys();\n\n const orderedDistantDictionaryKeys =\n distantDictionaryKeys.sort(sortAlphabetically);\n // Add distant dictionaries to the logger\n logger.addDictionaryKeys('distant', orderedDistantDictionaryKeys);\n\n // Fetch distant dictionaries\n distantDictionaries = await loadDistantDictionaries({\n dictionaryKeys: orderedDistantDictionaryKeys,\n });\n if (editor.dictionaryPriorityStrategy === 'distant_first') {\n // Merge the dictionaries\n mergedDictionaries = merge(localDictionaries, distantDictionaries, {\n arrayMerge: mergeByKey('key'),\n });\n } else {\n // Merge the dictionaries\n mergedDictionaries = merge(distantDictionaries, localDictionaries, {\n arrayMerge: mergeByKey('key'),\n });\n }\n } catch (error) {\n console.error('Error during fetching distant dictionaries');\n }\n }\n\n // Ensure the logger is stopped\n logger.stop();\n\n return mergedDictionaries;\n } catch (error) {\n // Ensure the logger is stopped\n logger.stop();\n\n throw error; // Re-throw the error after logging\n }\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,oBAAiC;AAEjC,uBAAkB;AAClB,wCAA2C;AAC3C,iBAAuB;AACvB,+BAA2B;AAC3B,mBAAmC;AACnC,oCAAwC;AACxC,qCAAwC;AAExC,MAAM,aAAa;AAEZ,MAAM,mBAAmB,OAC9B,6BAC0B;AAC1B,MAAI;AACF,UAAM,EAAE,OAAO,QAAI,gCAAiB;AAEpC,YAAQ,KAAK,GAAG,UAAU,eAAe;AAEzC,UAAM,QAAQ,MAAM,QAAQ,wBAAwB,IAChD,2BACA,CAAC,wBAAwB;AAE7B,UAAM,oBACJ,UAAM,uDAAwB,KAAK;AACrC,UAAM,sBAAsB,kBAAkB,IAAI,CAAC,SAAS,KAAK,GAAG;AAGpE,sBAAO,KAAK,qBAAqB,CAAC,CAAC;AAGnC,eAAW,QAAQ,mBAAmB;AACpC,wBAAO,aAAa,KAAK,KAAK,SAAS,EAAE,QAAQ,QAAQ,CAAC;AAAA,IAC5D;AAEA,QAAI,sBAAuC,CAAC;AAC5C,QAAI,wBAAkC,CAAC;AACvC,QAAI,qBAAqB;AAEzB,QAAI,OAAO,YAAY,OAAO,cAAc;AAC1C,UAAI;AAEF,gCAAwB,UAAM,8DAA2B;AAEzD,cAAM,+BACJ,sBAAsB,KAAK,+BAAkB;AAE/C,0BAAO,kBAAkB,WAAW,4BAA4B;AAGhE,8BAAsB,UAAM,wDAAwB;AAAA,UAClD,gBAAgB;AAAA,QAClB,CAAC;AACD,YAAI,OAAO,+BAA+B,iBAAiB;AAEzD,mCAAqB,iBAAAA,SAAM,mBAAmB,qBAAqB;AAAA,YACjE,gBAAY,qCAAW,KAAK;AAAA,UAC9B,CAAC;AAAA,QACH,OAAO;AAEL,mCAAqB,iBAAAA,SAAM,qBAAqB,mBAAmB;AAAA,YACjE,gBAAY,qCAAW,KAAK;AAAA,UAC9B,CAAC;AAAA,QACH;AAAA,MACF,SAAS,OAAO;AACd,gBAAQ,MAAM,4CAA4C;AAAA,MAC5D;AAAA,IACF;AAGA,sBAAO,KAAK;AAEZ,WAAO;AAAA,EACT,SAAS,OAAO;AAEd,sBAAO,KAAK;AAEZ,UAAM;AAAA,EACR;AACF;","names":["merge"]}
1
+ {"version":3,"sources":["../../../src/loadDictionaries/loadDictionaries.ts"],"sourcesContent":["// @ts-ignore @intlayer/backend not build yet\nimport { type DictionaryAPI } from '@intlayer/backend';\nimport { getConfiguration } from '@intlayer/config';\nimport { Dictionary } from '@intlayer/core';\nimport merge from 'deepmerge';\nimport { fetchDistantDictionaryKeys } from '../fetchDistantDictionaryKeys';\nimport { logger } from '../log';\nimport { mergeByKey } from '../mergeDictionaries';\nimport { sortAlphabetically } from '../utils';\nimport { loadContentDeclarations } from './loadContentDeclaration';\nimport { loadDistantDictionaries } from './loadDistantDictionaries';\n\nconst LOG_PREFIX = '[intlayer] ';\n\nexport const loadDictionaries = async (\n contentDeclarationsPaths: string[] | string\n): Promise<Dictionary[]> => {\n try {\n const { editor } = getConfiguration();\n\n console.info(`${LOG_PREFIX}Dictionaries:`);\n\n const files = Array.isArray(contentDeclarationsPaths)\n ? contentDeclarationsPaths\n : [contentDeclarationsPaths];\n\n const localDictionaries: Dictionary[] =\n await loadContentDeclarations(files);\n const localDictionaryKeys = localDictionaries.map((dict) => dict.key);\n\n // Initialize the logger with both local and distant dictionaries\n logger.init(localDictionaryKeys, []);\n\n // Update logger statuses for local dictionaries\n logger.updateStatus(\n localDictionaries.map((dict) => ({\n dictionaryKey: dict.key,\n type: 'local',\n status: { status: 'built' },\n }))\n );\n\n let distantDictionaries: DictionaryAPI[] = [];\n let distantDictionaryKeys: string[] = [];\n let mergedDictionaries = localDictionaries;\n\n if (editor.clientId && editor.clientSecret) {\n try {\n // Fetch distant dictionary keys\n distantDictionaryKeys = await fetchDistantDictionaryKeys();\n\n const orderedDistantDictionaryKeys =\n distantDictionaryKeys.sort(sortAlphabetically);\n // Add distant dictionaries to the logger\n logger.addDictionaryKeys('distant', orderedDistantDictionaryKeys);\n\n // Fetch distant dictionaries\n distantDictionaries = await loadDistantDictionaries({\n dictionaryKeys: orderedDistantDictionaryKeys,\n });\n if (editor.dictionaryPriorityStrategy === 'distant_first') {\n // Merge the dictionaries\n mergedDictionaries = merge(localDictionaries, distantDictionaries, {\n arrayMerge: mergeByKey('key'),\n });\n } else {\n // Merge the dictionaries\n mergedDictionaries = merge(distantDictionaries, localDictionaries, {\n arrayMerge: mergeByKey('key'),\n });\n }\n } catch (_error) {\n console.error('Error during fetching distant dictionaries');\n }\n }\n\n // Ensure the logger is stopped\n logger.stop();\n\n return mergedDictionaries;\n } catch (error) {\n // Ensure the logger is stopped\n logger.stop();\n\n throw error; // Re-throw the error after logging\n }\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,oBAAiC;AAEjC,uBAAkB;AAClB,wCAA2C;AAC3C,iBAAuB;AACvB,+BAA2B;AAC3B,mBAAmC;AACnC,oCAAwC;AACxC,qCAAwC;AAExC,MAAM,aAAa;AAEZ,MAAM,mBAAmB,OAC9B,6BAC0B;AAC1B,MAAI;AACF,UAAM,EAAE,OAAO,QAAI,gCAAiB;AAEpC,YAAQ,KAAK,GAAG,UAAU,eAAe;AAEzC,UAAM,QAAQ,MAAM,QAAQ,wBAAwB,IAChD,2BACA,CAAC,wBAAwB;AAE7B,UAAM,oBACJ,UAAM,uDAAwB,KAAK;AACrC,UAAM,sBAAsB,kBAAkB,IAAI,CAAC,SAAS,KAAK,GAAG;AAGpE,sBAAO,KAAK,qBAAqB,CAAC,CAAC;AAGnC,sBAAO;AAAA,MACL,kBAAkB,IAAI,CAAC,UAAU;AAAA,QAC/B,eAAe,KAAK;AAAA,QACpB,MAAM;AAAA,QACN,QAAQ,EAAE,QAAQ,QAAQ;AAAA,MAC5B,EAAE;AAAA,IACJ;AAEA,QAAI,sBAAuC,CAAC;AAC5C,QAAI,wBAAkC,CAAC;AACvC,QAAI,qBAAqB;AAEzB,QAAI,OAAO,YAAY,OAAO,cAAc;AAC1C,UAAI;AAEF,gCAAwB,UAAM,8DAA2B;AAEzD,cAAM,+BACJ,sBAAsB,KAAK,+BAAkB;AAE/C,0BAAO,kBAAkB,WAAW,4BAA4B;AAGhE,8BAAsB,UAAM,wDAAwB;AAAA,UAClD,gBAAgB;AAAA,QAClB,CAAC;AACD,YAAI,OAAO,+BAA+B,iBAAiB;AAEzD,mCAAqB,iBAAAA,SAAM,mBAAmB,qBAAqB;AAAA,YACjE,gBAAY,qCAAW,KAAK;AAAA,UAC9B,CAAC;AAAA,QACH,OAAO;AAEL,mCAAqB,iBAAAA,SAAM,qBAAqB,mBAAmB;AAAA,YACjE,gBAAY,qCAAW,KAAK;AAAA,UAC9B,CAAC;AAAA,QACH;AAAA,MACF,SAAS,QAAQ;AACf,gBAAQ,MAAM,4CAA4C;AAAA,MAC5D;AAAA,IACF;AAGA,sBAAO,KAAK;AAEZ,WAAO;AAAA,EACT,SAAS,OAAO;AAEd,sBAAO,KAAK;AAEZ,UAAM;AAAA,EACR;AACF;","names":["merge"]}
package/dist/cjs/log.cjs CHANGED
@@ -31,20 +31,25 @@ __export(log_exports, {
31
31
  logger: () => logger
32
32
  });
33
33
  module.exports = __toCommonJS(log_exports);
34
- var import_log_update = __toESM(require("log-update"));
34
+ var import_readline = __toESM(require("readline"));
35
35
  var import_utils = require('./utils.cjs');
36
+ const LINE_DETECTOR = "\u200B\u200B\u200B";
37
+ const SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
38
+ const RESET = "\x1B[0m";
39
+ const GREEN = "\x1B[32m";
40
+ const RED = "\x1B[31m";
41
+ const BLUE = "\x1B[34m";
42
+ const GREY = "\x1B[90m";
43
+ const GREY_DARK = "\x1B[90m";
36
44
  class Logger {
37
45
  dictionariesStatuses = [];
38
- spinnerFrames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
39
46
  spinnerTimer = null;
40
47
  maxDictionaryKeyLength = 0;
41
- // ANSI color codes
42
- RESET = "\x1B[0m";
43
- GREEN = "\x1B[32m";
44
- RED = "\x1B[31m";
45
- BLUE = "\x1B[34m";
46
- GREY = "\x1B[90m";
47
- GREY_DARK = "\x1B[90m";
48
+ previousLineCount = 0;
49
+ lineDifCounter = 0;
50
+ originalStdoutWrite = null;
51
+ extraLines = 0;
52
+ isUpdating = false;
48
53
  // Singleton instance
49
54
  static instance;
50
55
  constructor() {
@@ -139,49 +144,80 @@ class Logger {
139
144
  this.spinnerTimer = null;
140
145
  }
141
146
  }
147
+ // Method to update the terminal output
148
+ updateOutput(content) {
149
+ if (!this.originalStdoutWrite) {
150
+ this.originalStdoutWrite = process.stdout.write.bind(process.stdout);
151
+ this.extraLines = 0;
152
+ const write = (chunk, encoding, callback) => {
153
+ const str = typeof chunk === "string" ? chunk : chunk.toString();
154
+ const newLines = (str.match(/\n/g) ?? []).length;
155
+ if (!this.isUpdating) {
156
+ this.extraLines += newLines;
157
+ }
158
+ return this.originalStdoutWrite(chunk, encoding, callback);
159
+ };
160
+ process.stdout.write = write;
161
+ }
162
+ this.isUpdating = true;
163
+ const contentLines = content.split("\n");
164
+ const indexOfLineDetector = contentLines.indexOf(LINE_DETECTOR.trim());
165
+ if (indexOfLineDetector > 0) {
166
+ this.lineDifCounter = indexOfLineDetector;
167
+ } else {
168
+ this.lineDifCounter = 0;
169
+ }
170
+ const totalLinesToMoveUp = this.previousLineCount + this.lineDifCounter + this.extraLines;
171
+ import_readline.default.moveCursor(process.stdout, 0, -totalLinesToMoveUp);
172
+ import_readline.default.clearScreenDown(process.stdout);
173
+ contentLines.forEach((line) => {
174
+ process.stdout.write(`${line}\x1B[K
175
+ `);
176
+ });
177
+ this.previousLineCount = contentLines.length;
178
+ this.extraLines = 0;
179
+ this.isUpdating = false;
180
+ }
142
181
  stop() {
143
182
  this.stopSpinner();
144
- import_log_update.default.clear();
145
- const lines = this.dictionariesStatuses.map(
146
- (statusObj) => this.getStatusLine(statusObj)
147
- );
148
- console.log(lines.join("\n"));
149
183
  }
150
- updateStatus(dictionaryKey, type, status) {
151
- const statusObj = this.dictionariesStatuses.find(
152
- (ds) => ds.dictionaryKey === dictionaryKey
153
- );
154
- if (statusObj) {
155
- const state = statusObj.state.find((s) => s.type === type);
156
- if (state) {
157
- Object.assign(state, status);
158
- } else {
159
- if (status.status === void 0) {
160
- status.status = "pending";
184
+ updateStatus(dictionaries) {
185
+ for (const { dictionaryKey, type, status } of dictionaries) {
186
+ const statusObj = this.dictionariesStatuses.find(
187
+ (ds) => ds.dictionaryKey === dictionaryKey
188
+ );
189
+ if (statusObj) {
190
+ const state = statusObj.state.find((s) => s.type === type);
191
+ if (state) {
192
+ Object.assign(state, status);
193
+ } else {
194
+ if (status.status === void 0) {
195
+ status.status = "pending";
196
+ }
197
+ const newState = {
198
+ type,
199
+ status: status.status,
200
+ icon: status.icon ?? "",
201
+ error: status.error,
202
+ errorMessage: status.errorMessage,
203
+ spinnerFrameIndex: status.spinnerFrameIndex ?? 0
204
+ };
205
+ statusObj.state.push(newState);
161
206
  }
207
+ } else {
162
208
  const newState = {
163
209
  type,
164
- status: status.status,
210
+ status: status.status ?? "pending",
165
211
  icon: status.icon ?? "",
166
212
  error: status.error,
167
213
  errorMessage: status.errorMessage,
168
214
  spinnerFrameIndex: status.spinnerFrameIndex ?? 0
169
215
  };
170
- statusObj.state.push(newState);
216
+ this.dictionariesStatuses.push({
217
+ dictionaryKey,
218
+ state: [newState]
219
+ });
171
220
  }
172
- } else {
173
- const newState = {
174
- type,
175
- status: status.status ?? "pending",
176
- icon: status.icon ?? "",
177
- error: status.error,
178
- errorMessage: status.errorMessage,
179
- spinnerFrameIndex: status.spinnerFrameIndex ?? 0
180
- };
181
- this.dictionariesStatuses.push({
182
- dictionaryKey,
183
- state: [newState]
184
- });
185
221
  }
186
222
  this.updateAllStatusLines();
187
223
  }
@@ -204,34 +240,45 @@ class Logger {
204
240
  let colorEnd = "";
205
241
  let icon = this.getStatusIcon(state.status);
206
242
  if (state.status === "fetching") {
207
- icon = this.spinnerFrames[state.spinnerFrameIndex % this.spinnerFrames.length];
208
- colorStart = this.BLUE;
209
- colorEnd = this.RESET;
243
+ icon = SPINNER_FRAMES[state.spinnerFrameIndex % SPINNER_FRAMES.length];
244
+ colorStart = BLUE;
245
+ colorEnd = RESET;
210
246
  } else if (state.status === "error") {
211
- colorStart = this.RED;
212
- colorEnd = this.RESET;
247
+ colorStart = RED;
248
+ colorEnd = RESET;
213
249
  } else if (state.status === "imported" || state.status === "built") {
214
- colorStart = this.GREEN;
215
- colorEnd = this.RESET;
250
+ colorStart = GREEN;
251
+ colorEnd = RESET;
216
252
  } else {
217
- colorStart = this.GREY;
218
- colorEnd = this.RESET;
253
+ colorStart = GREY;
254
+ colorEnd = RESET;
219
255
  }
220
- const statusBlock = `${this.GREY_DARK}[${state.type}: ${colorStart}${icon} ${state.status}${this.GREY_DARK}]${colorEnd}`;
256
+ const statusBlock = `${GREY_DARK}[${state.type}: ${colorStart}${icon} ${state.status}${GREY_DARK}]${colorEnd}`;
221
257
  return `${colorStart}${statusBlock}${colorEnd}`;
222
258
  });
223
259
  return `- ${paddedKey} ${states.join(" ")}`;
224
260
  }
261
+ // Replace logUpdate calls with your custom methods
225
262
  updateAllStatusLines() {
263
+ const terminalHeight = process.stdout.rows;
264
+ const maxVisibleLines = terminalHeight - 1;
226
265
  const lines = this.dictionariesStatuses.map((statusObj) => {
227
266
  statusObj.state.forEach((state) => {
228
267
  if (state.status === "fetching") {
229
- state.spinnerFrameIndex = (state.spinnerFrameIndex + 1) % this.spinnerFrames.length;
268
+ state.spinnerFrameIndex = (state.spinnerFrameIndex + 1) % SPINNER_FRAMES.length;
230
269
  }
231
270
  });
232
271
  return this.getStatusLine(statusObj);
233
272
  });
234
- (0, import_log_update.default)(lines.join("\n"));
273
+ let content;
274
+ if (lines.length > maxVisibleLines) {
275
+ const visibleLines = lines.slice(0, maxVisibleLines - 5);
276
+ const summary = `... and ${lines.length - visibleLines.length} more lines`;
277
+ content = LINE_DETECTOR + visibleLines.join("\n") + "\n" + summary;
278
+ } else {
279
+ content = lines.join("\n");
280
+ }
281
+ this.updateOutput(content);
235
282
  }
236
283
  getStatuses() {
237
284
  return this.dictionariesStatuses;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/log.ts"],"sourcesContent":["import logUpdate from 'log-update';\nimport { sortAlphabetically } from './utils';\n\nexport type State = {\n type: 'local' | 'distant';\n status: 'pending' | 'fetching' | 'fetched' | 'error' | 'imported' | 'built';\n icon?: string;\n error?: Error;\n errorMessage?: string;\n spinnerFrameIndex?: number;\n};\n\nexport type DictionariesStatus = {\n dictionaryKey: string;\n state: State[];\n};\n\nclass Logger {\n private dictionariesStatuses: DictionariesStatus[] = [];\n private spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n private spinnerTimer: NodeJS.Timeout | null = null;\n private maxDictionaryKeyLength: number = 0;\n\n // ANSI color codes\n private RESET = '\\x1b[0m';\n private GREEN = '\\x1b[32m';\n private RED = '\\x1b[31m';\n private BLUE = '\\x1b[34m';\n private GREY = '\\x1b[90m';\n private GREY_DARK = '\\x1b[90m';\n\n // Singleton instance\n private static instance: Logger;\n\n private constructor() {}\n\n public static getInstance(): Logger {\n if (!Logger.instance) {\n Logger.instance = new Logger();\n }\n return Logger.instance;\n }\n\n public init(\n localDictionariesKeys: string[],\n distantDictionariesKeys: string[]\n ) {\n const allKeys = Array.from(\n new Set(\n [...localDictionariesKeys, ...distantDictionariesKeys].sort(\n sortAlphabetically\n )\n )\n );\n\n this.maxDictionaryKeyLength = allKeys.reduce(\n (max, key) => (key.length > max ? key.length : max),\n 0\n );\n\n this.dictionariesStatuses = allKeys.map((dictionaryKey) => {\n const states: State[] = [];\n\n if (localDictionariesKeys.includes(dictionaryKey)) {\n states.push({\n type: 'local',\n status: 'pending',\n spinnerFrameIndex: 0,\n });\n }\n if (distantDictionariesKeys.includes(dictionaryKey)) {\n states.push({\n type: 'distant',\n status: 'pending',\n spinnerFrameIndex: 0,\n });\n }\n\n return {\n dictionaryKey,\n state: states,\n };\n });\n\n // Start spinner timer\n this.startSpinner();\n\n // Update all status lines (this will output the initial statuses)\n this.updateAllStatusLines();\n }\n\n // New method to add dictionary keys after initialization\n public addDictionaryKeys(\n type: 'local' | 'distant',\n dictionaryKeys: string[]\n ) {\n for (const dictionaryKey of dictionaryKeys) {\n // Update maxDictionaryKeyLength if the new key is longer\n if (dictionaryKey.length > this.maxDictionaryKeyLength) {\n this.maxDictionaryKeyLength = dictionaryKey.length;\n }\n\n let statusObj = this.dictionariesStatuses.find(\n (ds) => ds.dictionaryKey === dictionaryKey\n );\n\n if (!statusObj) {\n // If the dictionaryKey doesn't exist yet, create a new DictionariesStatus\n\n statusObj = {\n dictionaryKey,\n state: [],\n };\n this.dictionariesStatuses.push(statusObj);\n\n const newState: State = {\n type,\n status: 'pending',\n spinnerFrameIndex: 0,\n };\n statusObj.state.push(newState);\n } else {\n const existingState = statusObj.state.find((s) => s.type === type);\n if (!existingState) {\n // Add new state for the type\n\n const newState: State = {\n type,\n status: 'pending',\n spinnerFrameIndex: 0,\n };\n statusObj.state.push(newState);\n }\n }\n }\n\n // Call updateAllStatusLines() to refresh the output\n this.updateAllStatusLines();\n }\n\n private startSpinner() {\n if (!this.spinnerTimer) {\n this.spinnerTimer = setInterval(() => {\n this.updateAllStatusLines();\n }, 100); // Update every 100ms\n }\n }\n\n private stopSpinner() {\n if (this.spinnerTimer) {\n clearInterval(this.spinnerTimer);\n this.spinnerTimer = null;\n }\n }\n\n public stop() {\n this.stopSpinner();\n logUpdate.clear(); // Clear the logUpdate output\n const lines = this.dictionariesStatuses.map((statusObj) =>\n this.getStatusLine(statusObj)\n );\n console.log(lines.join('\\n')); // Output final statuses\n }\n\n public updateStatus(\n dictionaryKey: string,\n type: 'local' | 'distant',\n status: Partial<State>\n ) {\n const statusObj = this.dictionariesStatuses.find(\n (ds) => ds.dictionaryKey === dictionaryKey\n );\n if (statusObj) {\n const state = statusObj.state.find((s) => s.type === type);\n if (state) {\n // Update existing state\n Object.assign(state, status);\n } else {\n // If the state for this type doesn't exist yet, add it\n if (status.status === undefined) {\n status.status = 'pending'; // Provide default status\n }\n const newState: State = {\n type,\n status: status.status,\n icon: status.icon ?? '',\n error: status.error,\n errorMessage: status.errorMessage,\n spinnerFrameIndex: status.spinnerFrameIndex ?? 0,\n };\n statusObj.state.push(newState);\n }\n } else {\n // If the status object doesn't exist, create it\n const newState: State = {\n type,\n status: status.status ?? 'pending',\n icon: status.icon ?? '',\n error: status.error,\n errorMessage: status.errorMessage,\n spinnerFrameIndex: status.spinnerFrameIndex ?? 0,\n };\n this.dictionariesStatuses.push({\n dictionaryKey,\n state: [newState],\n });\n }\n\n // Update the display after status change\n this.updateAllStatusLines();\n }\n\n private getStatusIcon(status: string): string {\n const statusIcons: Record<string, string> = {\n pending: '⏲',\n fetching: '', // Spinner handled separately\n built: '✔',\n imported: '✔',\n error: '✖',\n };\n return statusIcons[status] ?? '';\n }\n\n private getStatusLine(statusObj: DictionariesStatus): string {\n const keyPadding =\n this.maxDictionaryKeyLength - statusObj.dictionaryKey.length;\n const paddedKey = `${statusObj.dictionaryKey}${' '.repeat(keyPadding)}`;\n\n const states = statusObj.state.map((state) => {\n let colorStart = '';\n let colorEnd = '';\n let icon = this.getStatusIcon(state.status);\n if (state.status === 'fetching') {\n // Use spinner frame\n icon =\n this.spinnerFrames[\n state.spinnerFrameIndex! % this.spinnerFrames.length\n ];\n colorStart = this.BLUE;\n colorEnd = this.RESET;\n } else if (state.status === 'error') {\n colorStart = this.RED;\n colorEnd = this.RESET;\n } else if (state.status === 'imported' || state.status === 'built') {\n colorStart = this.GREEN;\n colorEnd = this.RESET;\n } else {\n colorStart = this.GREY;\n colorEnd = this.RESET;\n }\n\n // Format the status block\n const statusBlock = `${this.GREY_DARK}[${state.type}: ${colorStart}${icon} ${state.status}${this.GREY_DARK}]${colorEnd}`;\n\n return `${colorStart}${statusBlock}${colorEnd}`;\n });\n\n return `- ${paddedKey} ${states.join(' ')}`;\n }\n\n private updateAllStatusLines() {\n const lines = this.dictionariesStatuses.map((statusObj) => {\n statusObj.state.forEach((state) => {\n if (state.status === 'fetching') {\n // Update spinner frame\n state.spinnerFrameIndex =\n (state.spinnerFrameIndex! + 1) % this.spinnerFrames.length;\n }\n });\n return this.getStatusLine(statusObj);\n });\n\n logUpdate(lines.join('\\n'));\n }\n\n public getStatuses() {\n return this.dictionariesStatuses;\n }\n}\n\nexport const logger = Logger.getInstance();\n"],"mappings":"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","names":["logUpdate"]}
1
+ {"version":3,"sources":["../../src/log.ts"],"sourcesContent":["import readline from 'readline';\nimport { sortAlphabetically } from './utils';\n\nexport type State = {\n type: 'local' | 'distant';\n status: 'pending' | 'fetching' | 'fetched' | 'error' | 'imported' | 'built';\n icon?: string;\n error?: Error;\n errorMessage?: string;\n spinnerFrameIndex?: number;\n};\n\nexport type DictionariesStatus = {\n dictionaryKey: string;\n state: State[];\n};\n\nconst LINE_DETECTOR = '\\u200B\\u200B\\u200B'; // Three zero-width spaces\nconst SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n\n// ANSI color codes\nconst RESET = '\\x1b[0m';\nconst GREEN = '\\x1b[32m';\nconst RED = '\\x1b[31m';\nconst BLUE = '\\x1b[34m';\nconst GREY = '\\x1b[90m';\nconst GREY_DARK = '\\x1b[90m';\n\nclass Logger {\n private dictionariesStatuses: DictionariesStatus[] = [];\n private spinnerTimer: NodeJS.Timeout | null = null;\n private maxDictionaryKeyLength: number = 0;\n private previousLineCount: number = 0;\n private lineDifCounter: number = 0;\n private originalStdoutWrite:\n | ((\n chunk: string | Uint8Array, // `chunk` can be either a string or a Uint8Array\n encoding?: BufferEncoding, // `encoding` is optional and should be a BufferEncoding\n callback?: (err?: Error | null) => void // `callback` is optional and a function\n ) => boolean)\n | null = null;\n private extraLines: number = 0;\n private isUpdating: boolean = false;\n\n // Singleton instance\n private static instance: Logger;\n\n private constructor() {}\n\n public static getInstance(): Logger {\n if (!Logger.instance) {\n Logger.instance = new Logger();\n }\n return Logger.instance;\n }\n\n public init(\n localDictionariesKeys: string[],\n distantDictionariesKeys: string[]\n ) {\n const allKeys = Array.from(\n new Set(\n [...localDictionariesKeys, ...distantDictionariesKeys].sort(\n sortAlphabetically\n )\n )\n );\n\n this.maxDictionaryKeyLength = allKeys.reduce(\n (max, key) => (key.length > max ? key.length : max),\n 0\n );\n\n this.dictionariesStatuses = allKeys.map((dictionaryKey) => {\n const states: State[] = [];\n\n if (localDictionariesKeys.includes(dictionaryKey)) {\n states.push({\n type: 'local',\n status: 'pending',\n spinnerFrameIndex: 0,\n });\n }\n if (distantDictionariesKeys.includes(dictionaryKey)) {\n states.push({\n type: 'distant',\n status: 'pending',\n spinnerFrameIndex: 0,\n });\n }\n\n return {\n dictionaryKey,\n state: states,\n };\n });\n\n // Start spinner timer\n this.startSpinner();\n\n // Update all status lines (this will output the initial statuses)\n this.updateAllStatusLines();\n }\n\n // New method to add dictionary keys after initialization\n public addDictionaryKeys(\n type: 'local' | 'distant',\n dictionaryKeys: string[]\n ) {\n for (const dictionaryKey of dictionaryKeys) {\n // Update maxDictionaryKeyLength if the new key is longer\n if (dictionaryKey.length > this.maxDictionaryKeyLength) {\n this.maxDictionaryKeyLength = dictionaryKey.length;\n }\n\n let statusObj = this.dictionariesStatuses.find(\n (ds) => ds.dictionaryKey === dictionaryKey\n );\n\n if (!statusObj) {\n // If the dictionaryKey doesn't exist yet, create a new DictionariesStatus\n\n statusObj = {\n dictionaryKey,\n state: [],\n };\n this.dictionariesStatuses.push(statusObj);\n\n const newState: State = {\n type,\n status: 'pending',\n spinnerFrameIndex: 0,\n };\n statusObj.state.push(newState);\n } else {\n const existingState = statusObj.state.find((s) => s.type === type);\n if (!existingState) {\n // Add new state for the type\n\n const newState: State = {\n type,\n status: 'pending',\n spinnerFrameIndex: 0,\n };\n statusObj.state.push(newState);\n }\n }\n }\n\n // Call updateAllStatusLines() to refresh the output\n this.updateAllStatusLines();\n }\n\n private startSpinner() {\n if (!this.spinnerTimer) {\n this.spinnerTimer = setInterval(() => {\n this.updateAllStatusLines();\n }, 100); // Update every 100ms\n }\n }\n\n private stopSpinner() {\n if (this.spinnerTimer) {\n clearInterval(this.spinnerTimer);\n this.spinnerTimer = null;\n }\n }\n\n // Method to update the terminal output\n private updateOutput(content: string) {\n // Monkey-patch process.stdout.write to keep track of extra lines\n if (!this.originalStdoutWrite) {\n this.originalStdoutWrite = process.stdout.write.bind(process.stdout);\n this.extraLines = 0;\n\n const write = (\n chunk: string | Uint8Array, // `chunk` can be either a string or a Uint8Array\n encoding?: BufferEncoding, // `encoding` is optional and should be a BufferEncoding\n callback?: (err?: Error | null) => void // `callback` is optional and a function\n ) => {\n const str = typeof chunk === 'string' ? chunk : chunk.toString();\n const newLines = (str.match(/\\n/g) ?? []).length;\n\n // If the write is not initiated by Logger's updateOutput method\n if (!this.isUpdating) {\n this.extraLines += newLines;\n }\n\n return this.originalStdoutWrite!(chunk, encoding, callback);\n };\n\n process.stdout.write = write as typeof process.stdout.write;\n }\n\n // Set a flag to indicate that updateOutput is running\n this.isUpdating = true;\n\n // Adjust lineDifCounter if LINE_DETECTOR is not the first line\n const contentLines = content.split('\\n');\n const indexOfLineDetector = contentLines.indexOf(LINE_DETECTOR.trim());\n\n if (indexOfLineDetector > 0) {\n // LINE_DETECTOR is not at the first line\n this.lineDifCounter = indexOfLineDetector;\n } else {\n this.lineDifCounter = 0;\n }\n\n // Calculate total lines to move up\n const totalLinesToMoveUp =\n this.previousLineCount + this.lineDifCounter + this.extraLines;\n\n // Move cursor up by totalLinesToMoveUp\n readline.moveCursor(process.stdout, 0, -totalLinesToMoveUp);\n\n // Clear all lines downwards\n readline.clearScreenDown(process.stdout);\n\n // Write the updated content\n contentLines.forEach((line) => {\n process.stdout.write(`${line}\\x1b[K\\n`);\n });\n\n // Update previousLineCount\n this.previousLineCount = contentLines.length;\n\n // Reset extraLines counter and updating flag\n this.extraLines = 0;\n this.isUpdating = false;\n }\n\n public stop() {\n this.stopSpinner();\n }\n\n public updateStatus(\n dictionaries: {\n dictionaryKey: string;\n type: 'local' | 'distant';\n status: Partial<State>;\n }[]\n ) {\n for (const { dictionaryKey, type, status } of dictionaries) {\n const statusObj = this.dictionariesStatuses.find(\n (ds) => ds.dictionaryKey === dictionaryKey\n );\n if (statusObj) {\n const state = statusObj.state.find((s) => s.type === type);\n if (state) {\n // Update existing state\n Object.assign(state, status);\n } else {\n // If the state for this type doesn't exist yet, add it\n if (status.status === undefined) {\n status.status = 'pending'; // Provide default status\n }\n const newState: State = {\n type,\n status: status.status,\n icon: status.icon ?? '',\n error: status.error,\n errorMessage: status.errorMessage,\n spinnerFrameIndex: status.spinnerFrameIndex ?? 0,\n };\n statusObj.state.push(newState);\n }\n } else {\n // If the status object doesn't exist, create it\n const newState: State = {\n type,\n status: status.status ?? 'pending',\n icon: status.icon ?? '',\n error: status.error,\n errorMessage: status.errorMessage,\n spinnerFrameIndex: status.spinnerFrameIndex ?? 0,\n };\n this.dictionariesStatuses.push({\n dictionaryKey,\n state: [newState],\n });\n }\n }\n\n // Update the display after status change\n this.updateAllStatusLines();\n }\n\n private getStatusIcon(status: string): string {\n const statusIcons: Record<string, string> = {\n pending: '⏲',\n fetching: '', // Spinner handled separately\n built: '✔',\n imported: '✔',\n error: '✖',\n };\n return statusIcons[status] ?? '';\n }\n\n private getStatusLine(statusObj: DictionariesStatus): string {\n const keyPadding =\n this.maxDictionaryKeyLength - statusObj.dictionaryKey.length;\n const paddedKey = `${statusObj.dictionaryKey}${' '.repeat(keyPadding)}`;\n\n const states = statusObj.state.map((state) => {\n let colorStart = '';\n let colorEnd = '';\n let icon = this.getStatusIcon(state.status);\n if (state.status === 'fetching') {\n // Use spinner frame\n icon = SPINNER_FRAMES[state.spinnerFrameIndex! % SPINNER_FRAMES.length];\n colorStart = BLUE;\n colorEnd = RESET;\n } else if (state.status === 'error') {\n colorStart = RED;\n colorEnd = RESET;\n } else if (state.status === 'imported' || state.status === 'built') {\n colorStart = GREEN;\n colorEnd = RESET;\n } else {\n colorStart = GREY;\n colorEnd = RESET;\n }\n\n // Format the status block\n const statusBlock = `${GREY_DARK}[${state.type}: ${colorStart}${icon} ${state.status}${GREY_DARK}]${colorEnd}`;\n\n return `${colorStart}${statusBlock}${colorEnd}`;\n });\n\n return `- ${paddedKey} ${states.join(' ')}`;\n }\n\n // Replace logUpdate calls with your custom methods\n private updateAllStatusLines() {\n const terminalHeight = process.stdout.rows;\n const maxVisibleLines = terminalHeight - 1;\n\n const lines = this.dictionariesStatuses.map((statusObj) => {\n statusObj.state.forEach((state) => {\n if (state.status === 'fetching') {\n // Update spinner frame\n state.spinnerFrameIndex =\n (state.spinnerFrameIndex! + 1) % SPINNER_FRAMES.length;\n }\n });\n return this.getStatusLine(statusObj);\n });\n\n let content;\n\n if (lines.length > maxVisibleLines) {\n const visibleLines = lines.slice(0, maxVisibleLines - 5);\n const summary = `... and ${lines.length - visibleLines.length} more lines`;\n content = LINE_DETECTOR + visibleLines.join('\\n') + '\\n' + summary;\n } else {\n content = lines.join('\\n');\n }\n\n this.updateOutput(content);\n }\n\n public getStatuses() {\n return this.dictionariesStatuses;\n }\n}\n\nexport const logger = Logger.getInstance();\n"],"mappings":"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","names":["readline"]}
@@ -17,7 +17,13 @@ const fetchDistantDictionaries = async (options) => {
17
17
  const distantDictionariesKeys = options.dictionaryKeys;
18
18
  const limit = pLimit(5);
19
19
  const processDictionary = async (dictionaryKey) => {
20
- logger.updateStatus(dictionaryKey, "distant", { status: "fetching" });
20
+ logger.updateStatus([
21
+ {
22
+ dictionaryKey,
23
+ type: "distant",
24
+ status: { status: "fetching" }
25
+ }
26
+ ]);
21
27
  try {
22
28
  const getDictionaryResult = await intlayerAPI.dictionary.getDictionary(
23
29
  dictionaryKey,
@@ -30,19 +36,27 @@ const fetchDistantDictionaries = async (options) => {
30
36
  if (!distantDictionary) {
31
37
  throw new Error(`Dictionary ${dictionaryKey} not found on remote`);
32
38
  }
33
- logger.updateStatus(dictionaryKey, "distant", { status: "imported" });
39
+ logger.updateStatus([
40
+ { dictionaryKey, type: "distant", status: { status: "imported" } }
41
+ ]);
34
42
  return distantDictionary;
35
43
  } catch (error) {
36
- logger.updateStatus(dictionaryKey, "distant", {
37
- status: "error",
38
- error,
39
- errorMessage: `${options?.logPrefix ?? ""}Error fetching dictionary ${dictionaryKey}: ${error}`
40
- });
44
+ logger.updateStatus([
45
+ {
46
+ dictionaryKey,
47
+ type: "distant",
48
+ status: {
49
+ status: "error",
50
+ error,
51
+ errorMessage: `${options?.logPrefix ?? ""}Error fetching dictionary ${dictionaryKey}: ${error}`
52
+ }
53
+ }
54
+ ]);
41
55
  return void 0;
42
56
  }
43
57
  };
44
58
  const fetchPromises = distantDictionariesKeys.map(
45
- (dictionaryKey) => limit(() => processDictionary(dictionaryKey))
59
+ (dictionaryKey) => limit(async () => await processDictionary(dictionaryKey))
46
60
  );
47
61
  const result = await Promise.all(fetchPromises);
48
62
  const statuses = logger.getStatuses();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/fetchDistantDictionaries.ts"],"sourcesContent":["// @ts-ignore @intlayer/backend not build yet\nimport { type DictionaryAPI } from '@intlayer/backend';\nimport { getConfiguration } from '@intlayer/config';\n// @ts-ignore @intlayer/design-system not build yet\nimport { getIntlayerAPI } from '@intlayer/design-system/libs';\nimport pLimit from 'p-limit';\nimport { logger } from './log';\n\ntype FetchDistantDictionariesOptions = {\n dictionaryKeys: string[];\n newDictionariesPath?: string;\n logPrefix?: string;\n};\n\n/**\n * Fetch distant dictionaries and update the logger with their statuses.\n */\nexport const fetchDistantDictionaries = async (\n options: FetchDistantDictionariesOptions\n): Promise<DictionaryAPI[]> => {\n try {\n const config = getConfiguration();\n const { clientId, clientSecret } = config.editor;\n const intlayerAPI = getIntlayerAPI(undefined, config);\n\n if (!clientId || !clientSecret) {\n throw new Error(\n 'Missing OAuth2 client ID or client secret. To get access token go to https://intlayer.org/dashboard/project.'\n );\n }\n\n const oAuth2TokenResult = await intlayerAPI.auth.getOAuth2AccessToken();\n\n const oAuth2AccessToken = oAuth2TokenResult.data?.accessToken;\n\n const distantDictionariesKeys = options.dictionaryKeys;\n\n // Process dictionaries in parallel with a concurrency limit\n const limit = pLimit(5); // Adjust the limit as needed\n\n const processDictionary = async (\n dictionaryKey: string\n ): Promise<DictionaryAPI | undefined> => {\n logger.updateStatus(dictionaryKey, 'distant', { status: 'fetching' });\n\n try {\n // Fetch the dictionary\n const getDictionaryResult = await intlayerAPI.dictionary.getDictionary(\n dictionaryKey,\n undefined,\n {\n headers: { Authorization: `Bearer ${oAuth2AccessToken}` },\n }\n );\n\n const distantDictionary = getDictionaryResult.data;\n\n if (!distantDictionary) {\n throw new Error(`Dictionary ${dictionaryKey} not found on remote`);\n }\n\n logger.updateStatus(dictionaryKey, 'distant', { status: 'imported' });\n\n return distantDictionary;\n } catch (error) {\n logger.updateStatus(dictionaryKey, 'distant', {\n status: 'error',\n error: error as Error,\n errorMessage: `${options?.logPrefix ?? ''}Error fetching dictionary ${dictionaryKey}: ${error}`,\n });\n return undefined;\n }\n };\n\n const fetchPromises = distantDictionariesKeys.map((dictionaryKey) =>\n limit(() => processDictionary(dictionaryKey))\n );\n\n const result = await Promise.all(fetchPromises);\n\n // Output any error messages\n const statuses = logger.getStatuses();\n for (const statusObj of statuses) {\n const currentState = statusObj.state.find((s) => s.type === 'distant');\n if (currentState && currentState.errorMessage) {\n console.error(currentState.errorMessage);\n }\n }\n\n // Remove undefined values\n const filteredResult = result.filter(\n (dict): dict is DictionaryAPI => dict !== undefined\n );\n\n return filteredResult;\n } catch (error) {\n console.error(error);\n return [];\n }\n};\n"],"mappings":"AAEA,SAAS,wBAAwB;AAEjC,SAAS,sBAAsB;AAC/B,OAAO,YAAY;AACnB,SAAS,cAAc;AAWhB,MAAM,2BAA2B,OACtC,YAC6B;AAC7B,MAAI;AACF,UAAM,SAAS,iBAAiB;AAChC,UAAM,EAAE,UAAU,aAAa,IAAI,OAAO;AAC1C,UAAM,cAAc,eAAe,QAAW,MAAM;AAEpD,QAAI,CAAC,YAAY,CAAC,cAAc;AAC9B,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,oBAAoB,MAAM,YAAY,KAAK,qBAAqB;AAEtE,UAAM,oBAAoB,kBAAkB,MAAM;AAElD,UAAM,0BAA0B,QAAQ;AAGxC,UAAM,QAAQ,OAAO,CAAC;AAEtB,UAAM,oBAAoB,OACxB,kBACuC;AACvC,aAAO,aAAa,eAAe,WAAW,EAAE,QAAQ,WAAW,CAAC;AAEpE,UAAI;AAEF,cAAM,sBAAsB,MAAM,YAAY,WAAW;AAAA,UACvD;AAAA,UACA;AAAA,UACA;AAAA,YACE,SAAS,EAAE,eAAe,UAAU,iBAAiB,GAAG;AAAA,UAC1D;AAAA,QACF;AAEA,cAAM,oBAAoB,oBAAoB;AAE9C,YAAI,CAAC,mBAAmB;AACtB,gBAAM,IAAI,MAAM,cAAc,aAAa,sBAAsB;AAAA,QACnE;AAEA,eAAO,aAAa,eAAe,WAAW,EAAE,QAAQ,WAAW,CAAC;AAEpE,eAAO;AAAA,MACT,SAAS,OAAO;AACd,eAAO,aAAa,eAAe,WAAW;AAAA,UAC5C,QAAQ;AAAA,UACR;AAAA,UACA,cAAc,GAAG,SAAS,aAAa,EAAE,6BAA6B,aAAa,KAAK,KAAK;AAAA,QAC/F,CAAC;AACD,eAAO;AAAA,MACT;AAAA,IACF;AAEA,UAAM,gBAAgB,wBAAwB;AAAA,MAAI,CAAC,kBACjD,MAAM,MAAM,kBAAkB,aAAa,CAAC;AAAA,IAC9C;AAEA,UAAM,SAAS,MAAM,QAAQ,IAAI,aAAa;AAG9C,UAAM,WAAW,OAAO,YAAY;AACpC,eAAW,aAAa,UAAU;AAChC,YAAM,eAAe,UAAU,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,SAAS;AACrE,UAAI,gBAAgB,aAAa,cAAc;AAC7C,gBAAQ,MAAM,aAAa,YAAY;AAAA,MACzC;AAAA,IACF;AAGA,UAAM,iBAAiB,OAAO;AAAA,MAC5B,CAAC,SAAgC,SAAS;AAAA,IAC5C;AAEA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ,MAAM,KAAK;AACnB,WAAO,CAAC;AAAA,EACV;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/fetchDistantDictionaries.ts"],"sourcesContent":["// @ts-ignore @intlayer/backend not build yet\nimport { type DictionaryAPI } from '@intlayer/backend';\nimport { getConfiguration } from '@intlayer/config';\n// @ts-ignore @intlayer/design-system not build yet\nimport { getIntlayerAPI } from '@intlayer/design-system/libs';\nimport pLimit from 'p-limit';\nimport { logger } from './log';\n\ntype FetchDistantDictionariesOptions = {\n dictionaryKeys: string[];\n newDictionariesPath?: string;\n logPrefix?: string;\n};\n\n/**\n * Fetch distant dictionaries and update the logger with their statuses.\n */\nexport const fetchDistantDictionaries = async (\n options: FetchDistantDictionariesOptions\n): Promise<DictionaryAPI[]> => {\n try {\n const config = getConfiguration();\n const { clientId, clientSecret } = config.editor;\n const intlayerAPI = getIntlayerAPI(undefined, config);\n\n if (!clientId || !clientSecret) {\n throw new Error(\n 'Missing OAuth2 client ID or client secret. To get access token go to https://intlayer.org/dashboard/project.'\n );\n }\n\n const oAuth2TokenResult = await intlayerAPI.auth.getOAuth2AccessToken();\n\n const oAuth2AccessToken = oAuth2TokenResult.data?.accessToken;\n\n const distantDictionariesKeys = options.dictionaryKeys;\n\n // Process dictionaries in parallel with a concurrency limit\n const limit = pLimit(5); // Adjust the limit as needed\n\n const processDictionary = async (\n dictionaryKey: string\n ): Promise<DictionaryAPI | undefined> => {\n logger.updateStatus([\n {\n dictionaryKey,\n type: 'distant',\n status: { status: 'fetching' },\n },\n ]);\n\n try {\n // Fetch the dictionary\n const getDictionaryResult = await intlayerAPI.dictionary.getDictionary(\n dictionaryKey,\n undefined,\n {\n headers: { Authorization: `Bearer ${oAuth2AccessToken}` },\n }\n );\n\n const distantDictionary = getDictionaryResult.data;\n\n if (!distantDictionary) {\n throw new Error(`Dictionary ${dictionaryKey} not found on remote`);\n }\n\n logger.updateStatus([\n { dictionaryKey, type: 'distant', status: { status: 'imported' } },\n ]);\n\n return distantDictionary;\n } catch (error) {\n logger.updateStatus([\n {\n dictionaryKey,\n type: 'distant',\n status: {\n status: 'error',\n error: error as Error,\n errorMessage: `${options?.logPrefix ?? ''}Error fetching dictionary ${dictionaryKey}: ${error}`,\n },\n },\n ]);\n return undefined;\n }\n };\n\n const fetchPromises = distantDictionariesKeys.map((dictionaryKey) =>\n limit(async () => await processDictionary(dictionaryKey))\n );\n\n const result = await Promise.all(fetchPromises);\n\n // Output any error messages\n const statuses = logger.getStatuses();\n for (const statusObj of statuses) {\n const currentState = statusObj.state.find((s) => s.type === 'distant');\n if (currentState && currentState.errorMessage) {\n console.error(currentState.errorMessage);\n }\n }\n\n // Remove undefined values\n const filteredResult = result.filter(\n (dict): dict is DictionaryAPI => dict !== undefined\n );\n\n return filteredResult;\n } catch (error) {\n console.error(error);\n return [];\n }\n};\n"],"mappings":"AAEA,SAAS,wBAAwB;AAEjC,SAAS,sBAAsB;AAC/B,OAAO,YAAY;AACnB,SAAS,cAAc;AAWhB,MAAM,2BAA2B,OACtC,YAC6B;AAC7B,MAAI;AACF,UAAM,SAAS,iBAAiB;AAChC,UAAM,EAAE,UAAU,aAAa,IAAI,OAAO;AAC1C,UAAM,cAAc,eAAe,QAAW,MAAM;AAEpD,QAAI,CAAC,YAAY,CAAC,cAAc;AAC9B,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,oBAAoB,MAAM,YAAY,KAAK,qBAAqB;AAEtE,UAAM,oBAAoB,kBAAkB,MAAM;AAElD,UAAM,0BAA0B,QAAQ;AAGxC,UAAM,QAAQ,OAAO,CAAC;AAEtB,UAAM,oBAAoB,OACxB,kBACuC;AACvC,aAAO,aAAa;AAAA,QAClB;AAAA,UACE;AAAA,UACA,MAAM;AAAA,UACN,QAAQ,EAAE,QAAQ,WAAW;AAAA,QAC/B;AAAA,MACF,CAAC;AAED,UAAI;AAEF,cAAM,sBAAsB,MAAM,YAAY,WAAW;AAAA,UACvD;AAAA,UACA;AAAA,UACA;AAAA,YACE,SAAS,EAAE,eAAe,UAAU,iBAAiB,GAAG;AAAA,UAC1D;AAAA,QACF;AAEA,cAAM,oBAAoB,oBAAoB;AAE9C,YAAI,CAAC,mBAAmB;AACtB,gBAAM,IAAI,MAAM,cAAc,aAAa,sBAAsB;AAAA,QACnE;AAEA,eAAO,aAAa;AAAA,UAClB,EAAE,eAAe,MAAM,WAAW,QAAQ,EAAE,QAAQ,WAAW,EAAE;AAAA,QACnE,CAAC;AAED,eAAO;AAAA,MACT,SAAS,OAAO;AACd,eAAO,aAAa;AAAA,UAClB;AAAA,YACE;AAAA,YACA,MAAM;AAAA,YACN,QAAQ;AAAA,cACN,QAAQ;AAAA,cACR;AAAA,cACA,cAAc,GAAG,SAAS,aAAa,EAAE,6BAA6B,aAAa,KAAK,KAAK;AAAA,YAC/F;AAAA,UACF;AAAA,QACF,CAAC;AACD,eAAO;AAAA,MACT;AAAA,IACF;AAEA,UAAM,gBAAgB,wBAAwB;AAAA,MAAI,CAAC,kBACjD,MAAM,YAAY,MAAM,kBAAkB,aAAa,CAAC;AAAA,IAC1D;AAEA,UAAM,SAAS,MAAM,QAAQ,IAAI,aAAa;AAG9C,UAAM,WAAW,OAAO,YAAY;AACpC,eAAW,aAAa,UAAU;AAChC,YAAM,eAAe,UAAU,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,SAAS;AACrE,UAAI,gBAAgB,aAAa,cAAc;AAC7C,gBAAQ,MAAM,aAAa,YAAY;AAAA,MACzC;AAAA,IACF;AAGA,UAAM,iBAAiB,OAAO;AAAA,MAC5B,CAAC,SAAgC,SAAS;AAAA,IAC5C;AAEA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ,MAAM,KAAK;AACnB,WAAO,CAAC;AAAA,EACV;AACF;","names":[]}
@@ -15,9 +15,13 @@ const loadDictionaries = async (contentDeclarationsPaths) => {
15
15
  const localDictionaries = await loadContentDeclarations(files);
16
16
  const localDictionaryKeys = localDictionaries.map((dict) => dict.key);
17
17
  logger.init(localDictionaryKeys, []);
18
- for (const dict of localDictionaries) {
19
- logger.updateStatus(dict.key, "local", { status: "built" });
20
- }
18
+ logger.updateStatus(
19
+ localDictionaries.map((dict) => ({
20
+ dictionaryKey: dict.key,
21
+ type: "local",
22
+ status: { status: "built" }
23
+ }))
24
+ );
21
25
  let distantDictionaries = [];
22
26
  let distantDictionaryKeys = [];
23
27
  let mergedDictionaries = localDictionaries;
@@ -38,7 +42,7 @@ const loadDictionaries = async (contentDeclarationsPaths) => {
38
42
  arrayMerge: mergeByKey("key")
39
43
  });
40
44
  }
41
- } catch (error) {
45
+ } catch (_error) {
42
46
  console.error("Error during fetching distant dictionaries");
43
47
  }
44
48
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/loadDictionaries/loadDictionaries.ts"],"sourcesContent":["// @ts-ignore @intlayer/backend not build yet\nimport { type DictionaryAPI } from '@intlayer/backend';\nimport { getConfiguration } from '@intlayer/config';\nimport { Dictionary } from '@intlayer/core';\nimport merge from 'deepmerge';\nimport { fetchDistantDictionaryKeys } from '../fetchDistantDictionaryKeys';\nimport { logger } from '../log';\nimport { mergeByKey } from '../mergeDictionaries';\nimport { sortAlphabetically } from '../utils';\nimport { loadContentDeclarations } from './loadContentDeclaration';\nimport { loadDistantDictionaries } from './loadDistantDictionaries';\n\nconst LOG_PREFIX = '[intlayer] ';\n\nexport const loadDictionaries = async (\n contentDeclarationsPaths: string[] | string\n): Promise<Dictionary[]> => {\n try {\n const { editor } = getConfiguration();\n\n console.info(`${LOG_PREFIX}Dictionaries:`);\n\n const files = Array.isArray(contentDeclarationsPaths)\n ? contentDeclarationsPaths\n : [contentDeclarationsPaths];\n\n const localDictionaries: Dictionary[] =\n await loadContentDeclarations(files);\n const localDictionaryKeys = localDictionaries.map((dict) => dict.key);\n\n // Initialize the logger with both local and distant dictionaries\n logger.init(localDictionaryKeys, []);\n\n // Update logger statuses for local dictionaries\n for (const dict of localDictionaries) {\n logger.updateStatus(dict.key, 'local', { status: 'built' });\n }\n\n let distantDictionaries: DictionaryAPI[] = [];\n let distantDictionaryKeys: string[] = [];\n let mergedDictionaries = localDictionaries;\n\n if (editor.clientId && editor.clientSecret) {\n try {\n // Fetch distant dictionary keys\n distantDictionaryKeys = await fetchDistantDictionaryKeys();\n\n const orderedDistantDictionaryKeys =\n distantDictionaryKeys.sort(sortAlphabetically);\n // Add distant dictionaries to the logger\n logger.addDictionaryKeys('distant', orderedDistantDictionaryKeys);\n\n // Fetch distant dictionaries\n distantDictionaries = await loadDistantDictionaries({\n dictionaryKeys: orderedDistantDictionaryKeys,\n });\n if (editor.dictionaryPriorityStrategy === 'distant_first') {\n // Merge the dictionaries\n mergedDictionaries = merge(localDictionaries, distantDictionaries, {\n arrayMerge: mergeByKey('key'),\n });\n } else {\n // Merge the dictionaries\n mergedDictionaries = merge(distantDictionaries, localDictionaries, {\n arrayMerge: mergeByKey('key'),\n });\n }\n } catch (error) {\n console.error('Error during fetching distant dictionaries');\n }\n }\n\n // Ensure the logger is stopped\n logger.stop();\n\n return mergedDictionaries;\n } catch (error) {\n // Ensure the logger is stopped\n logger.stop();\n\n throw error; // Re-throw the error after logging\n }\n};\n"],"mappings":"AAEA,SAAS,wBAAwB;AAEjC,OAAO,WAAW;AAClB,SAAS,kCAAkC;AAC3C,SAAS,cAAc;AACvB,SAAS,kBAAkB;AAC3B,SAAS,0BAA0B;AACnC,SAAS,+BAA+B;AACxC,SAAS,+BAA+B;AAExC,MAAM,aAAa;AAEZ,MAAM,mBAAmB,OAC9B,6BAC0B;AAC1B,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,iBAAiB;AAEpC,YAAQ,KAAK,GAAG,UAAU,eAAe;AAEzC,UAAM,QAAQ,MAAM,QAAQ,wBAAwB,IAChD,2BACA,CAAC,wBAAwB;AAE7B,UAAM,oBACJ,MAAM,wBAAwB,KAAK;AACrC,UAAM,sBAAsB,kBAAkB,IAAI,CAAC,SAAS,KAAK,GAAG;AAGpE,WAAO,KAAK,qBAAqB,CAAC,CAAC;AAGnC,eAAW,QAAQ,mBAAmB;AACpC,aAAO,aAAa,KAAK,KAAK,SAAS,EAAE,QAAQ,QAAQ,CAAC;AAAA,IAC5D;AAEA,QAAI,sBAAuC,CAAC;AAC5C,QAAI,wBAAkC,CAAC;AACvC,QAAI,qBAAqB;AAEzB,QAAI,OAAO,YAAY,OAAO,cAAc;AAC1C,UAAI;AAEF,gCAAwB,MAAM,2BAA2B;AAEzD,cAAM,+BACJ,sBAAsB,KAAK,kBAAkB;AAE/C,eAAO,kBAAkB,WAAW,4BAA4B;AAGhE,8BAAsB,MAAM,wBAAwB;AAAA,UAClD,gBAAgB;AAAA,QAClB,CAAC;AACD,YAAI,OAAO,+BAA+B,iBAAiB;AAEzD,+BAAqB,MAAM,mBAAmB,qBAAqB;AAAA,YACjE,YAAY,WAAW,KAAK;AAAA,UAC9B,CAAC;AAAA,QACH,OAAO;AAEL,+BAAqB,MAAM,qBAAqB,mBAAmB;AAAA,YACjE,YAAY,WAAW,KAAK;AAAA,UAC9B,CAAC;AAAA,QACH;AAAA,MACF,SAAS,OAAO;AACd,gBAAQ,MAAM,4CAA4C;AAAA,MAC5D;AAAA,IACF;AAGA,WAAO,KAAK;AAEZ,WAAO;AAAA,EACT,SAAS,OAAO;AAEd,WAAO,KAAK;AAEZ,UAAM;AAAA,EACR;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/loadDictionaries/loadDictionaries.ts"],"sourcesContent":["// @ts-ignore @intlayer/backend not build yet\nimport { type DictionaryAPI } from '@intlayer/backend';\nimport { getConfiguration } from '@intlayer/config';\nimport { Dictionary } from '@intlayer/core';\nimport merge from 'deepmerge';\nimport { fetchDistantDictionaryKeys } from '../fetchDistantDictionaryKeys';\nimport { logger } from '../log';\nimport { mergeByKey } from '../mergeDictionaries';\nimport { sortAlphabetically } from '../utils';\nimport { loadContentDeclarations } from './loadContentDeclaration';\nimport { loadDistantDictionaries } from './loadDistantDictionaries';\n\nconst LOG_PREFIX = '[intlayer] ';\n\nexport const loadDictionaries = async (\n contentDeclarationsPaths: string[] | string\n): Promise<Dictionary[]> => {\n try {\n const { editor } = getConfiguration();\n\n console.info(`${LOG_PREFIX}Dictionaries:`);\n\n const files = Array.isArray(contentDeclarationsPaths)\n ? contentDeclarationsPaths\n : [contentDeclarationsPaths];\n\n const localDictionaries: Dictionary[] =\n await loadContentDeclarations(files);\n const localDictionaryKeys = localDictionaries.map((dict) => dict.key);\n\n // Initialize the logger with both local and distant dictionaries\n logger.init(localDictionaryKeys, []);\n\n // Update logger statuses for local dictionaries\n logger.updateStatus(\n localDictionaries.map((dict) => ({\n dictionaryKey: dict.key,\n type: 'local',\n status: { status: 'built' },\n }))\n );\n\n let distantDictionaries: DictionaryAPI[] = [];\n let distantDictionaryKeys: string[] = [];\n let mergedDictionaries = localDictionaries;\n\n if (editor.clientId && editor.clientSecret) {\n try {\n // Fetch distant dictionary keys\n distantDictionaryKeys = await fetchDistantDictionaryKeys();\n\n const orderedDistantDictionaryKeys =\n distantDictionaryKeys.sort(sortAlphabetically);\n // Add distant dictionaries to the logger\n logger.addDictionaryKeys('distant', orderedDistantDictionaryKeys);\n\n // Fetch distant dictionaries\n distantDictionaries = await loadDistantDictionaries({\n dictionaryKeys: orderedDistantDictionaryKeys,\n });\n if (editor.dictionaryPriorityStrategy === 'distant_first') {\n // Merge the dictionaries\n mergedDictionaries = merge(localDictionaries, distantDictionaries, {\n arrayMerge: mergeByKey('key'),\n });\n } else {\n // Merge the dictionaries\n mergedDictionaries = merge(distantDictionaries, localDictionaries, {\n arrayMerge: mergeByKey('key'),\n });\n }\n } catch (_error) {\n console.error('Error during fetching distant dictionaries');\n }\n }\n\n // Ensure the logger is stopped\n logger.stop();\n\n return mergedDictionaries;\n } catch (error) {\n // Ensure the logger is stopped\n logger.stop();\n\n throw error; // Re-throw the error after logging\n }\n};\n"],"mappings":"AAEA,SAAS,wBAAwB;AAEjC,OAAO,WAAW;AAClB,SAAS,kCAAkC;AAC3C,SAAS,cAAc;AACvB,SAAS,kBAAkB;AAC3B,SAAS,0BAA0B;AACnC,SAAS,+BAA+B;AACxC,SAAS,+BAA+B;AAExC,MAAM,aAAa;AAEZ,MAAM,mBAAmB,OAC9B,6BAC0B;AAC1B,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,iBAAiB;AAEpC,YAAQ,KAAK,GAAG,UAAU,eAAe;AAEzC,UAAM,QAAQ,MAAM,QAAQ,wBAAwB,IAChD,2BACA,CAAC,wBAAwB;AAE7B,UAAM,oBACJ,MAAM,wBAAwB,KAAK;AACrC,UAAM,sBAAsB,kBAAkB,IAAI,CAAC,SAAS,KAAK,GAAG;AAGpE,WAAO,KAAK,qBAAqB,CAAC,CAAC;AAGnC,WAAO;AAAA,MACL,kBAAkB,IAAI,CAAC,UAAU;AAAA,QAC/B,eAAe,KAAK;AAAA,QACpB,MAAM;AAAA,QACN,QAAQ,EAAE,QAAQ,QAAQ;AAAA,MAC5B,EAAE;AAAA,IACJ;AAEA,QAAI,sBAAuC,CAAC;AAC5C,QAAI,wBAAkC,CAAC;AACvC,QAAI,qBAAqB;AAEzB,QAAI,OAAO,YAAY,OAAO,cAAc;AAC1C,UAAI;AAEF,gCAAwB,MAAM,2BAA2B;AAEzD,cAAM,+BACJ,sBAAsB,KAAK,kBAAkB;AAE/C,eAAO,kBAAkB,WAAW,4BAA4B;AAGhE,8BAAsB,MAAM,wBAAwB;AAAA,UAClD,gBAAgB;AAAA,QAClB,CAAC;AACD,YAAI,OAAO,+BAA+B,iBAAiB;AAEzD,+BAAqB,MAAM,mBAAmB,qBAAqB;AAAA,YACjE,YAAY,WAAW,KAAK;AAAA,UAC9B,CAAC;AAAA,QACH,OAAO;AAEL,+BAAqB,MAAM,qBAAqB,mBAAmB;AAAA,YACjE,YAAY,WAAW,KAAK;AAAA,UAC9B,CAAC;AAAA,QACH;AAAA,MACF,SAAS,QAAQ;AACf,gBAAQ,MAAM,4CAA4C;AAAA,MAC5D;AAAA,IACF;AAGA,WAAO,KAAK;AAEZ,WAAO;AAAA,EACT,SAAS,OAAO;AAEd,WAAO,KAAK;AAEZ,UAAM;AAAA,EACR;AACF;","names":[]}
package/dist/esm/log.mjs CHANGED
@@ -1,17 +1,22 @@
1
- import logUpdate from "log-update";
1
+ import readline from "readline";
2
2
  import { sortAlphabetically } from './utils.mjs';
3
+ const LINE_DETECTOR = "\u200B\u200B\u200B";
4
+ const SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
5
+ const RESET = "\x1B[0m";
6
+ const GREEN = "\x1B[32m";
7
+ const RED = "\x1B[31m";
8
+ const BLUE = "\x1B[34m";
9
+ const GREY = "\x1B[90m";
10
+ const GREY_DARK = "\x1B[90m";
3
11
  class Logger {
4
12
  dictionariesStatuses = [];
5
- spinnerFrames = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
6
13
  spinnerTimer = null;
7
14
  maxDictionaryKeyLength = 0;
8
- // ANSI color codes
9
- RESET = "\x1B[0m";
10
- GREEN = "\x1B[32m";
11
- RED = "\x1B[31m";
12
- BLUE = "\x1B[34m";
13
- GREY = "\x1B[90m";
14
- GREY_DARK = "\x1B[90m";
15
+ previousLineCount = 0;
16
+ lineDifCounter = 0;
17
+ originalStdoutWrite = null;
18
+ extraLines = 0;
19
+ isUpdating = false;
15
20
  // Singleton instance
16
21
  static instance;
17
22
  constructor() {
@@ -106,49 +111,80 @@ class Logger {
106
111
  this.spinnerTimer = null;
107
112
  }
108
113
  }
114
+ // Method to update the terminal output
115
+ updateOutput(content) {
116
+ if (!this.originalStdoutWrite) {
117
+ this.originalStdoutWrite = process.stdout.write.bind(process.stdout);
118
+ this.extraLines = 0;
119
+ const write = (chunk, encoding, callback) => {
120
+ const str = typeof chunk === "string" ? chunk : chunk.toString();
121
+ const newLines = (str.match(/\n/g) ?? []).length;
122
+ if (!this.isUpdating) {
123
+ this.extraLines += newLines;
124
+ }
125
+ return this.originalStdoutWrite(chunk, encoding, callback);
126
+ };
127
+ process.stdout.write = write;
128
+ }
129
+ this.isUpdating = true;
130
+ const contentLines = content.split("\n");
131
+ const indexOfLineDetector = contentLines.indexOf(LINE_DETECTOR.trim());
132
+ if (indexOfLineDetector > 0) {
133
+ this.lineDifCounter = indexOfLineDetector;
134
+ } else {
135
+ this.lineDifCounter = 0;
136
+ }
137
+ const totalLinesToMoveUp = this.previousLineCount + this.lineDifCounter + this.extraLines;
138
+ readline.moveCursor(process.stdout, 0, -totalLinesToMoveUp);
139
+ readline.clearScreenDown(process.stdout);
140
+ contentLines.forEach((line) => {
141
+ process.stdout.write(`${line}\x1B[K
142
+ `);
143
+ });
144
+ this.previousLineCount = contentLines.length;
145
+ this.extraLines = 0;
146
+ this.isUpdating = false;
147
+ }
109
148
  stop() {
110
149
  this.stopSpinner();
111
- logUpdate.clear();
112
- const lines = this.dictionariesStatuses.map(
113
- (statusObj) => this.getStatusLine(statusObj)
114
- );
115
- console.log(lines.join("\n"));
116
150
  }
117
- updateStatus(dictionaryKey, type, status) {
118
- const statusObj = this.dictionariesStatuses.find(
119
- (ds) => ds.dictionaryKey === dictionaryKey
120
- );
121
- if (statusObj) {
122
- const state = statusObj.state.find((s) => s.type === type);
123
- if (state) {
124
- Object.assign(state, status);
125
- } else {
126
- if (status.status === void 0) {
127
- status.status = "pending";
151
+ updateStatus(dictionaries) {
152
+ for (const { dictionaryKey, type, status } of dictionaries) {
153
+ const statusObj = this.dictionariesStatuses.find(
154
+ (ds) => ds.dictionaryKey === dictionaryKey
155
+ );
156
+ if (statusObj) {
157
+ const state = statusObj.state.find((s) => s.type === type);
158
+ if (state) {
159
+ Object.assign(state, status);
160
+ } else {
161
+ if (status.status === void 0) {
162
+ status.status = "pending";
163
+ }
164
+ const newState = {
165
+ type,
166
+ status: status.status,
167
+ icon: status.icon ?? "",
168
+ error: status.error,
169
+ errorMessage: status.errorMessage,
170
+ spinnerFrameIndex: status.spinnerFrameIndex ?? 0
171
+ };
172
+ statusObj.state.push(newState);
128
173
  }
174
+ } else {
129
175
  const newState = {
130
176
  type,
131
- status: status.status,
177
+ status: status.status ?? "pending",
132
178
  icon: status.icon ?? "",
133
179
  error: status.error,
134
180
  errorMessage: status.errorMessage,
135
181
  spinnerFrameIndex: status.spinnerFrameIndex ?? 0
136
182
  };
137
- statusObj.state.push(newState);
183
+ this.dictionariesStatuses.push({
184
+ dictionaryKey,
185
+ state: [newState]
186
+ });
138
187
  }
139
- } else {
140
- const newState = {
141
- type,
142
- status: status.status ?? "pending",
143
- icon: status.icon ?? "",
144
- error: status.error,
145
- errorMessage: status.errorMessage,
146
- spinnerFrameIndex: status.spinnerFrameIndex ?? 0
147
- };
148
- this.dictionariesStatuses.push({
149
- dictionaryKey,
150
- state: [newState]
151
- });
152
188
  }
153
189
  this.updateAllStatusLines();
154
190
  }
@@ -171,34 +207,45 @@ class Logger {
171
207
  let colorEnd = "";
172
208
  let icon = this.getStatusIcon(state.status);
173
209
  if (state.status === "fetching") {
174
- icon = this.spinnerFrames[state.spinnerFrameIndex % this.spinnerFrames.length];
175
- colorStart = this.BLUE;
176
- colorEnd = this.RESET;
210
+ icon = SPINNER_FRAMES[state.spinnerFrameIndex % SPINNER_FRAMES.length];
211
+ colorStart = BLUE;
212
+ colorEnd = RESET;
177
213
  } else if (state.status === "error") {
178
- colorStart = this.RED;
179
- colorEnd = this.RESET;
214
+ colorStart = RED;
215
+ colorEnd = RESET;
180
216
  } else if (state.status === "imported" || state.status === "built") {
181
- colorStart = this.GREEN;
182
- colorEnd = this.RESET;
217
+ colorStart = GREEN;
218
+ colorEnd = RESET;
183
219
  } else {
184
- colorStart = this.GREY;
185
- colorEnd = this.RESET;
220
+ colorStart = GREY;
221
+ colorEnd = RESET;
186
222
  }
187
- const statusBlock = `${this.GREY_DARK}[${state.type}: ${colorStart}${icon} ${state.status}${this.GREY_DARK}]${colorEnd}`;
223
+ const statusBlock = `${GREY_DARK}[${state.type}: ${colorStart}${icon} ${state.status}${GREY_DARK}]${colorEnd}`;
188
224
  return `${colorStart}${statusBlock}${colorEnd}`;
189
225
  });
190
226
  return `- ${paddedKey} ${states.join(" ")}`;
191
227
  }
228
+ // Replace logUpdate calls with your custom methods
192
229
  updateAllStatusLines() {
230
+ const terminalHeight = process.stdout.rows;
231
+ const maxVisibleLines = terminalHeight - 1;
193
232
  const lines = this.dictionariesStatuses.map((statusObj) => {
194
233
  statusObj.state.forEach((state) => {
195
234
  if (state.status === "fetching") {
196
- state.spinnerFrameIndex = (state.spinnerFrameIndex + 1) % this.spinnerFrames.length;
235
+ state.spinnerFrameIndex = (state.spinnerFrameIndex + 1) % SPINNER_FRAMES.length;
197
236
  }
198
237
  });
199
238
  return this.getStatusLine(statusObj);
200
239
  });
201
- logUpdate(lines.join("\n"));
240
+ let content;
241
+ if (lines.length > maxVisibleLines) {
242
+ const visibleLines = lines.slice(0, maxVisibleLines - 5);
243
+ const summary = `... and ${lines.length - visibleLines.length} more lines`;
244
+ content = LINE_DETECTOR + visibleLines.join("\n") + "\n" + summary;
245
+ } else {
246
+ content = lines.join("\n");
247
+ }
248
+ this.updateOutput(content);
202
249
  }
203
250
  getStatuses() {
204
251
  return this.dictionariesStatuses;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/log.ts"],"sourcesContent":["import logUpdate from 'log-update';\nimport { sortAlphabetically } from './utils';\n\nexport type State = {\n type: 'local' | 'distant';\n status: 'pending' | 'fetching' | 'fetched' | 'error' | 'imported' | 'built';\n icon?: string;\n error?: Error;\n errorMessage?: string;\n spinnerFrameIndex?: number;\n};\n\nexport type DictionariesStatus = {\n dictionaryKey: string;\n state: State[];\n};\n\nclass Logger {\n private dictionariesStatuses: DictionariesStatus[] = [];\n private spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n private spinnerTimer: NodeJS.Timeout | null = null;\n private maxDictionaryKeyLength: number = 0;\n\n // ANSI color codes\n private RESET = '\\x1b[0m';\n private GREEN = '\\x1b[32m';\n private RED = '\\x1b[31m';\n private BLUE = '\\x1b[34m';\n private GREY = '\\x1b[90m';\n private GREY_DARK = '\\x1b[90m';\n\n // Singleton instance\n private static instance: Logger;\n\n private constructor() {}\n\n public static getInstance(): Logger {\n if (!Logger.instance) {\n Logger.instance = new Logger();\n }\n return Logger.instance;\n }\n\n public init(\n localDictionariesKeys: string[],\n distantDictionariesKeys: string[]\n ) {\n const allKeys = Array.from(\n new Set(\n [...localDictionariesKeys, ...distantDictionariesKeys].sort(\n sortAlphabetically\n )\n )\n );\n\n this.maxDictionaryKeyLength = allKeys.reduce(\n (max, key) => (key.length > max ? key.length : max),\n 0\n );\n\n this.dictionariesStatuses = allKeys.map((dictionaryKey) => {\n const states: State[] = [];\n\n if (localDictionariesKeys.includes(dictionaryKey)) {\n states.push({\n type: 'local',\n status: 'pending',\n spinnerFrameIndex: 0,\n });\n }\n if (distantDictionariesKeys.includes(dictionaryKey)) {\n states.push({\n type: 'distant',\n status: 'pending',\n spinnerFrameIndex: 0,\n });\n }\n\n return {\n dictionaryKey,\n state: states,\n };\n });\n\n // Start spinner timer\n this.startSpinner();\n\n // Update all status lines (this will output the initial statuses)\n this.updateAllStatusLines();\n }\n\n // New method to add dictionary keys after initialization\n public addDictionaryKeys(\n type: 'local' | 'distant',\n dictionaryKeys: string[]\n ) {\n for (const dictionaryKey of dictionaryKeys) {\n // Update maxDictionaryKeyLength if the new key is longer\n if (dictionaryKey.length > this.maxDictionaryKeyLength) {\n this.maxDictionaryKeyLength = dictionaryKey.length;\n }\n\n let statusObj = this.dictionariesStatuses.find(\n (ds) => ds.dictionaryKey === dictionaryKey\n );\n\n if (!statusObj) {\n // If the dictionaryKey doesn't exist yet, create a new DictionariesStatus\n\n statusObj = {\n dictionaryKey,\n state: [],\n };\n this.dictionariesStatuses.push(statusObj);\n\n const newState: State = {\n type,\n status: 'pending',\n spinnerFrameIndex: 0,\n };\n statusObj.state.push(newState);\n } else {\n const existingState = statusObj.state.find((s) => s.type === type);\n if (!existingState) {\n // Add new state for the type\n\n const newState: State = {\n type,\n status: 'pending',\n spinnerFrameIndex: 0,\n };\n statusObj.state.push(newState);\n }\n }\n }\n\n // Call updateAllStatusLines() to refresh the output\n this.updateAllStatusLines();\n }\n\n private startSpinner() {\n if (!this.spinnerTimer) {\n this.spinnerTimer = setInterval(() => {\n this.updateAllStatusLines();\n }, 100); // Update every 100ms\n }\n }\n\n private stopSpinner() {\n if (this.spinnerTimer) {\n clearInterval(this.spinnerTimer);\n this.spinnerTimer = null;\n }\n }\n\n public stop() {\n this.stopSpinner();\n logUpdate.clear(); // Clear the logUpdate output\n const lines = this.dictionariesStatuses.map((statusObj) =>\n this.getStatusLine(statusObj)\n );\n console.log(lines.join('\\n')); // Output final statuses\n }\n\n public updateStatus(\n dictionaryKey: string,\n type: 'local' | 'distant',\n status: Partial<State>\n ) {\n const statusObj = this.dictionariesStatuses.find(\n (ds) => ds.dictionaryKey === dictionaryKey\n );\n if (statusObj) {\n const state = statusObj.state.find((s) => s.type === type);\n if (state) {\n // Update existing state\n Object.assign(state, status);\n } else {\n // If the state for this type doesn't exist yet, add it\n if (status.status === undefined) {\n status.status = 'pending'; // Provide default status\n }\n const newState: State = {\n type,\n status: status.status,\n icon: status.icon ?? '',\n error: status.error,\n errorMessage: status.errorMessage,\n spinnerFrameIndex: status.spinnerFrameIndex ?? 0,\n };\n statusObj.state.push(newState);\n }\n } else {\n // If the status object doesn't exist, create it\n const newState: State = {\n type,\n status: status.status ?? 'pending',\n icon: status.icon ?? '',\n error: status.error,\n errorMessage: status.errorMessage,\n spinnerFrameIndex: status.spinnerFrameIndex ?? 0,\n };\n this.dictionariesStatuses.push({\n dictionaryKey,\n state: [newState],\n });\n }\n\n // Update the display after status change\n this.updateAllStatusLines();\n }\n\n private getStatusIcon(status: string): string {\n const statusIcons: Record<string, string> = {\n pending: '⏲',\n fetching: '', // Spinner handled separately\n built: '✔',\n imported: '✔',\n error: '✖',\n };\n return statusIcons[status] ?? '';\n }\n\n private getStatusLine(statusObj: DictionariesStatus): string {\n const keyPadding =\n this.maxDictionaryKeyLength - statusObj.dictionaryKey.length;\n const paddedKey = `${statusObj.dictionaryKey}${' '.repeat(keyPadding)}`;\n\n const states = statusObj.state.map((state) => {\n let colorStart = '';\n let colorEnd = '';\n let icon = this.getStatusIcon(state.status);\n if (state.status === 'fetching') {\n // Use spinner frame\n icon =\n this.spinnerFrames[\n state.spinnerFrameIndex! % this.spinnerFrames.length\n ];\n colorStart = this.BLUE;\n colorEnd = this.RESET;\n } else if (state.status === 'error') {\n colorStart = this.RED;\n colorEnd = this.RESET;\n } else if (state.status === 'imported' || state.status === 'built') {\n colorStart = this.GREEN;\n colorEnd = this.RESET;\n } else {\n colorStart = this.GREY;\n colorEnd = this.RESET;\n }\n\n // Format the status block\n const statusBlock = `${this.GREY_DARK}[${state.type}: ${colorStart}${icon} ${state.status}${this.GREY_DARK}]${colorEnd}`;\n\n return `${colorStart}${statusBlock}${colorEnd}`;\n });\n\n return `- ${paddedKey} ${states.join(' ')}`;\n }\n\n private updateAllStatusLines() {\n const lines = this.dictionariesStatuses.map((statusObj) => {\n statusObj.state.forEach((state) => {\n if (state.status === 'fetching') {\n // Update spinner frame\n state.spinnerFrameIndex =\n (state.spinnerFrameIndex! + 1) % this.spinnerFrames.length;\n }\n });\n return this.getStatusLine(statusObj);\n });\n\n logUpdate(lines.join('\\n'));\n }\n\n public getStatuses() {\n return this.dictionariesStatuses;\n }\n}\n\nexport const logger = Logger.getInstance();\n"],"mappings":"AAAA,OAAO,eAAe;AACtB,SAAS,0BAA0B;AAgBnC,MAAM,OAAO;AAAA,EACH,uBAA6C,CAAC;AAAA,EAC9C,gBAAgB,CAAC,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,UAAK,QAAG;AAAA,EACjE,eAAsC;AAAA,EACtC,yBAAiC;AAAA;AAAA,EAGjC,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AAAA,EACP,YAAY;AAAA;AAAA,EAGpB,OAAe;AAAA,EAEP,cAAc;AAAA,EAAC;AAAA,EAEvB,OAAc,cAAsB;AAClC,QAAI,CAAC,OAAO,UAAU;AACpB,aAAO,WAAW,IAAI,OAAO;AAAA,IAC/B;AACA,WAAO,OAAO;AAAA,EAChB;AAAA,EAEO,KACL,uBACA,yBACA;AACA,UAAM,UAAU,MAAM;AAAA,MACpB,IAAI;AAAA,QACF,CAAC,GAAG,uBAAuB,GAAG,uBAAuB,EAAE;AAAA,UACrD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,SAAK,yBAAyB,QAAQ;AAAA,MACpC,CAAC,KAAK,QAAS,IAAI,SAAS,MAAM,IAAI,SAAS;AAAA,MAC/C;AAAA,IACF;AAEA,SAAK,uBAAuB,QAAQ,IAAI,CAAC,kBAAkB;AACzD,YAAM,SAAkB,CAAC;AAEzB,UAAI,sBAAsB,SAAS,aAAa,GAAG;AACjD,eAAO,KAAK;AAAA,UACV,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,mBAAmB;AAAA,QACrB,CAAC;AAAA,MACH;AACA,UAAI,wBAAwB,SAAS,aAAa,GAAG;AACnD,eAAO,KAAK;AAAA,UACV,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,mBAAmB;AAAA,QACrB,CAAC;AAAA,MACH;AAEA,aAAO;AAAA,QACL;AAAA,QACA,OAAO;AAAA,MACT;AAAA,IACF,CAAC;AAGD,SAAK,aAAa;AAGlB,SAAK,qBAAqB;AAAA,EAC5B;AAAA;AAAA,EAGO,kBACL,MACA,gBACA;AACA,eAAW,iBAAiB,gBAAgB;AAE1C,UAAI,cAAc,SAAS,KAAK,wBAAwB;AACtD,aAAK,yBAAyB,cAAc;AAAA,MAC9C;AAEA,UAAI,YAAY,KAAK,qBAAqB;AAAA,QACxC,CAAC,OAAO,GAAG,kBAAkB;AAAA,MAC/B;AAEA,UAAI,CAAC,WAAW;AAGd,oBAAY;AAAA,UACV;AAAA,UACA,OAAO,CAAC;AAAA,QACV;AACA,aAAK,qBAAqB,KAAK,SAAS;AAExC,cAAM,WAAkB;AAAA,UACtB;AAAA,UACA,QAAQ;AAAA,UACR,mBAAmB;AAAA,QACrB;AACA,kBAAU,MAAM,KAAK,QAAQ;AAAA,MAC/B,OAAO;AACL,cAAM,gBAAgB,UAAU,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI;AACjE,YAAI,CAAC,eAAe;AAGlB,gBAAM,WAAkB;AAAA,YACtB;AAAA,YACA,QAAQ;AAAA,YACR,mBAAmB;AAAA,UACrB;AACA,oBAAU,MAAM,KAAK,QAAQ;AAAA,QAC/B;AAAA,MACF;AAAA,IACF;AAGA,SAAK,qBAAqB;AAAA,EAC5B;AAAA,EAEQ,eAAe;AACrB,QAAI,CAAC,KAAK,cAAc;AACtB,WAAK,eAAe,YAAY,MAAM;AACpC,aAAK,qBAAqB;AAAA,MAC5B,GAAG,GAAG;AAAA,IACR;AAAA,EACF;AAAA,EAEQ,cAAc;AACpB,QAAI,KAAK,cAAc;AACrB,oBAAc,KAAK,YAAY;AAC/B,WAAK,eAAe;AAAA,IACtB;AAAA,EACF;AAAA,EAEO,OAAO;AACZ,SAAK,YAAY;AACjB,cAAU,MAAM;AAChB,UAAM,QAAQ,KAAK,qBAAqB;AAAA,MAAI,CAAC,cAC3C,KAAK,cAAc,SAAS;AAAA,IAC9B;AACA,YAAQ,IAAI,MAAM,KAAK,IAAI,CAAC;AAAA,EAC9B;AAAA,EAEO,aACL,eACA,MACA,QACA;AACA,UAAM,YAAY,KAAK,qBAAqB;AAAA,MAC1C,CAAC,OAAO,GAAG,kBAAkB;AAAA,IAC/B;AACA,QAAI,WAAW;AACb,YAAM,QAAQ,UAAU,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI;AACzD,UAAI,OAAO;AAET,eAAO,OAAO,OAAO,MAAM;AAAA,MAC7B,OAAO;AAEL,YAAI,OAAO,WAAW,QAAW;AAC/B,iBAAO,SAAS;AAAA,QAClB;AACA,cAAM,WAAkB;AAAA,UACtB;AAAA,UACA,QAAQ,OAAO;AAAA,UACf,MAAM,OAAO,QAAQ;AAAA,UACrB,OAAO,OAAO;AAAA,UACd,cAAc,OAAO;AAAA,UACrB,mBAAmB,OAAO,qBAAqB;AAAA,QACjD;AACA,kBAAU,MAAM,KAAK,QAAQ;AAAA,MAC/B;AAAA,IACF,OAAO;AAEL,YAAM,WAAkB;AAAA,QACtB;AAAA,QACA,QAAQ,OAAO,UAAU;AAAA,QACzB,MAAM,OAAO,QAAQ;AAAA,QACrB,OAAO,OAAO;AAAA,QACd,cAAc,OAAO;AAAA,QACrB,mBAAmB,OAAO,qBAAqB;AAAA,MACjD;AACA,WAAK,qBAAqB,KAAK;AAAA,QAC7B;AAAA,QACA,OAAO,CAAC,QAAQ;AAAA,MAClB,CAAC;AAAA,IACH;AAGA,SAAK,qBAAqB;AAAA,EAC5B;AAAA,EAEQ,cAAc,QAAwB;AAC5C,UAAM,cAAsC;AAAA,MAC1C,SAAS;AAAA,MACT,UAAU;AAAA;AAAA,MACV,OAAO;AAAA,MACP,UAAU;AAAA,MACV,OAAO;AAAA,IACT;AACA,WAAO,YAAY,MAAM,KAAK;AAAA,EAChC;AAAA,EAEQ,cAAc,WAAuC;AAC3D,UAAM,aACJ,KAAK,yBAAyB,UAAU,cAAc;AACxD,UAAM,YAAY,GAAG,UAAU,aAAa,GAAG,IAAI,OAAO,UAAU,CAAC;AAErE,UAAM,SAAS,UAAU,MAAM,IAAI,CAAC,UAAU;AAC5C,UAAI,aAAa;AACjB,UAAI,WAAW;AACf,UAAI,OAAO,KAAK,cAAc,MAAM,MAAM;AAC1C,UAAI,MAAM,WAAW,YAAY;AAE/B,eACE,KAAK,cACH,MAAM,oBAAqB,KAAK,cAAc,MAChD;AACF,qBAAa,KAAK;AAClB,mBAAW,KAAK;AAAA,MAClB,WAAW,MAAM,WAAW,SAAS;AACnC,qBAAa,KAAK;AAClB,mBAAW,KAAK;AAAA,MAClB,WAAW,MAAM,WAAW,cAAc,MAAM,WAAW,SAAS;AAClE,qBAAa,KAAK;AAClB,mBAAW,KAAK;AAAA,MAClB,OAAO;AACL,qBAAa,KAAK;AAClB,mBAAW,KAAK;AAAA,MAClB;AAGA,YAAM,cAAc,GAAG,KAAK,SAAS,IAAI,MAAM,IAAI,KAAK,UAAU,GAAG,IAAI,IAAI,MAAM,MAAM,GAAG,KAAK,SAAS,IAAI,QAAQ;AAEtH,aAAO,GAAG,UAAU,GAAG,WAAW,GAAG,QAAQ;AAAA,IAC/C,CAAC;AAED,WAAO,KAAK,SAAS,IAAI,OAAO,KAAK,GAAG,CAAC;AAAA,EAC3C;AAAA,EAEQ,uBAAuB;AAC7B,UAAM,QAAQ,KAAK,qBAAqB,IAAI,CAAC,cAAc;AACzD,gBAAU,MAAM,QAAQ,CAAC,UAAU;AACjC,YAAI,MAAM,WAAW,YAAY;AAE/B,gBAAM,qBACH,MAAM,oBAAqB,KAAK,KAAK,cAAc;AAAA,QACxD;AAAA,MACF,CAAC;AACD,aAAO,KAAK,cAAc,SAAS;AAAA,IACrC,CAAC;AAED,cAAU,MAAM,KAAK,IAAI,CAAC;AAAA,EAC5B;AAAA,EAEO,cAAc;AACnB,WAAO,KAAK;AAAA,EACd;AACF;AAEO,MAAM,SAAS,OAAO,YAAY;","names":[]}
1
+ {"version":3,"sources":["../../src/log.ts"],"sourcesContent":["import readline from 'readline';\nimport { sortAlphabetically } from './utils';\n\nexport type State = {\n type: 'local' | 'distant';\n status: 'pending' | 'fetching' | 'fetched' | 'error' | 'imported' | 'built';\n icon?: string;\n error?: Error;\n errorMessage?: string;\n spinnerFrameIndex?: number;\n};\n\nexport type DictionariesStatus = {\n dictionaryKey: string;\n state: State[];\n};\n\nconst LINE_DETECTOR = '\\u200B\\u200B\\u200B'; // Three zero-width spaces\nconst SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];\n\n// ANSI color codes\nconst RESET = '\\x1b[0m';\nconst GREEN = '\\x1b[32m';\nconst RED = '\\x1b[31m';\nconst BLUE = '\\x1b[34m';\nconst GREY = '\\x1b[90m';\nconst GREY_DARK = '\\x1b[90m';\n\nclass Logger {\n private dictionariesStatuses: DictionariesStatus[] = [];\n private spinnerTimer: NodeJS.Timeout | null = null;\n private maxDictionaryKeyLength: number = 0;\n private previousLineCount: number = 0;\n private lineDifCounter: number = 0;\n private originalStdoutWrite:\n | ((\n chunk: string | Uint8Array, // `chunk` can be either a string or a Uint8Array\n encoding?: BufferEncoding, // `encoding` is optional and should be a BufferEncoding\n callback?: (err?: Error | null) => void // `callback` is optional and a function\n ) => boolean)\n | null = null;\n private extraLines: number = 0;\n private isUpdating: boolean = false;\n\n // Singleton instance\n private static instance: Logger;\n\n private constructor() {}\n\n public static getInstance(): Logger {\n if (!Logger.instance) {\n Logger.instance = new Logger();\n }\n return Logger.instance;\n }\n\n public init(\n localDictionariesKeys: string[],\n distantDictionariesKeys: string[]\n ) {\n const allKeys = Array.from(\n new Set(\n [...localDictionariesKeys, ...distantDictionariesKeys].sort(\n sortAlphabetically\n )\n )\n );\n\n this.maxDictionaryKeyLength = allKeys.reduce(\n (max, key) => (key.length > max ? key.length : max),\n 0\n );\n\n this.dictionariesStatuses = allKeys.map((dictionaryKey) => {\n const states: State[] = [];\n\n if (localDictionariesKeys.includes(dictionaryKey)) {\n states.push({\n type: 'local',\n status: 'pending',\n spinnerFrameIndex: 0,\n });\n }\n if (distantDictionariesKeys.includes(dictionaryKey)) {\n states.push({\n type: 'distant',\n status: 'pending',\n spinnerFrameIndex: 0,\n });\n }\n\n return {\n dictionaryKey,\n state: states,\n };\n });\n\n // Start spinner timer\n this.startSpinner();\n\n // Update all status lines (this will output the initial statuses)\n this.updateAllStatusLines();\n }\n\n // New method to add dictionary keys after initialization\n public addDictionaryKeys(\n type: 'local' | 'distant',\n dictionaryKeys: string[]\n ) {\n for (const dictionaryKey of dictionaryKeys) {\n // Update maxDictionaryKeyLength if the new key is longer\n if (dictionaryKey.length > this.maxDictionaryKeyLength) {\n this.maxDictionaryKeyLength = dictionaryKey.length;\n }\n\n let statusObj = this.dictionariesStatuses.find(\n (ds) => ds.dictionaryKey === dictionaryKey\n );\n\n if (!statusObj) {\n // If the dictionaryKey doesn't exist yet, create a new DictionariesStatus\n\n statusObj = {\n dictionaryKey,\n state: [],\n };\n this.dictionariesStatuses.push(statusObj);\n\n const newState: State = {\n type,\n status: 'pending',\n spinnerFrameIndex: 0,\n };\n statusObj.state.push(newState);\n } else {\n const existingState = statusObj.state.find((s) => s.type === type);\n if (!existingState) {\n // Add new state for the type\n\n const newState: State = {\n type,\n status: 'pending',\n spinnerFrameIndex: 0,\n };\n statusObj.state.push(newState);\n }\n }\n }\n\n // Call updateAllStatusLines() to refresh the output\n this.updateAllStatusLines();\n }\n\n private startSpinner() {\n if (!this.spinnerTimer) {\n this.spinnerTimer = setInterval(() => {\n this.updateAllStatusLines();\n }, 100); // Update every 100ms\n }\n }\n\n private stopSpinner() {\n if (this.spinnerTimer) {\n clearInterval(this.spinnerTimer);\n this.spinnerTimer = null;\n }\n }\n\n // Method to update the terminal output\n private updateOutput(content: string) {\n // Monkey-patch process.stdout.write to keep track of extra lines\n if (!this.originalStdoutWrite) {\n this.originalStdoutWrite = process.stdout.write.bind(process.stdout);\n this.extraLines = 0;\n\n const write = (\n chunk: string | Uint8Array, // `chunk` can be either a string or a Uint8Array\n encoding?: BufferEncoding, // `encoding` is optional and should be a BufferEncoding\n callback?: (err?: Error | null) => void // `callback` is optional and a function\n ) => {\n const str = typeof chunk === 'string' ? chunk : chunk.toString();\n const newLines = (str.match(/\\n/g) ?? []).length;\n\n // If the write is not initiated by Logger's updateOutput method\n if (!this.isUpdating) {\n this.extraLines += newLines;\n }\n\n return this.originalStdoutWrite!(chunk, encoding, callback);\n };\n\n process.stdout.write = write as typeof process.stdout.write;\n }\n\n // Set a flag to indicate that updateOutput is running\n this.isUpdating = true;\n\n // Adjust lineDifCounter if LINE_DETECTOR is not the first line\n const contentLines = content.split('\\n');\n const indexOfLineDetector = contentLines.indexOf(LINE_DETECTOR.trim());\n\n if (indexOfLineDetector > 0) {\n // LINE_DETECTOR is not at the first line\n this.lineDifCounter = indexOfLineDetector;\n } else {\n this.lineDifCounter = 0;\n }\n\n // Calculate total lines to move up\n const totalLinesToMoveUp =\n this.previousLineCount + this.lineDifCounter + this.extraLines;\n\n // Move cursor up by totalLinesToMoveUp\n readline.moveCursor(process.stdout, 0, -totalLinesToMoveUp);\n\n // Clear all lines downwards\n readline.clearScreenDown(process.stdout);\n\n // Write the updated content\n contentLines.forEach((line) => {\n process.stdout.write(`${line}\\x1b[K\\n`);\n });\n\n // Update previousLineCount\n this.previousLineCount = contentLines.length;\n\n // Reset extraLines counter and updating flag\n this.extraLines = 0;\n this.isUpdating = false;\n }\n\n public stop() {\n this.stopSpinner();\n }\n\n public updateStatus(\n dictionaries: {\n dictionaryKey: string;\n type: 'local' | 'distant';\n status: Partial<State>;\n }[]\n ) {\n for (const { dictionaryKey, type, status } of dictionaries) {\n const statusObj = this.dictionariesStatuses.find(\n (ds) => ds.dictionaryKey === dictionaryKey\n );\n if (statusObj) {\n const state = statusObj.state.find((s) => s.type === type);\n if (state) {\n // Update existing state\n Object.assign(state, status);\n } else {\n // If the state for this type doesn't exist yet, add it\n if (status.status === undefined) {\n status.status = 'pending'; // Provide default status\n }\n const newState: State = {\n type,\n status: status.status,\n icon: status.icon ?? '',\n error: status.error,\n errorMessage: status.errorMessage,\n spinnerFrameIndex: status.spinnerFrameIndex ?? 0,\n };\n statusObj.state.push(newState);\n }\n } else {\n // If the status object doesn't exist, create it\n const newState: State = {\n type,\n status: status.status ?? 'pending',\n icon: status.icon ?? '',\n error: status.error,\n errorMessage: status.errorMessage,\n spinnerFrameIndex: status.spinnerFrameIndex ?? 0,\n };\n this.dictionariesStatuses.push({\n dictionaryKey,\n state: [newState],\n });\n }\n }\n\n // Update the display after status change\n this.updateAllStatusLines();\n }\n\n private getStatusIcon(status: string): string {\n const statusIcons: Record<string, string> = {\n pending: '⏲',\n fetching: '', // Spinner handled separately\n built: '✔',\n imported: '✔',\n error: '✖',\n };\n return statusIcons[status] ?? '';\n }\n\n private getStatusLine(statusObj: DictionariesStatus): string {\n const keyPadding =\n this.maxDictionaryKeyLength - statusObj.dictionaryKey.length;\n const paddedKey = `${statusObj.dictionaryKey}${' '.repeat(keyPadding)}`;\n\n const states = statusObj.state.map((state) => {\n let colorStart = '';\n let colorEnd = '';\n let icon = this.getStatusIcon(state.status);\n if (state.status === 'fetching') {\n // Use spinner frame\n icon = SPINNER_FRAMES[state.spinnerFrameIndex! % SPINNER_FRAMES.length];\n colorStart = BLUE;\n colorEnd = RESET;\n } else if (state.status === 'error') {\n colorStart = RED;\n colorEnd = RESET;\n } else if (state.status === 'imported' || state.status === 'built') {\n colorStart = GREEN;\n colorEnd = RESET;\n } else {\n colorStart = GREY;\n colorEnd = RESET;\n }\n\n // Format the status block\n const statusBlock = `${GREY_DARK}[${state.type}: ${colorStart}${icon} ${state.status}${GREY_DARK}]${colorEnd}`;\n\n return `${colorStart}${statusBlock}${colorEnd}`;\n });\n\n return `- ${paddedKey} ${states.join(' ')}`;\n }\n\n // Replace logUpdate calls with your custom methods\n private updateAllStatusLines() {\n const terminalHeight = process.stdout.rows;\n const maxVisibleLines = terminalHeight - 1;\n\n const lines = this.dictionariesStatuses.map((statusObj) => {\n statusObj.state.forEach((state) => {\n if (state.status === 'fetching') {\n // Update spinner frame\n state.spinnerFrameIndex =\n (state.spinnerFrameIndex! + 1) % SPINNER_FRAMES.length;\n }\n });\n return this.getStatusLine(statusObj);\n });\n\n let content;\n\n if (lines.length > maxVisibleLines) {\n const visibleLines = lines.slice(0, maxVisibleLines - 5);\n const summary = `... and ${lines.length - visibleLines.length} more lines`;\n content = LINE_DETECTOR + visibleLines.join('\\n') + '\\n' + summary;\n } else {\n content = lines.join('\\n');\n }\n\n this.updateOutput(content);\n }\n\n public getStatuses() {\n return this.dictionariesStatuses;\n }\n}\n\nexport const logger = Logger.getInstance();\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"fetchDistantDictionaries.d.ts","sourceRoot":"","sources":["../../src/fetchDistantDictionaries.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAOvD,KAAK,+BAA+B,GAAG;IACrC,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,wBAAwB,YAC1B,+BAA+B,KACvC,OAAO,CAAC,aAAa,EAAE,CAgFzB,CAAC"}
1
+ {"version":3,"file":"fetchDistantDictionaries.d.ts","sourceRoot":"","sources":["../../src/fetchDistantDictionaries.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAOvD,KAAK,+BAA+B,GAAG;IACrC,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,wBAAwB,YAC1B,+BAA+B,KACvC,OAAO,CAAC,aAAa,EAAE,CA8FzB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"loadDictionaries.d.ts","sourceRoot":"","sources":["../../../src/loadDictionaries/loadDictionaries.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAW5C,eAAO,MAAM,gBAAgB,6BACD,MAAM,EAAE,GAAG,MAAM,KAC1C,OAAO,CAAC,UAAU,EAAE,CAkEtB,CAAC"}
1
+ {"version":3,"file":"loadDictionaries.d.ts","sourceRoot":"","sources":["../../../src/loadDictionaries/loadDictionaries.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAW5C,eAAO,MAAM,gBAAgB,6BACD,MAAM,EAAE,GAAG,MAAM,KAC1C,OAAO,CAAC,UAAU,EAAE,CAsEtB,CAAC"}
@@ -12,15 +12,13 @@ export type DictionariesStatus = {
12
12
  };
13
13
  declare class Logger {
14
14
  private dictionariesStatuses;
15
- private spinnerFrames;
16
15
  private spinnerTimer;
17
16
  private maxDictionaryKeyLength;
18
- private RESET;
19
- private GREEN;
20
- private RED;
21
- private BLUE;
22
- private GREY;
23
- private GREY_DARK;
17
+ private previousLineCount;
18
+ private lineDifCounter;
19
+ private originalStdoutWrite;
20
+ private extraLines;
21
+ private isUpdating;
24
22
  private static instance;
25
23
  private constructor();
26
24
  static getInstance(): Logger;
@@ -28,8 +26,13 @@ declare class Logger {
28
26
  addDictionaryKeys(type: 'local' | 'distant', dictionaryKeys: string[]): void;
29
27
  private startSpinner;
30
28
  private stopSpinner;
29
+ private updateOutput;
31
30
  stop(): void;
32
- updateStatus(dictionaryKey: string, type: 'local' | 'distant', status: Partial<State>): void;
31
+ updateStatus(dictionaries: {
32
+ dictionaryKey: string;
33
+ type: 'local' | 'distant';
34
+ status: Partial<State>;
35
+ }[]): void;
33
36
  private getStatusIcon;
34
37
  private getStatusLine;
35
38
  private updateAllStatusLines;
@@ -1 +1 @@
1
- {"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../src/log.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,KAAK,GAAG;IAClB,IAAI,EAAE,OAAO,GAAG,SAAS,CAAC;IAC1B,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,UAAU,GAAG,OAAO,CAAC;IAC5E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,KAAK,EAAE,CAAC;CAChB,CAAC;AAEF,cAAM,MAAM;IACV,OAAO,CAAC,oBAAoB,CAA4B;IACxD,OAAO,CAAC,aAAa,CAAsD;IAC3E,OAAO,CAAC,YAAY,CAA+B;IACnD,OAAO,CAAC,sBAAsB,CAAa;IAG3C,OAAO,CAAC,KAAK,CAAa;IAC1B,OAAO,CAAC,KAAK,CAAc;IAC3B,OAAO,CAAC,GAAG,CAAc;IACzB,OAAO,CAAC,IAAI,CAAc;IAC1B,OAAO,CAAC,IAAI,CAAc;IAC1B,OAAO,CAAC,SAAS,CAAc;IAG/B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAS;IAEhC,OAAO;WAEO,WAAW,IAAI,MAAM;IAO5B,IAAI,CACT,qBAAqB,EAAE,MAAM,EAAE,EAC/B,uBAAuB,EAAE,MAAM,EAAE;IA+C5B,iBAAiB,CACtB,IAAI,EAAE,OAAO,GAAG,SAAS,EACzB,cAAc,EAAE,MAAM,EAAE;IA8C1B,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,WAAW;IAOZ,IAAI;IASJ,YAAY,CACjB,aAAa,EAAE,MAAM,EACrB,IAAI,EAAE,OAAO,GAAG,SAAS,EACzB,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC;IA6CxB,OAAO,CAAC,aAAa;IAWrB,OAAO,CAAC,aAAa;IAqCrB,OAAO,CAAC,oBAAoB;IAerB,WAAW;CAGnB;AAED,eAAO,MAAM,MAAM,QAAuB,CAAC"}
1
+ {"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../src/log.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,KAAK,GAAG;IAClB,IAAI,EAAE,OAAO,GAAG,SAAS,CAAC;IAC1B,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,UAAU,GAAG,OAAO,CAAC;IAC5E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,KAAK,EAAE,CAAC;CAChB,CAAC;AAaF,cAAM,MAAM;IACV,OAAO,CAAC,oBAAoB,CAA4B;IACxD,OAAO,CAAC,YAAY,CAA+B;IACnD,OAAO,CAAC,sBAAsB,CAAa;IAC3C,OAAO,CAAC,iBAAiB,CAAa;IACtC,OAAO,CAAC,cAAc,CAAa;IACnC,OAAO,CAAC,mBAAmB,CAMX;IAChB,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,UAAU,CAAkB;IAGpC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAS;IAEhC,OAAO;WAEO,WAAW,IAAI,MAAM;IAO5B,IAAI,CACT,qBAAqB,EAAE,MAAM,EAAE,EAC/B,uBAAuB,EAAE,MAAM,EAAE;IA+C5B,iBAAiB,CACtB,IAAI,EAAE,OAAO,GAAG,SAAS,EACzB,cAAc,EAAE,MAAM,EAAE;IA8C1B,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,YAAY;IA8Db,IAAI;IAIJ,YAAY,CACjB,YAAY,EAAE;QACZ,aAAa,EAAE,MAAM,CAAC;QACtB,IAAI,EAAE,OAAO,GAAG,SAAS,CAAC;QAC1B,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;KACxB,EAAE;IA+CL,OAAO,CAAC,aAAa;IAWrB,OAAO,CAAC,aAAa;IAmCrB,OAAO,CAAC,oBAAoB;IA4BrB,WAAW;CAGnB;AAED,eAAO,MAAM,MAAM,QAAuB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intlayer/chokidar",
3
- "version": "3.3.4",
3
+ "version": "3.3.5",
4
4
  "private": false,
5
5
  "description": "Chokidar application for IntLayer - Transpile IntLayer declaration files into dictionaries.",
6
6
  "keywords": [
@@ -62,17 +62,16 @@
62
62
  "esbuild": "^0.24.0",
63
63
  "esbuild-loader": "^4.2.2",
64
64
  "fast-glob": "^3.3.2",
65
- "log-update": "^6.1.0",
66
65
  "node-loader": "^2.1.0",
67
66
  "p-limit": "^3.1.0",
68
67
  "quicktype-core": "^23.0.170",
69
68
  "react": "^18.3.1",
70
69
  "rimraf": "^6.0.1",
71
- "@intlayer/backend": "^3.3.4",
72
- "@intlayer/config": "^3.3.4",
73
- "@intlayer/core": "^3.3.4",
74
- "@intlayer/design-system": "^3.3.4",
75
- "intlayer": "^3.3.4"
70
+ "@intlayer/backend": "^3.3.5",
71
+ "@intlayer/config": "^3.3.5",
72
+ "@intlayer/core": "^3.3.5",
73
+ "@intlayer/design-system": "^3.3.5",
74
+ "intlayer": "^3.3.5"
76
75
  },
77
76
  "devDependencies": {
78
77
  "@changesets/cli": "2.27.10",
@@ -88,15 +87,15 @@
88
87
  "webpack-watch-files-plugin": "^1.2.1",
89
88
  "@utils/eslint-config": "^1.0.4",
90
89
  "@utils/ts-config": "^1.0.4",
91
- "@utils/tsup-config": "^1.0.4",
92
- "@utils/ts-config-types": "^1.0.4"
90
+ "@utils/ts-config-types": "^1.0.4",
91
+ "@utils/tsup-config": "^1.0.4"
93
92
  },
94
93
  "peerDependencies": {
95
- "@intlayer/config": "^3.3.4",
96
- "@intlayer/backend": "^3.3.4",
97
- "intlayer": "^3.3.4",
98
- "@intlayer/design-system": "^3.3.4",
99
- "@intlayer/core": "^3.3.4"
94
+ "@intlayer/backend": "^3.3.5",
95
+ "@intlayer/config": "^3.3.5",
96
+ "@intlayer/core": "^3.3.5",
97
+ "@intlayer/design-system": "^3.3.5",
98
+ "intlayer": "^3.3.5"
100
99
  },
101
100
  "engines": {
102
101
  "node": ">=14.18"