@oxyhq/contracts 0.9.0 → 0.10.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/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/deviceBoot.js +51 -8
- package/dist/cjs/index.js +3 -4
- package/dist/cjs/userResponse.js +1 -24
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/deviceBoot.js +50 -7
- package/dist/esm/index.js +2 -2
- package/dist/esm/userResponse.js +0 -23
- package/dist/types/.tsbuildinfo +1 -1
- package/dist/types/deviceBoot.d.ts +71 -16
- package/dist/types/deviceSession.d.ts +24 -24
- package/dist/types/index.d.ts +4 -4
- package/dist/types/userResponse.d.ts +4 -359
- package/package.json +1 -1
package/dist/esm/deviceBoot.js
CHANGED
|
@@ -48,17 +48,36 @@ import { userResponseSchema } from './userResponse.js';
|
|
|
48
48
|
export const deviceBootReasonSchema = z.enum(['session', 'no_session', 'new_device']);
|
|
49
49
|
/**
|
|
50
50
|
* The `#oxy_boot=<json>` fragment `GET /auth/device/bootstrap` appends to the
|
|
51
|
-
* `return_to` URL. Carries the CSRF `state` echo, the resolution `reason`,
|
|
52
|
-
*
|
|
53
|
-
*
|
|
51
|
+
* `return_to` URL. Carries the CSRF `state` echo, the resolution `reason`, the
|
|
52
|
+
* opaque `deviceToken`, and — ONLY on the `session` arm — the single-use
|
|
53
|
+
* exchange `code`. NEVER carries tokens or a deviceId.
|
|
54
|
+
*
|
|
55
|
+
* Discriminated on `reason` so the code↔reason coupling is enforced by the
|
|
56
|
+
* schema, not by the consumer: the `session` arm REQUIRES `code`, and the
|
|
57
|
+
* `no_session` / `new_device` arms omit it (a stray `code` on those arms is
|
|
58
|
+
* stripped). A `session` fragment WITHOUT a code therefore fails to parse and
|
|
59
|
+
* is treated as "no usable fragment" rather than half-processed.
|
|
54
60
|
*/
|
|
55
|
-
|
|
61
|
+
const deviceBootFragmentBase = {
|
|
56
62
|
v: z.literal(1),
|
|
57
63
|
state: z.string().min(1).max(256),
|
|
58
|
-
reason: deviceBootReasonSchema,
|
|
59
|
-
code: z.string().min(20).max(128).optional(),
|
|
60
64
|
deviceToken: z.string().min(20).max(512),
|
|
61
|
-
}
|
|
65
|
+
};
|
|
66
|
+
export const deviceBootFragmentSchema = z.discriminatedUnion('reason', [
|
|
67
|
+
z.object({
|
|
68
|
+
...deviceBootFragmentBase,
|
|
69
|
+
reason: z.literal('session'),
|
|
70
|
+
code: z.string().min(20).max(128),
|
|
71
|
+
}),
|
|
72
|
+
z.object({
|
|
73
|
+
...deviceBootFragmentBase,
|
|
74
|
+
reason: z.literal('no_session'),
|
|
75
|
+
}),
|
|
76
|
+
z.object({
|
|
77
|
+
...deviceBootFragmentBase,
|
|
78
|
+
reason: z.literal('new_device'),
|
|
79
|
+
}),
|
|
80
|
+
]);
|
|
62
81
|
/* -------------------------------------------------------------------------- */
|
|
63
82
|
/* Boot-code exchange */
|
|
64
83
|
/* -------------------------------------------------------------------------- */
|
|
@@ -73,6 +92,30 @@ export const authTokenBundleSchema = z.object({
|
|
|
73
92
|
expiresAt: z.string(),
|
|
74
93
|
user: userResponseSchema,
|
|
75
94
|
});
|
|
95
|
+
// Internal (unexported) arm schemas — PLAIN `z.object` literals (no
|
|
96
|
+
// `z.ZodType<>` annotation) so `z.discriminatedUnion` can introspect the
|
|
97
|
+
// `reason` discriminator. The node10 `.d.ts`-degradation safety comes from the
|
|
98
|
+
// EXPORTED symbols instead: the public types are explicit interfaces
|
|
99
|
+
// (`WebSessionSession` / `WebSessionNoSession` / `WebSessionResult`) and the
|
|
100
|
+
// exported schema is annotated `z.ZodType<WebSessionResult>` below, so the
|
|
101
|
+
// emitted declaration states the shape literally rather than a degradable
|
|
102
|
+
// `z.infer<>` of the nested `session` object.
|
|
103
|
+
const webSessionSessionSchema = z.object({
|
|
104
|
+
reason: z.literal('session'),
|
|
105
|
+
session: authTokenBundleSchema,
|
|
106
|
+
deviceToken: z.string().min(1),
|
|
107
|
+
});
|
|
108
|
+
const webSessionNoSessionSchema = z.object({
|
|
109
|
+
reason: z.enum(['no_session', 'new_device']),
|
|
110
|
+
deviceToken: z.string().min(1),
|
|
111
|
+
});
|
|
112
|
+
// Discriminated on `reason` — a true `discriminatedUnion` (not `z.union`): it
|
|
113
|
+
// dispatches on the discriminator instead of sequentially probing each arm,
|
|
114
|
+
// giving precise per-arm errors.
|
|
115
|
+
export const webSessionResultSchema = z.discriminatedUnion('reason', [
|
|
116
|
+
webSessionSessionSchema,
|
|
117
|
+
webSessionNoSessionSchema,
|
|
118
|
+
]);
|
|
76
119
|
/* -------------------------------------------------------------------------- */
|
|
77
120
|
/* Refresh-token rotation (web + native, one implementation) */
|
|
78
121
|
/* -------------------------------------------------------------------------- */
|
package/dist/esm/index.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
export {
|
|
13
13
|
// Schemas
|
|
14
|
-
userNameSchema, userResponseSchema, userProfileUpdateSchema,
|
|
14
|
+
userNameSchema, userResponseSchema, userProfileUpdateSchema, currentUserResponseSchema, deviceSessionAccountSchema, deviceSessionsResponseSchema,
|
|
15
15
|
// Helpers
|
|
16
16
|
resolveUserId, safeParseContract, } from './userResponse.js';
|
|
17
17
|
export {
|
|
@@ -43,4 +43,4 @@ linkPreviewSchema, linkPreviewBatchRequestSchema, linkPreviewBatchResponseSchema
|
|
|
43
43
|
export { sessionAccountSchema, deviceSessionStateSchema, activeTokenSchema, deviceSessionSyncSchema, } from './deviceSession.js';
|
|
44
44
|
export {
|
|
45
45
|
// Schemas
|
|
46
|
-
deviceBootReasonSchema, deviceBootFragmentSchema, deviceExchangeRequestSchema, authTokenBundleSchema, tokenRefreshRequestSchema, tokenRefreshResponseSchema, deviceTokenIssueResponseSchema, loginResultSchema, deviceResolveRequestSchema, deviceResolveResponseSchema, } from './deviceBoot.js';
|
|
46
|
+
deviceBootReasonSchema, deviceBootFragmentSchema, deviceExchangeRequestSchema, authTokenBundleSchema, webSessionResultSchema, tokenRefreshRequestSchema, tokenRefreshResponseSchema, deviceTokenIssueResponseSchema, loginResultSchema, deviceResolveRequestSchema, deviceResolveResponseSchema, } from './deviceBoot.js';
|
package/dist/esm/userResponse.js
CHANGED
|
@@ -106,7 +106,6 @@ export const userProfileUpdateSchema = z
|
|
|
106
106
|
phone: z.string().optional(),
|
|
107
107
|
address: z.string().optional(),
|
|
108
108
|
birthday: z.string().optional(),
|
|
109
|
-
location: z.string().optional(),
|
|
110
109
|
locations: z.array(z.unknown()).optional(),
|
|
111
110
|
links: z.array(z.string()).optional(),
|
|
112
111
|
linksMetadata: z
|
|
@@ -132,28 +131,6 @@ export const userProfileUpdateSchema = z
|
|
|
132
131
|
export function resolveUserId(user) {
|
|
133
132
|
return user.id ?? user._id;
|
|
134
133
|
}
|
|
135
|
-
/**
|
|
136
|
-
* One rotated account entry from `POST /auth/refresh-all`.
|
|
137
|
-
*
|
|
138
|
-
* `authuser` is the device-local slot index (`0..N-1`). `user` is the canonical
|
|
139
|
-
* {@link userResponseSchema} shape (the handler projects a whitelist and runs it
|
|
140
|
-
* through `formatUserResponse`).
|
|
141
|
-
*/
|
|
142
|
-
export const refreshAllAccountSchema = z.object({
|
|
143
|
-
authuser: z.number().int().nonnegative(),
|
|
144
|
-
accessToken: z.string(),
|
|
145
|
-
expiresAt: z.string(),
|
|
146
|
-
sessionId: z.string(),
|
|
147
|
-
user: userResponseSchema,
|
|
148
|
-
});
|
|
149
|
-
/**
|
|
150
|
-
* Wire shape of `POST /auth/refresh-all`: every valid device-local account,
|
|
151
|
-
* sorted by `authuser` ascending. An empty `accounts` array means "no signed-in
|
|
152
|
-
* accounts on this device" — the IdP must show the sign-in form.
|
|
153
|
-
*/
|
|
154
|
-
export const refreshAllResponseSchema = z.object({
|
|
155
|
-
accounts: z.array(refreshAllAccountSchema),
|
|
156
|
-
});
|
|
157
134
|
/**
|
|
158
135
|
* Wire shape of `GET /users/me` — the API success envelope (`{ data: <user> }`)
|
|
159
136
|
* wrapping the current-user DTO. Some older producers use `_id` instead of
|