@anby/cli 0.7.0 → 0.8.0

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.
@@ -3,5 +3,9 @@ import type { Command } from 'commander';
3
3
  * All app-lifecycle commands live under `anby app <verb>` so we can add
4
4
  * other command namespaces later (`anby tenant`, `anby events`, etc.)
5
5
  * without reshuffling.
6
+ *
7
+ * `init` is also exposed as a top-level `anby init` alias because that's
8
+ * the command publishers reach for first and the namespace prefix would
9
+ * be a needless papercut on the very first interaction with the CLI.
6
10
  */
7
11
  export declare function registerAppCommands(program: Command): void;
@@ -4,19 +4,39 @@ import { publishCommand } from './publish.js';
4
4
  import { installCommand } from './install.js';
5
5
  import { listCommand } from './list.js';
6
6
  import { codegenCommand } from './codegen.js';
7
+ import { loginCommand } from './login.js';
8
+ import { logoutCommand } from './logout.js';
7
9
  /**
8
10
  * All app-lifecycle commands live under `anby app <verb>` so we can add
9
11
  * other command namespaces later (`anby tenant`, `anby events`, etc.)
10
12
  * without reshuffling.
13
+ *
14
+ * `init` is also exposed as a top-level `anby init` alias because that's
15
+ * the command publishers reach for first and the namespace prefix would
16
+ * be a needless papercut on the very first interaction with the CLI.
11
17
  */
12
18
  export function registerAppCommands(program) {
19
+ // ── Top-level auth commands ──────────────────────────────────────────
20
+ program
21
+ .command('login')
22
+ .description('Authenticate with the Anby platform via Google OAuth')
23
+ .option('--auth-url <url>', '[dev] Override auth service URL')
24
+ .action(loginCommand);
25
+ program
26
+ .command('logout')
27
+ .description('Remove stored CLI credentials')
28
+ .action(logoutCommand);
13
29
  const app = program.command('app').description('Manage Anby apps');
30
+ // Top-level alias: `anby init` → same as `anby app init`.
31
+ program
32
+ .command('init')
33
+ .description('Scaffold and register an Anby app (interactive)')
34
+ .option('--registry-url <url>', '[dev] Override registry URL')
35
+ .action(initCommand);
14
36
  app
15
37
  .command('init')
16
- .description('Scaffold a new anby-app.manifest.json in the current directory')
17
- .option('--id <id>', 'Reverse-domain app id, e.g. com.bravebits.hello')
18
- .option('--name <name>', 'Human-readable app name')
19
- .option('--port <port>', 'Runtime port', '3099')
38
+ .description('Scaffold and register an Anby app (interactive)')
39
+ .option('--registry-url <url>', '[dev] Override registry URL')
20
40
  .action(initCommand);
21
41
  app
22
42
  .command('validate')
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAClD,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC;IAEnE,GAAG;SACA,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,gEAAgE,CAAC;SAC7E,MAAM,CAAC,WAAW,EAAE,iDAAiD,CAAC;SACtE,MAAM,CAAC,eAAe,EAAE,yBAAyB,CAAC;SAClD,MAAM,CAAC,eAAe,EAAE,cAAc,EAAE,MAAM,CAAC;SAC/C,MAAM,CAAC,WAAW,CAAC,CAAC;IAEvB,GAAG;SACA,OAAO,CAAC,UAAU,CAAC;SACnB,WAAW,CAAC,mEAAmE,CAAC;SAChF,MAAM,CAAC,mBAAmB,EAAE,uBAAuB,EAAE,0BAA0B,CAAC;SAChF,MAAM,CAAC,eAAe,CAAC,CAAC;IAE3B,GAAG;SACA,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,sDAAsD,CAAC;SACnE,MAAM,CAAC,mBAAmB,EAAE,uBAAuB,EAAE,0BAA0B,CAAC;SAChF,MAAM,CAAC,kBAAkB,EAAE,mBAAmB,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,uBAAuB,CAAC;SACpG,MAAM,CAAC,oBAAoB,EAAE,4CAA4C,CAAC;SAC1E,MAAM,CAAC,oBAAoB,EAAE,kDAAkD,CAAC;SAChF,MAAM,CAAC,YAAY,EAAE,8CAA8C,CAAC;SACpE,MAAM,CAAC,kBAAkB,EAAE,mEAAmE,CAAC;SAC/F,MAAM,CAAC,sBAAsB,EAAE,yGAAyG,CAAC;SACzI,MAAM,CAAC,cAAc,CAAC,CAAC;IAE1B,GAAG;SACA,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,6BAA6B,CAAC;SAC1C,cAAc,CAAC,qBAAqB,EAAE,WAAW,CAAC;SAClD,cAAc,CAAC,eAAe,EAAE,mBAAmB,CAAC;SACpD,MAAM,CAAC,kBAAkB,EAAE,mBAAmB,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,uBAAuB,CAAC;SACpG,MAAM,CAAC,cAAc,CAAC,CAAC;IAE1B,GAAG;SACA,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,6DAA6D,CAAC;SAC1E,MAAM,CAAC,qBAAqB,EAAE,qCAAqC,CAAC;SACpE,MAAM,CAAC,kBAAkB,EAAE,mBAAmB,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,uBAAuB,CAAC;SACpG,MAAM,CAAC,WAAW,CAAC,CAAC;IAEvB,GAAG;SACA,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,0EAA0E,CAAC;SACvF,MAAM,CAAC,mBAAmB,EAAE,uBAAuB,EAAE,0BAA0B,CAAC;SAChF,MAAM,CAAC,cAAc,EAAE,iCAAiC,EAAE,oBAAoB,CAAC;SAC/E,MAAM,CAAC,SAAS,EAAE,6CAA6C,CAAC;SAChE,MAAM,CAAC,cAAc,CAAC,CAAC;AAC5B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"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"}
@@ -1,22 +1,13 @@
1
1
  interface InitOptions {
2
- id?: string;
3
- name?: string;
4
- port?: string;
2
+ /** Hidden override for platform devs */
3
+ registryUrl?: string;
5
4
  }
