@anby/cli 0.7.0 → 0.9.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.
- package/dist/commands/index.d.ts +4 -0
- package/dist/commands/index.js +24 -4
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/init.d.ts +6 -15
- package/dist/commands/init.js +529 -67
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/login.d.ts +12 -0
- package/dist/commands/login.js +112 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.d.ts +1 -0
- package/dist/commands/logout.js +7 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/lib/auth-store.d.ts +23 -0
- package/dist/lib/auth-store.js +53 -0
- package/dist/lib/auth-store.js.map +1 -0
- package/package.json +2 -2
package/dist/commands/index.d.ts
CHANGED
|
@@ -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;
|
package/dist/commands/index.js
CHANGED
|
@@ -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
|
|
17
|
-
.option('--
|
|
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;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/init.d.ts
CHANGED
|
@@ -1,22 +1,13 @@
|
|
|
1
1
|
interface InitOptions {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
port?: string;
|
|
2
|
+
/** Hidden override for platform devs */
|
|
3
|
+
registryUrl?: string;
|
|
5
4
|
}
|
|
6
5
|
/**
|
|
7
|
-
*
|
|
6
|
+
* `anby init` — interactive scaffold + register.
|
|
8
7
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
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 {};
|
package/dist/commands/init.js
CHANGED
|
@@ -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://apps.anby.ai';
|
|
4
8
|
/**
|
|
5
|
-
*
|
|
9
|
+
* `anby init` — interactive scaffold + register.
|
|
6
10
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
|
|
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
|
+
}
|
|
86
|
+
}
|
|
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
|
|
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,447 @@ async function patchGitignore() {
|
|
|
159
195
|
catch {
|
|
160
196
|
// file doesn't exist — we'll create it below
|
|
161
197
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
.
|
|
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
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
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('✔
|
|
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
|
+
// Also scaffold the manifest route so Marketplace Submit UI can
|
|
314
|
+
// fetch /_anby/manifest.json from the running app. Remix intercepts
|
|
315
|
+
// /_anby/* before Vite's public/ middleware, so we need an explicit
|
|
316
|
+
// route to serve the file from disk.
|
|
317
|
+
const manifestRouteTarget = resolve('app/routes/[_anby].manifest[.json].tsx');
|
|
318
|
+
try {
|
|
319
|
+
await access(manifestRouteTarget);
|
|
320
|
+
}
|
|
321
|
+
catch {
|
|
322
|
+
await writeFile(manifestRouteTarget, MANIFEST_ROUTE_TEMPLATE, 'utf-8');
|
|
323
|
+
console.log(kleur.green('✔ Scaffolded app/routes/[_anby].manifest[.json].tsx'));
|
|
324
|
+
}
|
|
325
|
+
// Scaffold /_anby/set-token route for auth token refresh via postMessage.
|
|
326
|
+
// Browsers block document.cookie in cross-origin iframes, so this
|
|
327
|
+
// endpoint lets the client-side auth handler set the cookie server-side.
|
|
328
|
+
const setTokenRouteTarget = resolve('app/routes/[_anby].set-token.tsx');
|
|
329
|
+
try {
|
|
330
|
+
await access(setTokenRouteTarget);
|
|
331
|
+
}
|
|
332
|
+
catch {
|
|
333
|
+
await writeFile(setTokenRouteTarget, SET_TOKEN_ROUTE_TEMPLATE, 'utf-8');
|
|
334
|
+
console.log(kleur.green('✔ Scaffolded app/routes/[_anby].set-token.tsx'));
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
const MANIFEST_ROUTE_TEMPLATE = `import { readFile } from 'node:fs/promises';
|
|
338
|
+
import { resolve } from 'node:path';
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Serve public/_anby/manifest.json as a Remix route — auto-generated
|
|
342
|
+
* by \`anby init\`. Remix intercepts /_anby/* before Vite's public/
|
|
343
|
+
* middleware can serve the file, so we need an explicit route.
|
|
344
|
+
*/
|
|
345
|
+
export async function loader() {
|
|
346
|
+
try {
|
|
347
|
+
const path = resolve(process.cwd(), 'public/_anby/manifest.json');
|
|
348
|
+
const raw = await readFile(path, 'utf-8');
|
|
349
|
+
return new Response(raw, {
|
|
350
|
+
headers: { 'Content-Type': 'application/json' },
|
|
351
|
+
});
|
|
352
|
+
} catch (err) {
|
|
353
|
+
return new Response(
|
|
354
|
+
JSON.stringify({ error: 'manifest not found', detail: (err as Error).message }),
|
|
355
|
+
{ status: 404, headers: { 'Content-Type': 'application/json' } },
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
`;
|
|
360
|
+
const SET_TOKEN_ROUTE_TEMPLATE = `import type { ActionFunctionArgs } from '@remix-run/node';
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* POST /_anby/set-token — set auth-token cookie server-side.
|
|
364
|
+
* Auto-generated by \`anby init\`.
|
|
365
|
+
*
|
|
366
|
+
* Used by the platform auth postMessage handler to refresh the JWT
|
|
367
|
+
* cookie without relying on document.cookie (which browsers block in
|
|
368
|
+
* cross-origin iframes).
|
|
369
|
+
*/
|
|
370
|
+
export async function action({ request }: ActionFunctionArgs) {
|
|
371
|
+
if (request.method !== 'POST') {
|
|
372
|
+
return new Response(null, { status: 405 });
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
const { token } = await request.json();
|
|
376
|
+
if (!token || typeof token !== 'string') {
|
|
377
|
+
return new Response(JSON.stringify({ error: 'missing token' }), {
|
|
378
|
+
status: 400,
|
|
379
|
+
headers: { 'Content-Type': 'application/json' },
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
return new Response(JSON.stringify({ ok: true }), {
|
|
384
|
+
status: 200,
|
|
385
|
+
headers: {
|
|
386
|
+
'Content-Type': 'application/json',
|
|
387
|
+
'Set-Cookie': \`auth-token=\${token}; Path=/; HttpOnly; SameSite=None; Secure; Max-Age=86400\`,
|
|
388
|
+
},
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
`;
|
|
392
|
+
// ── Step 5: Patch entry.server.tsx ────────────────────────────────────
|
|
393
|
+
async function patchEntryServer(port) {
|
|
394
|
+
const target = resolve('app/entry.server.tsx');
|
|
395
|
+
let original;
|
|
396
|
+
try {
|
|
397
|
+
original = await readFile(target, 'utf-8');
|
|
398
|
+
}
|
|
399
|
+
catch {
|
|
400
|
+
console.log(kleur.dim('• No app/entry.server.tsx found — skipping entry patch.'));
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
if (original.includes('initAuth') && original.includes('_anby_token')) {
|
|
404
|
+
console.log(kleur.dim('• app/entry.server.tsx already has initAuth + token redirect — no patch needed'));
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
if (original.includes('initAuth') && !original.includes('_anby_token')) {
|
|
408
|
+
// Patch only the _anby_token redirect into handleRequest
|
|
409
|
+
if (!original.includes('handleRequest')) {
|
|
410
|
+
console.log(kleur.dim('• app/entry.server.tsx has initAuth but no handleRequest — skipping token redirect patch'));
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
// Insert token redirect at the start of handleRequest
|
|
414
|
+
const handleRequestBody = /handleRequest\s*\([^)]*\)\s*\{/;
|
|
415
|
+
const match = original.match(handleRequestBody);
|
|
416
|
+
if (match && match.index !== undefined) {
|
|
417
|
+
const insertPos = match.index + match[0].length;
|
|
418
|
+
const tokenRedirect = `
|
|
419
|
+
// When the platform shell embeds this app in an iframe, it passes the
|
|
420
|
+
// user's JWT via \`?_anby_token=...\`. Extract it, set a first-party
|
|
421
|
+
// cookie, and redirect to strip the token from the URL.
|
|
422
|
+
const url = new URL(request.url);
|
|
423
|
+
const anbyToken = url.searchParams.get('_anby_token');
|
|
424
|
+
if (anbyToken) {
|
|
425
|
+
url.searchParams.delete('_anby_token');
|
|
426
|
+
return new Response(null, {
|
|
427
|
+
status: 302,
|
|
428
|
+
headers: {
|
|
429
|
+
Location: url.pathname + url.search + url.hash,
|
|
430
|
+
'Set-Cookie': \`auth-token=\${anbyToken}; Path=/; HttpOnly; SameSite=None; Secure; Max-Age=86400\`,
|
|
431
|
+
},
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
`;
|
|
435
|
+
const patched = original.slice(0, insertPos) + tokenRedirect + original.slice(insertPos);
|
|
436
|
+
await writeFile(target, patched, 'utf-8');
|
|
437
|
+
console.log(kleur.green('✔ Patched app/entry.server.tsx (_anby_token redirect)'));
|
|
438
|
+
}
|
|
439
|
+
else {
|
|
440
|
+
console.log(kleur.dim('• Could not locate handleRequest body — add _anby_token handling manually'));
|
|
441
|
+
}
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
const sdkImport = "import { autoPublishOnBoot } from '@anby/platform-sdk';";
|
|
445
|
+
const authImport = "import { initAuth } from './lib/auth.server';";
|
|
446
|
+
const importRegex = /^import .+ from .+;?\s*$/gm;
|
|
447
|
+
let lastImportEnd = -1;
|
|
448
|
+
for (const match of original.matchAll(importRegex)) {
|
|
449
|
+
if (match.index !== undefined) {
|
|
450
|
+
lastImportEnd = match.index + match[0].length;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
let withImports;
|
|
454
|
+
if (lastImportEnd >= 0) {
|
|
455
|
+
withImports =
|
|
456
|
+
original.slice(0, lastImportEnd) +
|
|
457
|
+
'\n' +
|
|
458
|
+
sdkImport +
|
|
459
|
+
'\n' +
|
|
460
|
+
authImport +
|
|
461
|
+
original.slice(lastImportEnd);
|
|
462
|
+
}
|
|
463
|
+
else {
|
|
464
|
+
withImports = sdkImport + '\n' + authImport + '\n' + original;
|
|
465
|
+
}
|
|
466
|
+
const bootstrapBlock = `
|
|
467
|
+
// Anby platform bootstrap — auto-generated by \`anby init\`.
|
|
468
|
+
// Ensures auth + discovery are ready before the first request.
|
|
469
|
+
await initAuth();
|
|
470
|
+
autoPublishOnBoot({
|
|
471
|
+
publicUrl: process.env.APP_PUBLIC_URL || \`http://localhost:\${process.env.PORT || ${port}}\`,
|
|
472
|
+
});
|
|
473
|
+
`;
|
|
474
|
+
const exportRegex = /^export\s+(default|function|async\s+function)/m;
|
|
475
|
+
const exportMatch = withImports.match(exportRegex);
|
|
476
|
+
let patched;
|
|
477
|
+
if (exportMatch && exportMatch.index !== undefined) {
|
|
478
|
+
patched =
|
|
479
|
+
withImports.slice(0, exportMatch.index) +
|
|
480
|
+
bootstrapBlock +
|
|
481
|
+
'\n' +
|
|
482
|
+
withImports.slice(exportMatch.index);
|
|
483
|
+
}
|
|
484
|
+
else {
|
|
485
|
+
patched = withImports + '\n' + bootstrapBlock;
|
|
486
|
+
}
|
|
487
|
+
// Also add _anby_token redirect in handleRequest
|
|
488
|
+
const handleRequestBody = /handleRequest\s*\([^)]*\)\s*\{/;
|
|
489
|
+
const hrMatch = patched.match(handleRequestBody);
|
|
490
|
+
if (hrMatch && hrMatch.index !== undefined) {
|
|
491
|
+
const insertPos = hrMatch.index + hrMatch[0].length;
|
|
492
|
+
const tokenRedirect = `
|
|
493
|
+
// When the platform shell embeds this app in an iframe, it passes the
|
|
494
|
+
// user's JWT via \`?_anby_token=...\`. Extract it, set a first-party
|
|
495
|
+
// cookie, and redirect to strip the token from the URL.
|
|
496
|
+
const url = new URL(request.url);
|
|
497
|
+
const anbyToken = url.searchParams.get('_anby_token');
|
|
498
|
+
if (anbyToken) {
|
|
499
|
+
url.searchParams.delete('_anby_token');
|
|
500
|
+
return new Response(null, {
|
|
501
|
+
status: 302,
|
|
502
|
+
headers: {
|
|
503
|
+
Location: url.pathname + url.search + url.hash,
|
|
504
|
+
'Set-Cookie': \`auth-token=\${anbyToken}; Path=/; HttpOnly; SameSite=None; Secure; Max-Age=86400\`,
|
|
505
|
+
},
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
`;
|
|
509
|
+
patched = patched.slice(0, insertPos) + tokenRedirect + patched.slice(insertPos);
|
|
510
|
+
}
|
|
511
|
+
await writeFile(target, patched, 'utf-8');
|
|
512
|
+
console.log(kleur.green('✔ Patched app/entry.server.tsx (initAuth + autoPublishOnBoot + token redirect)'));
|
|
513
|
+
}
|
|
514
|
+
// ── Step 6: Self-register with registry ───────────────────────────────
|
|
515
|
+
async function registerAndWriteToken(opts) {
|
|
516
|
+
if (!opts.auth) {
|
|
517
|
+
console.log(kleur.yellow('! Not logged in — run `anby login` first, then `anby init` again'));
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
// Check if .env already has a valid ANBY_APP_TOKEN for THIS registry
|
|
521
|
+
const envPath = resolve('.env');
|
|
522
|
+
try {
|
|
523
|
+
const envContent = await readFile(envPath, 'utf-8');
|
|
524
|
+
const match = envContent.match(/^ANBY_APP_TOKEN=(.*)$/m);
|
|
525
|
+
if (match && match[1].trim()) {
|
|
526
|
+
// Decode token to check platformUrl
|
|
527
|
+
try {
|
|
528
|
+
const b64 = match[1].trim().replace('anby_v1_', '');
|
|
529
|
+
const payload = JSON.parse(Buffer.from(b64, 'base64url').toString());
|
|
530
|
+
const tokenPlatform = (payload.platformUrl || '').replace(/\/+$/, '');
|
|
531
|
+
const targetPlatform = opts.registryBase.replace(/\/+$/, '');
|
|
532
|
+
if (tokenPlatform === targetPlatform) {
|
|
533
|
+
console.log(kleur.dim('• .env already contains ANBY_APP_TOKEN for this registry — skipping registration'));
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
console.log(kleur.dim(`• Token in .env points to ${tokenPlatform}, re-registering for ${targetPlatform}`));
|
|
537
|
+
}
|
|
538
|
+
catch {
|
|
539
|
+
// Can't parse — re-register
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
catch {
|
|
544
|
+
// .env doesn't exist — fine, we'll create it
|
|
545
|
+
}
|
|
546
|
+
// Load the manifest we just wrote
|
|
547
|
+
let manifest;
|
|
548
|
+
try {
|
|
549
|
+
const raw = await readFile(resolve('anby-app.manifest.json'), 'utf-8');
|
|
550
|
+
manifest = JSON.parse(raw);
|
|
551
|
+
}
|
|
552
|
+
catch {
|
|
553
|
+
console.log(kleur.yellow('! Could not read anby-app.manifest.json — skipping registration'));
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
const publicUrl = `http://localhost:${opts.port}`;
|
|
557
|
+
const registryUrl = `${opts.registryBase}/registry/apps`;
|
|
558
|
+
// Register with a minimal manifest (just metadata, no entities).
|
|
559
|
+
// Entity declarations are published later by autoPublishOnBoot when
|
|
560
|
+
// the developer runs `npm run dev` — by then they've had time to
|
|
561
|
+
// edit the manifest with the correct provides/requires.
|
|
562
|
+
const registrationManifest = {
|
|
563
|
+
...manifest,
|
|
564
|
+
provides: { entities: [], events: [] },
|
|
565
|
+
requires: { ...manifest.requires, entities: [], events: [] },
|
|
566
|
+
};
|
|
567
|
+
const body = {
|
|
568
|
+
id: manifest.id,
|
|
569
|
+
name: manifest.name,
|
|
570
|
+
description: manifest.description,
|
|
571
|
+
icon: manifest.icon,
|
|
572
|
+
color: manifest.color,
|
|
573
|
+
publisherId: manifest.id.split('.').slice(0, 2).join('.'),
|
|
574
|
+
version: manifest.version,
|
|
575
|
+
publicUrl,
|
|
576
|
+
submittedBy: `cli:${opts.auth.email}`,
|
|
577
|
+
manifest: registrationManifest,
|
|
578
|
+
};
|
|
579
|
+
let res;
|
|
580
|
+
try {
|
|
581
|
+
res = await fetch(registryUrl, {
|
|
582
|
+
method: 'POST',
|
|
583
|
+
headers: {
|
|
584
|
+
'Content-Type': 'application/json',
|
|
585
|
+
Authorization: `Bearer ${opts.auth.token}`,
|
|
586
|
+
},
|
|
587
|
+
body: JSON.stringify(body),
|
|
588
|
+
signal: AbortSignal.timeout(10_000),
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
catch (err) {
|
|
592
|
+
console.log(kleur.yellow(`! Could not reach registry at ${registryUrl}: ${err.message}`));
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
if (!res.ok) {
|
|
596
|
+
const errBody = await res.text();
|
|
597
|
+
console.log(kleur.yellow(`! Registry rejected publish (${res.status}): ${errBody}`));
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
600
|
+
const result = await res.json();
|
|
601
|
+
if (!result.privateKey) {
|
|
602
|
+
console.log(kleur.dim('• App already registered (no new private key). Run `anby app rotate-token` for a new token.'));
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
// Assemble token — platformUrl is the registry base (used by SDK discovery)
|
|
606
|
+
const token = assembleToken({
|
|
607
|
+
appId: manifest.id,
|
|
608
|
+
platformUrl: opts.registryBase,
|
|
609
|
+
privateKey: result.privateKey,
|
|
610
|
+
});
|
|
611
|
+
// Upsert into .env: replace existing ANBY_APP_TOKEN/APP_PUBLIC_URL
|
|
612
|
+
// lines if present, otherwise append.
|
|
613
|
+
let envContent = '';
|
|
614
|
+
try {
|
|
615
|
+
envContent = await readFile(envPath, 'utf-8');
|
|
616
|
+
}
|
|
617
|
+
catch {
|
|
618
|
+
// File doesn't exist — start fresh
|
|
619
|
+
}
|
|
620
|
+
envContent = upsertEnvVar(envContent, 'ANBY_APP_TOKEN', token);
|
|
621
|
+
envContent = upsertEnvVar(envContent, 'APP_PUBLIC_URL', `http://localhost:${opts.port}`);
|
|
622
|
+
await writeFile(envPath, envContent, { mode: 0o600 });
|
|
623
|
+
console.log(kleur.green('✔ Registered app with registry'));
|
|
624
|
+
console.log(kleur.green('✔ Wrote ANBY_APP_TOKEN to .env'));
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* Upsert an env var into a .env file content string.
|
|
628
|
+
* If the key exists (with or without value), replace the line.
|
|
629
|
+
* Otherwise append to the end.
|
|
630
|
+
*/
|
|
631
|
+
function upsertEnvVar(content, key, value) {
|
|
632
|
+
const line = `${key}=${value}`;
|
|
633
|
+
const regex = new RegExp(`^${key}=.*$`, 'm');
|
|
634
|
+
if (regex.test(content)) {
|
|
635
|
+
return content.replace(regex, line);
|
|
636
|
+
}
|
|
637
|
+
// Append, ensuring file ends with newline
|
|
638
|
+
const sep = content.length === 0 || content.endsWith('\n') ? '' : '\n';
|
|
639
|
+
return content + sep + line + '\n';
|
|
178
640
|
}
|
|
179
641
|
//# 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":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function logoutCommand(): Promise<void>;
|
|
@@ -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.
|
|
3
|
+
"version": "0.9.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.
|
|
46
|
+
"@anby/platform-sdk": "^0.9.0",
|
|
47
47
|
"commander": "^12.1.0",
|
|
48
48
|
"kleur": "^4.1.5"
|
|
49
49
|
},
|