glotstack 0.0.8 → 0.0.10

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.
@@ -1,20 +1,70 @@
1
1
  import { existsSync } from 'fs'
2
2
  import { readFile } from 'fs/promises'
3
3
  import * as path from 'path'
4
+ import { loadYaml } from './yaml'
5
+
6
+
7
+ function dropKeys<T>(input: T | string, keysToDrop: string[]): T {
8
+ const obj = typeof input === 'string' ? JSON.parse(input) : structuredClone(input)
9
+
10
+ for (const path of keysToDrop) {
11
+ const segments = path.split('.')
12
+ let target: any = obj
13
+
14
+ for (let i = 0; i < segments.length - 1; i++) {
15
+ const key = segments[i]
16
+ const next = isNaN(Number(key)) ? key : Number(key)
17
+
18
+ if (target[next] === undefined) {
19
+ target = undefined
20
+ break
21
+ }
22
+ target = target[next]
23
+ }
24
+
25
+ if (target !== undefined) {
26
+ const finalKey = segments[segments.length - 1]
27
+ const final = isNaN(Number(finalKey)) ? finalKey : Number(finalKey)
28
+ delete target[final]
29
+ }
30
+ }
31
+
32
+ return obj
33
+ }
34
+
35
+
36
+ export interface GlotstackConfig {
37
+ outputDir?: string
38
+ sourcePath: string
39
+ sourceLocale: string
40
+ outputLocales: string[]
41
+ apiOrigin?: string
42
+ apiKey: string
43
+ projectId?: string
44
+ }
4
45
 
5
46
  /**
6
47
  * Recursively looks for `.glotstack.json` from the current directory up to the root.
7
48
  * @param startDir The directory to start the search from. Defaults to process.cwd().
8
49
  * @returns The absolute path to the file if found, or null if not found.
9
50
  */
10
- export async function findGlotstackConfig(startDir: string = process.cwd()): Promise<object | null> {
51
+ export async function findGlotstackConfig(startDir: string = process.cwd()): Promise<GlotstackConfig | null> {
11
52
  let currentDir = path.resolve(startDir)
12
53
  let configPath = null
13
54
 
14
55
  while (true) {
15
- const candidate = path.join(currentDir, '.glotstack.json')
16
- if (existsSync(candidate)) {
17
- configPath = candidate
56
+ const jsonCandidate = path.join(currentDir, '.glotstack.json')
57
+ const yamlCandidate = path.join(currentDir, '.glotstack.yaml')
58
+ const jsonExists = existsSync(jsonCandidate)
59
+ const yamlExists = existsSync(yamlCandidate)
60
+ if (jsonExists && yamlExists) {
61
+ console.error('Both .glotstack.json and .glotstack.yaml exist, please delete one\n\n json: ', jsonCandidate, '\n yaml: ', yamlCandidate)
62
+ throw new Error('Two config formats cannot be used at the same time')
63
+
64
+ } else if (jsonExists) {
65
+ configPath = jsonCandidate
66
+ } else if (yamlExists) {
67
+ configPath = yamlCandidate
18
68
  }
19
69
 
20
70
  const parentDir = path.dirname(currentDir)
@@ -24,19 +74,23 @@ export async function findGlotstackConfig(startDir: string = process.cwd()): Pro
24
74
  currentDir = parentDir
25
75
  }
26
76
 
27
- let config = {}
77
+ let config: GlotstackConfig
28
78
 
29
79
  if (configPath != null) {
30
- console.info('Loading config file at ', configPath)
80
+ console.info('Loading config file at ', dropKeys(configPath, ['apiKey']))
31
81
  try {
32
82
  const text = await readFile(configPath, 'utf-8')
33
- config = JSON.parse(text)
83
+ if (path.parse(configPath).ext === '.yaml') {
84
+ config = loadYaml(text) as GlotstackConfig
85
+ } else {
86
+ config = JSON.parse(text)
87
+ }
34
88
  console.info('Loaded config file', config)
35
89
  return config
36
90
  } catch (err) {
37
91
  console.warn('Could not load config', configPath)
38
92
  }
39
93
  }
40
- console.warn('Could not find any .glotstack.json config files')
94
+ console.warn('Could not find any .glotstack config files')
41
95
  return null
42
96
  }
@@ -21,12 +21,8 @@ function _merge(target: any, source: any): any {
21
21
  return target;
22
22
  }
23
23
 
24
- type MergeTarget = Record<string|number|symbol, any>
25
-
26
- export function merge(target: MergeTarget, ...sources: MergeTarget[]): MergeTarget {
27
- return sources.reduce((previous, current) => {
28
- return _merge(previous, current);
29
- }, target)
24
+ export function merge<T extends object>(target: T, ...sources: Partial<T>[]): T {
25
+ return sources.reduce((previous, current) => _merge(previous, current), target) as T
30
26
  }
31
27
 
32
28
  export function isEqual(a: any, b: any): boolean {