6
5
  /**
7
- * One-stop project bootstrap for an Anby app.
6
+ * `anby init` interactive scaffold + register.
8
7
  *
9
- * Run once after `npm create remix` (or any Vite-based stack):
10
- *
11
- * 1. Writes `anby-app.manifest.json` skeleton
12
- * 2. Patches `vite.config.ts` to load `anbyVitePlugin()` from
13
- * `@anby/platform-sdk/vite` (idempotent — skips if already wired)
14
- * 3. Adds `public/_anby/` to `.gitignore`
15
- *
16
- * After this single command the app is ready for the Marketplace
17
- * Submit-app form: every dev/build run regenerates
18
- * `public/_anby/manifest.json`, which the marketplace shell fetches
19
- * directly. The publisher never edits any code by hand.
8
+ * Prompts for app name and port, auto-generates a reverse-domain ID
9
+ * from the logged-in user's email domain, scaffolds all platform
10
+ * integration code, and registers with the registry.
20
11
  */
21
12
  export declare function initCommand(options: InitOptions): Promise<void>;
22
13
  export {};
@@ -1,31 +1,91 @@
1
- import { writeFile, readFile, access } from 'node:fs/promises';
1
+ import { writeFile, readFile, access, mkdir } from 'node:fs/promises';
2
2
  import { resolve } from 'node:path';
3
+ import { createInterface } from 'node:readline/promises';
3
4
  import kleur from 'kleur';
5
+ import { getStoredAuth, getEmailDomain } from '../lib/auth-store.js';
6
+ import { assembleToken } from '../lib/token.js';
7
+ const DEFAULT_REGISTRY_URL = 'https://registry.anby.ai';
4
8
  /**
5
- * One-stop project bootstrap for an Anby app.
9
+ * `anby init` interactive scaffold + register.
6
10
  *
7
- * Run once after `npm create remix` (or any Vite-based stack):
8
- *
9
- * 1. Writes `anby-app.manifest.json` skeleton
10
- * 2. Patches `vite.config.ts` to load `anbyVitePlugin()` from
11
- * `@anby/platform-sdk/vite` (idempotent — skips if already wired)
12
- * 3. Adds `public/_anby/` to `.gitignore`
13
- *
14
- * After this single command the app is ready for the Marketplace
15
- * Submit-app form: every dev/build run regenerates
16
- * `public/_anby/manifest.json`, which the marketplace shell fetches
17
- * directly. The publisher never edits any code by hand.
11
+ * Prompts for app name and port, auto-generates a reverse-domain ID
12
+ * from the logged-in user's email domain, scaffolds all platform
13
+ * integration code, and registers with the registry.
18
14
  */
