@objectstack/client 4.0.3 → 4.0.4
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/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +8 -0
- package/dist/index.d.mts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +23 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +23 -14
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -9
- package/src/client.hono.test.ts +11 -3
- package/src/index.ts +36 -22
- package/tests/integration/01-discovery.test.ts +5 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@objectstack/client",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.4",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "Official Client SDK for ObjectStack Protocol",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -13,20 +13,20 @@
|
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@objectstack/core": "4.0.
|
|
17
|
-
"@objectstack/spec": "4.0.
|
|
16
|
+
"@objectstack/core": "4.0.4",
|
|
17
|
+
"@objectstack/spec": "4.0.4"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
|
20
20
|
"@hono/node-server": "^1.19.14",
|
|
21
21
|
"msw": "^2.13.2",
|
|
22
22
|
"typescript": "^6.0.2",
|
|
23
23
|
"vitest": "^4.1.4",
|
|
24
|
-
"@objectstack/driver-memory": "4.0.
|
|
25
|
-
"@objectstack/hono": "4.0.
|
|
26
|
-
"@objectstack/objectql": "4.0.
|
|
27
|
-
"@objectstack/plugin-hono-server": "4.0.
|
|
28
|
-
"@objectstack/plugin-msw": "4.0.
|
|
29
|
-
"@objectstack/runtime": "4.0.
|
|
24
|
+
"@objectstack/driver-memory": "4.0.4",
|
|
25
|
+
"@objectstack/hono": "4.0.4",
|
|
26
|
+
"@objectstack/objectql": "4.0.4",
|
|
27
|
+
"@objectstack/plugin-hono-server": "4.0.4",
|
|
28
|
+
"@objectstack/plugin-msw": "4.0.4",
|
|
29
|
+
"@objectstack/runtime": "4.0.4"
|
|
30
30
|
},
|
|
31
31
|
"scripts": {
|
|
32
32
|
"build": "tsup --config ../../tsup.config.ts",
|
package/src/client.hono.test.ts
CHANGED
|
@@ -107,11 +107,19 @@ describe('ObjectStackClient (with Hono Server)', () => {
|
|
|
107
107
|
baseUrl = `http://localhost:${port}`;
|
|
108
108
|
|
|
109
109
|
console.log(`Test server running at ${baseUrl}`);
|
|
110
|
-
});
|
|
110
|
+
}, 30_000);
|
|
111
111
|
|
|
112
112
|
afterAll(async () => {
|
|
113
|
-
if (kernel)
|
|
114
|
-
|
|
113
|
+
if (kernel) {
|
|
114
|
+
// Race shutdown against a hard deadline.
|
|
115
|
+
// kernel.shutdown() can hang when pino's flush callback never fires
|
|
116
|
+
// in CI (worker-thread transport timing issues), so cap the wait.
|
|
117
|
+
await Promise.race([
|
|
118
|
+
kernel.shutdown(),
|
|
119
|
+
new Promise<void>((resolve) => setTimeout(resolve, 10_000)),
|
|
120
|
+
]);
|
|
121
|
+
}
|
|
122
|
+
}, 30_000);
|
|
115
123
|
|
|
116
124
|
it('should connect to hono server and discover endpoints', async () => {
|
|
117
125
|
const client = new ObjectStackClient({ baseUrl });
|
package/src/index.ts
CHANGED
|
@@ -253,12 +253,26 @@ export class ObjectStackClient {
|
|
|
253
253
|
*/
|
|
254
254
|
async connect() {
|
|
255
255
|
this.logger.debug('Connecting to ObjectStack server', { baseUrl: this.baseUrl });
|
|
256
|
-
|
|
256
|
+
|
|
257
257
|
try {
|
|
258
258
|
let data: DiscoveryResult | undefined;
|
|
259
259
|
|
|
260
|
-
// 1. Try
|
|
260
|
+
// 1. Try Protocol-standard Discovery Path /api/v1/discovery (primary)
|
|
261
261
|
try {
|
|
262
|
+
const discoveryUrl = `${this.baseUrl}/api/v1/discovery`;
|
|
263
|
+
this.logger.debug('Probing protocol-standard discovery endpoint', { url: discoveryUrl });
|
|
264
|
+
const res = await this.fetchImpl(discoveryUrl);
|
|
265
|
+
if (res.ok) {
|
|
266
|
+
const body = await res.json();
|
|
267
|
+
data = body.data || body;
|
|
268
|
+
this.logger.debug('Discovered via /api/v1/discovery');
|
|
269
|
+
}
|
|
270
|
+
} catch (e) {
|
|
271
|
+
this.logger.debug('Protocol-standard discovery probe failed', { error: (e as Error).message });
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// 2. Fallback to Standard Discovery (.well-known)
|
|
275
|
+
if (!data) {
|
|
262
276
|
let wellKnownUrl: string;
|
|
263
277
|
try {
|
|
264
278
|
// If baseUrl is absolute, get origin
|
|
@@ -269,24 +283,10 @@ export class ObjectStackClient {
|
|
|
269
283
|
wellKnownUrl = '/.well-known/objectstack';
|
|
270
284
|
}
|
|
271
285
|
|
|
272
|
-
this.logger.debug('
|
|
286
|
+
this.logger.debug('Falling back to .well-known discovery', { url: wellKnownUrl });
|
|
273
287
|
const res = await this.fetchImpl(wellKnownUrl);
|
|
274
|
-
if (res.ok) {
|
|
275
|
-
const body = await res.json();
|
|
276
|
-
data = body.data || body;
|
|
277
|
-
this.logger.debug('Discovered via .well-known');
|
|
278
|
-
}
|
|
279
|
-
} catch (e) {
|
|
280
|
-
this.logger.debug('Standard discovery probe failed', { error: (e as Error).message });
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
// 2. Fallback to Protocol-standard Discovery Path /api/v1/discovery
|
|
284
|
-
if (!data) {
|
|
285
|
-
const fallbackUrl = `${this.baseUrl}/api/v1/discovery`;
|
|
286
|
-
this.logger.debug('Falling back to standard discovery endpoint', { url: fallbackUrl });
|
|
287
|
-
const res = await this.fetchImpl(fallbackUrl);
|
|
288
288
|
if (!res.ok) {
|
|
289
|
-
throw new Error(`Failed to connect to ${
|
|
289
|
+
throw new Error(`Failed to connect to ${wellKnownUrl}: ${res.statusText}`);
|
|
290
290
|
}
|
|
291
291
|
const body = await res.json();
|
|
292
292
|
data = body.data || body;
|
|
@@ -297,13 +297,13 @@ export class ObjectStackClient {
|
|
|
297
297
|
}
|
|
298
298
|
|
|
299
299
|
this.discoveryInfo = data;
|
|
300
|
-
|
|
301
|
-
this.logger.info('Connected to ObjectStack server', {
|
|
300
|
+
|
|
301
|
+
this.logger.info('Connected to ObjectStack server', {
|
|
302
302
|
version: data.version,
|
|
303
303
|
apiName: data.apiName,
|
|
304
|
-
services: data.services
|
|
304
|
+
services: data.services
|
|
305
305
|
});
|
|
306
|
-
|
|
306
|
+
|
|
307
307
|
return data as DiscoveryResult;
|
|
308
308
|
} catch (e) {
|
|
309
309
|
this.logger.error('Failed to connect to ObjectStack server', e as Error, { baseUrl: this.baseUrl });
|
|
@@ -578,6 +578,16 @@ export class ObjectStackClient {
|
|
|
578
578
|
* Authentication Services
|
|
579
579
|
*/
|
|
580
580
|
auth = {
|
|
581
|
+
/**
|
|
582
|
+
* Get authentication configuration
|
|
583
|
+
* Returns available auth providers and features
|
|
584
|
+
*/
|
|
585
|
+
getConfig: async () => {
|
|
586
|
+
const route = this.getRoute('auth');
|
|
587
|
+
const res = await this.fetch(`${this.baseUrl}${route}/config`);
|
|
588
|
+
return this.unwrapResponse(res);
|
|
589
|
+
},
|
|
590
|
+
|
|
581
591
|
/**
|
|
582
592
|
* Login with email and password
|
|
583
593
|
* Uses better-auth endpoint: POST /sign-in/email
|
|
@@ -1872,4 +1882,8 @@ export type {
|
|
|
1872
1882
|
SubscribeResponse,
|
|
1873
1883
|
UnsubscribeResponse,
|
|
1874
1884
|
WellKnownCapabilities,
|
|
1885
|
+
GetAuthConfigResponse,
|
|
1886
|
+
AuthProviderInfo,
|
|
1887
|
+
EmailPasswordConfigPublic,
|
|
1888
|
+
AuthFeaturesConfig,
|
|
1875
1889
|
} from '@objectstack/spec/api';
|
|
@@ -13,15 +13,15 @@ import { ObjectStackClient } from '../../src/index';
|
|
|
13
13
|
const TEST_SERVER_URL = process.env.TEST_SERVER_URL || 'http://localhost:3000';
|
|
14
14
|
|
|
15
15
|
describe('Discovery & Connection', () => {
|
|
16
|
-
describe('TC-DISC-001:
|
|
17
|
-
test('should discover API from
|
|
18
|
-
const client = new ObjectStackClient({
|
|
16
|
+
describe('TC-DISC-001: Protocol-standard Discovery via /api/v1/discovery', () => {
|
|
17
|
+
test('should discover API from /api/v1/discovery', async () => {
|
|
18
|
+
const client = new ObjectStackClient({
|
|
19
19
|
baseUrl: TEST_SERVER_URL,
|
|
20
20
|
debug: true
|
|
21
21
|
});
|
|
22
|
-
|
|
22
|
+
|
|
23
23
|
const discovery = await client.connect();
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
expect(discovery.version).toBeDefined();
|
|
26
26
|
expect(discovery.apiName).toBeDefined();
|
|
27
27
|
expect(discovery.routes).toBeDefined();
|