clefbase 1.1.6 → 1.2.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.
Files changed (43) hide show
  1. package/README.md +169 -103
  2. package/bin/clefbase.js +15 -0
  3. package/dist/app.d.ts +16 -32
  4. package/dist/app.d.ts.map +1 -1
  5. package/dist/app.js +29 -44
  6. package/dist/app.js.map +1 -1
  7. package/dist/auth/index.d.ts +16 -44
  8. package/dist/auth/index.d.ts.map +1 -1
  9. package/dist/auth/index.js +40 -95
  10. package/dist/auth/index.js.map +1 -1
  11. package/dist/cli-src/cli/api.js +170 -0
  12. package/dist/cli-src/cli/commands/deploy.js +285 -0
  13. package/dist/cli-src/cli/commands/info.js +67 -0
  14. package/dist/cli-src/cli/commands/init.js +226 -0
  15. package/dist/cli-src/cli/config.js +82 -0
  16. package/dist/cli-src/cli/index.js +110 -0
  17. package/dist/cli-src/types.js +17 -0
  18. package/dist/cli.js +34375 -0
  19. package/dist/db/index.d.ts +26 -62
  20. package/dist/db/index.d.ts.map +1 -1
  21. package/dist/db/index.js +34 -70
  22. package/dist/db/index.js.map +1 -1
  23. package/dist/hosting/index.d.ts +123 -0
  24. package/dist/hosting/index.d.ts.map +1 -0
  25. package/dist/hosting/index.js +202 -0
  26. package/dist/hosting/index.js.map +1 -0
  27. package/dist/http.d.ts +2 -4
  28. package/dist/http.d.ts.map +1 -1
  29. package/dist/http.js +8 -22
  30. package/dist/http.js.map +1 -1
  31. package/dist/index.d.ts +11 -7
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +13 -6
  34. package/dist/index.js.map +1 -1
  35. package/dist/storage/index.d.ts +8 -50
  36. package/dist/storage/index.d.ts.map +1 -1
  37. package/dist/storage/index.js +9 -59
  38. package/dist/storage/index.js.map +1 -1
  39. package/dist/types.d.ts +10 -4
  40. package/dist/types.d.ts.map +1 -1
  41. package/dist/types.js +0 -1
  42. package/dist/types.js.map +1 -1
  43. package/package.json +21 -5
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # clefbase
2
2
 
