@funnelsgrove/cli 0.1.8 → 0.1.9
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 +7 -6
- package/dist/cli.d.ts +13 -0
- package/dist/cli.js +41 -21
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,24 +7,25 @@ npm install -g @funnelsgrove/cli
|
|
|
7
7
|
fgrove login
|
|
8
8
|
```
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Sync a funnel into its own local folder:
|
|
11
11
|
|
|
12
12
|
```bash
|
|
13
|
-
fgrove
|
|
14
|
-
|
|
13
|
+
fgrove sync down --funnel claimbee-ios --dir ./claimbee-ios
|
|
14
|
+
cd ./claimbee-ios
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
Common workflow:
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
|
-
fgrove
|
|
21
|
-
cd ./claimbee-ios
|
|
20
|
+
fgrove status
|
|
22
21
|
fgrove docs
|
|
23
22
|
fgrove sync up --message 'Update funnel copy'
|
|
24
23
|
fgrove publish --env preview
|
|
25
24
|
```
|
|
26
25
|
|
|
27
|
-
|
|
26
|
+
Inside a synced folder, `fgrove` reads `.funnelsgrove-sync.json` first, so you do not need to run `fgrove use` when switching between local funnel directories. Use `fgrove use` only when you want a global fallback context for commands outside a synced folder.
|
|
27
|
+
|
|
28
|
+
Use `fgrove env pull` from a synced folder to refresh only the ignored local `.env` file after project settings change, without replacing source files.
|
|
28
29
|
|
|
29
30
|
GitHub sync workflow:
|
|
30
31
|
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,2 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { type ActiveContext } from './authStore.js';
|
|
3
|
+
import { type SyncManifest } from './localSync.js';
|
|
4
|
+
type SyncTargetIdInput = {
|
|
5
|
+
explicitWorkspaceId?: string;
|
|
6
|
+
explicitFunnelId?: string;
|
|
7
|
+
manifest?: Pick<SyncManifest, 'workspaceId' | 'funnelId'> | null;
|
|
8
|
+
active?: Pick<ActiveContext, 'workspaceId' | 'funnelId'> | null;
|
|
9
|
+
defaultWorkspaceId?: string;
|
|
10
|
+
};
|
|
11
|
+
export declare function resolveSyncTargetIds(input: SyncTargetIdInput): {
|
|
12
|
+
workspaceId: string;
|
|
13
|
+
funnelId?: string;
|
|
14
|
+
};
|
|
2
15
|
export {};
|
package/dist/cli.js
CHANGED
|
@@ -37,6 +37,19 @@ const DEFAULT_API_URL = 'https://api.funnelsgrove.com/trpc';
|
|
|
37
37
|
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
38
38
|
const PUBLISH_POLL_INTERVAL_MS = 2_000;
|
|
39
39
|
const PUBLISH_WAIT_TIMEOUT_MS = 30 * 60_000;
|
|
40
|
+
export function resolveSyncTargetIds(input) {
|
|
41
|
+
const workspaceId = input.explicitWorkspaceId ||
|
|
42
|
+
input.manifest?.workspaceId ||
|
|
43
|
+
input.active?.workspaceId ||
|
|
44
|
+
input.defaultWorkspaceId;
|
|
45
|
+
if (!workspaceId) {
|
|
46
|
+
throw new Error('No workspace found for this account.');
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
workspaceId,
|
|
50
|
+
funnelId: input.explicitFunnelId || input.manifest?.funnelId || input.active?.funnelId,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
40
53
|
const getApiUrl = () => {
|
|
41
54
|
const options = program.opts();
|
|
42
55
|
return options.apiUrl || process.env.FUNNELSGROVE_API_URL || DEFAULT_API_URL;
|
|
@@ -218,18 +231,24 @@ const resolveSyncTarget = async (input) => {
|
|
|
218
231
|
const sourceDir = path.resolve(process.cwd(), input.dir || '.');
|
|
219
232
|
const manifest = await readSyncManifest(sourceDir);
|
|
220
233
|
const active = await loadActiveContext(getConfigPath());
|
|
221
|
-
const
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
234
|
+
const explicitWorkspaceId = input.workspace ? await resolveWorkspaceId(input.token, input.workspace) : undefined;
|
|
235
|
+
const fallbackWorkspaceId = explicitWorkspaceId || manifest?.workspaceId || active?.workspaceId || await resolveWorkspaceId(input.token);
|
|
236
|
+
const explicitFunnelId = input.funnel
|
|
237
|
+
? await resolveFunnelId(input.token, fallbackWorkspaceId, input.funnel)
|
|
238
|
+
: undefined;
|
|
239
|
+
const resolved = resolveSyncTargetIds({
|
|
240
|
+
explicitWorkspaceId,
|
|
241
|
+
explicitFunnelId,
|
|
242
|
+
manifest,
|
|
243
|
+
active,
|
|
244
|
+
defaultWorkspaceId: fallbackWorkspaceId,
|
|
245
|
+
});
|
|
246
|
+
if (!resolved.funnelId) {
|
|
247
|
+
throw new Error('No synced funnel found. Run from a synced funnel directory, pass `--funnel`, or set a fallback with `fgrove use --funnel <id-or-slug>`.');
|
|
229
248
|
}
|
|
230
249
|
return {
|
|
231
|
-
workspaceId,
|
|
232
|
-
funnelId,
|
|
250
|
+
workspaceId: resolved.workspaceId,
|
|
251
|
+
funnelId: resolved.funnelId,
|
|
233
252
|
sourceDir,
|
|
234
253
|
manifest,
|
|
235
254
|
};
|
|
@@ -277,8 +296,8 @@ program
|
|
|
277
296
|
.option('--config <path>', 'Auth config path', process.env.FUNNELSGROVE_CONFIG || getDefaultAuthConfigPath());
|
|
278
297
|
addExamples(program, [
|
|
279
298
|
'fgrove login',
|
|
280
|
-
'fgrove
|
|
281
|
-
'
|
|
299
|
+
'fgrove sync down --funnel claimbee-ios --dir ./claimbee-ios',
|
|
300
|
+
'cd ./claimbee-ios && fgrove status',
|
|
282
301
|
'fgrove publish --env preview',
|
|
283
302
|
]);
|
|
284
303
|
addExamples(program
|
|
@@ -372,9 +391,9 @@ addExamples(program
|
|
|
372
391
|
console.log(`user\t${me.user.email || me.user.id}`);
|
|
373
392
|
console.log(`api\t${getApiUrl()}`);
|
|
374
393
|
console.log(`config\t${getConfigPath()}`);
|
|
375
|
-
console.log(`workspace\t${active?.workspaceName || active?.workspaceSlug || active?.workspaceId || me.workspace?.name || 'Not set'}`);
|
|
376
|
-
console.log(`project\t${active?.projectName || active?.projectSlug || active?.projectId || 'Not set'}`);
|
|
377
|
-
console.log(`funnel\t${active?.funnelName || active?.funnelSlug || active?.funnelId || 'Not set'}`);
|
|
394
|
+
console.log(`workspace\t${manifest?.workspaceId || active?.workspaceName || active?.workspaceSlug || active?.workspaceId || me.workspace?.name || 'Not set'}`);
|
|
395
|
+
console.log(`project\t${manifest ? 'Not set' : active?.projectName || active?.projectSlug || active?.projectId || 'Not set'}`);
|
|
396
|
+
console.log(`funnel\t${manifest?.funnelId || active?.funnelName || active?.funnelSlug || active?.funnelId || 'Not set'}`);
|
|
378
397
|
if (manifest) {
|
|
379
398
|
console.log(`localWorkspace\t${manifest.workspaceId}`);
|
|
380
399
|
console.log(`localFunnel\t${manifest.funnelId}`);
|
|
@@ -441,7 +460,7 @@ addExamples(funnelsCommand
|
|
|
441
460
|
console.log(`${result.funnel.id}\t${result.funnel.name}\t${result.funnel.slug}`);
|
|
442
461
|
});
|
|
443
462
|
const syncCommand = addExamples(program.command('sync').description('Sync funnel source'), [
|
|
444
|
-
'fgrove sync down --dir ./claimbee-ios',
|
|
463
|
+
'fgrove sync down --funnel claimbee-ios --dir ./claimbee-ios',
|
|
445
464
|
'fgrove sync up --message "Update copy"',
|
|
446
465
|
]);
|
|
447
466
|
addExamples(syncCommand
|
|
@@ -450,7 +469,6 @@ addExamples(syncCommand
|
|
|
450
469
|
.option('--workspace <id-or-slug-or-name>', 'Workspace id, slug, or name')
|
|
451
470
|
.option('--funnel <id-or-slug>', 'Funnel id or slug')
|
|
452
471
|
.requiredOption('--dir <path>', 'Local target directory'), [
|
|
453
|
-
'fgrove sync down --dir ./claimbee-ios',
|
|
454
472
|
'fgrove sync down --funnel claimbee-ios --dir ./claimbee-ios',
|
|
455
473
|
])
|
|
456
474
|
.action(async (options) => {
|
|
@@ -827,7 +845,9 @@ addExamples(program
|
|
|
827
845
|
console.log(' npm install');
|
|
828
846
|
console.log(' npm run dev');
|
|
829
847
|
});
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
848
|
+
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
849
|
+
program.parseAsync().catch((error) => {
|
|
850
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
851
|
+
process.exitCode = 1;
|
|
852
|
+
});
|
|
853
|
+
}
|