@knocklabs/cli 0.1.14 → 0.1.15

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.
package/README.md CHANGED
@@ -16,7 +16,7 @@ $ npm install -g @knocklabs/cli
16
16
  $ knock COMMAND
17
17
  running command...
18
18
  $ knock (--version)
19
- @knocklabs/cli/0.1.14 linux-x64 node-v18.20.2
19
+ @knocklabs/cli/0.1.15 linux-x64 node-v18.20.2
20
20
  $ knock --help [COMMAND]
21
21
  USAGE
22
22
  $ knock COMMAND
@@ -31,7 +31,7 @@ USAGE
31
31
  * [`knock commit get ID`](#knock-commit-get-id)
32
32
  * [`knock commit list`](#knock-commit-list)
33
33
  * [`knock commit promote`](#knock-commit-promote)
34
- * [`knock help [COMMANDS]`](#knock-help-commands)
34
+ * [`knock help [COMMAND]`](#knock-help-command)
35
35
  * [`knock layout get EMAILLAYOUTKEY`](#knock-layout-get-emaillayoutkey)
36
36
  * [`knock layout list`](#knock-layout-list)
37
37
  * [`knock layout pull [EMAILLAYOUTKEY]`](#knock-layout-pull-emaillayoutkey)
@@ -78,7 +78,7 @@ FLAGS
78
78
  --service-token=<value> (required) The service token to authenticate with.
79
79
  ```
80
80
 
81
- _See code: [src/commands/commit/index.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.14/src/commands/commit/index.ts)_
81
+ _See code: [src/commands/commit/index.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.15/src/commands/commit/index.ts)_
82
82
 
83
83
  ## `knock commit get ID`
84
84
 
@@ -95,7 +95,7 @@ GLOBAL FLAGS
95
95
  --json Format output as json.
96
96
  ```
97
97
 
98
- _See code: [src/commands/commit/get.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.14/src/commands/commit/get.ts)_
98
+ _See code: [src/commands/commit/get.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.15/src/commands/commit/get.ts)_
99
99
 
100
100
  ## `knock commit list`
101
101
 
@@ -119,7 +119,7 @@ GLOBAL FLAGS
119
119
  --json Format output as json.
120
120
  ```
121
121
 
122
- _See code: [src/commands/commit/list.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.14/src/commands/commit/list.ts)_
122
+ _See code: [src/commands/commit/list.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.15/src/commands/commit/list.ts)_
123
123
 
124
124
  ## `knock commit promote`
125
125
 
@@ -136,18 +136,18 @@ FLAGS
136
136
  --to=<value> The destination environment to promote all changes from the preceding environment.
137
137
  ```
138
138
 
139
- _See code: [src/commands/commit/promote.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.14/src/commands/commit/promote.ts)_
139
+ _See code: [src/commands/commit/promote.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.15/src/commands/commit/promote.ts)_
140
140
 
141
- ## `knock help [COMMANDS]`
141
+ ## `knock help [COMMAND]`
142
142
 
143
143
  Display help for knock.
144
144
 
145
145
  ```
146
146
  USAGE
147
- $ knock help [COMMANDS...] [-n]
147
+ $ knock help [COMMAND...] [-n]
148
148
 
149
149
  ARGUMENTS
150
- COMMANDS... Command to show help for.
150
+ COMMAND... Command to show help for.
151
151
 
152
152
  FLAGS
153
153
  -n, --nested-commands Include all nested commands in the output.
@@ -156,7 +156,7 @@ DESCRIPTION
156
156
  Display help for knock.
157
157
  ```
158
158
 
159
- _See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v6.0.14/src/commands/help.ts)_
159
+ _See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v6.0.21/src/commands/help.ts)_
160
160
 
161
161
  ## `knock layout get EMAILLAYOUTKEY`
162
162
 
@@ -176,7 +176,7 @@ GLOBAL FLAGS
176
176
  --json Format output as json.
177
177
  ```
178
178
 
179
- _See code: [src/commands/layout/get.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.14/src/commands/layout/get.ts)_
179
+ _See code: [src/commands/layout/get.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.15/src/commands/layout/get.ts)_
180
180
 
181
181
  ## `knock layout list`
182
182
 
@@ -199,7 +199,7 @@ GLOBAL FLAGS
199
199
  --json Format output as json.
200
200
  ```
201
201
 
202
- _See code: [src/commands/layout/list.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.14/src/commands/layout/list.ts)_
202
+ _See code: [src/commands/layout/list.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.15/src/commands/layout/list.ts)_
203
203
 
204
204
  ## `knock layout pull [EMAILLAYOUTKEY]`
205
205
 
@@ -219,7 +219,7 @@ FLAGS
219
219
  --service-token=<value> (required) The service token to authenticate with.
220
220
  ```
221
221
 
222
- _See code: [src/commands/layout/pull.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.14/src/commands/layout/pull.ts)_
222
+ _See code: [src/commands/layout/pull.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.15/src/commands/layout/pull.ts)_
223
223
 
224
224
  ## `knock layout push [EMAILLAYOUTKEY]`
225
225
 
@@ -241,7 +241,7 @@ FLAGS
241
241
  --service-token=<value> (required) The service token to authenticate with.
242
242
  ```
243
243
 
244
- _See code: [src/commands/layout/push.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.14/src/commands/layout/push.ts)_
244
+ _See code: [src/commands/layout/push.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.15/src/commands/layout/push.ts)_
245
245
 
246
246
  ## `knock layout validate [EMAILLAYOUTKEY]`
247
247
 
@@ -260,7 +260,7 @@ FLAGS
260
260
  --service-token=<value> (required) The service token to authenticate with.
261
261
  ```
262
262
 
263
- _See code: [src/commands/layout/validate.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.14/src/commands/layout/validate.ts)_
263
+ _See code: [src/commands/layout/validate.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.15/src/commands/layout/validate.ts)_
264
264
 
265
265
  ## `knock plugins`
266
266
 
@@ -548,7 +548,7 @@ Display a single translation from an environment.
548
548
  ```
549
549
  USAGE
550
550
  $ knock translation get TRANSLATIONREF --service-token <value> [--json] [--environment <value>]
551
- [--hide-uncommitted-changes]
551
+ [--hide-uncommitted-changes] [--format json|po]
552
552
 
553
553
  ARGUMENTS
554
554
  TRANSLATIONREF Translation ref is a identifier string that refers to a unique translation.
@@ -557,6 +557,8 @@ ARGUMENTS
557
557
 
558
558
  FLAGS
559
559
  --environment=<value> [default: development] The environment to use.
560
+ --format=<option> [default: json] Specify the output format of the returned translations.
561
+ <options: json|po>
560
562
  --hide-uncommitted-changes Hide any uncommitted changes.
561
563
  --service-token=<value> (required) The service token to authenticate with.
562
564
 
@@ -564,7 +566,7 @@ GLOBAL FLAGS
564
566
  --json Format output as json.
565
567
  ```
566
568
 
567
- _See code: [src/commands/translation/get.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.14/src/commands/translation/get.ts)_
569
+ _See code: [src/commands/translation/get.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.15/src/commands/translation/get.ts)_
568
570
 
569
571
  ## `knock translation list`
570
572
 
@@ -587,7 +589,7 @@ GLOBAL FLAGS
587
589
  --json Format output as json.
588
590
  ```
589
591
 
590
- _See code: [src/commands/translation/list.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.14/src/commands/translation/list.ts)_
592
+ _See code: [src/commands/translation/list.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.15/src/commands/translation/list.ts)_
591
593
 
592
594
  ## `knock translation pull [TRANSLATIONREF]`
593
595
 
@@ -596,7 +598,7 @@ Pull one or more translations from an environment into a local file system.
596
598
  ```
597
599
  USAGE
598
600
  $ knock translation pull [TRANSLATIONREF] --service-token <value> [--environment <value>] [--translations-dir
599
- <value> --all] [--hide-uncommitted-changes] [--force]
601
+ <value> --all] [--hide-uncommitted-changes] [--force] [--format json|po]
600
602
 
601
603
  ARGUMENTS
602
604
  TRANSLATIONREF Translation ref is a identifier string that refers to a unique translation.
@@ -607,12 +609,14 @@ FLAGS
607
609
  --all Whether to pull all translations from the specified environment.
608
610
  --environment=<value> [default: development] The environment to use.
609
611
  --force Remove the confirmation prompt.
612
+ --format=<option> [default: json] Specify the output format of the returned translations.
613
+ <options: json|po>
610
614
  --hide-uncommitted-changes Hide any uncommitted changes.
611
615
  --service-token=<value> (required) The service token to authenticate with.
612
616
  --translations-dir=<value> The target directory path to pull all translations into.
613
617
  ```
614
618
 
615
- _See code: [src/commands/translation/pull.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.14/src/commands/translation/pull.ts)_
619
+ _See code: [src/commands/translation/pull.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.15/src/commands/translation/pull.ts)_
616
620
 
617
621
  ## `knock translation push [TRANSLATIONREF]`
618
622
 
@@ -639,7 +643,7 @@ FLAGS
639
643
  --translations-dir=<value> The target directory path to find all translations to push.
640
644
  ```
641
645
 
642
- _See code: [src/commands/translation/push.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.14/src/commands/translation/push.ts)_
646
+ _See code: [src/commands/translation/push.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.15/src/commands/translation/push.ts)_
643
647
 
644
648
  ## `knock translation validate [TRANSLATIONREF]`
645
649
 
@@ -664,7 +668,7 @@ FLAGS
664
668
  --translations-dir=<value> The target directory path to find all translations to validate.
665
669
  ```
666
670
 
667
- _See code: [src/commands/translation/validate.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.14/src/commands/translation/validate.ts)_
671
+ _See code: [src/commands/translation/validate.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.15/src/commands/translation/validate.ts)_
668
672
 
669
673
  ## `knock whoami`
670
674
 
@@ -681,7 +685,7 @@ GLOBAL FLAGS
681
685
  --json Format output as json.
682
686
  ```
683
687
 
684
- _See code: [src/commands/whoami.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.14/src/commands/whoami.ts)_
688
+ _See code: [src/commands/whoami.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.15/src/commands/whoami.ts)_
685
689
 
686
690
  ## `knock workflow activate WORKFLOWKEY`
687
691
 
@@ -708,7 +712,7 @@ DESCRIPTION
708
712
  with `false` in order to deactivate it.
709
713
  ```
710
714
 
711
- _See code: [src/commands/workflow/activate.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.14/src/commands/workflow/activate.ts)_
715
+ _See code: [src/commands/workflow/activate.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.15/src/commands/workflow/activate.ts)_
712
716
 
713
717
  ## `knock workflow get WORKFLOWKEY`
714
718
 
@@ -728,7 +732,7 @@ GLOBAL FLAGS
728
732
  --json Format output as json.
729
733
  ```
730
734
 
731
- _See code: [src/commands/workflow/get.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.14/src/commands/workflow/get.ts)_
735
+ _See code: [src/commands/workflow/get.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.15/src/commands/workflow/get.ts)_
732
736
 
733
737
  ## `knock workflow list`
734
738
 
@@ -751,7 +755,7 @@ GLOBAL FLAGS
751
755
  --json Format output as json.
752
756
  ```
753
757
 
754
- _See code: [src/commands/workflow/list.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.14/src/commands/workflow/list.ts)_
758
+ _See code: [src/commands/workflow/list.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.15/src/commands/workflow/list.ts)_
755
759
 
756
760
  ## `knock workflow pull [WORKFLOWKEY]`
757
761
 
@@ -771,7 +775,7 @@ FLAGS
771
775
  --workflows-dir=<value> The target directory path to pull all workflows into.
772
776
  ```
773
777
 
774
- _See code: [src/commands/workflow/pull.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.14/src/commands/workflow/pull.ts)_
778
+ _See code: [src/commands/workflow/pull.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.15/src/commands/workflow/pull.ts)_
775
779
 
776
780
  ## `knock workflow push [WORKFLOWKEY]`
777
781
 
@@ -792,7 +796,7 @@ FLAGS
792
796
  --workflows-dir=<value> The target directory path to find all workflows to push.
793
797
  ```
794
798
 
795
- _See code: [src/commands/workflow/push.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.14/src/commands/workflow/push.ts)_
799
+ _See code: [src/commands/workflow/push.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.15/src/commands/workflow/push.ts)_
796
800
 
797
801
  ## `knock workflow run WORKFLOWKEY`
798
802
 
@@ -813,7 +817,7 @@ FLAGS
813
817
  --tenant=<value> A tenant id for the workflow run.
814
818
  ```
815
819
 
816
- _See code: [src/commands/workflow/run.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.14/src/commands/workflow/run.ts)_
820
+ _See code: [src/commands/workflow/run.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.15/src/commands/workflow/run.ts)_
817
821
 
818
822
  ## `knock workflow validate [WORKFLOWKEY]`
819
823
 
@@ -832,5 +836,5 @@ FLAGS
832
836
  --workflows-dir=<value> The target directory path to find all workflows to validate.
833
837
  ```
834
838
 
835
- _See code: [src/commands/workflow/validate.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.14/src/commands/workflow/validate.ts)_
839
+ _See code: [src/commands/workflow/validate.ts](https://github.com/knocklabs/knock-cli/blob/v0.1.15/src/commands/workflow/validate.ts)_
836
840
  <!-- commandsstop -->
@@ -85,7 +85,7 @@ class TranslationGet extends _basecommand.default {
85
85
  }
86
86
  render(translation) {
87
87
  const { translationRef } = this.props.args;
88
- const { environment: env, "hide-uncommitted-changes": commitedOnly } = this.props.flags;
88
+ const { environment: env, "hide-uncommitted-changes": commitedOnly, format } = this.props.flags;
89
89
  const qualifier = env === "development" && !commitedOnly ? "(including uncommitted)" : "";
90
90
  this.log(`‣ Showing translation \`${translationRef}\` in \`${env}\` environment ${qualifier}\n`);
91
91
  /*
@@ -123,7 +123,11 @@ class TranslationGet extends _basecommand.default {
123
123
  }
124
124
  });
125
125
  this.log("");
126
- _core.ux.styledJSON(JSON.parse(translation.content));
126
+ if (format === "json") {
127
+ _core.ux.styledJSON(JSON.parse(translation.content));
128
+ } else {
129
+ _core.ux.log(translation.content);
130
+ }
127
131
  }
128
132
  }
129
133
  _define_property(TranslationGet, "summary", "Display a single translation from an environment.");
@@ -134,7 +138,15 @@ _define_property(TranslationGet, "flags", {
134
138
  }),
135
139
  "hide-uncommitted-changes": _core.Flags.boolean({
136
140
  summary: "Hide any uncommitted changes."
137
- })
141
+ }),
142
+ format: _core.Flags.option({
143
+ summary: "Specify the output format of the returned translations.",
144
+ options: [
145
+ "json",
146
+ "po"
147
+ ],
148
+ default: "json"
149
+ })()
138
150
  });
139
151
  _define_property(TranslationGet, "args", {
140
152
  translationRef: _core.Args.string({
@@ -102,7 +102,9 @@ class TranslationPull extends _basecommand.default {
102
102
  if (!input) return;
103
103
  }
104
104
  const resp = await (0, _request.withSpinner)(()=>this.apiV1.getTranslation(this.props, targetCtx));
105
- await _translation.writeTranslationFile(targetCtx, resp.data);
105
+ await _translation.writeTranslationFile(targetCtx, resp.data, {
106
+ format: flags.format
107
+ });
106
108
  const actioned = targetCtx.exists ? "updated" : "created";
107
109
  this.log(`‣ Successfully ${actioned} \`${targetCtx.ref}\` at ${targetCtx.abspath}`);
108
110
  }
@@ -120,7 +122,9 @@ class TranslationPull extends _basecommand.default {
120
122
  localeCode: targetCtx.key
121
123
  };
122
124
  const translations = await this.listAllTranslations(filters);
123
- await _translation.writeTranslationFiles(targetCtx, translations);
125
+ await _translation.writeTranslationFiles(targetCtx, translations, {
126
+ format: flags.format
127
+ });
124
128
  _ux.spinner.stop();
125
129
  const actioned = targetCtx.exists ? "updated" : "created";
126
130
  this.log(`‣ Successfully ${actioned} the \`${targetCtx.key}\` translations directory at ${targetCtx.abspath}`);
@@ -135,7 +139,9 @@ class TranslationPull extends _basecommand.default {
135
139
  // Fetch all translations then write them to the local file system.
136
140
  _ux.spinner.start(`‣ Loading`);
137
141
  const translations = await this.listAllTranslations();
138
- await _translation.writeTranslationFiles(targetCtx, translations);
142
+ await _translation.writeTranslationFiles(targetCtx, translations, {
143
+ format: flags.format
144
+ });
139
145
  _ux.spinner.stop();
140
146
  const action = targetCtx.exists ? "updated" : "created";
141
147
  this.log(`‣ Successfully ${action} the translations directory at ${targetCtx.abspath}`);
@@ -182,7 +188,15 @@ _define_property(TranslationPull, "flags", {
182
188
  }),
183
189
  force: _core.Flags.boolean({
184
190
  summary: "Remove the confirmation prompt."
185
- })
191
+ }),
192
+ format: _core.Flags.option({
193
+ summary: "Specify the output format of the returned translations.",
194
+ options: [
195
+ "json",
196
+ "po"
197
+ ],
198
+ default: "json"
199
+ })()
186
200
  });
187
201
  _define_property(TranslationPull, "args", {
188
202
  translationRef: _core.Args.string({
@@ -107,7 +107,8 @@ class TranslationPush extends _basecommand.default {
107
107
  const resp = await this.apiV1.upsertTranslation(this.props, {
108
108
  locale_code: translation.localeCode,
109
109
  namespace: translation.namespace,
110
- content: translation.content
110
+ content: translation.content,
111
+ format: translation.format
111
112
  });
112
113
  if ((0, _request.isSuccessResp)(resp)) continue;
113
114
  const message = (0, _request.formatErrorRespMessage)(resp);
@@ -106,7 +106,8 @@ class TranslationValidate extends _basecommand.default {
106
106
  const resp = await api.validateTranslation(props, {
107
107
  locale_code: translation.localeCode,
108
108
  namespace: translation.namespace,
109
- content: translation.content
109
+ content: translation.content,
110
+ format: translation.format
110
111
  });
111
112
  if ((0, _request.isSuccessResp)(resp)) return;
112
113
  const message = (0, _request.formatErrorRespMessage)(resp);
@@ -149,6 +149,7 @@ class ApiV1 {
149
149
  hide_uncommitted_changes: flags["hide-uncommitted-changes"],
150
150
  locale_code: filters.localeCode,
151
151
  namespace: filters.namespace,
152
+ format: flags.format,
152
153
  ...(0, _page.toPageParams)(flags)
153
154
  });
154
155
  return this.get("/translations", {
@@ -159,7 +160,8 @@ class ApiV1 {
159
160
  const params = (0, _objectisomorphic.prune)({
160
161
  environment: flags.environment,
161
162
  hide_uncommitted_changes: flags["hide-uncommitted-changes"],
162
- namespace: translation.namespace
163
+ namespace: translation.namespace,
164
+ format: flags.format
163
165
  });
164
166
  return this.get(`/translations/${translation.localeCode}`, {
165
167
  params
@@ -104,15 +104,15 @@ const isTranslationDir = (dirPath)=>{
104
104
  const locale = _nodepath.basename(dirPath);
105
105
  return isValidLocale(locale);
106
106
  };
107
- const buildTranslationFileCtx = async (dirPath, localeCode, namespace)=>{
108
- const ref = (0, _processorisomorphic.formatRef)(localeCode, namespace);
109
- const filename = (0, _processorisomorphic.formatFileName)(ref);
107
+ const buildTranslationFileCtx = async (dirPath, translationIdentifier, options)=>{
108
+ const ref = (0, _processorisomorphic.formatRef)(translationIdentifier.localeCode, translationIdentifier.namespace);
109
+ const filename = (0, _processorisomorphic.formatFileName)(ref, options);
110
110
  const abspath = _nodepath.resolve(dirPath, filename);
111
111
  const exists = await _fsextra.pathExists(abspath);
112
112
  return {
113
113
  ref,
114
- localeCode,
115
- namespace,
114
+ localeCode: translationIdentifier.localeCode,
115
+ namespace: translationIdentifier.namespace,
116
116
  abspath,
117
117
  exists
118
118
  };
@@ -182,10 +182,34 @@ const ensureValidCommandTarget = async (props, runContext)=>{
182
182
  // Got translationRef arg but no --all flag, which means target only a single
183
183
  // translation file.
184
184
  if (!flags.all) {
185
- const translationFileCtx = await buildTranslationFileCtx(targetDirPath, localeCode, namespace);
185
+ // If specified, check the given format; otherwise check for all supported formats
186
+ const formats = flags.format ? [
187
+ flags.format
188
+ ] : _processorisomorphic.SUPPORTED_TRANSLATION_FORMATS;
189
+ const translationFileCtxs = await Promise.all(formats.map(async (format)=>buildTranslationFileCtx(targetDirPath, {
190
+ localeCode,
191
+ namespace
192
+ }, {
193
+ format
194
+ })));
195
+ if (flags.format) {
196
+ return {
197
+ type: "translationFile",
198
+ context: translationFileCtxs[0]
199
+ };
200
+ }
201
+ // If no format is specified, look for the first existing file and return that context
202
+ const existingFileCtx = translationFileCtxs.find((ctx)=>ctx.exists);
203
+ if (existingFileCtx) {
204
+ return {
205
+ type: "translationFile",
206
+ context: existingFileCtx
207
+ };
208
+ }
209
+ // If no file exists, fall back to the file context with the default format (json)
186
210
  return {
187
211
  type: "translationFile",
188
- context: translationFileCtx
212
+ context: translationFileCtxs[0]
189
213
  };
190
214
  }
191
215
  // From this point on, we have both translationRef and --all flag used
@@ -212,7 +236,8 @@ const lsTranslationDir = async (pathToDir)=>{
212
236
  return dirents.filter((dirent)=>{
213
237
  if (dirent.isDirectory()) return false;
214
238
  const filename = dirent.name.toLowerCase();
215
- if (!filename.endsWith(`${localeCode}.json`)) return false;
239
+ const isValidExtension = _processorisomorphic.SUPPORTED_TRANSLATION_FORMATS.some((extension)=>filename.endsWith(`${localeCode}.${extension}`));
240
+ if (!isValidExtension) return false;
216
241
  const { name: translationRef } = _nodepath.parse(filename);
217
242
  const parsedRef = parseTranslationRef(translationRef);
218
243
  if (!parsedRef) return false;
@@ -9,6 +9,12 @@ function _export(target, all) {
9
9
  });
10
10
  }
11
11
  _export(exports, {
12
+ DEFAULT_TRANSLATION_FORMAT: function() {
13
+ return DEFAULT_TRANSLATION_FORMAT;
14
+ },
15
+ SUPPORTED_TRANSLATION_FORMATS: function() {
16
+ return SUPPORTED_TRANSLATION_FORMATS;
17
+ },
12
18
  buildTranslationDirBundle: function() {
13
19
  return buildTranslationDirBundle;
14
20
  },
@@ -19,21 +25,35 @@ _export(exports, {
19
25
  return formatRef;
20
26
  }
21
27
  });
28
+ const SUPPORTED_TRANSLATION_FORMATS = [
29
+ "json",
30
+ "po"
31
+ ];
32
+ const DEFAULT_TRANSLATION_FORMAT = "json";
22
33
  const formatRef = (localeCode, namespace)=>namespace ? `${namespace}.${localeCode}` : localeCode;
23
- const formatFileName = (input)=>{
34
+ const formatFileName = (input, options)=>{
35
+ var _options_format;
36
+ const extension = (_options_format = options === null || options === void 0 ? void 0 : options.format) !== null && _options_format !== void 0 ? _options_format : DEFAULT_TRANSLATION_FORMAT;
24
37
  const ref = typeof input === "string" ? input : formatRef(input.locale_code, input.namespace);
25
- return `${ref}.json`;
38
+ return `${ref}.${extension}`;
26
39
  };
27
- const buildTranslationDirBundle = (input)=>{
40
+ const buildTranslationDirBundle = (input, options)=>{
41
+ var _options_format;
42
+ const format = (_options_format = options === null || options === void 0 ? void 0 : options.format) !== null && _options_format !== void 0 ? _options_format : DEFAULT_TRANSLATION_FORMAT;
28
43
  if (Array.isArray(input)) {
29
44
  const translations = input;
30
45
  return Object.fromEntries(translations.map((translation)=>[
31
- formatFileName(translation),
46
+ formatFileName(translation, {
47
+ format
48
+ }),
32
49
  JSON.parse(translation.content)
33
50
  ]));
34
51
  }
35
52
  const translation = input;
53
+ const content = format === "json" ? JSON.parse(translation.content) : translation.content;
36
54
  return {
37
- [formatFileName(translation)]: JSON.parse(translation.content)
55
+ [formatFileName(translation, {
56
+ format
57
+ })]: content
38
58
  };
39
59
  };
@@ -14,6 +14,7 @@ const _fsextra = /*#__PURE__*/ _interop_require_wildcard(require("fs-extra"));
14
14
  const _error = require("../../helpers/error");
15
15
  const _json = require("../../helpers/json");
16
16
  const _helpers = require("./helpers");
17
+ const _processorisomorphic = require("./processor.isomorphic");
17
18
  function _getRequireWildcardCache(nodeInterop) {
18
19
  if (typeof WeakMap !== "function") return null;
19
20
  var cacheBabelInterop = new WeakMap();
@@ -76,10 +77,9 @@ function _interop_require_wildcard(obj, nodeInterop) {
76
77
  // push commands. Consider making this an option in the future.
77
78
  if (namespace === _helpers.SYSTEM_NAMESPACE) continue;
78
79
  // eslint-disable-next-line no-await-in-loop
79
- const [content, readJsonErrors] = await (0, _json.readJson)(abspath);
80
- if (readJsonErrors.length > 0) {
81
- const e = new _error.SourceError((0, _error.formatErrors)(readJsonErrors), abspath);
82
- errors.push(e);
80
+ const [content, sourceError, format] = await readTranslationFile(abspath);
81
+ if (sourceError) {
82
+ errors.push(sourceError);
83
83
  continue;
84
84
  }
85
85
  translations.push({
@@ -88,7 +88,8 @@ function _interop_require_wildcard(obj, nodeInterop) {
88
88
  namespace,
89
89
  abspath,
90
90
  exists: true,
91
- content: JSON.stringify(content)
91
+ content,
92
+ format
92
93
  });
93
94
  }
94
95
  return [
@@ -96,6 +97,56 @@ function _interop_require_wildcard(obj, nodeInterop) {
96
97
  errors
97
98
  ];
98
99
  };
100
+ const readTranslationFile = async (filePath)=>{
101
+ // Get translation format from file extension
102
+ const format = getFormatFromFilePath(filePath);
103
+ switch(format){
104
+ case "json":
105
+ {
106
+ const [jsonContent, readErrors] = await (0, _json.readJson)(filePath);
107
+ if (readErrors.length > 0) {
108
+ const e = new _error.SourceError((0, _error.formatErrors)(readErrors), filePath);
109
+ return [
110
+ undefined,
111
+ e,
112
+ format
113
+ ];
114
+ }
115
+ const content = JSON.stringify(jsonContent);
116
+ return [
117
+ content,
118
+ undefined,
119
+ format
120
+ ];
121
+ }
122
+ case "po":
123
+ {
124
+ try {
125
+ const content = await _fsextra.readFile(filePath, "utf8");
126
+ return [
127
+ content,
128
+ undefined,
129
+ format
130
+ ];
131
+ } catch (error) {
132
+ const e = new _error.SourceError(error.message, filePath);
133
+ return [
134
+ undefined,
135
+ e,
136
+ format
137
+ ];
138
+ }
139
+ }
140
+ default:
141
+ throw new Error(`unsupported translation file extension: ${filePath}`);
142
+ }
143
+ };
144
+ const getFormatFromFilePath = (filePath)=>{
145
+ // Path.extname returns the extension with a period (e.g. .json)
146
+ // so we use slice to get just the name
147
+ const extension = _nodepath.extname(filePath).slice(1);
148
+ return _processorisomorphic.SUPPORTED_TRANSLATION_FORMATS.includes(extension) ? extension : undefined;
149
+ };
99
150
  const readAllForCommandTarget = async (target)=>{
100
151
  const { type: targetType, context: targetCtx } = target;
101
152
  if (!targetCtx.exists) {
@@ -1,4 +1,3 @@
1
- // Translation payload data from the API.
2
1
  "use strict";
3
2
  Object.defineProperty(exports, "__esModule", {
4
3
  value: true
@@ -22,6 +22,7 @@ const _lodash = require("lodash");
22
22
  const _const = require("../../helpers/const");
23
23
  const _json = require("../../helpers/json");
24
24
  const _helpers = require("./helpers");
25
+ const _processorisomorphic = require("./processor.isomorphic");
25
26
  function _getRequireWildcardCache(nodeInterop) {
26
27
  if (typeof WeakMap !== "function") return null;
27
28
  var cacheBabelInterop = new WeakMap();
@@ -63,10 +64,21 @@ function _interop_require_wildcard(obj, nodeInterop) {
63
64
  }
64
65
  return newObj;
65
66
  }
66
- const writeTranslationFile = async (translationFileCtx, translation)=>_fsextra.outputJson(translationFileCtx.abspath, JSON.parse(translation.content), {
67
- spaces: _json.DOUBLE_SPACES
68
- });
69
- const writeTranslationFiles = async (targetDirCtx, translations)=>{
67
+ const writeTranslationFile = async (translationFileCtx, translation, options)=>{
68
+ var _options_format;
69
+ const format = (_options_format = options === null || options === void 0 ? void 0 : options.format) !== null && _options_format !== void 0 ? _options_format : _processorisomorphic.DEFAULT_TRANSLATION_FORMAT;
70
+ switch(format){
71
+ case "json":
72
+ return _fsextra.outputJson(translationFileCtx.abspath, JSON.parse(translation.content), {
73
+ spaces: _json.DOUBLE_SPACES
74
+ });
75
+ case "po":
76
+ return _fsextra.outputFile(translationFileCtx.abspath, translation.content);
77
+ default:
78
+ throw new Error(`Invalid translation file format: ${options === null || options === void 0 ? void 0 : options.format}`);
79
+ }
80
+ };
81
+ const writeTranslationFiles = async (targetDirCtx, translations, options)=>{
70
82
  const backupDirPath = _nodepath.resolve(_const.sandboxDir, (0, _lodash.uniqueId)("backup"));
71
83
  try {
72
84
  // If the index directory already exists, back it up in the temp sandbox
@@ -81,8 +93,11 @@ const writeTranslationFiles = async (targetDirCtx, translations)=>{
81
93
  // to write translation files in; otherwise for translations index
82
94
  // directory, we want to nest translation files under each locale dir.
83
95
  const localeDirPath = "key" in targetDirCtx ? targetDirCtx.abspath : _nodepath.resolve(targetDirCtx.abspath, translation.locale_code);
84
- const translationFileCtx = await (0, _helpers.buildTranslationFileCtx)(localeDirPath, translation.locale_code, translation.namespace);
85
- return writeTranslationFile(translationFileCtx, translation);
96
+ const translationFileCtx = await (0, _helpers.buildTranslationFileCtx)(localeDirPath, {
97
+ localeCode: translation.locale_code,
98
+ namespace: translation.namespace
99
+ }, options);
100
+ return writeTranslationFile(translationFileCtx, translation, options);
86
101
  });
87
102
  await Promise.all(writeTranslationDirPromises);
88
103
  } catch (error) {
@@ -817,6 +817,18 @@
817
817
  "summary": "Hide any uncommitted changes.",
818
818
  "allowNo": false,
819
819
  "type": "boolean"
820
+ },
821
+ "format": {
822
+ "name": "format",
823
+ "summary": "Specify the output format of the returned translations.",
824
+ "default": "json",
825
+ "hasDynamicHelp": false,
826
+ "multiple": false,
827
+ "options": [
828
+ "json",
829
+ "po"
830
+ ],
831
+ "type": "option"
820
832
  }
821
833
  },
822
834
  "hasDynamicHelp": false,
@@ -979,6 +991,18 @@
979
991
  "summary": "Remove the confirmation prompt.",
980
992
  "allowNo": false,
981
993
  "type": "boolean"
994
+ },
995
+ "format": {
996
+ "name": "format",
997
+ "summary": "Specify the output format of the returned translations.",
998
+ "default": "json",
999
+ "hasDynamicHelp": false,
1000
+ "multiple": false,
1001
+ "options": [
1002
+ "json",
1003
+ "po"
1004
+ ],
1005
+ "type": "option"
982
1006
  }
983
1007
  },
984
1008
  "hasDynamicHelp": false,
@@ -1758,5 +1782,5 @@
1758
1782
  ]
1759
1783
  }
1760
1784
  },
1761
- "version": "0.1.14"
1785
+ "version": "0.1.15"
1762
1786
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knocklabs/cli",
3
- "version": "0.1.14",
3
+ "version": "0.1.15",
4
4
  "description": "Knock CLI",
5
5
  "author": "@knocklabs",
6
6
  "bin": {
@@ -21,18 +21,18 @@
21
21
  "@oclif/plugin-help": "^6",
22
22
  "@oclif/plugin-plugins": "^4",
23
23
  "@prantlf/jsonlint": "^14.0.3",
24
- "axios": "^1.5.1",
24
+ "axios": "^1.6.8",
25
25
  "date-fns": "^2.30.0",
26
26
  "enquirer": "^2.4.1",
27
27
  "fs-extra": "^11.2.0",
28
- "liquidjs": "^10.10.2",
28
+ "liquidjs": "^10.12.0",
29
29
  "locale-codes": "^1.3.1",
30
30
  "lodash": "^4.17.21",
31
31
  "yup": "^1.4.0"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@oclif/test": "^3",
35
- "@swc/cli": "^0.3.9",
35
+ "@swc/cli": "^0.3.12",
36
36
  "@swc/core": "^1.4.6",
37
37
  "@swc/helpers": "^0.5.6",
38
38
  "@types/chai": "^4",
@@ -47,7 +47,7 @@
47
47
  "eslint-plugin-prettier": "^4.2.1",
48
48
  "eslint-plugin-simple-import-sort": "^10.0.0",
49
49
  "mocha": "^10",
50
- "nock": "^13.5.3",
50
+ "nock": "^13.5.4",
51
51
  "oclif": "^4",
52
52
  "prettier": "2.8.8",
53
53
  "shx": "^0.3.4",