@romaintaillandier1978/dotenv-never-lies 0.4.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,6 +13,7 @@ export type ExportCliOptions = {
13
13
  hideSecret?: boolean;
14
14
  excludeSecret?: boolean;
15
15
  includeComments?: boolean;
16
+ serializeTyped?: boolean;
16
17
  out?: string | undefined;
17
18
  force?: boolean;
18
19
  k8sName?: string | undefined;
@@ -20,15 +21,15 @@ export type ExportCliOptions = {
20
21
  };
21
22
  export declare const exportCommand: (options: ExportCliOptions) => Promise<ExportResult>;
22
23
  export declare const contentByFormat: (format: ExportFormat, envDef: dnl.EnvDefinitionHelper<any>, options: ExportCliOptions, warnings: string[]) => string;
23
- export declare const exportJson: (envDef: dnl.EnvDefinitionHelper<any>, options: ExportCliOptions, warnings: string[]) => string;
24
24
  export declare const exportEnv: (envDef: dnl.EnvDefinitionHelper<any>, options: ExportCliOptions, warnings: string[]) => string;
25
25
  export declare const exportDockerArgs: (envDef: dnl.EnvDefinitionHelper<any>, options: ExportCliOptions, warnings: string[]) => string;
26
26
  export declare const exportDockerEnv: (envDef: dnl.EnvDefinitionHelper<any>, options: ExportCliOptions, warnings: string[]) => string;
27
27
  export declare const exportK8sConfigmap: (envDef: dnl.EnvDefinitionHelper<any>, options: ExportCliOptions, warnings: string[]) => string;
28
28
  export declare const exportK8sSecret: (envDef: dnl.EnvDefinitionHelper<any>, options: ExportCliOptions, warnings: string[]) => string;
29
- export declare const exportTs: (envDef: dnl.EnvDefinitionHelper<any>, options: ExportCliOptions, warnings: string[]) => string;
30
- export declare const exportJs: (envDef: dnl.EnvDefinitionHelper<any>, options: ExportCliOptions, warnings: string[]) => string;
31
29
  export declare const exportGithubEnv: (envDef: dnl.EnvDefinitionHelper<any>, options: ExportCliOptions, warnings: string[]) => string;
32
30
  export declare const exportGithubSecret: (envDef: dnl.EnvDefinitionHelper<any>, options: ExportCliOptions, warnings: string[]) => string;
33
31
  export declare const exportGitlabEnv: (envDef: dnl.EnvDefinitionHelper<any>, options: ExportCliOptions, warnings: string[]) => string;
32
+ export declare const exportJson: (envDef: dnl.EnvDefinitionHelper<any>, options: ExportCliOptions, warnings: string[]) => string;
33
+ export declare const exportTs: (envDef: dnl.EnvDefinitionHelper<any>, options: ExportCliOptions, warnings: string[]) => string;
34
+ export declare const exportJs: (envDef: dnl.EnvDefinitionHelper<any>, options: ExportCliOptions, warnings: string[]) => string;
34
35
  //# sourceMappingURL=export.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/export.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/export.ts"],"names":[],"mappings":"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"}
@@ -16,12 +16,21 @@ export const exportFormatsNames = [
16
16
  "ts",
17
17
  "js",
18
18
  ];
19
+ const shellEscape = (value) => {
20
+ if (value.length === 0) {
21
+ return "''";
22
+ }
23
+ return `'${value.replace(/'/g, "'\\''")}'`;
24
+ };
19
25
  export const exportCommand = async (options) => {
20
26
  if (options.githubOrg && options.format !== "github-secret") {
21
- throw new UsageError("--github-org ne peut être utilisé qu’avec le format github-secret");
27
+ throw new UsageError("--github-org can only be used with the github-secret format");
22
28
  }
23
29
  if (options.k8sName && !options.format.startsWith("k8s-")) {
24
- throw new UsageError("--k8s-name ne peut être utilisé qu’avec un format k8s-*");
30
+ throw new UsageError("--k8s-name can only be used with a k8s-* format");
31
+ }
32
+ if (options.serializeTyped && !["js", "ts", "json"].includes(options.format)) {
33
+ throw new UsageError("--serialize-typed is only valid for js, ts and json exports");
25
34
  }
26
35
  const schemaPath = resolveSchemaPath(options?.schema);
27
36
  const envDef = (await loadDef(schemaPath));
@@ -58,67 +67,47 @@ export const contentByFormat = (format, envDef, options, warnings) => {
58
67
  case "docker-env":
59
68
  return exportDockerEnv(envDef, options, warnings);
60
69
  default:
61
- throw new UsageError(`Format ${format} non supporté`);
70
+ throw new UsageError(`Unsupported format: ${format}`);
62
71
  }
63
72
  };
64
- export const exportJson = (envDef, options, warnings) => {
65
- if (options?.includeComments) {
66
- warnings.push("--include-comments option ignorée pour le format json");
73
+ // #region serialisation env-like
74
+ const getRawValue = (key, source, envDef, options) => {
75
+ if (options?.hideSecret && envDef.def[key].secret) {
76
+ return "********";
67
77
  }
68
- const source = options?.source ? dnl.readEnvFile(path.resolve(process.cwd(), options.source)) : process.env;
69
- const values = envDef.assert({ source });
70
- const args = {};
71
- for (const [key, value] of Object.entries(values)) {
72
- if (options?.excludeSecret && envDef.def[key].secret) {
73
- continue;
74
- }
75
- if (options?.hideSecret && envDef.def[key].secret) {
76
- args[key] = "********";
77
- }
78
- else {
79
- args[key] = value;
80
- }
81
- }
82
- return JSON.stringify(args, null, 2);
78
+ const raw = source[key]; // raw value from source (i.e. .env or process.env)
79
+ return raw == null ? "" : String(raw);
83
80
  };
84
- // ca clone le .env
81
+ // this clones the .env
85
82
  export const exportEnv = (envDef, options, warnings) => {
86
83
  const source = options?.source ? dnl.readEnvFile(path.resolve(process.cwd(), options.source)) : process.env;
87
84
  const values = envDef.assert({ source });
88
85
  const args = [];
89
- for (const [key, value] of Object.entries(values)) {
86
+ for (const key of Object.keys(values)) {
90
87
  if (options?.excludeSecret && envDef.def[key].secret) {
91
88
  continue;
92
89
  }
93
90
  if (options?.includeComments && envDef.def[key].description) {
94
91
  args.push(`# ${envDef.def[key].description}`);
95
92
  }
96
- if (options?.hideSecret && envDef.def[key].secret) {
97
- args.push(`${key}=********`);
98
- }
99
- else {
100
- args.push(`${key}=${value}`);
101
- }
93
+ const rawValue = getRawValue(key, source, envDef, options);
94
+ args.push(`${key}=${rawValue}`);
102
95
  }
103
96
  return args.join("\n");
104
97
  };
105
98
  export const exportDockerArgs = (envDef, options, warnings) => {
106
99
  if (options?.includeComments) {
107
- warnings.push("--include-comments option invalide avec le format docker-args");
100
+ warnings.push("The --include-comments option is invalid with the docker-args format");
108
101
  }
109
102
  const source = options?.source ? dnl.readEnvFile(path.resolve(process.cwd(), options.source)) : process.env;
110
103
  const values = envDef.assert({ source });
111
104
  const args = [];
112
- for (const [key, value] of Object.entries(values)) {
105
+ for (const key of Object.keys(values)) {
113
106
  if (options?.excludeSecret && envDef.def[key].secret) {
114
107
  continue;
115
108
  }
116
- if (options?.hideSecret && envDef.def[key].secret) {
117
- args.push(`-e "${key}=********"`);
118
- }
119
- else {
120
- args.push(`-e "${key}=${value}"`);
121
- }
109
+ const rawValue = getRawValue(key, source, envDef, options);
110
+ args.push(`-e ${shellEscape(`${key}=${rawValue}`)}`);
122
111
  }
123
112
  return args.join(" ");
124
113
  };
@@ -126,19 +115,15 @@ export const exportDockerEnv = (envDef, options, warnings) => {
126
115
  const source = options?.source ? dnl.readEnvFile(path.resolve(process.cwd(), options.source)) : process.env;
127
116
  const values = envDef.assert({ source });
128
117
  const args = [];
129
- for (const [key, value] of Object.entries(values)) {
118
+ for (const key of Object.keys(values)) {
130
119
  if (options?.excludeSecret && envDef.def[key].secret) {
131
120
  continue;
132
121
  }
133
122
  if (options?.includeComments && envDef.def[key].description) {
134
123
  args.push(`# ${envDef.def[key].description}`);
135
124
  }
136
- if (options?.hideSecret && envDef.def[key].secret) {
137
- args.push(`${key}=********`);
138
- }
139
- else {
140
- args.push(`${key}=${value}`);
141
- }
125
+ const rawValue = getRawValue(key, source, envDef, options);
126
+ args.push(`${key}=${rawValue}`);
142
127
  }
143
128
  return args.join("\n");
144
129
  };
@@ -152,16 +137,16 @@ export const exportK8sConfigmap = (envDef, options, warnings) => {
152
137
  const name = options?.k8sName ?? "env-config";
153
138
  args.push(` name: ${name}`);
154
139
  args.push(`data:`);
155
- for (const [key, value] of Object.entries(values)) {
140
+ for (const key of Object.keys(values)) {
156
141
  if (envDef.def[key].secret) {
157
142
  if (options?.excludeSecret)
158
143
  continue;
159
144
  if (!options?.hideSecret) {
160
- warnings.push(`Secret ${key} exporté dans un ConfigMap. Utilisez le format k8s-secret.`);
145
+ warnings.push(`Secret ${key} exported in a ConfigMap. Use the k8s-secret format.`);
161
146
  }
162
147
  }
163
- const v = options?.hideSecret && envDef.def[key].secret ? "********" : value;
164
- args.push(` ${key}: ${JSON.stringify(v)}`);
148
+ const rawValue = getRawValue(key, source, envDef, options);
149
+ args.push(` ${key}: ${JSON.stringify(rawValue)}`);
165
150
  }
166
151
  return args.join("\n");
167
152
  };
@@ -176,88 +161,108 @@ export const exportK8sSecret = (envDef, options, warnings) => {
176
161
  const name = options?.k8sName ?? "env-secret";
177
162
  args.push(` name: ${name}`);
178
163
  args.push(`stringData:`);
179
- for (const [key, value] of Object.entries(values)) {
164
+ for (const key of Object.keys(values)) {
180
165
  if (options?.excludeSecret && envDef.def[key].secret)
181
166
  continue;
182
167
  if (!envDef.def[key].secret)
183
- continue; // Secret = uniquement les variables marquées secret
184
- const v = options?.hideSecret ? "********" : value;
185
- args.push(` ${key}: ${JSON.stringify(v)}`);
168
+ continue; // Secret = only variables marked as secret
169
+ const rawValue = getRawValue(key, source, envDef, options);
170
+ args.push(` ${key}: ${JSON.stringify(rawValue)}`);
186
171
  }
187
172
  return args.join("\n");
188
173
  };
189
- export const exportTs = (envDef, options, warnings) => {
190
- const source = options?.source ? dnl.readEnvFile(path.resolve(process.cwd(), options.source)) : process.env;
191
- const values = envDef.assert({ source });
192
- const middle = [];
193
- for (const [key, value] of Object.entries(values)) {
194
- if (options?.excludeSecret && envDef.def[key].secret) {
195
- continue;
196
- }
197
- if (options?.includeComments && envDef.def[key].description) {
198
- middle.push(` // ${envDef.def[key].description}`);
199
- }
200
- if (options?.hideSecret && envDef.def[key].secret) {
201
- middle.push(` ${key}: "********",`);
202
- }
203
- else {
204
- middle.push(` ${key}: ${JSON.stringify(value, null, 2)},`);
205
- }
206
- }
207
- return `export const env = {\n${middle.join("\n")}\n} as const;`;
208
- };
209
- export const exportJs = (envDef, options, warnings) => {
210
- const source = options?.source ? dnl.readEnvFile(path.resolve(process.cwd(), options.source)) : process.env;
211
- const values = envDef.assert({ source });
212
- const middle = [];
213
- for (const [key, value] of Object.entries(values)) {
214
- if (options?.excludeSecret && envDef.def[key].secret) {
215
- continue;
216
- }
217
- if (options?.includeComments && envDef.def[key].description) {
218
- middle.push(` // ${envDef.def[key].description}`);
219
- }
220
- if (options?.hideSecret && envDef.def[key].secret) {
221
- middle.push(` ${key}: "********",`);
222
- }
223
- else {
224
- middle.push(` ${key}: ${JSON.stringify(value, null, 2)},`);
225
- }
226
- }
227
- return `export const env = {\n${middle.join("\n")}\n};`;
228
- };
229
174
  export const exportGithubEnv = (envDef, options, warnings) => {
230
175
  const source = options?.source ? dnl.readEnvFile(path.resolve(process.cwd(), options.source)) : process.env;
231
176
  const values = envDef.assert({ source });
232
177
  const args = [];
233
- for (const [key, value] of Object.entries(values)) {
178
+ for (const key of Object.keys(values)) {
234
179
  if (options?.excludeSecret && envDef.def[key].secret)
235
180
  continue;
236
- const v = options?.hideSecret && envDef.def[key].secret ? "********" : value;
237
- args.push(`echo "${key}=${v}" >> $GITHUB_ENV`);
181
+ const rawValue = getRawValue(key, source, envDef, options);
182
+ args.push(`printf '%s\\n' ${shellEscape(`${key}=${rawValue}`)} >> "$GITHUB_ENV"`);
238
183
  }
239
184
  return args.join("\n");
240
185
  };
241
186
  export const exportGithubSecret = (envDef, options, warnings) => {
242
187
  if (options?.hideSecret) {
243
- warnings.push("--hide-secret est incompatible avec github-secret");
188
+ warnings.push("The --hide-secret option is incompatible with github-secret");
244
189
  }
245
190
  if (options?.githubOrg && options.githubOrg.includes(" ")) {
246
- warnings.push("github-org contient un espace, commande gh probablement invalide");
191
+ warnings.push("github-org contains a space; gh command likely invalid");
247
192
  }
248
193
  const source = options?.source ? dnl.readEnvFile(path.resolve(process.cwd(), options.source)) : process.env;
249
194
  const values = envDef.assert({ source });
250
- const scopeFlag = options?.githubOrg ? `--org ${options?.githubOrg}` : "";
195
+ const scopeFlag = options?.githubOrg ? `--org ${shellEscape(options.githubOrg)}` : "";
251
196
  const args = [];
252
- for (const [key, value] of Object.entries(values)) {
197
+ for (const key of Object.keys(values)) {
253
198
  if (!envDef.def[key].secret)
254
199
  continue;
255
200
  if (options?.excludeSecret)
256
201
  continue;
257
- args.push(`echo ${JSON.stringify(value)} | gh secret set ${key} ${scopeFlag}`.trim());
202
+ const rawValue = getRawValue(key, source, envDef, options);
203
+ args.push(`printf '%s' ${shellEscape(rawValue)} | gh secret set ${key} ${scopeFlag} --body-file -`.trim());
258
204
  }
259
205
  return args.join("\n");
260
206
  };
261
207
  export const exportGitlabEnv = (envDef, options, warnings) => {
262
208
  return exportEnv(envDef, options, warnings);
263
209
  };
210
+ // #endregion serialisation env-like
211
+ // #region serialisation json/ts/js
212
+ // WARNING : For design reasons and separation of concerns, do not attempt to merge getRawValue and getTypedOrRawValue into a single function.
213
+ const getTypedOrRawValue = (key, source, values, envDef, options) => {
214
+ if (options?.hideSecret && envDef.def[key].secret) {
215
+ return "********";
216
+ }
217
+ if (options?.serializeTyped) {
218
+ return values[key]; // runtime validated value
219
+ }
220
+ const raw = source[key]; // raw value from source (i.e. .env or process.env)
221
+ return raw == null ? "" : String(raw);
222
+ };
223
+ export const exportJson = (envDef, options, warnings) => {
224
+ if (options?.includeComments) {
225
+ warnings.push("The --include-comments option is ignored for the json format");
226
+ }
227
+ const source = options?.source ? dnl.readEnvFile(path.resolve(process.cwd(), options.source)) : process.env;
228
+ const values = envDef.assert({ source });
229
+ const args = {};
230
+ for (const key of Object.keys(values)) {
231
+ if (options?.excludeSecret && envDef.def[key].secret) {
232
+ continue;
233
+ }
234
+ args[key] = getTypedOrRawValue(key, source, values, envDef, options);
235
+ }
236
+ return JSON.stringify(args, null, 2);
237
+ };
238
+ export const exportTs = (envDef, options, warnings) => {
239
+ const source = options?.source ? dnl.readEnvFile(path.resolve(process.cwd(), options.source)) : process.env;
240
+ const values = envDef.assert({ source });
241
+ const middle = [];
242
+ for (const key of Object.keys(values)) {
243
+ if (options?.excludeSecret && envDef.def[key].secret) {
244
+ continue;
245
+ }
246
+ if (options?.includeComments && envDef.def[key].description) {
247
+ middle.push(` // ${envDef.def[key].description}`);
248
+ }
249
+ middle.push(` ${key}: ${JSON.stringify(getTypedOrRawValue(key, source, values, envDef, options), null, 2)},`);
250
+ }
251
+ return `export const env = {\n${middle.join("\n")}\n} as const;`;
252
+ };
253
+ export const exportJs = (envDef, options, warnings) => {
254
+ const source = options?.source ? dnl.readEnvFile(path.resolve(process.cwd(), options.source)) : process.env;
255
+ const values = envDef.assert({ source });
256
+ const middle = [];
257
+ for (const key of Object.keys(values)) {
258
+ if (options?.excludeSecret && envDef.def[key].secret) {
259
+ continue;
260
+ }
261
+ if (options?.includeComments && envDef.def[key].description) {
262
+ middle.push(` // ${envDef.def[key].description}`);
263
+ }
264
+ middle.push(` ${key}: ${JSON.stringify(getTypedOrRawValue(key, source, values, envDef, options), null, 2)},`);
265
+ }
266
+ return `export const env = {\n${middle.join("\n")}\n};`;
267
+ };
268
+ // #endregion serialisation json/ts/js
@@ -8,5 +8,8 @@ export type GenerateResult = {
8
8
  content: string;
9
9
  out: string;
10
10
  };
11
- export declare const generateCommand: (opts?: GenerateCliOptions | undefined) => Promise<GenerateResult>;
11
+ export declare const generateCommand: (opts?: GenerateCliOptions | undefined) => Promise<{
12
+ content: string;
13
+ out: string;
14
+ }>;
12
15
  //# sourceMappingURL=generate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/generate.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,kBAAkB,GAAG;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AACF,MAAM,MAAM,cAAc,GAAG;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,eAAO,MAAM,eAAe,GAAU,OAAO,kBAAkB,GAAG,SAAS,KAAG,OAAO,CAAC,cAAc,CA6BnG,CAAC"}
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/generate.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,kBAAkB,GAAG;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AACF,MAAM,MAAM,cAAc,GAAG;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,eAAO,MAAM,eAAe,GAAU,OAAO,kBAAkB,GAAG,SAAS,KAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CA6BrH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"reverseEnv.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/reverseEnv.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,oBAAoB,GAAG;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,EAAE,CAAC;CACtB,CAAC;AACF,eAAO,MAAM,iBAAiB,GAAU,OAAO,oBAAoB,GAAG,SAAS,KAAG,OAAO,CAAC,gBAAgB,CAuCzG,CAAC"}
1
+ {"version":3,"file":"reverseEnv.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/reverseEnv.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,oBAAoB,GAAG;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,EAAE,CAAC;CACtB,CAAC;AACF,eAAO,MAAM,iBAAiB,GAAU,OAAO,oBAAoB,GAAG,SAAS,KAAG,OAAO,CAAC,gBAAgB,CA6CzG,CAAC"}
@@ -15,6 +15,7 @@ export const reverseEnvCommand = async (opts) => {
15
15
  }
16
16
  const env = dnl.readEnvFile(source);
17
17
  const lines = [];
18
+ const warnings = [];
18
19
  lines.push(`// ⚠️ This file was generated by dotenv-never-lies`);
19
20
  lines.push(`// Review and adjust schemas, descriptions and secrets before using`);
20
21
  lines.push("");
@@ -23,7 +24,12 @@ export const reverseEnvCommand = async (opts) => {
23
24
  lines.push("");
24
25
  lines.push(`export default define({`);
25
26
  for (const [key, value] of Object.entries(env)) {
26
- lines.push(` ${key}: {`);
27
+ const isValidIdentifier = /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key);
28
+ const safeKey = isValidIdentifier ? key : JSON.stringify(key);
29
+ if (!isValidIdentifier) {
30
+ warnings.push(`Key ${key} is not a valid identifier. It has been escaped to ${safeKey}.`);
31
+ }
32
+ lines.push(` ${safeKey}: {`);
27
33
  lines.push(` description: "TODO",`);
28
34
  lines.push(` schema: ${inferSchema(value)},`);
29
35
  if (opts?.guessSecret && guessSecret(key)) {
@@ -35,6 +41,6 @@ export const reverseEnvCommand = async (opts) => {
35
41
  return {
36
42
  content: lines.join("\n"),
37
43
  out: target,
38
- warnings: ["Generated schema is a prototype. Review schemas, descriptions and secrets before using."],
44
+ warnings: [...warnings, "Generated schema is a prototype. Review schemas, descriptions and secrets before using."],
39
45
  };
40
46
  };