@flowerforce/flowerbase-client 0.1.1-beta.2

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 (63) hide show
  1. package/CHANGELOG.md +0 -0
  2. package/LICENSE +3 -0
  3. package/README.md +198 -0
  4. package/dist/app.d.ts +40 -0
  5. package/dist/app.d.ts.map +1 -0
  6. package/dist/app.js +186 -0
  7. package/dist/bson.d.ts +8 -0
  8. package/dist/bson.d.ts.map +1 -0
  9. package/dist/bson.js +10 -0
  10. package/dist/credentials.d.ts +7 -0
  11. package/dist/credentials.d.ts.map +1 -0
  12. package/dist/credentials.js +24 -0
  13. package/dist/functions.d.ts +3 -0
  14. package/dist/functions.d.ts.map +1 -0
  15. package/dist/functions.js +30 -0
  16. package/dist/http.d.ts +15 -0
  17. package/dist/http.d.ts.map +1 -0
  18. package/dist/http.js +74 -0
  19. package/dist/index.d.ts +7 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +14 -0
  22. package/dist/mongo.d.ts +4 -0
  23. package/dist/mongo.d.ts.map +1 -0
  24. package/dist/mongo.js +61 -0
  25. package/dist/session.d.ts +12 -0
  26. package/dist/session.d.ts.map +1 -0
  27. package/dist/session.js +53 -0
  28. package/dist/session.native.d.ts +14 -0
  29. package/dist/session.native.d.ts.map +1 -0
  30. package/dist/session.native.js +81 -0
  31. package/dist/types.d.ts +73 -0
  32. package/dist/types.d.ts.map +1 -0
  33. package/dist/types.js +2 -0
  34. package/dist/user.d.ts +17 -0
  35. package/dist/user.d.ts.map +1 -0
  36. package/dist/user.js +30 -0
  37. package/dist/watch.d.ts +3 -0
  38. package/dist/watch.d.ts.map +1 -0
  39. package/dist/watch.js +138 -0
  40. package/jest.config.ts +13 -0
  41. package/package.json +30 -0
  42. package/project.json +11 -0
  43. package/rollup.config.js +17 -0
  44. package/src/__tests__/auth.test.ts +164 -0
  45. package/src/__tests__/compat.test.ts +12 -0
  46. package/src/__tests__/functions.test.ts +76 -0
  47. package/src/__tests__/mongo.test.ts +48 -0
  48. package/src/__tests__/session.test.ts +103 -0
  49. package/src/__tests__/watch.test.ts +138 -0
  50. package/src/app.ts +235 -0
  51. package/src/bson.ts +6 -0
  52. package/src/credentials.ts +24 -0
  53. package/src/functions.ts +32 -0
  54. package/src/http.ts +92 -0
  55. package/src/index.ts +14 -0
  56. package/src/mongo.ts +63 -0
  57. package/src/session.native.ts +98 -0
  58. package/src/session.ts +59 -0
  59. package/src/types.ts +84 -0
  60. package/src/user.ts +39 -0
  61. package/src/watch.ts +150 -0
  62. package/tsconfig.json +34 -0
  63. package/tsconfig.spec.json +13 -0
