@quonfig/cli 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +707 -0
  3. package/bin/dev.cmd +3 -0
  4. package/bin/dev.js +9 -0
  5. package/bin/run.cmd +3 -0
  6. package/bin/run.js +8 -0
  7. package/dist/api/get-environments.d.ts +10 -0
  8. package/dist/api/get-environments.js +11 -0
  9. package/dist/codegen/code-generators/base-generator.d.ts +11 -0
  10. package/dist/codegen/code-generators/base-generator.js +8 -0
  11. package/dist/codegen/code-generators/base-typescript-generator.d.ts +17 -0
  12. package/dist/codegen/code-generators/base-typescript-generator.js +35 -0
  13. package/dist/codegen/code-generators/node-typescript-generator.d.ts +8 -0
  14. package/dist/codegen/code-generators/node-typescript-generator.js +96 -0
  15. package/dist/codegen/code-generators/react-typescript-generator.d.ts +11 -0
  16. package/dist/codegen/code-generators/react-typescript-generator.js +116 -0
  17. package/dist/codegen/config-downloader.d.ts +7 -0
  18. package/dist/codegen/config-downloader.js +26 -0
  19. package/dist/codegen/json-schema-to-zod.d.ts +3 -0
  20. package/dist/codegen/json-schema-to-zod.js +170 -0
  21. package/dist/codegen/language-mappers/json-to-zod-mapper.d.ts +4 -0
  22. package/dist/codegen/language-mappers/json-to-zod-mapper.js +55 -0
  23. package/dist/codegen/language-mappers/zod-base-mapper.d.ts +35 -0
  24. package/dist/codegen/language-mappers/zod-base-mapper.js +111 -0
  25. package/dist/codegen/language-mappers/zod-to-string-mapper.d.ts +25 -0
  26. package/dist/codegen/language-mappers/zod-to-string-mapper.js +87 -0
  27. package/dist/codegen/language-mappers/zod-to-typescript-mapper.d.ts +35 -0
  28. package/dist/codegen/language-mappers/zod-to-typescript-mapper.js +133 -0
  29. package/dist/codegen/language-mappers/zod-to-typescript-return-value-mapper.d.ts +36 -0
  30. package/dist/codegen/language-mappers/zod-to-typescript-return-value-mapper.js +150 -0
  31. package/dist/codegen/mustache-extractor.d.ts +6 -0
  32. package/dist/codegen/mustache-extractor.js +83 -0
  33. package/dist/codegen/schema-evaluator.d.ts +37 -0
  34. package/dist/codegen/schema-evaluator.js +283 -0
  35. package/dist/codegen/schema-extractor.d.ts +24 -0
  36. package/dist/codegen/schema-extractor.js +265 -0
  37. package/dist/codegen/types.d.ts +44 -0
  38. package/dist/codegen/types.js +5 -0
  39. package/dist/codegen/zod-introspection.d.ts +85 -0
  40. package/dist/codegen/zod-introspection.js +205 -0
  41. package/dist/commands/create.d.ts +19 -0
  42. package/dist/commands/create.js +175 -0
  43. package/dist/commands/download.d.ts +13 -0
  44. package/dist/commands/download.js +63 -0
  45. package/dist/commands/generate-new-hex-key.d.ts +7 -0
  46. package/dist/commands/generate-new-hex-key.js +10 -0
  47. package/dist/commands/generate.d.ts +16 -0
  48. package/dist/commands/generate.js +220 -0
  49. package/dist/commands/get.d.ts +13 -0
  50. package/dist/commands/get.js +141 -0
  51. package/dist/commands/info.d.ts +21 -0
  52. package/dist/commands/info.js +464 -0
  53. package/dist/commands/interactive.d.ts +5 -0
  54. package/dist/commands/interactive.js +8 -0
  55. package/dist/commands/list.d.ts +13 -0
  56. package/dist/commands/list.js +61 -0
  57. package/dist/commands/login.d.ts +10 -0
  58. package/dist/commands/login.js +124 -0
  59. package/dist/commands/logout.d.ts +7 -0
  60. package/dist/commands/logout.js +12 -0
  61. package/dist/commands/mcp.d.ts +13 -0
  62. package/dist/commands/mcp.js +145 -0
  63. package/dist/commands/override.d.ts +17 -0
  64. package/dist/commands/override.js +170 -0
  65. package/dist/commands/profile.d.ts +7 -0
  66. package/dist/commands/profile.js +47 -0
  67. package/dist/commands/schema.d.ts +21 -0
  68. package/dist/commands/schema.js +168 -0
  69. package/dist/commands/serve.d.ts +13 -0
  70. package/dist/commands/serve.js +99 -0
  71. package/dist/commands/set-default.d.ts +20 -0
  72. package/dist/commands/set-default.js +273 -0
  73. package/dist/commands/verify.d.ts +12 -0
  74. package/dist/commands/verify.js +48 -0
  75. package/dist/commands/whoami.d.ts +7 -0
  76. package/dist/commands/whoami.js +52 -0
  77. package/dist/commands/workspace.d.ts +7 -0
  78. package/dist/commands/workspace.js +38 -0
  79. package/dist/constants.d.ts +2 -0
  80. package/dist/constants.js +2 -0
  81. package/dist/help.d.ts +4 -0
  82. package/dist/help.js +10 -0
  83. package/dist/index.d.ts +40 -0
  84. package/dist/index.js +112 -0
  85. package/dist/interactive-prompt.d.ts +2 -0
  86. package/dist/interactive-prompt.js +162 -0
  87. package/dist/quonfig.d.ts +15 -0
  88. package/dist/quonfig.js +75 -0
  89. package/dist/result.d.ts +35 -0
  90. package/dist/result.js +9 -0
  91. package/dist/services/mcp.d.ts +15 -0
  92. package/dist/services/mcp.js +59 -0
  93. package/dist/ui/get-confirmation.d.ts +10 -0
  94. package/dist/ui/get-confirmation.js +4 -0
  95. package/dist/ui/get-environment.d.ts +11 -0
  96. package/dist/ui/get-environment.js +42 -0
  97. package/dist/ui/get-key.d.ts +27 -0
  98. package/dist/ui/get-key.js +15 -0
  99. package/dist/ui/get-string.d.ts +5 -0
  100. package/dist/ui/get-string.js +8 -0
  101. package/dist/ui/get-value.d.ts +18 -0
  102. package/dist/ui/get-value.js +46 -0
  103. package/dist/util/autocomplete.d.ts +6 -0
  104. package/dist/util/autocomplete.js +25 -0
  105. package/dist/util/coerce.d.ts +7 -0
  106. package/dist/util/coerce.js +62 -0
  107. package/dist/util/color.d.ts +3 -0
  108. package/dist/util/color.js +4 -0
  109. package/dist/util/config-value-dto.d.ts +16 -0
  110. package/dist/util/config-value-dto.js +82 -0
  111. package/dist/util/context.d.ts +18 -0
  112. package/dist/util/context.js +10 -0
  113. package/dist/util/domain-urls.d.ts +3 -0
  114. package/dist/util/domain-urls.js +18 -0
  115. package/dist/util/encryption.d.ts +20 -0
  116. package/dist/util/encryption.js +153 -0
  117. package/dist/util/file-manager.d.ts +12 -0
  118. package/dist/util/file-manager.js +16 -0
  119. package/dist/util/get-client.d.ts +7 -0
  120. package/dist/util/get-client.js +127 -0
  121. package/dist/util/is-interactive.d.ts +5 -0
  122. package/dist/util/is-interactive.js +7 -0
  123. package/dist/util/json-maybe.d.ts +3 -0
  124. package/dist/util/json-maybe.js +14 -0
  125. package/dist/util/name-arg.d.ts +4 -0
  126. package/dist/util/name-arg.js +3 -0
  127. package/dist/util/oauth-client.d.ts +30 -0
  128. package/dist/util/oauth-client.js +99 -0
  129. package/dist/util/secret-flags.d.ts +13 -0
  130. package/dist/util/secret-flags.js +13 -0
  131. package/dist/util/token-storage.d.ts +25 -0
  132. package/dist/util/token-storage.js +90 -0
  133. package/dist/validations/value.d.ts +4 -0
  134. package/dist/validations/value.js +11 -0
  135. package/dist/verify/standalone.d.ts +14 -0
  136. package/dist/verify/standalone.js +133 -0
  137. package/dist/verify/validate.d.ts +43 -0
  138. package/dist/verify/validate.js +756 -0
  139. package/dist/version.d.ts +2 -0
  140. package/dist/version.js +2 -0
  141. package/oclif.manifest.json +1429 -0
  142. package/package.json +104 -0
