@opice/cli 0.0.2 → 0.0.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opice/cli",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "CLI for opice — scaffolds projects and wraps `bun test` to stream E2E results to the reporting platform",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli.ts CHANGED
@@ -22,11 +22,12 @@ Commands:
22
22
  failures <run-url|run-id> [--json]
23
23
  Pull a failed run's details (failed scenarios, the failing step,
24
24
  error, screenshot URL, and source files) for the re-eval workflow.
25
- Token comes from the URL's ?token= or OPICE_READ_TOKEN.
25
+ Read token comes from the URL's ?token= or OPICE_READ_TOKEN (a
26
+ read-only share link).
26
27
 
27
28
  users create <email> [--password=...] [--name=...] [--endpoint=URL] [--admin-token=TOKEN]
28
- Create a dashboard login (every user is admin). Needs the admin
29
- token (--admin-token or OPICE_ADMIN_TOKEN) and the platform endpoint
29
+ Create a dashboard login (admin role by default). Needs the bootstrap
30
+ admin token (--admin-token or OPICE_ADMIN_TOKEN) and the platform endpoint
30
31
  (--endpoint, OPICE_ENDPOINT, or opice.config.json). A password is
31
32
  generated and printed if you don't pass one.
32
33
 
@@ -52,12 +52,12 @@ export async function testCommand(args: string[]): Promise<number> {
52
52
 
53
53
  // After bun test exits, look for handoff files the reporter wrote and
54
54
  // POST /finish for each run so it leaves "running" state.
55
- await finalizeHandoffs(child.pid, project, process.env['OPICE_READ_TOKEN'])
55
+ await finalizeHandoffs(child.pid, project)
56
56
 
57
57
  return exitCode
58
58
  }
59
59
 
60
- async function finalizeHandoffs(childPid: number | undefined, slug: string | undefined, readToken: string | undefined): Promise<void> {
60
+ async function finalizeHandoffs(childPid: number | undefined, slug: string | undefined): Promise<void> {
61
61
  let files: string[]
62
62
  try {
63
63
  files = await fs.readdir(HANDOFF_DIR)
@@ -70,7 +70,7 @@ async function finalizeHandoffs(childPid: number | undefined, slug: string | und
70
70
  try {
71
71
  const handoff = JSON.parse(await fs.readFile(full, 'utf-8')) as Handoff
72
72
  await finishRun(handoff)
73
- printRunUrl(handoff, slug, readToken)
73
+ printRunUrl(handoff, slug)
74
74
  } catch (err) {
75
75
  warn(`Failed to finalize run from ${file}: ${(err as Error).message}`)
76
76
  } finally {
@@ -79,14 +79,11 @@ async function finalizeHandoffs(childPid: number | undefined, slug: string | und
79
79
  }
80
80
  }
81
81
 
82
- function printRunUrl(handoff: Handoff, slug: string | undefined, readToken: string | undefined): void {
82
+ function printRunUrl(handoff: Handoff, slug: string | undefined): void {
83
83
  if (!slug) return
84
- const query = readToken ? `?token=${readToken}` : ''
85
- const url = `${handoff.endpoint}/p/${slug}/r/${handoff.runId}${query}`
84
+ const url = `${handoff.endpoint}/p/${slug}/r/${handoff.runId}`
86
85
  console.error(`[opice] View run: ${url}`)
87
- if (!readToken) {
88
- console.error('[opice] (open the dashboard for the tokened read-only link, or set OPICE_READ_TOKEN to embed it here)')
89
- }
86
+ console.error('[opice] (sign in to view, or create a read-only share link from the run page)')
90
87
  }
91
88
 
92
89
  async function finishRun(handoff: Handoff): Promise<void> {
@@ -2,9 +2,10 @@
2
2
  * `opice users create <email>` — create a dashboard login.
3
3
  *
4
4
  * Self-service signup is disabled on the platform; this is the sanctioned way
5
- * to mint an account. It calls the admin endpoint, so it needs the admin token
6
- * (--admin-token or OPICE_ADMIN_TOKEN) and the platform endpoint (--endpoint,
7
- * OPICE_ENDPOINT, or opice.config.json). Every account is a full admin.
5
+ * to mint an account. It calls the `admin.createUser` RPC with the bootstrap
6
+ * admin token as a Bearer credential (--admin-token or OPICE_ADMIN_TOKEN) and
7
+ * the platform endpoint (--endpoint, OPICE_ENDPOINT, or opice.config.json).
8
+ * Accounts are created with the `admin` role by default.
8
9
  *
9
10
  * If no password is given one is generated and printed once.
10
11
  */
@@ -50,24 +51,29 @@ export async function usersCommand(args: string[]): Promise<number> {
50
51
 
51
52
  let response: Response
52
53
  try {
53
- response = await fetch(`${endpoint.replace(/\/$/, '')}/api/v1/admin/users`, {
54
+ response = await fetch(`${endpoint.replace(/\/$/, '')}/rpc`, {
54
55
  method: 'POST',
55
- headers: { 'content-type': 'application/json', 'x-admin-token': adminToken },
56
- body: JSON.stringify({ email: flags.email, password, ...(flags.name ? { name: flags.name } : {}) }),
56
+ headers: { 'content-type': 'application/json', authorization: `Bearer ${adminToken}` },
57
+ body: JSON.stringify({
58
+ method: 'admin.createUser',
59
+ input: { email: flags.email, password, ...(flags.name ? { name: flags.name } : {}) },
60
+ }),
57
61
  })
58
62
  } catch (err) {
59
63
  console.error(`[opice] request failed: ${(err as Error).message}`)
60
64
  return 1
61
65
  }
62
66
 
63
- const data = (await response.json().catch(() => null)) as { email?: string; error?: { message?: string } } | null
64
- if (!response.ok || !data || data.error) {
67
+ const data = (await response.json().catch(() => null)) as
68
+ | { result?: { email?: string }; error?: { message?: string } }
69
+ | null
70
+ if (!response.ok || !data || data.error || !data.result) {
65
71
  const message = data?.error?.message ?? `${response.status} ${response.statusText}`
66
72
  console.error(`[opice] could not create user: ${message}`)
67
73
  return 1
68
74
  }
69
75
 
70
- console.log(`✓ Created user ${data.email ?? flags.email}`)
76
+ console.log(`✓ Created user ${data.result.email ?? flags.email}`)
71
77
  if (generated) {
72
78
  console.log(` password: ${password}`)
73
79
  console.log(' (shown once — store it in your password manager now)')