3
- Firebase-style SDK for your Clefbase server. Drop-in for Node.js and browser apps.
3
+ Firebase-style SDK and CLI for Clefbase / [Cleforyx](https://cleforyx.com). Database, auth, storage, and hosting in one package.
4
4
 
5
5
  ## Install
6
6
 
@@ -12,18 +12,26 @@ npm install clefbase
12
12
 
13
13
  ## Quick Start
14
14
 
15
+ ### 1 — Initialise your project
16
+
17
+ ```bash
18
+ npx clefbase init
19
+ ```
20
+
21
+ The CLI will ask for your Project ID, API Key, and Admin Secret, let you pick which services you need, and optionally set up hosting. It writes a `clefbase.json` config file (automatically added to `.gitignore`) and a `.env.example`.
22
+
23
+ ### 2 — Use the SDK
24
+
15
25
  ```ts
16
- import { initClefbase, getDatabase, getAuth, getStorage } from "clefbase";
26
+ import { initClefbase, getDatabase, getAuth, getStorage, getHosting } from "clefbase";
27
+ import config from "./clefbase.json";
17
28
 
18
- const app = initClefbase({
19
- serverUrl: "https://your-clefbase-server.com",
20
- projectId: "my_project_1abc", // from your dashboard
21
- apiKey: "cfx_abc123...", // generated API key
22
- });
29
+ const app = initClefbase(config);
23
30
 
24
31
  const db = getDatabase(app);
25
32
  const auth = getAuth(app);
26
33
  const storage = getStorage(app);
34
+ const hosting = getHosting(app); // requires adminSecret in config
27
35
  ```
28
36
 
29
37
  ---
@@ -38,7 +46,7 @@ const post = await db.collection("posts").add({
38
46
  published: true,
39
47
  views: 0,
40
48
  });
41
- // post._id, post._createdAt, post._updatedAt are auto-set
49
+ // post._id, post._createdAt, post._updatedAt are set by the server
42
50
  ```
43
51
 
44
52
  ### Get a document
@@ -71,27 +79,23 @@ const results = await db.collection("posts")
71
79
  .where({ published: true, views: { $gt: 100 } })
72
80
  .orderBy("_createdAt", "desc")
73
81
  .limit(10)
74
- .get();
75
-
76
- // results.data — array of documents
77
- // results.total — total matching count
78
- // results.limit, results.offset
82
+ .query(); // returns { data, total, limit, offset }
79
83
 
80
- // Or just get the array:
84
+ // Or just the array:
81
85
  const posts = await db.collection("posts")
82
86
  .where({ published: true })
83
- .getDocs();
87
+ .getDocs(); // alias: .get()
84
88
  ```
85
89
 
86
- ### Available filter operators
90
+ ### Filter operators
87
91
 
88
- | Operator | Meaning |
89
- |----------------|----------------------|
90
- | `{ $gt: n }` | greater than |
91
- | `{ $gte: n }` | greater than or equal|
92
- | `{ $lt: n }` | less than |
93
- | `{ $lte: n }` | less than or equal |
94
- | `{ $ne: val }` | not equal |
92
+ | Operator | Meaning |
93
+ |---|---|
94
+ | `{ $gt: n }` | greater than |
95
+ | `{ $gte: n }` | greater than or equal |
96
+ | `{ $lt: n }` | less than |
97
+ | `{ $lte: n }` | less than or equal |
98
+ | `{ $ne: val }` | not equal |
95
99
  | `{ $contains: "str" }` | string contains (case-insensitive) |
96
100
 
97
101
  ### Subcollections
@@ -99,12 +103,11 @@ const posts = await db.collection("posts")
99
103
  ```ts
100
104
  // posts → [postId] → comments
101
105
  const comments = db.collection("posts").doc("post-abc").collection("comments");
102
-
103
106
  await comments.add({ text: "Great post!", author: "Bob" });
104
107
  const all = await comments.getDocs();
105
108
  ```
106
109
 
107
- ### Convenience top-level helpers
110
+ ### Convenience helpers
108
111
 
109
112
  ```ts
110
113
  await db.getDoc("users", "uid-123");
@@ -117,139 +120,202 @@ await db.deleteDoc("users", "uid-123");
117
120
 
118
121
  ## Auth
119
122
 
120
- ### Sign up
121
-
122
123
  ```ts
124
+ // Sign up
123
125
  const { user, token } = await auth.signUp("alice@example.com", "password123", {
124
126
  displayName: "Alice",
125
127
  metadata: { role: "member" },
126
128
  });
127
- ```
128
129
 
129
- ### Sign in / Sign out
130
-
131
- ```ts
130
+ // Sign in / out
132
131
  const { user } = await auth.signIn("alice@example.com", "password123");
133
-
134
132
  await auth.signOut();
135
- ```
136
-
137
- ### Current user
138
133
 
139
- ```ts
134
+ // Current user
140
135
  const me = auth.currentUser; // AuthUser | null
141
- ```
142
-
143
- ### Listen for auth state changes
144
136
 
145
- ```ts
137
+ // Listen for auth state changes
146
138
  const unsubscribe = auth.onAuthStateChanged((user) => {
147
- if (user) {
148
- console.log("Signed in as", user.email);
149
- } else {
150
- console.log("Signed out");
151
- }
139
+ if (user) console.log("Signed in as", user.email);
140
+ else console.log("Signed out");
152
141
  });
153
-
154
- // Stop listening
155
142
  unsubscribe();
156
- ```
157
-
158
- ### Update profile
159
143
 
160
- ```ts
144
+ // Update profile
161
145
  await auth.updateProfile({ displayName: "Bob", metadata: { theme: "dark" } });
162
- ```
163
146
 
164
- ### Password management
165
-
166
- ```ts
167
- // Change password (must be signed in)
147
+ // Password management
168
148
  await auth.changePassword("oldPass", "newPass");
169
-
170
- // Request reset email
171
149
  await auth.sendPasswordResetEmail("alice@example.com");
172
-
173
- // Confirm reset with token from email
174
150
  await auth.confirmPasswordReset(resetToken, "newPassword");
175
- ```
176
151
 
177
- ### Email verification
178
-
179
- ```ts
152
+ // Email verification
180
153
  await auth.sendEmailVerification();
181
- await auth.verifyEmail("ABC123"); // code from email
154
+ await auth.verifyEmail("ABC123");
182
155
  ```
183
156
 
184
157
  ---
185
158
 
186
159
  ## Storage
187
160
 
188
- ### Upload a file
189
-
190
161
  ```ts
191
- // Node.js
162
+ // Upload (Node.js)
192
163
  import fs from "fs";
193
- const buffer = fs.readFileSync("./photo.jpg");
194
- const meta = await storage.ref("avatars/user-123.jpg").upload(buffer, {
195
- contentType: "image/jpeg",
196
- });
164
+ const meta = await storage.ref("avatars/user-123.jpg").upload(
165
+ fs.readFileSync("./photo.jpg"),
166
+ { contentType: "image/jpeg" }
167
+ );
197
168
 
198
- // Browser
199
- const file = fileInput.files[0];
169
+ // Upload (browser)
200
170
  const meta = await storage.ref(`uploads/${file.name}`).upload(file);
201
- ```
202
171
 
203
- ### Get download URL
204
-
205
- ```ts
172
+ // Download URL
206
173
  const url = await storage.ref("avatars/user-123.jpg").getDownloadURL();
207
- ```
208
174
 
209
- ### Get metadata
210
-
211
- ```ts
175
+ // Metadata
212
176
  const meta = await storage.ref("avatars/user-123.jpg").getMetadata();
213
- // meta.size, meta.mimeType, meta.url, meta.createdAt
177
+
178
+ // Delete
179
+ await storage.ref("avatars/user-123.jpg").delete();
180
+
181
+ // List files
182
+ const files = await storage.ref("avatars/").list({ limit: 20 });
183
+
184
+ // Named bucket
185
+ const ref = storage.bucket("user-uploads").ref("doc.pdf");
186
+ await ref.upload(buffer, { contentType: "application/pdf" });
214
187
  ```
215
188
 
216
- ### Delete a file
189
+ ---
190
+
191
+ ## Hosting
192
+
193
+ ### SDK
217
194
 
218
195
  ```ts
219
- await storage.ref("avatars/user-123.jpg").delete();
196
+ import fs from "fs";
197
+ const hosting = getHosting(app);
198
+
199
+ // List sites
200
+ const sites = await hosting.listSites();
201
+
202
+ // Create a site
203
+ const site = await hosting.createSite("my-app", "My awesome app");
204
+
205
+ // Deploy files
206
+ const result = await hosting.site(site.id).deployFiles({
207
+ "index.html": fs.readFileSync("dist/index.html"),
208
+ "app.js": fs.readFileSync("dist/app.js"),
209
+ "styles.css": fs.readFileSync("dist/styles.css"),
210
+ }, {
211
+ entrypoint: "index.html",
212
+ message: "v1.2.0 release",
213
+ onProgress: (done, total) => console.log(`${done}/${total} files`),
214
+ });
215
+
216
+ console.log(`Live at: ${result.url}`);
217
+
218
+ // Get active deploy
219
+ const active = await hosting.site(site.id).getActiveDeploy();
220
220
  ```
221
221
 
222
- ### List files
222
+ ### CLI
223
223
 
224
- ```ts
225
- const files = await storage.ref("avatars/").list({ limit: 20 });
224
+ ```bash
225
+ # First-time setup (interactive)
226
+ clefbase init
227
+
228
+ # Build then deploy in one step
229
+ npm run build && clefbase deploy
230
+
231
+ # Deploy with options
232
+ clefbase deploy --dir ./build --message "v2 release"
233
+ clefbase deploy --site <siteId> # override the linked site
234
+
235
+ # Manage hosting
236
+ clefbase hosting:init # link/create a site
237
+ clefbase hosting:status # show current live deploy
238
+ clefbase hosting:sites # list all sites
239
+
240
+ # Project info
241
+ clefbase info # config + connectivity check
226
242
  ```
227
243
 
228
- ### Use a specific bucket
244
+ ---
229
245
 
230
- ```ts
231
- const ref = storage.bucket("user-uploads").ref("doc.pdf");
232
- await ref.upload(buffer, { contentType: "application/pdf" });
246
+ ## CLI Reference
247
+
248
+ | Command | Description |
249
+ |---|---|
250
+ | `clefbase init` | Interactive project setup |
251
+ | `clefbase deploy` | Deploy your built site |
252
+ | `clefbase deploy -d <dir>` | Deploy from a specific directory |
253
+ | `clefbase deploy -m <msg>` | Deploy with a release note |
254
+ | `clefbase deploy -s <siteId>` | Deploy to a specific site |
255
+ | `clefbase hosting:init` | Link or create a hosted site |
256
+ | `clefbase hosting:status` | Show current live deploy |
257
+ | `clefbase hosting:sites` | List all sites |
258
+ | `clefbase info` | Show config and connectivity |
259
+
260
+ ---
261
+
262
+ ## clefbase.json
263
+
264
+ Written by `clefbase init`. Never commit this file — it contains your secrets. The CLI adds it to `.gitignore` automatically.
265
+
266
+ ```json
267
+ {
268
+ "serverUrl": "https://api.cleforyx.com",
269
+ "projectId": "my_project_abc123",
270
+ "apiKey": "cfx_...",
271
+ "adminSecret": "...",
272
+ "services": {
273
+ "database": true,
274
+ "auth": true,
275
+ "storage": false,
276
+ "hosting": true
277
+ },
278
+ "hosting": {
279
+ "siteId": "355f3976-89dc-...",
280
+ "siteName": "my-app",
281
+ "distDir": "dist",
282
+ "entrypoint": "index.html"
283
+ }
284
+ }
233
285
  ```
234
286
 
235
287
  ---
236
288
 
237
289
  ## TypeScript
238
290
 
239
- The SDK is fully typed. Pass your own document shape as a generic:
291
+ Full types with generics:
240
292
 
241
293
  ```ts
242
- interface Post {
243
- _id: string;
244
- _createdAt: string;
245
- _updatedAt: string;
246
- title: string;
294
+ interface Post extends ClefbaseDocument {
295
+ title: string;
247
296
  published: boolean;
248
- views: number;
297
+ views: number;
249
298
  }
250
299
 
251
300
  const posts = db.collection<Post>("posts");
252
- const post = await posts.doc("abc").get(); // typed as Post | null
301
+ const post = await posts.doc("abc").get(); // Post | null
302
+ ```
303
+
304
+ ---
305
+
306
+ ## Error handling
307
+
308
+ ```ts
309
+ import { ClefbaseError } from "clefbase";
310
+
311
+ try {
312
+ await auth.signIn("bad@example.com", "wrong");
313
+ } catch (err) {
314
+ if (err instanceof ClefbaseError) {
315
+ console.log(err.message); // "Invalid credentials"
316
+ console.log(err.status); // 401
317
+ }
318
+ }
253
319
  ```
254
320
 
255
321
  ---
@@ -257,9 +323,9 @@ const post = await posts.doc("abc").get(); // typed as Post | null
257
323
  ## Multiple apps
258
324
 
259
325
  ```ts
260
- const defaultApp = initClefbase({ ... });
261
- const adminApp = initClefbase({ ..., apiKey: "admin-key" }, "admin");
326
+ const defaultApp = initClefbase({ serverUrl, projectId, apiKey });
327
+ const adminApp = initClefbase({ serverUrl, projectId, apiKey: adminKey, adminSecret }, "admin");
262
328
 
263
329
  const db = getDatabase(defaultApp);
264
- const adminDb = getDatabase(adminApp);
330
+ const hosting = getHosting(adminApp);
265
331
  ```
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ // Gracefully tell the user if the package hasn't been built yet
5
+ try {
6
+ require("../dist/cli.js");
7
+ } catch (e) {
8
+ if (e.code === "MODULE_NOT_FOUND") {
9
+ console.error(
10
+ "\nclefbase CLI not built yet. Run:\n\n npm run build\n\nthen try again.\n"
11
+ );
12
+ process.exit(1);
13
+ }
14
+ throw e;
15
+ }
package/dist/app.d.ts CHANGED
@@ -2,19 +2,22 @@ import { HttpClient } from "./http";
2
2
  import { Database } from "./db";
3
3
  import { Auth } from "./auth";
4
4
  import { ClefbaseStorage } from "./storage";
5
+ import { ClefbaseHosting } from "./hosting";
5
6
  import type { ClefbaseConfig } from "./types";
6
7
  /**
7
8
  * A Clefbase application instance.
8
- * Created by `initClefbase()` and passed to `getDatabase()`, `getAuth()`, `getStorage()`.
9
+ * Created by `initClefbase()` pass it to `getDatabase()`, `getAuth()`, etc.
9
10
  */
10
11
  export declare class ClefbaseApp {
11
12
  readonly config: ClefbaseConfig;
12
13
  /** @internal */ readonly _dbHttp: HttpClient;
13
14
  /** @internal */ readonly _authHttp: HttpClient;
14
15
  /** @internal */ readonly _storageHttp: HttpClient;
16
+ /** @internal */ readonly _hostingHttp: HttpClient;
15
17
  private _db;
16
18
  private _auth;
17
19
  private _storage;
20
+ private _hosting;
18
21
  constructor(config: ClefbaseConfig);
19
22
  /** @internal */
20
23
  _getDb(): Database;
@@ -22,6 +25,8 @@ export declare class ClefbaseApp {
22
25
  _getAuth(): Auth;
23
26
  /** @internal */
24
27
  _getStorage(): ClefbaseStorage;
28
+ /** @internal */
29
+ _getHosting(): ClefbaseHosting;
25
30
  }
26
31
  /**
27
32
  * Initialise a Clefbase app. Call once at startup.
@@ -29,42 +34,21 @@ export declare class ClefbaseApp {
29
34
  *
30
35
  * @example
31
36
  * const app = initClefbase({
32
- * serverUrl: "https://your-server.com",
33
- * projectId: "my_project_1abc",
34
- * apiKey: "cfx_abc123...",
37
+ * serverUrl: "https://api.cleforyx.com",
38
+ * projectId: "my_project_abc",
39
+ * apiKey: "cfx_...",
40
+ * adminSecret: "secret", // only needed for hosting
35
41
  * });
36
- *
37
- * // Named app (multiple projects)
38
- * const admin = initClefbase({ ... }, "admin");
39
42
  */
40
43
  export declare function initClefbase(config: ClefbaseConfig, name?: string): ClefbaseApp;
41
- /**
42
- * Retrieve an already-initialised app by name.
43
- * Throws if `initClefbase()` has not been called for that name.
44
- */
44
+ /** Retrieve an already-initialised app by name. Throws if not found. */
45
45
  export declare function getApp(name?: string): ClefbaseApp;
46
- /**
47
- * Get the Database service for an app.
48
- *
49
- * @example
50
- * const db = getDatabase(app);
51
- * const user = await db.collection("users").doc("123").get();
52
- */
46
+ /** Get the Database service. */
53
47
  export declare function getDatabase(app?: ClefbaseApp): Database;
54
- /**
55
- * Get the Auth service for an app.
56
- *
57
- * @example
58
- * const auth = getAuth(app);
59
- * const { user } = await auth.signIn("user@example.com", "pass");
60
- */
48
+ /** Get the Auth service. */
61
49
  export declare function getAuth(app?: ClefbaseApp): Auth;
62
- /**
63
- * Get the Storage service for an app.
64
- *
65
- * @example
66
- * const storage = getStorage(app);
67
- * const url = await storage.ref("files/doc.pdf").getDownloadURL();
68
- */
50
+ /** Get the Storage service. */
69
51
  export declare function getStorage(app?: ClefbaseApp): ClefbaseStorage;
52
+ /** Get the Hosting service. Requires `adminSecret` in config. */
53
+ export declare function getHosting(app?: ClefbaseApp): ClefbaseHosting;
70
54
  //# sourceMappingURL=app.d.ts.map
package/dist/app.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAI9C;;;GAGG;AACH,qBAAa,WAAW;IACtB,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAGhC,gBAAgB,CAAC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC9C,gBAAgB,CAAC,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC;IAChD,gBAAgB,CAAC,QAAQ,CAAC,YAAY,EAAE,UAAU,CAAC;IAEnD,OAAO,CAAC,GAAG,CAAuB;IAClC,OAAO,CAAC,KAAK,CAAmB;IAChC,OAAO,CAAC,QAAQ,CAA8B;gBAElC,MAAM,EAAE,cAAc;IAelC,gBAAgB;IAChB,MAAM,IAAI,QAAQ;IAKlB,gBAAgB;IAChB,QAAQ,IAAI,IAAI;IAKhB,gBAAgB;IAChB,WAAW,IAAI,eAAe;CAS/B;AAOD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,cAAc,EACtB,IAAI,GAAE,MAAgB,GACrB,WAAW,CAKb;AAED;;;GAGG;AACH,wBAAgB,MAAM,CAAC,IAAI,GAAE,MAAgB,GAAG,WAAW,CAQ1D;AAID;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,GAAG,CAAC,EAAE,WAAW,GAAG,QAAQ,CAEvD;AAED;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,GAAG,CAAC,EAAE,WAAW,GAAG,IAAI,CAE/C;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,GAAG,CAAC,EAAE,WAAW,GAAG,eAAe,CAE7D"}
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAI9C;;;GAGG;AACH,qBAAa,WAAW;IACtB,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAEhC,gBAAgB,CAAC,QAAQ,CAAC,OAAO,EAAO,UAAU,CAAC;IACnD,gBAAgB,CAAC,QAAQ,CAAC,SAAS,EAAK,UAAU,CAAC;IACnD,gBAAgB,CAAC,QAAQ,CAAC,YAAY,EAAE,UAAU,CAAC;IACnD,gBAAgB,CAAC,QAAQ,CAAC,YAAY,EAAE,UAAU,CAAC;IAEnD,OAAO,CAAC,GAAG,CAAoC;IAC/C,OAAO,CAAC,KAAK,CAAkC;IAC/C,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,QAAQ,CAA+B;gBAEnC,MAAM,EAAE,cAAc;IAYlC,gBAAgB;IAChB,MAAM,IAAI,QAAQ;IAKlB,gBAAgB;IAChB,QAAQ,IAAI,IAAI;IAKhB,gBAAgB;IAChB,WAAW,IAAI,eAAe;IAU9B,gBAAgB;IAChB,WAAW,IAAI,eAAe;CAS/B;AAOD;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,cAAc,EACtB,IAAI,GAAE,MAAgB,GACrB,WAAW,CAKb;AAED,wEAAwE;AACxE,wBAAgB,MAAM,CAAC,IAAI,GAAE,MAAgB,GAAG,WAAW,CAQ1D;AAID,gCAAgC;AAChC,wBAAgB,WAAW,CAAC,GAAG,CAAC,EAAE,WAAW,GAAG,QAAQ,CAEvD;AAED,4BAA4B;AAC5B,wBAAgB,OAAO,CAAC,GAAG,CAAC,EAAE,WAAW,GAAG,IAAI,CAE/C;AAED,+BAA+B;AAC/B,wBAAgB,UAAU,CAAC,GAAG,CAAC,EAAE,WAAW,GAAG,eAAe,CAE7D;AAED,iEAAiE;AACjE,wBAAgB,UAAU,CAAC,GAAG,CAAC,EAAE,WAAW,GAAG,eAAe,CAE7D"}
package/dist/app.js CHANGED
@@ -6,28 +6,27 @@ exports.getApp = getApp;
6
6
  exports.getDatabase = getDatabase;
7
7
  exports.getAuth = getAuth;
8
8
  exports.getStorage = getStorage;
9
+ exports.getHosting = getHosting;
9
10
  const http_1 = require("./http");
10
11
  const db_1 = require("./db");
11
12
  const auth_1 = require("./auth");
12
13
  const storage_1 = require("./storage");
14
+ const hosting_1 = require("./hosting");
13
15
  // ─── App ──────────────────────────────────────────────────────────────────────
14
16
  /**
15
17
  * A Clefbase application instance.
16
- * Created by `initClefbase()` and passed to `getDatabase()`, `getAuth()`, `getStorage()`.
18
+ * Created by `initClefbase()` pass it to `getDatabase()`, `getAuth()`, etc.
17
19
  */
18
20
  class ClefbaseApp {
19
21
  constructor(config) {
20
22
  this.config = config;
21
23
  const base = config.serverUrl.replace(/\/+$/, "");
22
- const keyHeader = { "x-cfx-key": config.apiKey };
23
- // Server mounts (from index.ts):
24
- // app.use("/db", ..., dbApiKeyMiddleware, createExternalDbRouter())
25
- // app.use("/auth", ..., dbApiKeyMiddleware, createExternalAuthRouter())
26
- // app.use("/storage", ..., createPublicStorageRouter()) ← public reads
27
- // app.use("/storage", ..., dbApiKeyMiddleware, createExternalStorageRouter()) ← writes
28
- this._dbHttp = new http_1.HttpClient(`${base}/db`, keyHeader);
29
- this._authHttp = new http_1.HttpClient(`${base}/auth`, keyHeader);
30
- this._storageHttp = new http_1.HttpClient(`${base}/storage`, keyHeader);
24
+ const cfxKey = { "x-cfx-key": config.apiKey };
25
+ const admin = { "x-admin-secret": config.adminSecret ?? "" };
26
+ this._dbHttp = new http_1.HttpClient(`${base}/db`, cfxKey);
27
+ this._authHttp = new http_1.HttpClient(`${base}/auth`, cfxKey);
28
+ this._storageHttp = new http_1.HttpClient(`${base}/storage`, cfxKey);
29
+ this._hostingHttp = new http_1.HttpClient(`${base}/api/hosting`, admin);
31
30
  }
32
31
  /** @internal */
33
32
  _getDb() {
@@ -44,13 +43,18 @@ class ClefbaseApp {
44
43
  /** @internal */
45
44
  _getStorage() {
46
45
  if (!this._storage)
47
- this._storage = new storage_1.ClefbaseStorage(this._storageHttp, this.config.projectId, // passed as ?projectId= on public storage reads
48
- this._getAuth());
46
+ this._storage = new storage_1.ClefbaseStorage(this._storageHttp, this.config.projectId, this._getAuth());
49
47
  return this._storage;
50
48
  }
49
+ /** @internal */
50
+ _getHosting() {
51
+ if (!this._hosting)
52
+ this._hosting = new hosting_1.ClefbaseHosting(this._hostingHttp, this.config.projectId, this.config.serverUrl);
53
+ return this._hosting;
54
+ }
51
55
  }
52
56
  exports.ClefbaseApp = ClefbaseApp;
53
- // ─── App registry ─────────────────────────────────────────────────────────────
57
+ // ─── Registry ─────────────────────────────────────────────────────────────────
54
58
  const DEFAULT = "[DEFAULT]";
55
59
  const registry = new Map();
56
60
  /**
@@ -59,13 +63,11 @@ const registry = new Map();
59
63
  *
60
64
  * @example
61
65
  * const app = initClefbase({
62
- * serverUrl: "https://your-server.com",
63
- * projectId: "my_project_1abc",
64
- * apiKey: "cfx_abc123...",
66
+ * serverUrl: "https://api.cleforyx.com",
67
+ * projectId: "my_project_abc",
68
+ * apiKey: "cfx_...",
69
+ * adminSecret: "secret", // only needed for hosting
65
70
  * });
66
- *
67
- * // Named app (multiple projects)
68
- * const admin = initClefbase({ ... }, "admin");
69
71
  */
70
72
  function initClefbase(config, name = DEFAULT) {
71
73
  if (registry.has(name))
@@ -74,10 +76,7 @@ function initClefbase(config, name = DEFAULT) {
74
76
  registry.set(name, app);
75
77
  return app;
76
78
  }
77
- /**
78
- * Retrieve an already-initialised app by name.
79
- * Throws if `initClefbase()` has not been called for that name.
80
- */
79
+ /** Retrieve an already-initialised app by name. Throws if not found. */
81
80
  function getApp(name = DEFAULT) {
82
81
  const app = registry.get(name);
83
82
  if (!app) {
@@ -86,34 +85,20 @@ function getApp(name = DEFAULT) {
86
85
  return app;
87
86
  }
88
87
  // ─── Service accessors ────────────────────────────────────────────────────────
89
- /**
90
- * Get the Database service for an app.
91
- *
92
- * @example
93
- * const db = getDatabase(app);
94
- * const user = await db.collection("users").doc("123").get();
95
- */
88
+ /** Get the Database service. */
96
89
  function getDatabase(app) {
97
90
  return (app ?? getApp())._getDb();
98
91
  }
99
- /**
100
- * Get the Auth service for an app.
101
- *
102
- * @example
103
- * const auth = getAuth(app);
104
- * const { user } = await auth.signIn("user@example.com", "pass");
105
- */
92
+ /** Get the Auth service. */
106
93
  function getAuth(app) {
107
94
  return (app ?? getApp())._getAuth();
108
95
  }
109
- /**
110
- * Get the Storage service for an app.
111
- *
112
- * @example
113
- * const storage = getStorage(app);
114
- * const url = await storage.ref("files/doc.pdf").getDownloadURL();
115
- */
96
+ /** Get the Storage service. */
116
97
  function getStorage(app) {
117
98
  return (app ?? getApp())._getStorage();
118
99
  }
100
+ /** Get the Hosting service. Requires `adminSecret` in config. */
101
+ function getHosting(app) {
102
+ return (app ?? getApp())._getHosting();
103
+ }
119
104
  //# sourceMappingURL=app.js.map
package/dist/app.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}