@@ -0,0 +1,85 @@
1
+ import { z } from 'zod';
2
+ import { $ZodFunctionArgs, $ZodFunctionOut, $ZodType, util, $ZodRecordKey } from 'zod/v4/core';
3
+ export declare function isString(schema: $ZodType): schema is z.ZodString;
4
+ export declare function isNumber(schema: $ZodType): schema is z.ZodNumber;
5
+ export declare function isBoolean(schema: $ZodType): schema is z.ZodBoolean;
6
+ export declare function isNull(schema: $ZodType): schema is z.ZodNull;
7
+ export declare function isLiteral(schema: $ZodType): schema is z.ZodLiteral<string | number | boolean | null>;
8
+ export declare function isUndefined(schema: $ZodType): schema is z.ZodUndefined;
9
+ export declare function isUnknown(schema: $ZodType): schema is z.ZodUnknown;
10
+ export declare function isNever(schema: $ZodType): schema is z.ZodNever;
11
+ export declare function isAny(schema: $ZodType): schema is z.ZodAny;
12
+ export declare function isArray(schema: $ZodType): schema is z.ZodArray<z.ZodTypeAny>;
13
+ export declare function isObject(schema: $ZodType): schema is z.ZodObject<z.ZodRawShape>;
14
+ export declare function isTuple(schema: $ZodType): schema is z.ZodTuple;
15
+ export declare function isRecord(schema: $ZodType): schema is z.ZodRecord;
16
+ export declare function isEnum(schema: $ZodType): schema is z.ZodEnum<util.EnumLike>;
17
+ export declare function isUnion(schema: $ZodType): schema is z.ZodUnion<[z.ZodTypeAny, ...z.ZodTypeAny[]]>;
18
+ export declare function isOptional(schema: $ZodType): schema is z.ZodOptional<z.ZodTypeAny>;
19
+ export declare function isNullable(schema: $ZodType): schema is z.ZodNullable<z.ZodTypeAny>;
20
+ export declare function isDefault(schema: $ZodType): schema is z.ZodDefault<z.ZodTypeAny>;
21
+ export declare function isFunction(schema: $ZodType): schema is z.ZodFunction<$ZodFunctionArgs, $ZodFunctionOut>;
22
+ /**
23
+ * Gets the element type from an array schema
24
+ */
25
+ export declare function getArrayElement(schema: z.ZodArray<z.ZodTypeAny>): z.ZodTypeAny;
26
+ /**
27
+ * Gets the shape from an object schema
28
+ */
29
+ export declare function getObjectShape(schema: z.ZodObject<z.ZodRawShape>): z.ZodRawShape;
30
+ /**
31
+ * Gets the items from a tuple schema
32
+ */
33
+ export declare function getTupleItems(schema: z.ZodTuple): readonly $ZodType[];
34
+ /**
35
+ * Gets the key and value types from a record schema
36
+ */
37
+ export declare function getRecordTypes(schema: z.ZodRecord): {
38
+ keyType: $ZodRecordKey;
39
+ valueType: $ZodType;
40
+ };
41
+ /**
42
+ * Gets the enum values from an enum schema
43
+ */
44
+ export declare function getEnumValues(schema: z.ZodEnum<util.EnumLike>): util.EnumValue[];
45
+ export declare function getLiteralValue(schema: z.ZodLiteral<string | number | boolean | null>): string | number | boolean | null;
46
+ /**
47
+ * Gets the options from a union schema
48
+ */
49
+ export declare function getUnionOptions(schema: z.ZodUnion<[z.ZodTypeAny, ...z.ZodTypeAny[]]>): z.ZodTypeAny[];
50
+ /**
51
+ * Unwraps an optional schema to get its inner type
52
+ */
53
+ export declare function unwrapOptional(schema: z.ZodOptional<z.ZodTypeAny>): z.ZodTypeAny;
54
+ /**
55
+ * Unwraps a nullable schema to get its inner type
56
+ */
57
+ export declare function unwrapNullable(schema: z.ZodNullable<z.ZodTypeAny>): z.ZodTypeAny;
58
+ /**
59
+ * Unwraps a default schema to get its inner type and default value
60
+ */
61
+ export declare function unwrapDefault(schema: z.ZodDefault<z.ZodTypeAny>): {
62
+ defaultValue: unknown;
63
+ innerType: z.ZodTypeAny;
64
+ };
65
+ /**
66
+ * Gets function arguments and return type from a function schema
67
+ */
68
+ export declare function getFunctionSignature(schema: z.ZodFunction<$ZodFunctionArgs, $ZodFunctionOut>): {
69
+ args: $ZodFunctionArgs;
70
+ returns: $ZodFunctionOut;
71
+ };
72
+ /**
73
+ * Checks if a number schema has integer constraint
74
+ */
75
+ export declare function isNumberInteger(schema: z.ZodNumber): boolean;
76
+ /**
77
+ * Gets metadata from a schema if it has been set with .meta()
78
+ */
79
+ export declare function getMeta(schema: $ZodType): Record<string, unknown> | undefined;
80
+ /**
81
+ * Gets a comment string from metadata.
82
+ * If meta only contains a description key, returns the description string.
83
+ * Otherwise, returns a JSON representation of the entire meta object.
84
+ */
85
+ export declare function getMetaDescription(schema: $ZodType): string | undefined;
@@ -0,0 +1,205 @@
1
+ import { z } from 'zod';
2
+ // ============================================================================
3
+ // Type Guards
4
+ // ============================================================================
5
+ export function isString(schema) {
6
+ return schema instanceof z.ZodString;
7
+ }
8
+ export function isNumber(schema) {
9
+ return schema instanceof z.ZodNumber;
10
+ }
11
+ export function isBoolean(schema) {
12
+ return schema instanceof z.ZodBoolean;
13
+ }
14
+ export function isNull(schema) {
15
+ return schema instanceof z.ZodNull;
16
+ }
17
+ export function isLiteral(schema) {
18
+ return schema instanceof z.ZodLiteral;
19
+ }
20
+ export function isUndefined(schema) {
21
+ return schema instanceof z.ZodUndefined;
22
+ }
23
+ export function isUnknown(schema) {
24
+ return schema instanceof z.ZodUnknown;
25
+ }
26
+ export function isNever(schema) {
27
+ return schema instanceof z.ZodNever;
28
+ }
29
+ export function isAny(schema) {
30
+ return schema instanceof z.ZodAny;
31
+ }
32
+ export function isArray(schema) {
33
+ return schema instanceof z.ZodArray;
34
+ }
35
+ export function isObject(schema) {
36
+ return schema instanceof z.ZodObject;
37
+ }
38
+ export function isTuple(schema) {
39
+ return schema instanceof z.ZodTuple;
40
+ }
41
+ export function isRecord(schema) {
42
+ return schema instanceof z.ZodRecord;
43
+ }
44
+ export function isEnum(schema) {
45
+ return schema instanceof z.ZodEnum;
46
+ }
47
+ export function isUnion(schema) {
48
+ return schema instanceof z.ZodUnion;
49
+ }
50
+ export function isOptional(schema) {
51
+ return schema instanceof z.ZodOptional;
52
+ }
53
+ export function isNullable(schema) {
54
+ return schema instanceof z.ZodNullable;
55
+ }
56
+ export function isDefault(schema) {
57
+ return schema instanceof z.ZodDefault;
58
+ }
59
+ export function isFunction(schema) {
60
+ return schema instanceof z.ZodFunction;
61
+ }
62
+ function isCheckNumberFormat(checkDef) {
63
+ return checkDef?.check === 'number_format';
64
+ }
65
+ // ============================================================================
66
+ // Property Extractors
67
+ // ============================================================================
68
+ /**
69
+ * Gets the element type from an array schema
70
+ */
71
+ export function getArrayElement(schema) {
72
+ return schema.def.element;
73
+ }
74
+ /**
75
+ * Gets the shape from an object schema
76
+ */
77
+ export function getObjectShape(schema) {
78
+ return schema.def.shape;
79
+ }
80
+ /**
81
+ * Gets the items from a tuple schema
82
+ */
83
+ export function getTupleItems(schema) {
84
+ return schema.def.items;
85
+ }
86
+ /**
87
+ * Gets the key and value types from a record schema
88
+ */
89
+ export function getRecordTypes(schema) {
90
+ return {
91
+ keyType: schema.def.keyType,
92
+ valueType: schema.def.valueType,
93
+ };
94
+ }
95
+ /**
96
+ * Gets the enum values from an enum schema
97
+ */
98
+ export function getEnumValues(schema) {
99
+ // In v4, enum entries is an object like { "a": "a", "b": "b", "c": "c" }
100
+ const entries = schema.def.entries;
101
+ if (entries && typeof entries === 'object') {
102
+ return Object.values(entries);
103
+ }
104
+ return [];
105
+ }
106
+ export function getLiteralValue(schema) {
107
+ return schema.def.values[0];
108
+ }
109
+ /**
110
+ * Gets the options from a union schema
111
+ */
112
+ export function getUnionOptions(schema) {
113
+ return schema.def.options || [];
114
+ }
115
+ /**
116
+ * Unwraps an optional schema to get its inner type
117
+ */
118
+ export function unwrapOptional(schema) {
119
+ return schema.def.innerType;
120
+ }
121
+ /**
122
+ * Unwraps a nullable schema to get its inner type
123
+ */
124
+ export function unwrapNullable(schema) {
125
+ return schema.def.innerType;
126
+ }
127
+ /**
128
+ * Unwraps a default schema to get its inner type and default value
129
+ */
130
+ export function unwrapDefault(schema) {
131
+ return {
132
+ defaultValue: schema.def.defaultValue,
133
+ innerType: schema.def.innerType,
134
+ };
135
+ }
136
+ /**
137
+ * Gets function arguments and return type from a function schema
138
+ */
139
+ export function getFunctionSignature(schema) {
140
+ // In v4, function uses input/output properties
141
+ return {
142
+ args: schema.def.input,
143
+ returns: schema.def.output,
144
+ };
145
+ }
146
+ /**
147
+ * Checks if a number schema has integer constraint
148
+ */
149
+ export function isNumberInteger(schema) {
150
+ const checks = schema.def.checks || [];
151
+ // Look for number_format check with integer formats
152
+ return checks.some((check) => {
153
+ const checkDef = check._zod?.def;
154
+ if (isCheckNumberFormat(checkDef)) {
155
+ const format = checkDef.format;
156
+ return format === 'int32' || format === 'uint32' || format === 'safeint';
157
+ }
158
+ return false;
159
+ });
160
+ }
161
+ /**
162
+ * Gets metadata from a schema if it has been set with .meta()
163
+ */
164
+ export function getMeta(schema) {
165
+ if (!schema) {
166
+ return undefined;
167
+ }
168
+ // Call .meta() without arguments to retrieve metadata
169
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
170
+ if (typeof schema.meta === 'function') {
171
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
172
+ return schema.meta();
173
+ }
174
+ return undefined;
175
+ }
176
+ /**
177
+ * Gets a comment string from metadata.
178
+ * If meta only contains a description key, returns the description string.
179
+ * Otherwise, returns a JSON representation of the entire meta object.
180
+ */
181
+ export function getMetaDescription(schema) {
182
+ const meta = getMeta(schema);
183
+ if (!meta || Object.keys(meta).length === 0) {
184
+ return undefined;
185
+ }
186
+ // If meta only has a description key, return just the description
187
+ const keys = Object.keys(meta);
188
+ if (keys.length === 1 && keys[0] === 'description' && typeof meta.description === 'string') {
189
+ return meta.description;
190
+ }
191
+ if (typeof meta.description === 'string') {
192
+ return meta.description;
193
+ }
194
+ if (typeof meta.title === 'string') {
195
+ return meta.title;
196
+ }
197
+ // Otherwise, return JSON representation of the entire meta object
198
+ try {
199
+ return JSON.stringify(meta, null, 2);
200
+ }
201
+ catch {
202
+ // If JSON serialization fails, return undefined
203
+ return undefined;
204
+ }
205
+ }
@@ -0,0 +1,19 @@
1
+ import { APICommand } from '../index.js';
2
+ import { JsonObj } from '../result.js';
3
+ export default class Create extends APICommand {
4
+ static args: {
5
+ name: import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
6
+ };
7
+ static description: string;
8
+ static examples: string[];
9
+ static flags: {
10
+ secret: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
11
+ 'secret-key-name': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
12
+ confidential: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
13
+ 'env-var': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
14
+ type: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
15
+ value: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
16
+ };
17
+ run(): Promise<JsonObj | void>;
18
+ private createBooleanFlag;
19
+ }
@@ -0,0 +1,175 @@
1
+ import { Args, Flags } from '@oclif/core';
2
+ import { ProvidedSource } from '@quonfig/node';
3
+ import { APICommand } from '../index.js';
4
+ import getValue from '../ui/get-value.js';
5
+ import { TYPE_MAPPING, coerceBool, coerceIntoType } from '../util/coerce.js';
6
+ import { checkmark } from '../util/color.js';
7
+ import { mapConfigValueToDto, mapValueTypeToString } from '../util/config-value-dto.js';
8
+ import { makeConfidentialValue } from '../util/encryption.js';
9
+ import secretFlags, { parsedSecretFlags } from '../util/secret-flags.js';
10
+ export default class Create extends APICommand {
11
+ static args = {
12
+ name: Args.string({ description: 'name for your new item (e.g. my.new.flag)', required: true }),
13
+ };
14
+ static description = 'Create a new item in Quonfig';
15
+ static examples = [
16
+ '<%= config.bin %> <%= command.id %> my.new.flag --type boolean-flag',
17
+ '<%= config.bin %> <%= command.id %> my.new.flag --type boolean-flag --value=true',
18
+ '<%= config.bin %> <%= command.id %> my.new.string --type string --value="hello world"',
19
+ '<%= config.bin %> <%= command.id %> my.new.string --type string --value="hello world" --secret',
20
+ '<%= config.bin %> <%= command.id %> my.new.string --type string --env-var=MY_ENV_VAR_NAME',
21
+ '<%= config.bin %> <%= command.id %> my.new.string --type json --value="{\\"key\\": \\"value\\"}"',
22
+ ];
23
+ static flags = {
24
+ confidential: Flags.boolean({ default: false, description: 'mark the value as confidential' }),
25
+ 'env-var': Flags.string({ description: 'environment variable to get value from' }),
26
+ type: Flags.string({
27
+ options: ['boolean-flag', 'boolean', 'string', 'double', 'int', 'string-list', 'json'],
28
+ required: true,
29
+ }),
30
+ value: Flags.string({ description: 'default value for your new item', required: false }),
31
+ ...secretFlags('encrypt the value of this item'),
32
+ };
33
+ async run() {
34
+ const { args, flags } = await this.parse(Create);
35
+ if (flags.type === 'boolean-flag') {
36
+ return this.createBooleanFlag(args, flags.value);
37
+ }
38
+ const key = args.name;
39
+ const secret = parsedSecretFlags(flags);
40
+ if (flags['env-var'] && flags.value) {
41
+ return this.err('cannot specify both --env-var and --value');
42
+ }
43
+ if (flags['env-var'] && secret.selected) {
44
+ return this.err('cannot specify both --env-var and --secret');
45
+ }
46
+ if (flags.confidential && secret.selected) {
47
+ console.warn("Note: --confidential is implied when using --secret, so you don't need to specify both.");
48
+ }
49
+ if (secret.selected && flags.type !== 'string') {
50
+ return this.err('--secret flag only works with string type');
51
+ }
52
+ let configValue = {};
53
+ let valueType = TYPE_MAPPING[flags.type];
54
+ if (flags['env-var']) {
55
+ configValue = {
56
+ provided: {
57
+ lookup: flags['env-var'],
58
+ source: ProvidedSource.EnvVar,
59
+ },
60
+ };
61
+ }
62
+ else {
63
+ const valueInput = await getValue({
64
+ desiredValue: flags.value,
65
+ flags,
66
+ message: 'Default value',
67
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
68
+ quonfig: undefined,
69
+ });
70
+ if (valueInput.ok) {
71
+ const rawValue = valueInput.value;
72
+ const parsedConfigValue = coerceIntoType(flags.type, rawValue);
73
+ if (!parsedConfigValue) {
74
+ return this.err(`Failed to coerce value into type: ${flags.type}`, { key, phase: 'coercion' });
75
+ }
76
+ configValue = parsedConfigValue[0];
77
+ valueType = parsedConfigValue[1];
78
+ if (secret.selected) {
79
+ const confidentialValueResult = await makeConfidentialValue(this, rawValue, secret, '');
80
+ if (!confidentialValueResult.ok) {
81
+ this.resultMessage(confidentialValueResult);
82
+ return;
83
+ }
84
+ configValue = confidentialValueResult.value;
85
+ }
86
+ }
87
+ else {
88
+ return;
89
+ }
90
+ }
91
+ if (flags.confidential) {
92
+ configValue.confidential = true;
93
+ }
94
+ // Build oRPC input for configs/create
95
+ const createInput = {
96
+ workspaceId: this.workspaceId,
97
+ config: {
98
+ key: args.name,
99
+ valueType: mapValueTypeToString(valueType),
100
+ sendToClientSdk: false,
101
+ default: {
102
+ rules: [
103
+ {
104
+ criteria: [],
105
+ value: mapConfigValueToDto(configValue, valueType),
106
+ },
107
+ ],
108
+ },
109
+ },
110
+ };
111
+ this.verboseLog('RPC configs/create', createInput);
112
+ const request = await this.apiClient.post('/api/v1/configs/create', createInput);
113
+ if (!request.ok) {
114
+ const errMsg = request.status === 409
115
+ ? `Failed to create config: ${key} already exists`
116
+ : `Failed to create config: ${request.status} | ${JSON.stringify(request.error)}`;
117
+ return this.err(errMsg, { key, phase: 'creation', serverError: request.error });
118
+ }
119
+ const response = request.json;
120
+ const confidentialMaybe = flags.confidential ? '(confidential) ' : '';
121
+ return this.ok(`${checkmark} Created ${confidentialMaybe}config: ${key}`, { key, ...response });
122
+ }
123
+ async createBooleanFlag(args, rawDefault) {
124
+ const key = args.name;
125
+ const defaultValue = coerceBool(rawDefault ?? 'false');
126
+ // Build oRPC input for flags/create
127
+ const createInput = {
128
+ workspaceId: this.workspaceId,
129
+ flag: {
130
+ key,
131
+ valueType: 'bool',
132
+ sendToClientSdk: true,
133
+ variants: [
134
+ {
135
+ value: {
136
+ type: 'bool',
137
+ value: true,
138
+ },
139
+ name: 'True',
140
+ description: 'Enabled',
141
+ },
142
+ {
143
+ value: {
144
+ type: 'bool',
145
+ value: false,
146
+ },
147
+ name: 'False',
148
+ description: 'Disabled',
149
+ },
150
+ ],
151
+ default: {
152
+ rules: [
153
+ {
154
+ criteria: [],
155
+ value: {
156
+ type: 'bool',
157
+ value: defaultValue,
158
+ },
159
+ },
160
+ ],
161
+ },
162
+ },
163
+ };
164
+ this.verboseLog('RPC flags/create', createInput);
165
+ const request = await this.apiClient.post('/api/v1/flags/create', createInput);
166
+ if (!request.ok) {
167
+ const errMsg = request.status === 409
168
+ ? `Failed to create boolean flag: ${key} already exists`
169
+ : `Failed to create boolean flag: ${request.status} | ${JSON.stringify(request.error)}`;
170
+ return this.err(errMsg, { key, phase: 'creation', serverError: request.error });
171
+ }
172
+ const response = request.json;
173
+ return this.ok(`${checkmark} Created boolean flag: ${key}`, { key, ...response });
174
+ }
175
+ }
@@ -0,0 +1,13 @@
1
+ import type { JsonObj } from '../result.js';
2
+ import { APICommand } from '../index.js';
3
+ export default class Download extends APICommand {
4
+ static description: string;
5
+ static examples: string[];
6
+ static flags: {
7
+ environment: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
8
+ 'sdk-key': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
9
+ };
10
+ init(): Promise<void>;
11
+ run(): Promise<JsonObj | void>;
12
+ private writeFile;
13
+ }
@@ -0,0 +1,63 @@
1
+ import { Flags } from '@oclif/core';
2
+ import * as fs from 'node:fs';
3
+ import * as path from 'node:path';
4
+ import { APICommand } from '../index.js';
5
+ import { getProjectEnvFromSdkKey } from '@quonfig/node';
6
+ import getEnvironment from '../ui/get-environment.js';
7
+ import { checkmark } from '../util/color.js';
8
+ import getClient from '../util/get-client.js';
9
+ export default class Download extends APICommand {
10
+ static description = `Download a Datafile for a given environment
11
+
12
+ You can serve a datafile using the \`serve\` command.`;
13
+ static examples = [
14
+ '<%= config.bin %> <%= command.id %> --environment=test',
15
+ '<%= config.bin %> <%= command.id %> --environment=test --sdk-key=YOUR_SDK_KEY',
16
+ ];
17
+ static flags = {
18
+ environment: Flags.string({ description: 'environment to download' }),
19
+ 'sdk-key': Flags.string({
20
+ description: 'SDK key for authentication (uses legacy download endpoint)',
21
+ required: false,
22
+ }),
23
+ };
24
+ async init() {
25
+ await super.init();
26
+ const { flags } = await this.parse(Download);
27
+ // If SDK key is provided, reinitialize the client with it
28
+ if (flags['sdk-key']) {
29
+ this.rawApiClient = await getClient(this, flags['sdk-key'], flags.profile);
30
+ this.currentEnvironment = getProjectEnvFromSdkKey(flags['sdk-key']);
31
+ }
32
+ }
33
+ async run() {
34
+ const { flags } = await this.parse(Download);
35
+ const environment = await getEnvironment({
36
+ command: this,
37
+ flags,
38
+ message: 'Which environment would you like to download?',
39
+ providedEnvironment: flags.environment,
40
+ });
41
+ if (!environment) {
42
+ return;
43
+ }
44
+ this.verboseLog({ environment, usingSdkKey: Boolean(flags['sdk-key']) });
45
+ // Use legacy endpoint if SDK key is provided, otherwise use new OAuth endpoint
46
+ const downloadUrl = flags['sdk-key']
47
+ ? `/api/v2/configs/download?envId=${environment.id}`
48
+ : `/all-config-types/v1/download?envId=${environment.id}`;
49
+ const download = await this.apiClient.get(downloadUrl);
50
+ if (download.ok) {
51
+ return this.writeFile(download, environment);
52
+ }
53
+ this.verboseLog({ result: download });
54
+ return this.err(`Failed to download file. Status=${download.status}`, download.error);
55
+ }
56
+ writeFile(result, environment) {
57
+ const fileName = `quonfig.${environment.name}.${environment.id}.config.json`;
58
+ const filePath = path.join(process.cwd(), fileName);
59
+ fs.writeFileSync(filePath, JSON.stringify(result.json, null, 2));
60
+ this.log(`${checkmark} Successfully downloaded ${fileName}`);
61
+ return { filePath, succes: true };
62
+ }
63
+ }
@@ -0,0 +1,7 @@
1
+ import { BaseCommand } from '../index.js';
2
+ import { JsonObj } from '../result.js';
3
+ export default class GenerateNewHexKey extends BaseCommand {
4
+ static description: string;
5
+ static examples: string[];
6
+ run(): Promise<JsonObj | void>;
7
+ }
@@ -0,0 +1,10 @@
1
+ import { encryption } from '@quonfig/node';
2
+ import { BaseCommand } from '../index.js';
3
+ export default class GenerateNewHexKey extends BaseCommand {
4
+ static description = 'Generate a new hex key suitable for secrets';
5
+ static examples = ['<%= config.bin %> <%= command.id %>'];
6
+ async run() {
7
+ const key = encryption.generateNewHexKey();
8
+ return this.ok(key, { key });
9
+ }
10
+ }
@@ -0,0 +1,16 @@
1
+ import type { JsonObj } from '../result.js';
2
+ import { APICommand } from '../index.js';
3
+ export default class Generate extends APICommand {
4
+ static description: string;
5
+ static examples: string[];
6
+ static flags: {
7
+ 'output-directory': import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
8
+ targets: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
9
+ };
10
+ static summary: string;
11
+ run(): Promise<JsonObj | void>;
12
+ private generateParsedConfig;
13
+ private readLocalConfig;
14
+ private resolveGenerator;
15
+ private resolveLanguage;
16
+ }