19
15
  export async function initCommand(options) {
20
- await writeManifest(options);
21
- await patchViteConfig();
22
- await patchGitignore();
23
- const port = Number.parseInt(options.port ?? '3099', 10);
24
- console.log('');
25
- console.log(kleur.green(' Anby app bootstrap complete'));
26
- console.log(kleur.dim(` Next: npm run dev — then submit ${kleur.cyan(`http://localhost:${port}`)} via the Marketplace UI`));
16
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
17
+ try {
18
+ // ── Collect inputs interactively ────────────────────────────────
19
+ const name = (await rl.question(kleur.bold('App name: '))).trim();
20
+ if (!name) {
21
+ console.log(kleur.red(' App name is required'));
22
+ return;
23
+ }
24
+ const portInput = (await rl.question(kleur.bold(`Port (default 3099): `))).trim();
25
+ const port = portInput ? Number.parseInt(portInput, 10) : 3099;
26
+ if (Number.isNaN(port)) {
27
+ console.log(kleur.red('✖ Invalid port'));
28
+ return;
29
+ }
30
+ // ── Auto-generate app ID ────────────────────────────────────────
31
+ const auth = await getStoredAuth();
32
+ const emailDomain = auth ? getEmailDomain(auth.email) : 'example.com';
33
+ // "bravebits.vn" → "vn.bravebits"
34
+ const reverseDomain = emailDomain.split('.').reverse().join('.');
35
+ // "Organization Chart" → "organization-chart"
36
+ const slug = name
37
+ .toLowerCase()
38
+ .replace(/[^a-z0-9]+/g, '-')
39
+ .replace(/^-|-$/g, '');
40
+ let id = `${reverseDomain}.${slug}`;
41
+ // Check if ID already exists in registry, append suffix if so
42
+ const registryBase = (options.registryUrl ||
43
+ process.env.ANBY_REGISTRY_URL ||
44
+ DEFAULT_REGISTRY_URL).replace(/\/+$/, '');
45
+ const existingId = await checkAppExists(registryBase, id);
46
+ if (existingId) {
47
+ // Append a short random suffix
48
+ const suffix = Math.random().toString(36).slice(2, 6);
49
+ id = `${reverseDomain}.${slug}-${suffix}`;
50
+ console.log(kleur.dim(` App ID "${reverseDomain}.${slug}" already taken → using ${id}`));
51
+ }
52
+ console.log(kleur.dim(` App ID: ${id}`));
53
+ console.log('');
54
+ // ── Scaffold ────────────────────────────────────────────────────
55
+ await writeManifest({ id, name, port });
56
+ await patchViteConfig();
57
+ await patchGitignore();
58
+ await scaffoldAuthServer();
59
+ await patchEntryServer(port);
60
+ await registerAndWriteToken({ id, name, port, registryBase, auth });
61
+ console.log('');
62
+ console.log(kleur.green('✔ Anby app bootstrap complete'));
63
+ console.log('');
64
+ console.log(kleur.bold('Next steps:'));
65
+ console.log(kleur.dim(` 1. Edit ${kleur.cyan('anby-app.manifest.json')} to declare provides/requires`));
66
+ console.log(kleur.dim(` (entities your app shares with or consumes from other apps)`));
67
+ console.log(kleur.dim(` 2. ${kleur.cyan('npm run dev')} — app auto-publishes manifest to registry on boot`));
68
+ console.log(kleur.dim(` 3. Install via Marketplace UI at ${kleur.cyan(`http://localhost:${port}`)}`));
69
+ }
70
+ finally {
71
+ rl.close();
72
+ }
73
+ }
74
+ // ── Helpers ─────────────────────────────────────────────────────────────
75
+ async function checkAppExists(registryBase, appId) {
76
+ try {
77
+ const res = await fetch(`${registryBase}/registry/apps/${appId}/manifest`, {
78
+ signal: AbortSignal.timeout(3000),
79
+ });
80
+ return res.ok;
81
+ }
82
+ catch {
83
+ // Registry unreachable — assume not taken
84
+ return false;
85
+ }
27
86
  }
28
- async function writeManifest(options) {
87
+ // ── Step 1: Manifest ──────────────────────────────────────────────────
88
+ async function writeManifest(opts) {
29
89
  const target = resolve('anby-app.manifest.json');
30
90
  try {
31
91
  await access(target);
@@ -35,26 +95,23 @@ async function writeManifest(options) {
35
95
  catch {
36
96
  // ok — file doesn't exist
37
97
  }
38
- const id = options.id ?? 'com.example.my-app';
39
- const name = options.name ?? 'My App';
40
- const port = Number.parseInt(options.port ?? '3099', 10);
41
98
  const manifest = {
42
99
  $schema: 'https://anby.dev/schemas/app-manifest.v1.json',
43
- id,
100
+ id: opts.id,
44
101
  version: '1.0.0',
45
- name,
46
- description: `${name} — submitted via @anby/cli`,
102
+ name: opts.name,
103
+ description: `${opts.name} — submitted via @anby/cli`,
47
104
  icon: '📦',
48
105
  color: '#E63426',
49
106
  runtime: {
50
107
  type: 'remix',
51
- port,
108
+ port: opts.port,
52
109
  healthCheck: '/api/health',
53
110
  readyCheck: '/api/health',
54
111
  },
55
112
  frontend: {
56
113
  type: 'iframe',
57
- routes: [{ path: '/', label: name, icon: '📦' }],
114
+ routes: [{ path: '/', label: opts.name, icon: '📦' }],
58
115
  navPosition: 'sidebar',
59
116
  },
60
117
  provides: { entities: [], events: [] },
@@ -68,19 +125,9 @@ async function writeManifest(options) {
68
125
  database: { type: 'postgresql' },
69
126
  };
70
127
  await writeFile(target, JSON.stringify(manifest, null, 2) + '\n', 'utf-8');
71
- console.log(kleur.green(`✔ Wrote ${target}`));
128
+ console.log(kleur.green(`✔ Wrote anby-app.manifest.json`));
72
129
  }
73
- /**
74
- * Idempotently patch `vite.config.ts` (or `.js`/`.mts`/`.mjs`) to load
75
- * `anbyVitePlugin()`. The patch is a deliberately small textual edit:
76
- * we add the import line near the existing imports and inject
77
- * `anbyVitePlugin(),` as the first entry of the `plugins: [` array.
78
- *
79
- * If the file is too unusual to patch safely (no `plugins: [` literal),
80
- * we print a clear instruction for the publisher to add the lines by
81
- * hand. Either way the manifest skeleton has already been written, so
82
- * the command stays useful even when the patch fails.
83
- */
130
+ // ── Step 2: Vite config ───────────────────────────────────────────────
84
131
  async function patchViteConfig() {
85
132
  const candidates = [
86
133
  'vite.config.ts',
@@ -110,8 +157,6 @@ async function patchViteConfig() {
110
157
  return;
111
158
  }
112
159
  const importLine = "import { anbyVitePlugin } from '@anby/platform-sdk/vite';";
113
- // Insert the import after the last existing top-level `import ... from`
114
- // line so we don't accidentally split a multi-line import statement.
115
160
  const importRegex = /^import .+ from .+;?\s*$/gm;
116
161
  let lastImportEnd = -1;
117
162
  for (const match of original.matchAll(importRegex)) {
@@ -130,10 +175,6 @@ async function patchViteConfig() {
130
175
  else {
131
176
  withImport = importLine + '\n' + original;
132
177
  }
133
- // Inject `anbyVitePlugin(),` as the first item of the `plugins: [` array.
134
- // We match `plugins:` followed by `[` and any whitespace, and insert
135
- // right after the `[`. Idempotency is enforced by the earlier
136
- // `includes('anbyVitePlugin')` check above.
137
178
  const pluginsArrayRegex = /(plugins\s*:\s*\[)(\s*)/;
138
179
  if (!pluginsArrayRegex.test(withImport)) {
139
180
  console.log(kleur.yellow(`! Could not find a \`plugins: [...]\` array in ${target}. ` +
@@ -144,14 +185,9 @@ async function patchViteConfig() {
144
185
  await writeFile(path, patched, 'utf-8');
145
186
  console.log(kleur.green(`✔ Patched ${target} to load anbyVitePlugin`));
146
187
  }
147
- /**
148
- * Append `public/_anby/` to `.gitignore` so the auto-generated wire
149
- * manifest doesn't pollute commits. Idempotent — does nothing if the
150
- * line is already present, and creates the file if missing.
151
- */
188
+ // ── Step 3: .gitignore ────────────────────────────────────────────────
152
189
  async function patchGitignore() {
153
190
  const path = resolve('.gitignore');
154
- const line = 'public/_anby/';
155
191
  let existing = '';
156
192
  try {
157
193
  existing = await readFile(path, 'utf-8');
@@ -159,21 +195,283 @@ async function patchGitignore() {
159
195
  catch {
160
196
  // file doesn't exist — we'll create it below
161
197
  }
162
- // Match either `public/_anby/` or `public/_anby` on its own line, with
163
- // optional trailing slash and surrounding whitespace.
164
- const alreadyIgnored = existing
165
- .split(/\r?\n/)
166
- .map((l) => l.trim())
167
- .some((l) => l === line || l === 'public/_anby');
168
- if (alreadyIgnored) {
169
- console.log(kleur.dim('• .gitignore already covers public/_anby/ — no change'));
198
+ const lines = existing.split(/\r?\n/).map((l) => l.trim());
199
+ const needsPublicAnby = !lines.some((l) => l === 'public/_anby/' || l === 'public/_anby');
200
+ const needsDotAnby = !lines.some((l) => l === '.anby/' || l === '.anby');
201
+ if (!needsPublicAnby && !needsDotAnby) {
202
+ console.log(kleur.dim('• .gitignore already covers Anby paths — no change'));
170
203
  return;
171
204
  }
172
- const block = (existing.length === 0 || existing.endsWith('\n') ? '' : '\n') +
173
- '\n# Anby — auto-generated wire manifest (do not commit)\n' +
174
- line +
175
- '\n';
205
+ let block = '';
206
+ if (needsPublicAnby || needsDotAnby) {
207
+ block +=
208
+ (existing.length === 0 || existing.endsWith('\n') ? '' : '\n') +
209
+ '\n# Anby — auto-generated files (do not commit)\n';
210
+ if (needsPublicAnby)
211
+ block += 'public/_anby/\n';
212
+ if (needsDotAnby)
213
+ block += '.anby/\n';
214
+ }
176
215
  await writeFile(path, existing + block, 'utf-8');
177
- console.log(kleur.green('✔ Added public/_anby/ to .gitignore'));
216
+ console.log(kleur.green('✔ Updated .gitignore for Anby paths'));
217
+ }
218
+ // ── Step 4: auth.server.ts scaffold ───────────────────────────────────
219
+ const AUTH_SERVER_TEMPLATE = `/**
220
+ * Auth utilities — auto-generated by \`anby init\`.
221
+ *
222
+ * Uses @anby/platform-sdk for authentication.
223
+ * Supports RS256 JWT (browser/Bearer/cookie) + HMAC (service-to-service).
224
+ * Extracts tenantId from JWT payload.
225
+ */
226
+
227
+ import {
228
+ bootstrapFromToken,
229
+ authenticateRequest as sdkAuthenticate,
230
+ requireAuth as sdkRequireAuth,
231
+ type AuthUser,
232
+ } from '@anby/platform-sdk';
233
+
234
+ const ANBY_APP_TOKEN = process.env.ANBY_APP_TOKEN || '';
235
+
236
+ if (!ANBY_APP_TOKEN) {
237
+ throw new Error(
238
+ 'ANBY_APP_TOKEN is required. Run \\\`anby login && anby init\\\` to generate one.',
239
+ );
240
+ }
241
+
242
+ let _bootstrapPromise: Promise<void> | null = null;
243
+
244
+ /**
245
+ * Initialize the SDK by bootstrapping from ANBY_APP_TOKEN. Returns a
246
+ * promise that resolves when discovery + auth public key are fetched
247
+ * and the SDK is ready to verify tokens. Idempotent.
248
+ */
249
+ export function initAuth(): Promise<void> {
250
+ if (_bootstrapPromise) return _bootstrapPromise;
251
+ _bootstrapPromise = bootstrapFromToken({ appToken: ANBY_APP_TOKEN }).catch(
252
+ (err) => {
253
+ _bootstrapPromise = null;
254
+ throw err;
255
+ },
256
+ );
257
+ return _bootstrapPromise;
258
+ }
259
+
260
+ // Kick off bootstrap at module load.
261
+ initAuth().catch((err) => {
262
+ console.error('[anby] bootstrap failed at module load:', err);
263
+ });
264
+
265
+ export type { AuthUser };
266
+
267
+ /**
268
+ * Authenticate a request via JWT or HMAC.
269
+ * Returns the authenticated user with tenantId or null.
270
+ */
271
+ export function authenticateRequest(request: Request): AuthUser | null {
272
+ return sdkAuthenticate(request);
273
+ }
274
+
275
+ /**
276
+ * Require authentication — throws 401 if not authenticated.
277
+ */
278
+ export function requireAuth(request: Request): AuthUser {
279
+ return sdkRequireAuth(request);
280
+ }
281
+
282
+ /**
283
+ * Extract tenantId from the authenticated user.
284
+ * Falls back to 'default' if not present.
285
+ */
286
+ export function getTenantId(request: Request): string {
287
+ const user = authenticateRequest(request);
288
+ return user?.tenantId || 'default';
289
+ }
290
+ `;
291
+ async function scaffoldAuthServer() {
292
+ const appDir = resolve('app');
293
+ try {
294
+ await access(appDir);
295
+ }
296
+ catch {
297
+ console.log(kleur.dim('• No app/ directory found (not a Remix project?) — skipping auth.server.ts scaffold'));
298
+ return;
299
+ }
300
+ const libDir = resolve('app/lib');
301
+ const target = resolve('app/lib/auth.server.ts');
302
+ try {
303
+ await access(target);
304
+ console.log(kleur.dim(`• app/lib/auth.server.ts already exists — leaving it alone`));
305
+ return;
306
+ }
307
+ catch {
308
+ // ok — file doesn't exist, we'll create it
309
+ }
310
+ await mkdir(libDir, { recursive: true });
311
+ await writeFile(target, AUTH_SERVER_TEMPLATE, 'utf-8');
312
+ console.log(kleur.green('✔ Scaffolded app/lib/auth.server.ts'));
313
+ }
314
+ // ── Step 5: Patch entry.server.tsx ────────────────────────────────────
315
+ async function patchEntryServer(port) {
316
+ const target = resolve('app/entry.server.tsx');
317
+ let original;
318
+ try {
319
+ original = await readFile(target, 'utf-8');
320
+ }
321
+ catch {
322
+ console.log(kleur.dim('• No app/entry.server.tsx found — skipping entry patch.'));
323
+ return;
324
+ }
325
+ if (original.includes('initAuth')) {
326
+ console.log(kleur.dim('• app/entry.server.tsx already has initAuth — no patch needed'));
327
+ return;
328
+ }
329
+ const sdkImport = "import { autoPublishOnBoot } from '@anby/platform-sdk';";
330
+ const authImport = "import { initAuth } from './lib/auth.server';";
331
+ const importRegex = /^import .+ from .+;?\s*$/gm;
332
+ let lastImportEnd = -1;
333
+ for (const match of original.matchAll(importRegex)) {
334
+ if (match.index !== undefined) {
335
+ lastImportEnd = match.index + match[0].length;
336
+ }
337
+ }
338
+ let withImports;
339
+ if (lastImportEnd >= 0) {
340
+ withImports =
341
+ original.slice(0, lastImportEnd) +
342
+ '\n' +
343
+ sdkImport +
344
+ '\n' +
345
+ authImport +
346
+ original.slice(lastImportEnd);
347
+ }
348
+ else {
349
+ withImports = sdkImport + '\n' + authImport + '\n' + original;
350
+ }
351
+ const bootstrapBlock = `
352
+ // Anby platform bootstrap — auto-generated by \`anby init\`.
353
+ // Ensures auth + discovery are ready before the first request.
354
+ await initAuth();
355
+ autoPublishOnBoot({
356
+ publicUrl: process.env.APP_PUBLIC_URL || \`http://localhost:\${process.env.PORT || ${port}}\`,
357
+ });
358
+ `;
359
+ const exportRegex = /^export\s+(default|function|async\s+function)/m;
360
+ const exportMatch = withImports.match(exportRegex);
361
+ let patched;
362
+ if (exportMatch && exportMatch.index !== undefined) {
363
+ patched =
364
+ withImports.slice(0, exportMatch.index) +
365
+ bootstrapBlock +
366
+ '\n' +
367
+ withImports.slice(exportMatch.index);
368
+ }
369
+ else {
370
+ patched = withImports + '\n' + bootstrapBlock;
371
+ }
372
+ await writeFile(target, patched, 'utf-8');
373
+ console.log(kleur.green('✔ Patched app/entry.server.tsx (initAuth + autoPublishOnBoot)'));
374
+ }
375
+ // ── Step 6: Self-register with registry ───────────────────────────────
376
+ async function registerAndWriteToken(opts) {
377
+ if (!opts.auth) {
378
+ console.log(kleur.yellow('! Not logged in — run `anby login` first, then `anby init` again'));
379
+ return;
380
+ }
381
+ // Check if .env.local already has ANBY_APP_TOKEN
382
+ const envLocalPath = resolve('.env.local');
383
+ try {
384
+ const envContent = await readFile(envLocalPath, 'utf-8');
385
+ if (envContent.includes('ANBY_APP_TOKEN=')) {
386
+ console.log(kleur.dim('• .env.local already contains ANBY_APP_TOKEN — skipping registration'));
387
+ return;
388
+ }
389
+ }
390
+ catch {
391
+ // .env.local doesn't exist — fine
392
+ }
393
+ // Load the manifest we just wrote
394
+ let manifest;
395
+ try {
396
+ const raw = await readFile(resolve('anby-app.manifest.json'), 'utf-8');
397
+ manifest = JSON.parse(raw);
398
+ }
399
+ catch {
400
+ console.log(kleur.yellow('! Could not read anby-app.manifest.json — skipping registration'));
401
+ return;
402
+ }
403
+ const publicUrl = `http://localhost:${opts.port}`;
404
+ const registryUrl = `${opts.registryBase}/registry/apps`;
405
+ // Register with a minimal manifest (just metadata, no entities).
406
+ // Entity declarations are published later by autoPublishOnBoot when
407
+ // the developer runs `npm run dev` — by then they've had time to
408
+ // edit the manifest with the correct provides/requires.
409
+ const registrationManifest = {
410
+ ...manifest,
411
+ provides: { entities: [], events: [] },
412
+ requires: { ...manifest.requires, entities: [], events: [] },
413
+ };
414
+ const body = {
415
+ id: manifest.id,
416
+ name: manifest.name,
417
+ description: manifest.description,
418
+ icon: manifest.icon,
419
+ color: manifest.color,
420
+ publisherId: manifest.id.split('.').slice(0, 2).join('.'),
421
+ version: manifest.version,
422
+ publicUrl,
423
+ submittedBy: `cli:${opts.auth.email}`,
424
+ manifest: registrationManifest,
425
+ };
426
+ let res;
427
+ try {
428
+ res = await fetch(registryUrl, {
429
+ method: 'POST',
430
+ headers: {
431
+ 'Content-Type': 'application/json',
432
+ Authorization: `Bearer ${opts.auth.token}`,
433
+ },
434
+ body: JSON.stringify(body),
435
+ signal: AbortSignal.timeout(10_000),
436
+ });
437
+ }
438
+ catch (err) {
439
+ console.log(kleur.yellow(`! Could not reach registry at ${registryUrl}: ${err.message}`));
440
+ return;
441
+ }
442
+ if (!res.ok) {
443
+ const errBody = await res.text();
444
+ console.log(kleur.yellow(`! Registry rejected publish (${res.status}): ${errBody}`));
445
+ return;
446
+ }
447
+ const result = await res.json();
448
+ if (!result.privateKey) {
449
+ console.log(kleur.dim('• App already registered (no new private key). Run `anby app rotate-token` for a new token.'));
450
+ return;
451
+ }
452
+ // Assemble token — platformUrl is the registry base (used by SDK discovery)
453
+ const token = assembleToken({
454
+ appId: manifest.id,
455
+ platformUrl: opts.registryBase,
456
+ privateKey: result.privateKey,
457
+ });
458
+ // Write to .env.local
459
+ let envContent = '';
460
+ try {
461
+ envContent = await readFile(envLocalPath, 'utf-8');
462
+ }
463
+ catch {
464
+ // File doesn't exist
465
+ }
466
+ const newLines = [
467
+ ...(envContent ? [] : ['# Auto-generated by anby init']),
468
+ `ANBY_APP_TOKEN=${token}`,
469
+ `APP_PUBLIC_URL=http://localhost:${opts.port}`,
470
+ ];
471
+ const separator = envContent.length === 0 || envContent.endsWith('\n') ? '' : '\n';
472
+ const appended = envContent + separator + newLines.join('\n') + '\n';
473
+ await writeFile(envLocalPath, appended, { mode: 0o600 });
474
+ console.log(kleur.green('✔ Registered app with registry'));
475
+ console.log(kleur.green('✔ Wrote ANBY_APP_TOKEN to .env.local'));
178
476
  }
179
477
  //# sourceMappingURL=init.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ interface LoginOptions {
2
+ /** Hidden override for platform devs (--auth-url) */
3
+ authUrl?: string;
4
+ }
5
+ /**
6
+ * `anby login` — authenticate with the Anby platform via Google OAuth.
7
+ *
8
+ * Default auth URL: https://auth.anby.ai
9
+ * Platform devs can override with: anby login --auth-url http://localhost:3000
10
+ */
11
+ export declare function loginCommand(options: LoginOptions): Promise<void>;
12
+ export {};
@@ -0,0 +1,112 @@
1
+ import { createServer } from 'node:http';
2
+ import { URL } from 'node:url';
3
+ import kleur from 'kleur';
4
+ import { saveAuth, getStoredAuth } from '../lib/auth-store.js';
5
+ const DEFAULT_AUTH_URL = 'https://auth.anby.ai';
6
+ /**
7
+ * `anby login` — authenticate with the Anby platform via Google OAuth.
8
+ *
9
+ * Default auth URL: https://auth.anby.ai
10
+ * Platform devs can override with: anby login --auth-url http://localhost:3000
11
+ */
12
+ export async function loginCommand(options) {
13
+ const existing = await getStoredAuth();
14
+ if (existing) {
15
+ console.log(kleur.dim(`Already logged in as ${existing.email}`));
16
+ console.log(kleur.dim('Run `anby logout` to sign out first.'));
17
+ return;
18
+ }
19
+ const authUrl = (options.authUrl ||
20
+ process.env.ANBY_AUTH_URL ||
21
+ DEFAULT_AUTH_URL).replace(/\/+$/, '');
22
+ const { token, email } = await runOAuthFlow(authUrl);
23
+ // JWT exp is 7 days from issuance.
24
+ const payload = JSON.parse(Buffer.from(token.split('.')[1], 'base64url').toString());
25
+ const expiresAt = new Date(payload.exp * 1000).toISOString();
26
+ await saveAuth({ token, email: email || payload.email || 'unknown', expiresAt });
27
+ console.log('');
28
+ console.log(kleur.green(`✔ Logged in as ${email || payload.email}`));
29
+ console.log(kleur.dim(` Token expires: ${expiresAt}`));
30
+ }
31
+ function runOAuthFlow(authUrl) {
32
+ return new Promise((resolve, reject) => {
33
+ const server = createServer((req, res) => {
34
+ const url = new URL(req.url || '/', `http://localhost`);
35
+ if (url.pathname === '/callback') {
36
+ const token = url.searchParams.get('token');
37
+ const email = url.searchParams.get('email') || '';
38
+ const error = url.searchParams.get('error');
39
+ if (error || !token) {
40
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
41
+ res.end(errorPage(error || 'no_token'));
42
+ server.close();
43
+ reject(new Error(`Login failed: ${error || 'no token received'}`));
44
+ return;
45
+ }
46
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
47
+ res.end(successPage());
48
+ server.close();
49
+ resolve({ token, email });
50
+ return;
51
+ }
52
+ res.writeHead(404);
53
+ res.end('Not found');
54
+ });
55
+ server.listen(0, '127.0.0.1', () => {
56
+ const addr = server.address();
57
+ if (!addr || typeof addr === 'string') {
58
+ reject(new Error('Failed to bind local server'));
59
+ return;
60
+ }
61
+ const callbackUrl = `http://localhost:${addr.port}/callback`;
62
+ const loginUrl = `${authUrl}/auth/google?returnUrl=${encodeURIComponent(callbackUrl)}&mode=cli`;
63
+ console.log(kleur.dim(`Opening browser for login...`));
64
+ console.log(kleur.dim(`If the browser doesn't open, visit:`));
65
+ console.log(kleur.cyan(loginUrl));
66
+ console.log('');
67
+ openBrowser(loginUrl).catch(() => {
68
+ // Browser didn't open — user can copy the URL above.
69
+ });
70
+ });
71
+ // Timeout after 3 minutes
72
+ setTimeout(() => {
73
+ server.close();
74
+ reject(new Error('Login timed out after 3 minutes'));
75
+ }, 180_000);
76
+ });
77
+ }
78
+ async function openBrowser(url) {
79
+ const { exec } = await import('node:child_process');
80
+ const { promisify } = await import('node:util');
81
+ const execAsync = promisify(exec);
82
+ const platform = process.platform;
83
+ if (platform === 'darwin') {
84
+ await execAsync(`open "${url}"`);
85
+ }
86
+ else if (platform === 'win32') {
87
+ await execAsync(`start "" "${url}"`);
88
+ }
89
+ else {
90
+ await execAsync(`xdg-open "${url}"`);
91
+ }
92
+ }
93
+ function successPage() {
94
+ return `<!DOCTYPE html>
95
+ <html><head><meta charset="utf-8"><title>Anby CLI</title></head>
96
+ <body style="font-family:system-ui;display:flex;align-items:center;justify-content:center;min-height:100vh;margin:0;background:#0a0a0a;color:#fafafa">
97
+ <div style="text-align:center">
98
+ <h1 style="color:#22c55e">✔ Logged in</h1>
99
+ <p>You can close this tab and return to the terminal.</p>
100
+ </div></body></html>`;
101
+ }
102
+ function errorPage(error) {
103
+ return `<!DOCTYPE html>
104
+ <html><head><meta charset="utf-8"><title>Anby CLI</title></head>
105
+ <body style="font-family:system-ui;display:flex;align-items:center;justify-content:center;min-height:100vh;margin:0;background:#0a0a0a;color:#fafafa">
106
+ <div style="text-align:center">
107
+ <h1 style="color:#ef4444">✖ Login failed</h1>
108
+ <p>${error}</p>
109
+ <p>Return to the terminal and try again.</p>
110
+ </div></body></html>`;
111
+ }
112
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAA6C,MAAM,WAAW,CAAC;AACpF,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE/D,MAAM,gBAAgB,GAAG,sBAAsB,CAAC;AAOhD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAqB;IACtD,MAAM,QAAQ,GAAG,MAAM,aAAa,EAAE,CAAC;IACvC,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,GAAG,CAAC,wBAAwB,QAAQ,CAAC,KAAK,EAAE,CAAC,CACpD,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC,CAAC;QAC/D,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,CACd,OAAO,CAAC,OAAO;QACf,OAAO,CAAC,GAAG,CAAC,aAAa;QACzB,gBAAgB,CACjB,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAEtB,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,CAAC;IAErD,mCAAmC;IACnC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CACxB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,QAAQ,EAAE,CACzD,CAAC;IACF,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IAE7D,MAAM,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,IAAI,OAAO,CAAC,KAAK,IAAI,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC;IAEjF,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,kBAAkB,KAAK,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACrE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,oBAAoB,SAAS,EAAE,CAAC,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,YAAY,CAAC,OAAe;IACnC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAG,YAAY,CAAC,CAAC,GAAoB,EAAE,GAAmB,EAAE,EAAE;YACxE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,kBAAkB,CAAC,CAAC;YAExD,IAAI,GAAG,CAAC,QAAQ,KAAK,WAAW,EAAE,CAAC;gBACjC,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBAC5C,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;gBAClD,MAAM,KAAK,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBAE5C,IAAI,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;oBACpB,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,0BAA0B,EAAE,CAAC,CAAC;oBACnE,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,IAAI,UAAU,CAAC,CAAC,CAAC;oBACxC,MAAM,CAAC,KAAK,EAAE,CAAC;oBACf,MAAM,CAAC,IAAI,KAAK,CAAC,iBAAiB,KAAK,IAAI,mBAAmB,EAAE,CAAC,CAAC,CAAC;oBACnE,OAAO;gBACT,CAAC;gBAED,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,0BAA0B,EAAE,CAAC,CAAC;gBACnE,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;gBACvB,MAAM,CAAC,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;gBAC1B,OAAO;YACT,CAAC;YAED,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YACnB,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACvB,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,WAAW,EAAE,GAAG,EAAE;YACjC,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;YAC9B,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACtC,MAAM,CAAC,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC,CAAC;gBACjD,OAAO;YACT,CAAC;YAED,MAAM,WAAW,GAAG,oBAAoB,IAAI,CAAC,IAAI,WAAW,CAAC;YAC7D,MAAM,QAAQ,GAAG,GAAG,OAAO,0BAA0B,kBAAkB,CAAC,WAAW,CAAC,WAAW,CAAC;YAEhG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC,CAAC;YACvD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC,CAAC;YAC9D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;YAClC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAEhB,WAAW,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;gBAC/B,qDAAqD;YACvD,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,0BAA0B;QAC1B,UAAU,CAAC,GAAG,EAAE;YACd,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC,CAAC;QACvD,CAAC,EAAE,OAAO,CAAC,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,GAAW;IACpC,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;IACpD,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;IAChD,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAElC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAClC,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,MAAM,SAAS,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC;IACnC,CAAC;SAAM,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;QAChC,MAAM,SAAS,CAAC,aAAa,GAAG,GAAG,CAAC,CAAC;IACvC,CAAC;SAAM,CAAC;QACN,MAAM,SAAS,CAAC,aAAa,GAAG,GAAG,CAAC,CAAC;IACvC,CAAC;AACH,CAAC;AAED,SAAS,WAAW;IAClB,OAAO;;;;;;qBAMY,CAAC;AACtB,CAAC;AAED,SAAS,SAAS,CAAC,KAAa;IAC9B,OAAO;;;;;KAKJ,KAAK;;qBAEW,CAAC;AACtB,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function logoutCommand(): Promise<void>;
@@ -0,0 +1,7 @@
1
+ import kleur from 'kleur';
2
+ import { clearAuth } from '../lib/auth-store.js';
3
+ export async function logoutCommand() {
4
+ await clearAuth();
5
+ console.log(kleur.green('✔ Logged out'));
6
+ }
7
+ //# sourceMappingURL=logout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjD,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,SAAS,EAAE,CAAC;IAClB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,23 @@
1
+ export interface StoredAuth {
2
+ token: string;
3
+ email: string;
4
+ expiresAt: string;
5
+ }
6
+ /**
7
+ * Read stored CLI credentials from ~/.anby/auth.json.
8
+ * Returns null if the file doesn't exist or the token has expired.
9
+ */
10
+ export declare function getStoredAuth(): Promise<StoredAuth | null>;
11
+ /**
12
+ * Persist CLI credentials to ~/.anby/auth.json (0600).
13
+ */
14
+ export declare function saveAuth(auth: StoredAuth): Promise<void>;
15
+ /**
16
+ * Remove stored credentials.
17
+ */
18
+ export declare function clearAuth(): Promise<void>;
19
+ /**
20
+ * Extract email domain from stored auth.
21
+ * e.g. "user@bravebits.vn" → "bravebits.vn"
22
+ */
23
+ export declare function getEmailDomain(email: string): string;
@@ -0,0 +1,53 @@
1
+ import { readFile, writeFile, mkdir } from 'node:fs/promises';
2
+ import { homedir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ const ANBY_DIR = join(homedir(), '.anby');
5
+ const AUTH_FILE = join(ANBY_DIR, 'auth.json');
6
+ /**
7
+ * Read stored CLI credentials from ~/.anby/auth.json.
8
+ * Returns null if the file doesn't exist or the token has expired.
9
+ */
10
+ export async function getStoredAuth() {
11
+ try {
12
+ const raw = await readFile(AUTH_FILE, 'utf-8');
13
+ const data = JSON.parse(raw);
14
+ if (!data.token)
15
+ return null;
16
+ if (new Date(data.expiresAt) < new Date())
17
+ return null;
18
+ return data;
19
+ }
20
+ catch {
21
+ return null;
22
+ }
23
+ }
24
+ /**
25
+ * Persist CLI credentials to ~/.anby/auth.json (0600).
26
+ */
27
+ export async function saveAuth(auth) {
28
+ await mkdir(ANBY_DIR, { recursive: true });
29
+ await writeFile(AUTH_FILE, JSON.stringify(auth, null, 2) + '\n', {
30
+ mode: 0o600,
31
+ });
32
+ }
33
+ /**
34
+ * Remove stored credentials.
35
+ */
36
+ export async function clearAuth() {
37
+ try {
38
+ const { unlink } = await import('node:fs/promises');
39
+ await unlink(AUTH_FILE);
40
+ }
41
+ catch {
42
+ // Already gone — fine.
43
+ }
44
+ }
45
+ /**
46
+ * Extract email domain from stored auth.
47
+ * e.g. "user@bravebits.vn" → "bravebits.vn"
48
+ */
49
+ export function getEmailDomain(email) {
50
+ const parts = email.split('@');
51
+ return parts[1] || 'example.com';
52
+ }
53
+ //# sourceMappingURL=auth-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-store.js","sourceRoot":"","sources":["../../src/lib/auth-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;AAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;AAQ9C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAe,CAAC;QAC3C,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QAC7B,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,IAAI,EAAE;YAAE,OAAO,IAAI,CAAC;QACvD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAgB;IAC7C,MAAM,KAAK,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,MAAM,SAAS,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE;QAC/D,IAAI,EAAE,KAAK;KACZ,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;QACpD,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,uBAAuB;IACzB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/B,OAAO,KAAK,CAAC,CAAC,CAAC,IAAI,aAAa,CAAC;AACnC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anby/cli",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Anby Platform CLI — scaffold, validate, publish, and install Anby apps",
5
5
  "keywords": [
6
6
  "anby",
@@ -43,7 +43,7 @@
43
43
  },
44
44
  "dependencies": {
45
45
  "@anby/manifest-schema": "^0.1.1",
46
- "@anby/platform-sdk": "^0.7.0",
46
+ "@anby/platform-sdk": "^0.8.0",
47
47
  "commander": "^12.1.0",
48
48
  "kleur": "^4.1.5"
49
49
  },