@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.
- 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 +364 -66
- 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://registry.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
|
-
|
|
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
|
-
|
|
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,283 @@ 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
|
+
}
|
|
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":"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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.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.
|
|
46
|
+
"@anby/platform-sdk": "^0.8.0",
|
|
47
47
|
"commander": "^12.1.0",
|
|
48
48
|
"kleur": "^4.1.5"
|
|
49
49
|
},
|