@quonfig/cli 0.0.1 → 0.0.2

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
@@ -14,7 +14,7 @@ $ npm install -g @quonfig/cli
14
14
  $ qfg COMMAND
15
15
  running command...
16
16
  $ qfg (--version)
17
- @quonfig/cli/0.0.1 darwin-arm64 node-v24.4.1
17
+ @quonfig/cli/0.0.2 darwin-arm64 node-v24.4.1
18
18
  $ qfg --help [COMMAND]
19
19
  USAGE
20
20
  $ qfg COMMAND
@@ -31,6 +31,7 @@ USAGE
31
31
  * [`qfg generate-new-hex-key`](#qfg-generate-new-hex-key)
32
32
  * [`qfg get [NAME]`](#qfg-get-name)
33
33
  * [`qfg info [NAME]`](#qfg-info-name)
34
+ * [`qfg init [DIRECTORY]`](#qfg-init-directory)
34
35
  * [`qfg interactive`](#qfg-interactive)
35
36
  * [`qfg list`](#qfg-list)
36
37
  * [`qfg login`](#qfg-login)
@@ -92,7 +93,7 @@ EXAMPLES
92
93
  $ qfg create my.new.string --type json --value="{\"key\": \"value\"}"
93
94
  ```
94
95
 
95
- _See code: [src/commands/create.ts](https://github.com/quonfig/cli/blob/v0.0.1/src/commands/create.ts)_
96
+ _See code: [src/commands/create.ts](https://github.com/quonfig/cli/blob/v0.0.2/src/commands/create.ts)_
96
97
 
97
98
  ## `qfg download`
98
99
 
@@ -125,7 +126,7 @@ EXAMPLES
125
126
  $ qfg download --environment=test --sdk-key=YOUR_SDK_KEY
126
127
  ```
127
128
 
128
- _See code: [src/commands/download.ts](https://github.com/quonfig/cli/blob/v0.0.1/src/commands/download.ts)_
129
+ _See code: [src/commands/download.ts](https://github.com/quonfig/cli/blob/v0.0.2/src/commands/download.ts)_
129
130
 
130
131
  ## `qfg generate`
131
132
 
@@ -195,7 +196,7 @@ EXAMPLES
195
196
  $ qfg generate --targets node-ts -o ./dist # combine with targets
196
197
  ```
197
198
 
198
- _See code: [src/commands/generate.ts](https://github.com/quonfig/cli/blob/v0.0.1/src/commands/generate.ts)_
199
+ _See code: [src/commands/generate.ts](https://github.com/quonfig/cli/blob/v0.0.2/src/commands/generate.ts)_
199
200
 
200
201
  ## `qfg generate-new-hex-key`
201
202
 
@@ -218,7 +219,7 @@ EXAMPLES
218
219
  $ qfg generate-new-hex-key
219
220
  ```
220
221
 
221
- _See code: [src/commands/generate-new-hex-key.ts](https://github.com/quonfig/cli/blob/v0.0.1/src/commands/generate-new-hex-key.ts)_
222
+ _See code: [src/commands/generate-new-hex-key.ts](https://github.com/quonfig/cli/blob/v0.0.2/src/commands/generate-new-hex-key.ts)_
222
223
 
223
224
  ## `qfg get [NAME]`
224
225
 
@@ -250,7 +251,7 @@ EXAMPLES
250
251
  $ qfg get my.config.name --environment=production
251
252
  ```
252
253
 
253
- _See code: [src/commands/get.ts](https://github.com/quonfig/cli/blob/v0.0.1/src/commands/get.ts)_
254
+ _See code: [src/commands/get.ts](https://github.com/quonfig/cli/blob/v0.0.2/src/commands/get.ts)_
254
255
 
255
256
  ## `qfg info [NAME]`
256
257
 
@@ -280,7 +281,45 @@ EXAMPLES
280
281
  $ qfg info my.config.name
281
282
  ```
282
283
 
283
- _See code: [src/commands/info.ts](https://github.com/quonfig/cli/blob/v0.0.1/src/commands/info.ts)_
284
+ _See code: [src/commands/info.ts](https://github.com/quonfig/cli/blob/v0.0.2/src/commands/info.ts)_
285
+
286
+ ## `qfg init [DIRECTORY]`
287
+
288
+ Initialize or update a Quonfig workspace
289
+
290
+ ```
291
+ USAGE
292
+ $ qfg init [DIRECTORY] [--json] [--interactive] [--no-color] [--verbose] [--dry-run] [--samples]
293
+
294
+ ARGUMENTS
295
+ DIRECTORY [default: .] Target directory (default: current directory)
296
+
297
+ FLAGS
298
+ --dry-run Show what would be done without writing anything
299
+ --[no-]samples Include sample configs (default: yes on first init, no on update)
300
+
301
+ GLOBAL FLAGS
302
+ --[no-]interactive Force interactive mode
303
+ --json Format output as json.
304
+ --no-color Do not colorize output
305
+ --verbose Verbose output
306
+
307
+ DESCRIPTION
308
+ Initialize or update a Quonfig workspace
309
+
310
+ EXAMPLES
311
+ $ qfg init
312
+
313
+ $ qfg init ./my-workspace
314
+
315
+ $ qfg init --no-samples
316
+
317
+ $ qfg init --samples
318
+
319
+ $ qfg init --dry-run
320
+ ```
321
+
322
+ _See code: [src/commands/init.ts](https://github.com/quonfig/cli/blob/v0.0.2/src/commands/init.ts)_
284
323
 
285
324
  ## `qfg interactive`
286
325
 
@@ -298,7 +337,7 @@ EXAMPLES
298
337
  $ qfg
299
338
  ```
300
339
 
301
- _See code: [src/commands/interactive.ts](https://github.com/quonfig/cli/blob/v0.0.1/src/commands/interactive.ts)_
340
+ _See code: [src/commands/interactive.ts](https://github.com/quonfig/cli/blob/v0.0.2/src/commands/interactive.ts)_
302
341
 
303
342
  ## `qfg list`
304
343
 
@@ -335,7 +374,7 @@ EXAMPLES
335
374
  $ qfg list --feature-flags
336
375
  ```
337
376
 
338
- _See code: [src/commands/list.ts](https://github.com/quonfig/cli/blob/v0.0.1/src/commands/list.ts)_
377
+ _See code: [src/commands/list.ts](https://github.com/quonfig/cli/blob/v0.0.2/src/commands/list.ts)_
339
378
 
340
379
  ## `qfg login`
341
380
 
@@ -363,7 +402,7 @@ EXAMPLES
363
402
  $ qfg login --profile myprofile
364
403
  ```
365
404
 
366
- _See code: [src/commands/login.ts](https://github.com/quonfig/cli/blob/v0.0.1/src/commands/login.ts)_
405
+ _See code: [src/commands/login.ts](https://github.com/quonfig/cli/blob/v0.0.2/src/commands/login.ts)_
367
406
 
368
407
  ## `qfg logout`
369
408
 
@@ -386,7 +425,7 @@ EXAMPLES
386
425
  $ qfg logout
387
426
  ```
388
427
 
389
- _See code: [src/commands/logout.ts](https://github.com/quonfig/cli/blob/v0.0.1/src/commands/logout.ts)_
428
+ _See code: [src/commands/logout.ts](https://github.com/quonfig/cli/blob/v0.0.2/src/commands/logout.ts)_
390
429
 
391
430
  ## `qfg mcp`
392
431
 
@@ -419,7 +458,7 @@ EXAMPLES
419
458
  $ qfg mcp --url http://local-app.goatsofquonfig.com:3003/api/v1/mcp
420
459
  ```
421
460
 
422
- _See code: [src/commands/mcp.ts](https://github.com/quonfig/cli/blob/v0.0.1/src/commands/mcp.ts)_
461
+ _See code: [src/commands/mcp.ts](https://github.com/quonfig/cli/blob/v0.0.2/src/commands/mcp.ts)_
423
462
 
424
463
  ## `qfg override [NAME]`
425
464
 
@@ -458,7 +497,7 @@ EXAMPLES
458
497
  $ qfg override my.double.config --value=3.14159
459
498
  ```
460
499
 
461
- _See code: [src/commands/override.ts](https://github.com/quonfig/cli/blob/v0.0.1/src/commands/override.ts)_
500
+ _See code: [src/commands/override.ts](https://github.com/quonfig/cli/blob/v0.0.2/src/commands/override.ts)_
462
501
 
463
502
  ## `qfg profile`
464
503
 
@@ -481,7 +520,7 @@ EXAMPLES
481
520
  $ qfg profile
482
521
  ```
483
522
 
484
- _See code: [src/commands/profile.ts](https://github.com/quonfig/cli/blob/v0.0.1/src/commands/profile.ts)_
523
+ _See code: [src/commands/profile.ts](https://github.com/quonfig/cli/blob/v0.0.2/src/commands/profile.ts)_
485
524
 
486
525
  ## `qfg schema NAME`
487
526
 
@@ -519,7 +558,7 @@ EXAMPLES
519
558
  $ qfg schema my-schema --set-json-schema=@schemas/my-schema.json --protected
520
559
  ```
521
560
 
522
- _See code: [src/commands/schema.ts](https://github.com/quonfig/cli/blob/v0.0.1/src/commands/schema.ts)_
561
+ _See code: [src/commands/schema.ts](https://github.com/quonfig/cli/blob/v0.0.2/src/commands/schema.ts)_
523
562
 
524
563
  ## `qfg serve DATA-FILE`
525
564
 
@@ -555,7 +594,7 @@ EXAMPLES
555
594
  $ qfg serve ./quonfig.test.588.config.json --port=3099
556
595
  ```
557
596
 
558
- _See code: [src/commands/serve.ts](https://github.com/quonfig/cli/blob/v0.0.1/src/commands/serve.ts)_
597
+ _See code: [src/commands/serve.ts](https://github.com/quonfig/cli/blob/v0.0.2/src/commands/serve.ts)_
559
598
 
560
599
  ## `qfg set-default [NAME]`
561
600
 
@@ -599,7 +638,7 @@ EXAMPLES
599
638
  $ qfg set-default my.config.name --env-var=MY_ENV_VAR_NAME --environment=production
600
639
  ```
601
640
 
602
- _See code: [src/commands/set-default.ts](https://github.com/quonfig/cli/blob/v0.0.1/src/commands/set-default.ts)_
641
+ _See code: [src/commands/set-default.ts](https://github.com/quonfig/cli/blob/v0.0.2/src/commands/set-default.ts)_
603
642
 
604
643
  ## `qfg verify [PATH]`
605
644
 
@@ -632,7 +671,7 @@ EXAMPLES
632
671
  $ qfg verify --json
633
672
  ```
634
673
 
635
- _See code: [src/commands/verify.ts](https://github.com/quonfig/cli/blob/v0.0.1/src/commands/verify.ts)_
674
+ _See code: [src/commands/verify.ts](https://github.com/quonfig/cli/blob/v0.0.2/src/commands/verify.ts)_
636
675
 
637
676
  ## `qfg whoami`
638
677
 
@@ -655,7 +694,7 @@ EXAMPLES
655
694
  $ qfg whoami
656
695
  ```
657
696
 
658
- _See code: [src/commands/whoami.ts](https://github.com/quonfig/cli/blob/v0.0.1/src/commands/whoami.ts)_
697
+ _See code: [src/commands/whoami.ts](https://github.com/quonfig/cli/blob/v0.0.2/src/commands/whoami.ts)_
659
698
 
660
699
  ## `qfg workspace`
661
700
 
@@ -678,7 +717,7 @@ EXAMPLES
678
717
  $ qfg workspace
679
718
  ```
680
719
 
681
- _See code: [src/commands/workspace.ts](https://github.com/quonfig/cli/blob/v0.0.1/src/commands/workspace.ts)_
720
+ _See code: [src/commands/workspace.ts](https://github.com/quonfig/cli/blob/v0.0.2/src/commands/workspace.ts)_
682
721
  <!-- commandsstop -->
683
722
 
684
723
  ## Local Development
@@ -0,0 +1,13 @@
1
+ import { BaseCommand } from '../index.js';
2
+ export default class Init extends BaseCommand {
3
+ static args: {
4
+ directory: import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
5
+ };
6
+ static description: string;
7
+ static examples: string[];
8
+ static flags: {
9
+ 'dry-run': import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
10
+ samples: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
11
+ };
12
+ run(): Promise<object>;
13
+ }
@@ -0,0 +1,83 @@
1
+ import { Args, Flags } from '@oclif/core';
2
+ import { BaseCommand } from '../index.js';
3
+ import { executeInit, planInit } from '../init/init-workspace.js';
4
+ export default class Init extends BaseCommand {
5
+ static args = {
6
+ directory: Args.string({
7
+ default: '.',
8
+ description: 'Target directory (default: current directory)',
9
+ }),
10
+ };
11
+ static description = 'Initialize or update a Quonfig workspace';
12
+ static examples = [
13
+ '<%= config.bin %> init',
14
+ '<%= config.bin %> init ./my-workspace',
15
+ '<%= config.bin %> init --no-samples',
16
+ '<%= config.bin %> init --samples',
17
+ '<%= config.bin %> init --dry-run',
18
+ ];
19
+ static flags = {
20
+ 'dry-run': Flags.boolean({
21
+ default: false,
22
+ description: 'Show what would be done without writing anything',
23
+ }),
24
+ samples: Flags.boolean({
25
+ allowNo: true,
26
+ description: 'Include sample configs (default: yes on first init, no on update)',
27
+ }),
28
+ };
29
+ async run() {
30
+ const { args, flags } = await this.parse(Init);
31
+ const dir = args.directory;
32
+ const plan = planInit({
33
+ dir,
34
+ dryRun: flags['dry-run'],
35
+ samples: flags.samples,
36
+ });
37
+ const mode = plan.isFirstTime ? 'Initializing' : 'Updating';
38
+ const writeActions = plan.actions.filter((a) => a.kind !== 'skip-file' && a.kind !== 'skip-hook');
39
+ const skipActions = plan.actions.filter((a) => a.kind === 'skip-file' || a.kind === 'skip-hook');
40
+ if (flags['dry-run']) {
41
+ this.log(`${mode} workspace (dry run)\n`);
42
+ if (writeActions.length > 0) {
43
+ this.log('Would perform:');
44
+ for (const action of writeActions) {
45
+ this.log(` + ${action.description}`);
46
+ }
47
+ }
48
+ if (skipActions.length > 0) {
49
+ this.log('\nSkipped:');
50
+ for (const action of skipActions) {
51
+ this.log(` - ${action.description}`);
52
+ }
53
+ }
54
+ if (writeActions.length === 0) {
55
+ this.log(' Nothing to do.');
56
+ }
57
+ if (this.jsonEnabled()) {
58
+ return { actions: plan.actions, dryRun: true, isFirstTime: plan.isFirstTime, samplesIncluded: plan.samplesIncluded };
59
+ }
60
+ return plan;
61
+ }
62
+ // Execute for real
63
+ executeInit(plan, dir);
64
+ this.log(`${mode} workspace: ${dir === '.' ? process.cwd() : dir}\n`);
65
+ for (const action of writeActions) {
66
+ this.log(` + ${action.description}`);
67
+ }
68
+ for (const action of skipActions) {
69
+ this.log(` - ${action.description}`);
70
+ }
71
+ if (!plan.samplesIncluded && plan.isFirstTime) {
72
+ this.log('\nSample data skipped. Run `qfg init --samples` to add examples.');
73
+ }
74
+ else if (!plan.isFirstTime && !plan.samplesIncluded) {
75
+ this.log('\nDocs updated. Run `qfg init --samples` to add example configs.');
76
+ }
77
+ this.log('\nRun `qfg verify` to validate the workspace.');
78
+ if (this.jsonEnabled()) {
79
+ return { actions: plan.actions, dryRun: false, isFirstTime: plan.isFirstTime, samplesIncluded: plan.samplesIncluded };
80
+ }
81
+ return plan;
82
+ }
83
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Core logic for `qfg init`.
3
+ *
4
+ * Uses a plan/execute pattern so --dry-run can show what *would* happen
5
+ * without writing anything.
6
+ */
7
+ export interface InitOptions {
8
+ dir: string;
9
+ /** true = force include samples, false = force skip, undefined = auto-detect */
10
+ samples: boolean | undefined;
11
+ dryRun: boolean;
12
+ }
13
+ export type ActionKind = 'git-init' | 'create-dir' | 'write-file' | 'skip-file' | 'create-hook' | 'update-hook' | 'skip-hook';
14
+ export interface InitAction {
15
+ kind: ActionKind;
16
+ path: string;
17
+ description: string;
18
+ }
19
+ export interface InitPlan {
20
+ actions: InitAction[];
21
+ isFirstTime: boolean;
22
+ samplesIncluded: boolean;
23
+ }
24
+ export declare function planInit(options: InitOptions): InitPlan;
25
+ export declare function executeInit(plan: InitPlan, dir: string): void;
@@ -0,0 +1,162 @@
1
+ /**
2
+ * Core logic for `qfg init`.
3
+ *
4
+ * Uses a plan/execute pattern so --dry-run can show what *would* happen
5
+ * without writing anything.
6
+ */
7
+ import { execSync } from 'node:child_process';
8
+ import * as fs from 'node:fs';
9
+ import * as path from 'node:path';
10
+ import { SAMPLE_FILES } from './samples.js';
11
+ import { storedConfigJsonSchema } from './schema.js';
12
+ import { PRE_COMMIT_MARKER, agentsMdTemplate, claudeMdTemplate, preCommitHookContent, readmeTemplate, } from './templates.js';
13
+ // ── Directories that define a workspace ────────────────────────────────
14
+ const WORKSPACE_DIRS = [
15
+ 'configs',
16
+ 'feature-flags',
17
+ 'segments',
18
+ 'log-levels',
19
+ 'schemas',
20
+ ];
21
+ // ── Plan ───────────────────────────────────────────────────────────────
22
+ export function planInit(options) {
23
+ const { dir } = options;
24
+ const actions = [];
25
+ // Detect first-time vs update: do any workspace dirs already exist?
26
+ const isFirstTime = !WORKSPACE_DIRS.some((d) => fs.existsSync(path.join(dir, d)));
27
+ // Resolve samples flag: first-time → default on, update → default off
28
+ const includeSamples = options.samples ?? isFirstTime;
29
+ // 0. Ensure it's a git repo
30
+ const gitDir = path.join(dir, '.git');
31
+ const needsGitInit = !fs.existsSync(gitDir);
32
+ if (needsGitInit) {
33
+ actions.push({ kind: 'git-init', path: '.git', description: 'Initialize git repository' });
34
+ }
35
+ // 1. Ensure directories exist
36
+ for (const d of WORKSPACE_DIRS) {
37
+ const dirPath = path.join(dir, d);
38
+ if (fs.existsSync(dirPath)) {
39
+ // directory already exists, nothing to do
40
+ }
41
+ else {
42
+ actions.push({ kind: 'create-dir', path: d, description: `Create ${d}/` });
43
+ }
44
+ }
45
+ // 2. Managed files — always overwrite
46
+ const managedFiles = [
47
+ { file: 'quonfig.schema.json', content: JSON.stringify(storedConfigJsonSchema(), null, 2) + '\n' },
48
+ { file: 'README.md', content: readmeTemplate() },
49
+ { file: 'CLAUDE.md', content: claudeMdTemplate() },
50
+ { file: 'AGENTS.md', content: agentsMdTemplate() },
51
+ ];
52
+ for (const { file, content: _content } of managedFiles) {
53
+ const filePath = path.join(dir, file);
54
+ const verb = fs.existsSync(filePath) ? 'Update' : 'Create';
55
+ actions.push({ kind: 'write-file', path: file, description: `${verb} ${file}` });
56
+ }
57
+ // 3. environments.json — create if missing
58
+ const envsPath = path.join(dir, 'environments.json');
59
+ if (fs.existsSync(envsPath)) {
60
+ // leave it alone
61
+ }
62
+ else {
63
+ actions.push({ kind: 'write-file', path: 'environments.json', description: 'Create environments.json' });
64
+ }
65
+ // 4. Sample data
66
+ if (includeSamples) {
67
+ for (const sample of SAMPLE_FILES) {
68
+ const samplePath = path.join(dir, sample.path);
69
+ if (fs.existsSync(samplePath)) {
70
+ actions.push({ kind: 'skip-file', path: sample.path, description: `Skip ${sample.path} (already exists)` });
71
+ }
72
+ else {
73
+ actions.push({ kind: 'write-file', path: sample.path, description: `Create ${sample.path}` });
74
+ }
75
+ }
76
+ }
77
+ // 5. Git pre-commit hook (always runs — git repo guaranteed by step 0)
78
+ if (needsGitInit) {
79
+ // Fresh git init — hook will be created
80
+ actions.push({ kind: 'create-hook', path: '.git/hooks/pre-commit', description: 'Install pre-commit hook (qfg verify)' });
81
+ }
82
+ else {
83
+ const hooksDir = path.join(gitDir, 'hooks');
84
+ const hookPath = path.join(hooksDir, 'pre-commit');
85
+ if (fs.existsSync(hookPath)) {
86
+ const existing = fs.readFileSync(hookPath, 'utf-8');
87
+ if (existing.includes(PRE_COMMIT_MARKER)) {
88
+ actions.push({ kind: 'skip-hook', path: '.git/hooks/pre-commit', description: 'Pre-commit hook already installed' });
89
+ }
90
+ else if (existing.includes('qfg verify')) {
91
+ actions.push({ kind: 'skip-hook', path: '.git/hooks/pre-commit', description: 'Pre-commit hook already runs qfg verify' });
92
+ }
93
+ else {
94
+ actions.push({ kind: 'update-hook', path: '.git/hooks/pre-commit', description: 'Append qfg verify to existing pre-commit hook' });
95
+ }
96
+ }
97
+ else {
98
+ actions.push({ kind: 'create-hook', path: '.git/hooks/pre-commit', description: 'Install pre-commit hook (qfg verify)' });
99
+ }
100
+ }
101
+ return { actions, isFirstTime, samplesIncluded: includeSamples };
102
+ }
103
+ // ── Execute ────────────────────────────────────────────────────────────
104
+ export function executeInit(plan, dir) {
105
+ // Build a lookup for managed file content
106
+ const managedContent = {
107
+ 'quonfig.schema.json': JSON.stringify(storedConfigJsonSchema(), null, 2) + '\n',
108
+ 'README.md': readmeTemplate(),
109
+ 'CLAUDE.md': claudeMdTemplate(),
110
+ 'AGENTS.md': agentsMdTemplate(),
111
+ 'environments.json': JSON.stringify({ environments: [] }, null, 2) + '\n',
112
+ };
113
+ // Build a lookup for sample content
114
+ const sampleContent = {};
115
+ for (const sample of SAMPLE_FILES) {
116
+ sampleContent[sample.path] = JSON.stringify(sample.content, null, 2) + '\n';
117
+ }
118
+ for (const action of plan.actions) {
119
+ const fullPath = path.join(dir, action.path);
120
+ switch (action.kind) {
121
+ case 'git-init': {
122
+ execSync('git init', { cwd: dir, stdio: 'pipe' });
123
+ break;
124
+ }
125
+ case 'create-dir': {
126
+ fs.mkdirSync(fullPath, { recursive: true });
127
+ break;
128
+ }
129
+ case 'write-file': {
130
+ // Ensure parent directory exists
131
+ const parentDir = path.dirname(fullPath);
132
+ if (!fs.existsSync(parentDir)) {
133
+ fs.mkdirSync(parentDir, { recursive: true });
134
+ }
135
+ const content = managedContent[action.path] ?? sampleContent[action.path];
136
+ if (content) {
137
+ fs.writeFileSync(fullPath, content, 'utf-8');
138
+ }
139
+ break;
140
+ }
141
+ case 'create-hook': {
142
+ const hooksDir = path.dirname(fullPath);
143
+ if (!fs.existsSync(hooksDir)) {
144
+ fs.mkdirSync(hooksDir, { recursive: true });
145
+ }
146
+ fs.writeFileSync(fullPath, preCommitHookContent(), 'utf-8');
147
+ fs.chmodSync(fullPath, 0o755);
148
+ break;
149
+ }
150
+ case 'update-hook': {
151
+ const existing = fs.readFileSync(fullPath, 'utf-8');
152
+ const appended = existing.trimEnd() + '\n\n' + preCommitHookContent().split('\n').slice(1).join('\n');
153
+ fs.writeFileSync(fullPath, appended, 'utf-8');
154
+ break;
155
+ }
156
+ case 'skip-file':
157
+ case 'skip-hook':
158
+ // Nothing to do
159
+ break;
160
+ }
161
+ }
162
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Sample config data for `qfg init --samples`.
3
+ *
4
+ * Each entry maps a relative path (e.g. "configs/example.greeting.json")
5
+ * to the JSON object that should be written there.
6
+ */
7
+ export interface SampleFile {
8
+ path: string;
9
+ content: object;
10
+ }
11
+ export declare const SAMPLE_FILES: SampleFile[];
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Sample config data for `qfg init --samples`.
3
+ *
4
+ * Each entry maps a relative path (e.g. "configs/example.greeting.json")
5
+ * to the JSON object that should be written there.
6
+ */
7
+ export const SAMPLE_FILES = [
8
+ {
9
+ path: 'configs/example.greeting.json',
10
+ content: {
11
+ key: 'example.greeting',
12
+ type: 'config',
13
+ valueType: 'string',
14
+ sendToClientSdk: true,
15
+ description: 'A greeting message shown to users.',
16
+ default: {
17
+ rules: [
18
+ {
19
+ criteria: [{ operator: 'ALWAYS_TRUE' }],
20
+ value: { type: 'string', value: 'Hello, world!' },
21
+ },
22
+ ],
23
+ },
24
+ environments: [
25
+ {
26
+ id: 'production',
27
+ rules: [
28
+ {
29
+ criteria: [{ operator: 'ALWAYS_TRUE' }],
30
+ value: { type: 'string', value: 'Welcome to our app!' },
31
+ },
32
+ ],
33
+ },
34
+ ],
35
+ variants: [],
36
+ },
37
+ },
38
+ {
39
+ path: 'feature-flags/example.dark-mode.json',
40
+ content: {
41
+ key: 'example.dark-mode',
42
+ type: 'feature_flag',
43
+ valueType: 'bool',
44
+ sendToClientSdk: true,
45
+ description: 'Enable dark mode UI.',
46
+ default: {
47
+ rules: [
48
+ {
49
+ criteria: [{ operator: 'ALWAYS_TRUE' }],
50
+ value: { type: 'bool', value: false },
51
+ },
52
+ ],
53
+ },
54
+ environments: [
55
+ {
56
+ id: 'staging',
57
+ rules: [
58
+ {
59
+ criteria: [{ operator: 'ALWAYS_TRUE' }],
60
+ value: { type: 'bool', value: true },
61
+ },
62
+ ],
63
+ },
64
+ ],
65
+ variants: [],
66
+ },
67
+ },
68
+ {
69
+ path: 'segments/example.beta-users.json',
70
+ content: {
71
+ key: 'example.beta-users',
72
+ type: 'segment',
73
+ valueType: 'bool',
74
+ sendToClientSdk: false,
75
+ description: 'Users who opted in to the beta program.',
76
+ default: {
77
+ rules: [
78
+ {
79
+ criteria: [
80
+ {
81
+ operator: 'PROP_IS_ONE_OF',
82
+ propertyName: 'user.beta',
83
+ valueToMatch: { type: 'string_list', value: ['true'] },
84
+ },
85
+ ],
86
+ value: { type: 'bool', value: true },
87
+ },
88
+ {
89
+ criteria: [{ operator: 'ALWAYS_TRUE' }],
90
+ value: { type: 'bool', value: false },
91
+ },
92
+ ],
93
+ },
94
+ environments: [],
95
+ variants: [],
96
+ },
97
+ },
98
+ {
99
+ path: 'log-levels/example.app.json',
100
+ content: {
101
+ key: 'example.app',
102
+ type: 'log_level',
103
+ valueType: 'log_level',
104
+ sendToClientSdk: false,
105
+ description: 'Application log level.',
106
+ default: {
107
+ rules: [
108
+ {
109
+ criteria: [{ operator: 'ALWAYS_TRUE' }],
110
+ value: { type: 'log_level', value: 'INFO' },
111
+ },
112
+ ],
113
+ },
114
+ environments: [],
115
+ variants: [],
116
+ },
117
+ },
118
+ ];
@@ -0,0 +1,9 @@
1
+ /**
2
+ * JSON Schema for Quonfig StoredConfig files.
3
+ *
4
+ * This is the machine-readable schema for files in configs/, feature-flags/,
5
+ * segments/, and log-levels/. Written to `quonfig.schema.json` by `qfg init`.
6
+ *
7
+ * Derived from the Zod schemas in verify/validate.ts — keep in sync.
8
+ */
9
+ export declare function storedConfigJsonSchema(): object;