@odla-ai/cli 0.1.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/llms.txt ADDED
@@ -0,0 +1,260 @@
1
+ # @odla-ai/cli — LLM context
2
+
3
+ > Project-neutral CLI for provisioning odla apps, database schemas, AI settings, and local runtime files.
4
+
5
+ Project-neutral provisioning CLI for odla apps. It creates and validates an
6
+ `odla.config.mjs`, then uses that config to register an app, enable services,
7
+ push odla-db schema/rules, configure platform AI, configure Clerk auth, record
8
+ deployment links, and write local runtime credentials.
9
+
10
+ It does not know about any specific app. App identity, environments, services,
11
+ schema, rules, auth, AI provider, and links all come from config.
12
+
13
+ ## Install
14
+
15
+ No install needed — the package ships a single `odla-ai` binary, so npx can run
16
+ it directly:
17
+
18
+ ```bash
19
+ npx @odla-ai/cli init --app-id my-app --name "My App"
20
+ ```
21
+
22
+ For a project you keep working in, install it as a dev dependency so the
23
+ shorter `npx odla-ai` form works and the version is pinned by your lockfile:
24
+
25
+ ```bash
26
+ npm i -D @odla-ai/cli
27
+ ```
28
+
29
+ ## Prerequisites
30
+
31
+ - Node.js 20 or newer (`node --version`).
32
+ - odla apps usually deploy as Cloudflare Workers. If you have never used
33
+ Cloudflare:
34
+ 1. Create a free account at <https://dash.cloudflare.com/sign-up>.
35
+ 2. You do not need to install anything: `npx wrangler login` opens the
36
+ browser once to link your account, `npx wrangler dev` runs a Worker
37
+ locally, and `npx wrangler deploy` ships it.
38
+ 3. The `.dev.vars` file this CLI writes with `provision --write-dev-vars` is
39
+ wrangler's local secrets file — `wrangler dev` picks it up automatically.
40
+ It is chmod `0600` and gitignored; never commit it or paste its contents
41
+ into `wrangler.toml`.
42
+
43
+ ## Commands
44
+
45
+ ```bash
46
+ npx odla-ai init --app-id my-app --name "My App"
47
+ npx odla-ai doctor
48
+ npx odla-ai provision --dry-run
49
+ npx odla-ai provision --write-dev-vars
50
+ npx odla-ai smoke --env dev
51
+ npx odla-ai version
52
+ ```
53
+
54
+ `init` writes:
55
+
56
+ - `odla.config.mjs`
57
+ - `src/odla/schema.mjs`
58
+ - `src/odla/rules.mjs`
59
+ - `.gitignore` entries for local credentials
60
+
61
+ `provision` performs the standard safe setup flow:
62
+
63
+ 1. Gets an `odla_dev_...` token by device handshake, or reuses
64
+ `ODLA_DEV_TOKEN` / `.odla/dev-token.json`.
65
+ In an interactive terminal it opens the approval page in your browser when
66
+ the code is displayed. Pass `--open` to force browser launch from a
67
+ non-interactive shell, or `--no-open` to suppress it. Browser launch is
68
+ best-effort; the printed URL and code always remain the fallback.
69
+ 2. Creates the platform app if needed.
70
+ 3. Enables configured services in every configured environment.
71
+ 4. Mints or reuses each env's odla-db app key.
72
+ 5. Pushes the configured schema and rules.
73
+ 6. Configures platform AI and stores provider keys in the tenant vault when the
74
+ configured key env var is set.
75
+ 7. Writes `.odla/credentials.local.json` with mode `0600`.
76
+
77
+ Pass `--rotate-keys` to mint fresh db keys. Pass `--no-write-credentials` to
78
+ skip writing the local credentials file.
79
+
80
+ `smoke` verifies a provisioned environment from local credentials. It fetches
81
+ the platform public config, checks the configured AI provider, fetches the live
82
+ odla-db schema with the tenant key, compares expected schema entities, and runs
83
+ a count aggregate against the first entity. It fails early with a clear message
84
+ when provisioning has not written `.odla/credentials.local.json`.
85
+
86
+ ## Config
87
+
88
+ ```js
89
+ export default {
90
+ platformUrl: process.env.ODLA_PLATFORM_URL ?? "https://odla.ai",
91
+ dbEndpoint: process.env.ODLA_ENDPOINT ?? process.env.ODLA_DB_ENDPOINT ?? "https://db.odla.ai",
92
+ app: { id: "my-app", name: "My App" },
93
+ envs: ["prod", "dev"],
94
+ services: ["db", "ai"],
95
+ db: {
96
+ schema: "./src/odla/schema.mjs",
97
+ rules: "./src/odla/rules.mjs",
98
+ defaultRules: "deny",
99
+ },
100
+ ai: {
101
+ provider: process.env.ODLA_AI_PROVIDER ?? "anthropic",
102
+ keyEnv: "ANTHROPIC_API_KEY",
103
+ },
104
+ auth: {
105
+ clerk: {
106
+ dev: "$CLERK_PUBLISHABLE_KEY",
107
+ prod: "$CLERK_PUBLISHABLE_KEY",
108
+ },
109
+ },
110
+ links: {
111
+ dev: "https://dev.example.com",
112
+ prod: "https://example.com",
113
+ },
114
+ };
115
+ ```
116
+
117
+ `db.schema` and `db.rules` may be inline objects, JSON files, or JS modules
118
+ exporting `default`, `schema` / `SCHEMA`, or `rules` / `RULES`.
119
+
120
+ If schema is present and rules are omitted, `defaultRules: "deny"` generates
121
+ deny-all rules for every schema entity. That is the safe default for Workers
122
+ that mediate reads and writes with an app key.
123
+
124
+ ## API reference (generated from dist/index.d.ts, v0.1.0)
125
+
126
+ ```ts
127
+ declare function runCli(argv?: string[]): Promise<void>;
128
+
129
+ interface DoctorOptions {
130
+ configPath: string;
131
+ stdout?: Pick<typeof console, "log" | "error">;
132
+ }
133
+ declare function doctor(options: DoctorOptions): Promise<void>;
134
+
135
+ interface InitOptions {
136
+ rootDir?: string;
137
+ configPath?: string;
138
+ appId: string;
139
+ name: string;
140
+ envs?: string[];
141
+ services?: string[];
142
+ aiProvider?: string;
143
+ force?: boolean;
144
+ stdout?: Pick<typeof console, "log" | "error">;
145
+ }
146
+ declare function initProject(options: InitOptions): void;
147
+
148
+ type OdlaEnvName = string;
149
+ type AppRules = Record<string, {
150
+ view?: string;
151
+ create?: string;
152
+ update?: string;
153
+ delete?: string;
154
+ }>;
155
+ interface ClerkAuthConfig {
156
+ publishableKey?: string;
157
+ audience?: string;
158
+ mode?: "client" | "full";
159
+ }
160
+ interface OdlaProjectConfig {
161
+ platformUrl?: string;
162
+ dbEndpoint?: string;
163
+ app: {
164
+ id: string;
165
+ name: string;
166
+ };
167
+ envs?: OdlaEnvName[];
168
+ services?: string[];
169
+ db?: {
170
+ /** Inline SerializedSchema, JSON file, or JS module path exporting default/schema. */
171
+ schema?: unknown;
172
+ /** Inline rule map, JSON file, or JS module path exporting default/rules. */
173
+ rules?: AppRules | string;
174
+ /** Generate deny-all rules from schema when rules are omitted. Defaults to true when schema exists. */
175
+ defaultRules?: "deny" | false;
176
+ };
177
+ ai?: {
178
+ provider?: string;
179
+ model?: string;
180
+ /** Env var containing the provider key to store in the platform vault. */
181
+ keyEnv?: string;
182
+ /** Vault secret name. Defaults to @odla-ai/ai's provider default. */
183
+ secretName?: string;
184
+ };
185
+ auth?: {
186
+ clerk?: Record<OdlaEnvName, ClerkAuthConfig | string | null | undefined>;
187
+ };
188
+ links?: Record<OdlaEnvName, string | null | undefined>;
189
+ local?: {
190
+ tokenFile?: string;
191
+ credentialsFile?: string;
192
+ devVarsFile?: string;
193
+ gitignore?: boolean;
194
+ };
195
+ }
196
+ interface LoadedProjectConfig extends OdlaProjectConfig {
197
+ configPath: string;
198
+ rootDir: string;
199
+ platformUrl: string;
200
+ dbEndpoint: string;
201
+ envs: OdlaEnvName[];
202
+ services: string[];
203
+ local: {
204
+ tokenFile: string;
205
+ credentialsFile: string;
206
+ devVarsFile: string;
207
+ gitignore: boolean;
208
+ };
209
+ }
210
+ interface LocalCredentials {
211
+ appId: string;
212
+ platformUrl: string;
213
+ dbEndpoint: string;
214
+ updatedAt: string;
215
+ envs: Record<string, {
216
+ tenantId: string;
217
+ dbKey?: string;
218
+ }>;
219
+ }
220
+ interface ProvisionOptions {
221
+ configPath: string;
222
+ dryRun?: boolean;
223
+ rotateKeys?: boolean;
224
+ writeCredentials?: boolean;
225
+ writeDevVars?: string | boolean;
226
+ token?: string;
227
+ /** true forces browser launch, false disables it, undefined auto-opens only for interactive terminals. */
228
+ open?: boolean;
229
+ /** Test/embedding override for terminal interactivity. Defaults to stdin/stdout TTY detection. */
230
+ interactive?: boolean;
231
+ /** Test/embedding override for opening the approval URL. Defaults to the OS browser opener. */
232
+ openApprovalUrl?: (url: string) => Promise<void>;
233
+ yes?: boolean;
234
+ fetch?: typeof fetch;
235
+ stdout?: Pick<typeof console, "log" | "error">;
236
+ }
237
+ interface ProvisionPlan {
238
+ appId: string;
239
+ appName: string;
240
+ platformUrl: string;
241
+ dbEndpoint: string;
242
+ envs: string[];
243
+ services: string[];
244
+ hasSchema: boolean;
245
+ hasRules: boolean;
246
+ aiProvider?: string;
247
+ }
248
+ interface SmokeOptions {
249
+ configPath: string;
250
+ env?: string;
251
+ fetch?: typeof fetch;
252
+ stdout?: Pick<typeof console, "log" | "error">;
253
+ }
254
+
255
+ declare function provision(options: ProvisionOptions): Promise<void>;
256
+
257
+ declare function smoke(options: SmokeOptions): Promise<void>;
258
+
259
+ export { type LoadedProjectConfig, type LocalCredentials, type OdlaProjectConfig, type ProvisionOptions, type ProvisionPlan, type SmokeOptions, doctor, initProject, provision, runCli, smoke };
260
+ ```
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@odla-ai/cli",
3
+ "version": "0.1.0",
4
+ "description": "Project-neutral CLI for provisioning odla apps, database schemas, AI settings, and local runtime files.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "bin": {
8
+ "odla-ai": "./dist/bin.js"
9
+ },
10
+ "main": "./dist/index.cjs",
11
+ "module": "./dist/index.js",
12
+ "types": "./dist/index.d.ts",
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js",
17
+ "require": "./dist/index.cjs"
18
+ }
19
+ },
20
+ "files": [
21
+ "dist",
22
+ "README.md",
23
+ "REQUIREMENTS.md",
24
+ "llms.txt"
25
+ ],
26
+ "sideEffects": false,
27
+ "engines": {
28
+ "node": ">=20"
29
+ },
30
+ "publishConfig": {
31
+ "access": "public"
32
+ },
33
+ "keywords": [
34
+ "odla",
35
+ "odla-ai",
36
+ "cli",
37
+ "provisioning",
38
+ "cloudflare",
39
+ "database",
40
+ "knowledge-graph",
41
+ "ai"
42
+ ],
43
+ "scripts": {
44
+ "build": "tsup",
45
+ "clean": "rm -rf dist",
46
+ "typecheck": "tsc --noEmit",
47
+ "test": "vitest run",
48
+ "coverage": "vitest run --coverage",
49
+ "gen:llms": "node ../../scripts/gen-llms.mjs",
50
+ "prepublishOnly": "npm run build && npm run gen:llms"
51
+ },
52
+ "dependencies": {
53
+ "@odla-ai/ai": "^0.2.1",
54
+ "@odla-ai/apps": "^0.7.1",
55
+ "@odla-ai/db": "^0.5.0"
56
+ },
57
+ "devDependencies": {
58
+ "@types/node": "^22.10.0",
59
+ "tsup": "^8.5.1",
60
+ "typescript": "^6.0.3",
61
+ "vitest": "^4.1.9"
62
+ }
63
+ }