package/CHANGELOG.md ADDED
File without changes
package/LICENSE ADDED
@@ -0,0 +1,3 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Flowerbase
package/README.md ADDED
@@ -0,0 +1,198 @@
1
+ # @flowerforce/flowerbase-client
2
+
3
+ Client TypeScript leggero per usare Flowerbase con API in stile Realm:
4
+
5
+ - autenticazione (`local-userpass`, `anon-user`, `custom-function`)
6
+ - chiamate funzioni (`user.functions.<name>(...)`)
7
+ - accesso a MongoDB Atlas service (`user.mongoClient("mongodb-atlas")`)
8
+ - change stream via `watch()` con async iterator
9
+ - supporto BSON/EJSON (`ObjectId`, `Date`, ecc.)
10
+
11
+ ## Installazione
12
+
13
+ ```bash
14
+ npm i @flowerforce/flowerbase-client
15
+ ```
16
+
17
+ ## Quick start
18
+
19
+ ```ts
20
+ import { App, Credentials } from '@flowerforce/flowerbase-client'
21
+
22
+ const app = new App({
23
+ id: 'my-app-id',
24
+ baseUrl: 'http://localhost:8000',
25
+ timeout: 10000
26
+ })
27
+
28
+ await app.logIn(Credentials.emailPassword('user@example.com', 'secret'))
29
+
30
+ const user = app.currentUser
31
+ if (!user) throw new Error('User not logged in')
32
+
33
+ const result = await user.functions.myFunction('hello')
34
+ console.log(result)
35
+ ```
36
+
37
+ ## Configurazione `App`
38
+
39
+ ```ts
40
+ new App({
41
+ id: string, // app id Flowerbase
42
+ baseUrl: string, // URL base backend (es: http://localhost:8000)
43
+ timeout?: number // default 10000
44
+ })
45
+ ```
46
+
47
+ ## Autenticazione
48
+
49
+ ### Local user/pass
50
+
51
+ ```ts
52
+ await app.logIn(Credentials.emailPassword(email, password))
53
+ ```
54
+
55
+ ### Anonymous
56
+
57
+ ```ts
58
+ await app.logIn(Credentials.anonymous())
59
+ ```
60
+
61
+ ### Custom function auth
62
+
63
+ ```ts
64
+ await app.logIn(
65
+ Credentials.function({
66
+ username: 'demo',
67
+ pin: '1234'
68
+ })
69
+ )
70
+ ```
71
+
72
+ ### Utility `emailPasswordAuth`
73
+
74
+ ```ts
75
+ await app.emailPasswordAuth.registerUser({ email, password })
76
+ await app.emailPasswordAuth.sendResetPasswordEmail(email)
77
+ await app.emailPasswordAuth.callResetPasswordFunction(email, newPassword, extraArg1, extraArg2)
78
+ await app.emailPasswordAuth.resetPassword({ token, tokenId, password })
79
+ ```
80
+
81
+ ## Current user
82
+
83
+ Dopo il login:
84
+
85
+ ```ts
86
+ const user = app.currentUser
87
+ ```
88
+
89
+ Interfaccia principale:
90
+
91
+ - `user.id`
92
+ - `user.functions.<functionName>(...args)`
93
+ - `user.mongoClient('mongodb-atlas')`
94
+ - `user.refreshAccessToken()`
95
+ - `user.refreshCustomData()`
96
+ - `user.logOut()`
97
+
98
+ ## Funzioni server
99
+
100
+ ```ts
101
+ const response = await user.functions.calculateScore({ workspaceId: 'w1' })
102
+ ```
103
+
104
+ Le risposte sono normalizzate lato client per gestire payload JSON/EJSON.
105
+
106
+ ## Mongo service
107
+
108
+ ```ts
109
+ const mongo = user.mongoClient('mongodb-atlas')
110
+ const collection = mongo.db('mydb').collection('todos')
111
+
112
+ const one = await collection.findOne({ done: false })
113
+ const many = await collection.find({ done: false })
114
+
115
+ await collection.insertOne({ title: 'Task', createdAt: new Date() })
116
+ await collection.updateOne({ title: 'Task' }, { $set: { done: true } })
117
+ await collection.deleteOne({ title: 'Task' })
118
+ ```
119
+
120
+ Metodi disponibili su `collection`:
121
+
122
+ - `find(query?, options?)`
123
+ - `findOne(query?, options?)`
124
+ - `insertOne(document, options?)`
125
+ - `updateOne(filter, update, options?)`
126
+ - `updateMany(filter, update, options?)`
127
+ - `deleteOne(filter, options?)`
128
+ - `watch(pipeline?, options?)`
129
+
130
+ ## Watch / Change streams
131
+
132
+ `watch()` restituisce un async iterator con reconnect automatico e metodo `close()`.
133
+
134
+ ```ts
135
+ const stream = collection.watch()
136
+
137
+ try {
138
+ for await (const change of stream) {
139
+ console.log(change)
140
+ }
141
+ } finally {
142
+ stream.close()
143
+ }
144
+ ```
145
+
146
+ ## BSON / EJSON
147
+
148
+ Il client esporta anche:
149
+
150
+ ```ts
151
+ import { BSON, EJSON, ObjectId, ObjectID } from '@flowerforce/flowerbase-client'
152
+ ```
153
+
154
+ Il layer Mongo client serializza query/opzioni con EJSON e deserializza le risposte, così tipi BSON come `ObjectId` e `Date` restano coerenti con l'uso Realm-like.
155
+
156
+ ## Sessione
157
+
158
+ La sessione (`accessToken`, `refreshToken`, `userId`) viene salvata con chiave:
159
+
160
+ - `flowerbase:<appId>:session`
161
+
162
+ Storage usato:
163
+
164
+ - `localStorage` se disponibile (browser)
165
+ - memory store fallback (ambienti senza `localStorage`)
166
+
167
+ Su bootstrap dell'app viene tentato un refresh automatico dell'access token usando il refresh token salvato.
168
+
169
+ ## Logout
170
+
171
+ ```ts
172
+ await user.logOut()
173
+ ```
174
+
175
+ Invia `DELETE /auth/session` con refresh token e pulisce la sessione locale.
176
+
177
+ ## Tipi esportati
178
+
179
+ - `AppConfig`
180
+ - `CredentialsLike`
181
+ - `UserLike`
182
+ - `MongoClientLike`
183
+ - `CollectionLike`
184
+ - `WatchAsyncIterator`
185
+
186
+ ## Build e test (workspace)
187
+
188
+ ```bash
189
+ npm run build --workspace @flowerforce/flowerbase-client
190
+ npm run test --workspace @flowerforce/flowerbase-client
191
+ ```
192
+
193
+ Oppure dal package:
194
+
195
+ ```bash
196
+ npm run build
197
+ npm test
198
+ ```
package/dist/app.d.ts ADDED
@@ -0,0 +1,40 @@
1
+ import { AppConfig, CredentialsLike, ProfileData, SessionData } from './types';
2
+ import { User } from './user';
3
+ export declare class App {
4
+ readonly id: string;
5
+ readonly baseUrl: string;
6
+ readonly timeout: number;
7
+ private readonly sessionManager;
8
+ currentUser: User | null;
9
+ private readonly sessionBootstrapPromise;
10
+ emailPasswordAuth: {
11
+ registerUser: (input: {
12
+ email: string;
13
+ password: string;
14
+ }) => Promise<unknown>;
15
+ sendResetPasswordEmail: (email: string) => Promise<unknown>;
16
+ callResetPasswordFunction: (email: string, password: string, ...args: unknown[]) => Promise<unknown>;
17
+ resetPassword: (input: {
18
+ token: string;
19
+ tokenId: string;
20
+ password: string;
21
+ }) => Promise<unknown>;
22
+ };
23
+ constructor(config: AppConfig);
24
+ private providerUrl;
25
+ private authUrl;
26
+ private functionsUrl;
27
+ private createSession;
28
+ private bootstrapSessionOnLoad;
29
+ private ensureSessionBootstrapped;
30
+ private setLoggedInUser;
31
+ logIn(credentials: CredentialsLike): Promise<User>;
32
+ getSessionOrThrow(): SessionData;
33
+ postProvider<T = unknown>(path: string, body: unknown): Promise<T>;
34
+ callFunction(name: string, args: unknown[]): Promise<any>;
35
+ callService(name: string, args: unknown[]): Promise<unknown>;
36
+ getProfile(): Promise<ProfileData>;
37
+ refreshAccessToken(): Promise<string>;
38
+ logoutUser(): Promise<void>;
39
+ }
40
+ //# sourceMappingURL=app.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAuB,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AACnG,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAc7B,qBAAa,GAAG;IACd,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAgB;IAC/C,WAAW,EAAE,IAAI,GAAG,IAAI,CAAO;IAC/B,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAe;IAEvD,iBAAiB,EAAE;QACjB,YAAY,EAAE,CAAC,KAAK,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAA;SAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;QAC9E,sBAAsB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;QAC3D,yBAAyB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;QACpG,aAAa,EAAE,CAAC,KAAK,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAA;SAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;KACjG,CAAA;gBAEW,MAAM,EAAE,SAAS;IAwB7B,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,YAAY;YAIN,aAAa;YASb,sBAAsB;YAkBtB,yBAAyB;YAIzB,eAAe;IAevB,KAAK,CAAC,WAAW,EAAE,eAAe;IAkBxC,iBAAiB;IAQX,YAAY,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IASlE,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE;IAmB1C,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE;IAkBzC,UAAU,IAAI,OAAO,CAAC,WAAW,CAAC;IAWlC,kBAAkB;IAoBlB,UAAU;CAgBjB"}
package/dist/app.js ADDED
@@ -0,0 +1,186 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.App = void 0;
4
+ const functions_1 = require("./functions");
5
+ const http_1 = require("./http");
6
+ const session_1 = require("./session");
7
+ const user_1 = require("./user");
8
+ const API_PREFIX = '/api/client/v2.0';
9
+ class App {
10
+ constructor(config) {
11
+ this.currentUser = null;
12
+ this.id = config.id;
13
+ this.baseUrl = config.baseUrl.replace(/\/$/, '');
14
+ this.timeout = config.timeout ?? 10000;
15
+ this.sessionManager = new session_1.SessionManager(this.id);
16
+ const session = this.sessionManager.get();
17
+ if (session?.userId) {
18
+ this.currentUser = new user_1.User(this, session.userId);
19
+ }
20
+ this.sessionBootstrapPromise = this.bootstrapSessionOnLoad();
21
+ this.emailPasswordAuth = {
22
+ registerUser: ({ email, password }) => this.postProvider('/local-userpass/register', { email, password }),
23
+ sendResetPasswordEmail: (email) => this.postProvider('/local-userpass/reset/send', { email }),
24
+ callResetPasswordFunction: (email, password, ...args) => this.postProvider('/local-userpass/reset/call', { email, password, arguments: args }),
25
+ resetPassword: ({ token, tokenId, password }) => this.postProvider('/local-userpass/reset', { token, tokenId, password })
26
+ };
27
+ }
28
+ providerUrl(path) {
29
+ return `${this.baseUrl}${API_PREFIX}/app/${this.id}/auth/providers${path}`;
30
+ }
31
+ authUrl(path) {
32
+ return `${this.baseUrl}${API_PREFIX}/auth${path}`;
33
+ }
34
+ functionsUrl(path = '/call') {
35
+ return `${this.baseUrl}${API_PREFIX}/app/${this.id}/functions${path}`;
36
+ }
37
+ async createSession(refreshToken) {
38
+ return (0, http_1.requestJson)({
39
+ url: this.authUrl('/session'),
40
+ method: 'POST',
41
+ bearerToken: refreshToken,
42
+ timeout: this.timeout
43
+ });
44
+ }
45
+ async bootstrapSessionOnLoad() {
46
+ const session = this.sessionManager.get();
47
+ if (!session || typeof localStorage === 'undefined') {
48
+ return;
49
+ }
50
+ try {
51
+ const result = await this.createSession(session.refreshToken);
52
+ this.sessionManager.set({
53
+ ...session,
54
+ accessToken: result.access_token
55
+ });
56
+ }
57
+ catch {
58
+ this.sessionManager.clear();
59
+ this.currentUser = null;
60
+ }
61
+ }
62
+ async ensureSessionBootstrapped() {
63
+ await this.sessionBootstrapPromise;
64
+ }
65
+ async setLoggedInUser(data, profileEmail) {
66
+ const sessionResult = await this.createSession(data.refresh_token);
67
+ const session = {
68
+ accessToken: sessionResult.access_token,
69
+ refreshToken: data.refresh_token,
70
+ userId: data.user_id
71
+ };
72
+ this.sessionManager.set(session);
73
+ this.currentUser = new user_1.User(this, data.user_id);
74
+ if (profileEmail) {
75
+ this.currentUser.profile = { email: profileEmail };
76
+ }
77
+ return this.currentUser;
78
+ }
79
+ async logIn(credentials) {
80
+ if (credentials.provider === 'local-userpass') {
81
+ const result = await this.postProvider('/local-userpass/login', {
82
+ username: credentials.email,
83
+ password: credentials.password
84
+ });
85
+ return this.setLoggedInUser(result, credentials.email);
86
+ }
87
+ if (credentials.provider === 'anon-user') {
88
+ const result = await this.postProvider('/anon-user/login', {});
89
+ return this.setLoggedInUser(result);
90
+ }
91
+ const result = await this.postProvider('/custom-function/login', credentials.payload);
92
+ return this.setLoggedInUser(result);
93
+ }
94
+ getSessionOrThrow() {
95
+ const session = this.sessionManager.get();
96
+ if (!session) {
97
+ throw new Error('User is not authenticated');
98
+ }
99
+ return session;
100
+ }
101
+ async postProvider(path, body) {
102
+ return (0, http_1.requestJson)({
103
+ url: this.providerUrl(path),
104
+ method: 'POST',
105
+ body,
106
+ timeout: this.timeout
107
+ });
108
+ }
109
+ async callFunction(name, args) {
110
+ await this.ensureSessionBootstrapped();
111
+ const session = this.getSessionOrThrow();
112
+ const payload = {
113
+ name,
114
+ arguments: args
115
+ };
116
+ const result = await (0, http_1.requestJson)({
117
+ url: this.functionsUrl('/call'),
118
+ method: 'POST',
119
+ body: payload,
120
+ bearerToken: session.accessToken,
121
+ timeout: this.timeout
122
+ });
123
+ return (0, functions_1.normalizeFunctionResponse)(result);
124
+ }
125
+ async callService(name, args) {
126
+ await this.ensureSessionBootstrapped();
127
+ const session = this.getSessionOrThrow();
128
+ const payload = {
129
+ name,
130
+ service: 'mongodb-atlas',
131
+ arguments: args
132
+ };
133
+ return (0, http_1.requestJson)({
134
+ url: this.functionsUrl('/call'),
135
+ method: 'POST',
136
+ body: payload,
137
+ bearerToken: session.accessToken,
138
+ timeout: this.timeout
139
+ });
140
+ }
141
+ async getProfile() {
142
+ await this.ensureSessionBootstrapped();
143
+ const session = this.getSessionOrThrow();
144
+ return (0, http_1.requestJson)({
145
+ url: this.authUrl('/profile'),
146
+ method: 'GET',
147
+ bearerToken: session.accessToken,
148
+ timeout: this.timeout
149
+ });
150
+ }
151
+ async refreshAccessToken() {
152
+ await this.ensureSessionBootstrapped();
153
+ const session = this.getSessionOrThrow();
154
+ try {
155
+ const result = await this.createSession(session.refreshToken);
156
+ this.sessionManager.set({
157
+ ...session,
158
+ accessToken: result.access_token
159
+ });
160
+ return result.access_token;
161
+ }
162
+ catch (error) {
163
+ this.sessionManager.clear();
164
+ this.currentUser = null;
165
+ throw error;
166
+ }
167
+ }
168
+ async logoutUser() {
169
+ const session = this.sessionManager.get();
170
+ try {
171
+ if (session) {
172
+ await (0, http_1.requestJson)({
173
+ url: this.authUrl('/session'),
174
+ method: 'DELETE',
175
+ bearerToken: session.refreshToken,
176
+ timeout: this.timeout
177
+ });
178
+ }
179
+ }
180
+ finally {
181
+ this.sessionManager.clear();
182
+ this.currentUser = null;
183
+ }
184
+ }
185
+ }
186
+ exports.App = App;
package/dist/bson.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ import { EJSON, ObjectId, BSON as RawBSON } from 'bson';
2
+ declare const ObjectID: typeof ObjectId;
3
+ declare const BSON: typeof RawBSON & {
4
+ ObjectId: typeof ObjectId;
5
+ ObjectID: typeof ObjectId;
6
+ };
7
+ export { BSON, EJSON, ObjectId, ObjectID };
8
+ //# sourceMappingURL=bson.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bson.d.ts","sourceRoot":"","sources":["../src/bson.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,IAAI,OAAO,EAAE,MAAM,MAAM,CAAA;AAEvD,QAAA,MAAM,QAAQ,iBAAW,CAAA;AACzB,QAAA,MAAM,IAAI;;;CAAqD,CAAA;AAE/D,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAA"}
package/dist/bson.js ADDED
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ObjectID = exports.ObjectId = exports.EJSON = exports.BSON = void 0;
4
+ const bson_1 = require("bson");
5
+ Object.defineProperty(exports, "EJSON", { enumerable: true, get: function () { return bson_1.EJSON; } });
6
+ Object.defineProperty(exports, "ObjectId", { enumerable: true, get: function () { return bson_1.ObjectId; } });
7
+ const ObjectID = bson_1.ObjectId;
8
+ exports.ObjectID = ObjectID;
9
+ const BSON = Object.assign({}, bson_1.BSON, { ObjectId: bson_1.ObjectId, ObjectID });
10
+ exports.BSON = BSON;
@@ -0,0 +1,7 @@
1
+ import { CredentialsLike } from './types';
2
+ export declare class Credentials {
3
+ static emailPassword(email: string, password: string): CredentialsLike;
4
+ static anonymous(): CredentialsLike;
5
+ static function(payload: Record<string, unknown>): CredentialsLike;
6
+ }
7
+ //# sourceMappingURL=credentials.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAEzC,qBAAa,WAAW;IACtB,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,eAAe;IAQtE,MAAM,CAAC,SAAS,IAAI,eAAe;IAMnC,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,eAAe;CAMnE"}
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Credentials = void 0;
4
+ class Credentials {
5
+ static emailPassword(email, password) {
6
+ return {
7
+ provider: 'local-userpass',
8
+ email,
9
+ password
10
+ };
11
+ }
12
+ static anonymous() {
13
+ return {
14
+ provider: 'anon-user'
15
+ };
16
+ }
17
+ static function(payload) {
18
+ return {
19
+ provider: 'custom-function',
20
+ payload
21
+ };
22
+ }
23
+ }
24
+ exports.Credentials = Credentials;
@@ -0,0 +1,3 @@
1
+ export declare const normalizeFunctionResponse: (value: unknown) => any;
2
+ export declare const createFunctionsProxy: (callFunction: (name: string, args: unknown[]) => Promise<unknown>) => Record<string, (...args: unknown[]) => Promise<unknown>>;
3
+ //# sourceMappingURL=functions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"functions.d.ts","sourceRoot":"","sources":["../src/functions.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,yBAAyB,UAAW,OAAO,QAWvD,CAAA;AAED,eAAO,MAAM,oBAAoB,iBACjB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,QAAQ,OAAO,CAAC,KAChE,OAAO,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,QAAQ,OAAO,CAAC,CASK,CAAA"}
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createFunctionsProxy = exports.normalizeFunctionResponse = void 0;
4
+ const bson_1 = require("./bson");
5
+ const deserialize = (value) => {
6
+ if (!value || typeof value !== 'object')
7
+ return value;
8
+ return bson_1.EJSON.deserialize(value);
9
+ };
10
+ const normalizeFunctionResponse = (value) => {
11
+ if (typeof value === 'string') {
12
+ try {
13
+ const parsed = JSON.parse(value);
14
+ return deserialize(parsed);
15
+ }
16
+ catch {
17
+ return value;
18
+ }
19
+ }
20
+ return deserialize(value);
21
+ };
22
+ exports.normalizeFunctionResponse = normalizeFunctionResponse;
23
+ const createFunctionsProxy = (callFunction) => new Proxy({}, {
24
+ get: (_, key) => {
25
+ if (typeof key !== 'string')
26
+ return undefined;
27
+ return (...args) => callFunction(key, args);
28
+ }
29
+ });
30
+ exports.createFunctionsProxy = createFunctionsProxy;
package/dist/http.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ export declare class FlowerbaseHttpError extends Error {
2
+ status: number;
3
+ payload?: unknown;
4
+ constructor(message: string, status: number, payload?: unknown);
5
+ }
6
+ type RequestParams = {
7
+ url: string;
8
+ method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
9
+ body?: unknown;
10
+ bearerToken?: string;
11
+ timeout?: number;
12
+ };
13
+ export declare const requestJson: <T = unknown>({ url, method, body, bearerToken, timeout }: RequestParams) => Promise<T>;
14
+ export {};
15
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,OAAO,CAAA;gBAEL,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO;CAM/D;AAED,KAAK,aAAa,GAAG;IACnB,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAA;IACpD,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAsBD,eAAO,MAAM,WAAW,6DAMrB,aAAa,KAAG,QAAQ,CAAC,CA6C3B,CAAA"}
package/dist/http.js ADDED
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.requestJson = exports.FlowerbaseHttpError = void 0;
4
+ class FlowerbaseHttpError extends Error {
5
+ constructor(message, status, payload) {
6
+ super(message);
7
+ this.name = 'FlowerbaseHttpError';
8
+ this.status = status;
9
+ this.payload = payload;
10
+ }
11
+ }
12
+ exports.FlowerbaseHttpError = FlowerbaseHttpError;
13
+ const parseBody = async (response) => {
14
+ const text = await response.text();
15
+ if (!text)
16
+ return null;
17
+ try {
18
+ return JSON.parse(text);
19
+ }
20
+ catch {
21
+ return text;
22
+ }
23
+ };
24
+ const timeoutSignal = (timeout = 10000) => {
25
+ const controller = new AbortController();
26
+ const timer = setTimeout(() => controller.abort(), timeout);
27
+ return {
28
+ signal: controller.signal,
29
+ clear: () => clearTimeout(timer)
30
+ };
31
+ };
32
+ const requestJson = async ({ url, method = 'GET', body, bearerToken, timeout }) => {
33
+ const { signal, clear } = timeoutSignal(timeout);
34
+ try {
35
+ const response = await fetch(url, {
36
+ method,
37
+ headers: {
38
+ ...(body !== undefined ? { 'Content-Type': 'application/json' } : {}),
39
+ ...(bearerToken ? { Authorization: `Bearer ${bearerToken}` } : {})
40
+ },
41
+ body: body !== undefined ? JSON.stringify(body) : undefined,
42
+ signal
43
+ });
44
+ const payload = await parseBody(response);
45
+ if (!response.ok) {
46
+ let parsedErrorMessage = null;
47
+ if (payload && typeof payload === 'object' && 'error' in payload && typeof payload.error === 'string') {
48
+ try {
49
+ const parsed = JSON.parse(payload.error);
50
+ if (parsed && typeof parsed === 'object' && 'message' in parsed && typeof parsed.message === 'string') {
51
+ parsedErrorMessage = parsed.message;
52
+ }
53
+ }
54
+ catch {
55
+ parsedErrorMessage = null;
56
+ }
57
+ }
58
+ const message = parsedErrorMessage ||
59
+ (payload && typeof payload === 'object' && 'message' in payload && typeof payload.message === 'string'
60
+ ? payload.message
61
+ : null) ||
62
+ (payload && typeof payload === 'object' && 'error' in payload && typeof payload.error === 'string'
63
+ ? payload.error
64
+ : null) ||
65
+ `HTTP ${response.status}`;
66
+ throw new FlowerbaseHttpError(message, response.status, payload);
67
+ }
68
+ return payload;
69
+ }
70
+ finally {
71
+ clear();
72
+ }
73
+ };
74
+ exports.requestJson = requestJson;
@@ -0,0 +1,7 @@
1
+ import { BSON, EJSON, ObjectId, ObjectID } from './bson';
2
+ export { App } from './app';
3
+ export { User } from './user';
4
+ export { Credentials } from './credentials';
5
+ export { BSON, EJSON, ObjectId, ObjectID };
6
+ export type { AppConfig, CredentialsLike, UserLike, MongoClientLike, CollectionLike, WatchAsyncIterator } from './types';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAExD,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAC3B,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAA;AAC1C,YAAY,EACV,SAAS,EACT,eAAe,EACf,QAAQ,EACR,eAAe,EACf,cAAc,EACd,kBAAkB,EACnB,MAAM,SAAS,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ObjectID = exports.ObjectId = exports.EJSON = exports.BSON = exports.Credentials = exports.User = exports.App = void 0;
4
+ const bson_1 = require("./bson");
5
+ Object.defineProperty(exports, "BSON", { enumerable: true, get: function () { return bson_1.BSON; } });
6
+ Object.defineProperty(exports, "EJSON", { enumerable: true, get: function () { return bson_1.EJSON; } });
7
+ Object.defineProperty(exports, "ObjectId", { enumerable: true, get: function () { return bson_1.ObjectId; } });
8
+ Object.defineProperty(exports, "ObjectID", { enumerable: true, get: function () { return bson_1.ObjectID; } });
9
+ var app_1 = require("./app");
10
+ Object.defineProperty(exports, "App", { enumerable: true, get: function () { return app_1.App; } });
11
+ var user_1 = require("./user");
12
+ Object.defineProperty(exports, "User", { enumerable: true, get: function () { return user_1.User; } });
13
+ var credentials_1 = require("./credentials");
14
+ Object.defineProperty(exports, "Credentials", { enumerable: true, get: function () { return credentials_1.Credentials; } });
@@ -0,0 +1,4 @@
1
+ import type { App } from './app';
2
+ import { MongoClientLike } from './types';
3
+ export declare const createMongoClient: (app: App) => MongoClientLike;
4
+ //# sourceMappingURL=mongo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mongo.d.ts","sourceRoot":"","sources":["../src/mongo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAA;AAEhC,OAAO,EAAkB,eAAe,EAAE,MAAM,SAAS,CAAA;AAoBzD,eAAO,MAAM,iBAAiB,QAAS,GAAG,KAAG,eAwC3C,CAAA"}