1515
1616import type { ArtifactClient } from "./client.js" ;
1717import { parseDuration } from "./duration.js" ;
18- import { ArtifactError } from "./errors.js" ;
18+ import { ARTIFACTS_NOT_CONFIGURED_MESSAGE , ArtifactError } from "./errors.js" ;
1919import type { ArtifactScope } from "./types.js" ;
2020
2121/**
@@ -58,31 +58,35 @@ export interface ArtifactsCLIResult {
5858export async function runArtifactsCLI (
5959 client : ArtifactClient ,
6060 input : ArtifactsCLIInput ,
61+ bindingConfigured = true ,
6162) : Promise < ArtifactsCLIResult > {
6263 const argv = input . argv ;
63- // Help describes the scoping the client actually applies, so every
64- // help path is told whether this client sits in one session or
65- // spans the namespace.
66- const scoped = client . sessionId !== undefined ;
64+ // Help describes the state the client actually runs in: one
65+ // session, the whole namespace, or no binding at all.
66+ const mode : ArtifactsHelpMode = bindingConfigured
67+ ? client . sessionId === undefined
68+ ? "namespace"
69+ : "session"
70+ : "unconfigured" ;
6771 if ( argv . length === 0 ) {
6872 // Bare invocation: print help but signal misuse, the way `git`
6973 // with no args exits non-zero.
70- return { stdout : topLevelHelp ( scoped ) , stderr : "" , exitCode : 1 } ;
74+ return { stdout : topLevelHelp ( mode ) , stderr : "" , exitCode : 1 } ;
7175 }
7276 const [ group , ...rest ] = argv ;
7377 switch ( group ) {
7478 case "help" :
7579 case "--help" :
7680 case "-h" :
77- return ok ( topLevelHelp ( scoped ) ) ;
81+ return ok ( topLevelHelp ( mode ) ) ;
7882 case "create" :
7983 return await runCreate ( client , rest , input . remoteAdd ) ;
8084 case "share" :
8185 return await runShare ( client , rest ) ;
8286 case "repo" :
83- return await runRepo ( client , rest , scoped ) ;
87+ return await runRepo ( client , rest , mode ) ;
8488 case "token" :
85- return await runToken ( client , rest , scoped ) ;
89+ return await runToken ( client , rest , mode ) ;
8690 default :
8791 return fail ( `artifacts: '${ group } ' is not an artifacts command. See 'artifacts help'.` ) ;
8892 }
@@ -322,17 +326,17 @@ export function credentialURL(remote: string, token: string): string {
322326async function runRepo (
323327 client : ArtifactClient ,
324328 args : string [ ] ,
325- scoped : boolean ,
329+ mode : ArtifactsHelpMode ,
326330) : Promise < ArtifactsCLIResult > {
327331 if ( args . length === 0 ) {
328- return { stdout : repoHelp ( scoped ) , stderr : "" , exitCode : 1 } ;
332+ return { stdout : repoHelp ( mode ) , stderr : "" , exitCode : 1 } ;
329333 }
330334 const [ sub , ...rest ] = args ;
331335 switch ( sub ) {
332336 case "help" :
333337 case "--help" :
334338 case "-h" :
335- return ok ( repoHelp ( scoped ) ) ;
339+ return ok ( repoHelp ( mode ) ) ;
336340 case "create" :
337341 return await runRepoCreate ( client , rest ) ;
338342 case "get" :
@@ -472,17 +476,17 @@ async function runRepoImport(client: ArtifactClient, args: string[]): Promise<Ar
472476async function runToken (
473477 client : ArtifactClient ,
474478 args : string [ ] ,
475- scoped : boolean ,
479+ mode : ArtifactsHelpMode ,
476480) : Promise < ArtifactsCLIResult > {
477481 if ( args . length === 0 ) {
478- return { stdout : tokenHelp ( scoped ) , stderr : "" , exitCode : 1 } ;
482+ return { stdout : tokenHelp ( mode ) , stderr : "" , exitCode : 1 } ;
479483 }
480484 const [ sub , ...rest ] = args ;
481485 switch ( sub ) {
482486 case "help" :
483487 case "--help" :
484488 case "-h" :
485- return ok ( tokenHelp ( scoped ) ) ;
489+ return ok ( tokenHelp ( mode ) ) ;
486490 case "create" :
487491 return await runTokenCreate ( client , rest ) ;
488492 case "list" :
@@ -591,11 +595,14 @@ async function runTokenDelete(client: ArtifactClient, args: string[]): Promise<A
591595// help text
592596// ---------------------------------------------------------------
593597//
594- // The two name paragraphs are the only thing scoping changes. A
595- // client bound to a session works in local names; one bound to the
596- // namespace works in stored names and sees every session's
597- // repositories. Help states whichever is true, because a consumer
598- // that believes the wrong one addresses the wrong repository.
598+ // The naming paragraph follows the client state. A client bound to
599+ // a session works in local names; one bound to the namespace works
600+ // in stored names and sees every session's repositories; one with
601+ // no binding has neither authority. Help states whichever is true,
602+ // because a consumer that believes the wrong one addresses the
603+ // wrong repository.
604+
605+ type ArtifactsHelpMode = "session" | "namespace" | "unconfigured" ;
599606
600607const SCOPED_NAMES = `Every repository name you pass is implicitly scoped to this
601608session: the name 'starter' addresses the repo stored as
@@ -611,12 +618,28 @@ including those a session owns (stored as '<session>__<name>'), and
611618any of them can be read, written to, or deleted under that name.
612619` ;
613620
614- function topLevelHelp ( scoped : boolean ) : string {
621+ const UNCONFIGURED_NAMES = `${ ARTIFACTS_NOT_CONFIGURED_MESSAGE } .
622+ Configure WorkspaceOptions.artifacts before running repository or
623+ token commands.
624+ ` ;
625+
626+ function namingHelp ( mode : ArtifactsHelpMode ) : string {
627+ switch ( mode ) {
628+ case "session" :
629+ return SCOPED_NAMES ;
630+ case "namespace" :
631+ return UNSCOPED_NAMES ;
632+ case "unconfigured" :
633+ return UNCONFIGURED_NAMES ;
634+ }
635+ }
636+
637+ function topLevelHelp ( mode : ArtifactsHelpMode ) : string {
615638 return `usage: artifacts <command> [<args>]
616639
617640Manage Cloudflare Artifacts repositories and git tokens.
618641
619- ${ scoped ? SCOPED_NAMES : UNSCOPED_NAMES }
642+ ${ namingHelp ( mode ) }
620643Commands:
621644 create Create a repo, mint a token, and register a git remote.
622645 share Mint a token and print one clone-ready remote URL.
@@ -660,15 +683,18 @@ Secrets: 'create', 'share', and 'token create' all surface a token
660683` ;
661684}
662685
663- function repoHelp ( scoped : boolean ) : string {
664- const nameKind = scoped ? "a local name" : "the stored name" ;
686+ function repoHelp ( mode : ArtifactsHelpMode ) : string {
687+ const nameKind =
688+ mode === "session" ? "a local name" : mode === "namespace" ? "the stored name" : "its name" ;
689+ const listScope =
690+ mode === "session"
691+ ? "this session's repository"
692+ : mode === "namespace"
693+ ? "the namespace's repository"
694+ : "repository" ;
665695 return `usage: artifacts repo <subcommand> [<args>]
666696
667- ${
668- scoped
669- ? "All names are session-scoped; pass local names only."
670- : "Names are namespace-wide; pass the name a repository is stored under."
671- }
697+ ${ namingHelp ( mode ) }
672698
673699 repo create <name> [--description <text>] [--default-branch <branch>] [--read-only]
674700 Create a repository. Prints JSON: { name, remote, defaultBranch, token }.
678704 Print JSON metadata for a repository: ArtifactsRepoInfo with ${ nameKind } .
679705
680706 repo list
681- Print a JSON array of ${ scoped ? "this session's" : "the namespace's" } repository metadata (without remote).
707+ Print a JSON array of ${ listScope } metadata (without remote).
682708
683709 repo delete <name>
684710 Delete a repository. Prints a one-line confirmation.
@@ -692,15 +718,11 @@ Example:
692718` ;
693719}
694720
695- function tokenHelp ( scoped : boolean ) : string {
721+ function tokenHelp ( mode : ArtifactsHelpMode ) : string {
696722 return `usage: artifacts token <subcommand> [<args>]
697723
698724Tokens authenticate git operations against a repository's remote.
699- ${
700- scoped
701- ? "The <repo> argument is a session-scoped local name."
702- : "The <repo> argument is the name a repository is stored under."
703- }
725+ ${ namingHelp ( mode ) }
704726
705727 token create <repo> [--scope read|write] [--ttl <dur>]
706728 Mint a token. Prints JSON: { id, plaintext, scope, expiresAt }.
0 commit comments