@raisindb/client 0.4.0 → 0.4.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.
package/dist/index.mjs CHANGED
@@ -2688,6 +2688,13 @@ var Branches = class {
2688
2688
  * Each root's parent path must already exist on the target branch. With
2689
2689
  * `deleteMissing`, target nodes under the roots that are absent from the
2690
2690
  * copied source set are pruned (one-way sync).
2691
+ *
2692
+ * `sourceRevision` pins the read to a point in time. A promotion of a large
2693
+ * set is not instantaneous, so without it the copy reads each node when its
2694
+ * turn comes and a writer working in parallel lands partly inside the result
2695
+ * — a torn snapshot. Pass the revision captured when the operation was
2696
+ * decided (see `getHead`) to copy exactly that state. The target branch is
2697
+ * always resolved at its head: the pin says WHAT to copy, never where.
2691
2698
  */
2692
2699
  async copyNodes(sourceBranch, targetBranch, opts) {
2693
2700
  return this.sendRequest(
@@ -2697,7 +2704,8 @@ var Branches = class {
2697
2704
  workspace: opts.workspace,
2698
2705
  roots: opts.roots,
2699
2706
  recursive: opts.recursive ?? true,
2700
- delete_missing: opts.deleteMissing ?? false
2707
+ delete_missing: opts.deleteMissing ?? false,
2708
+ source_revision: opts.sourceRevision ?? null
2701
2709
  },
2702
2710
  "branch_copy_nodes" /* BranchCopyNodes */
2703
2711
  );
@@ -5698,6 +5706,101 @@ var McpClient = class {
5698
5706
  }
5699
5707
  };
5700
5708
 
5709
+ // src/identity-auth.ts
5710
+ var IdentityAuthApi = class {
5711
+ constructor(repository, transport) {
5712
+ this.repository = repository;
5713
+ this.transport = transport;
5714
+ }
5715
+ get base() {
5716
+ return `/auth/${encodeURIComponent(this.repository)}`;
5717
+ }
5718
+ /**
5719
+ * Ask RaisinDB to email a sign-in link.
5720
+ *
5721
+ * The reply is an acknowledgement, never a token — the token only exists in
5722
+ * the email. It also resolves for an address that has no account, because a
5723
+ * response that differed would turn this endpoint into an account-existence
5724
+ * oracle.
5725
+ */
5726
+ async sendMagicLink(email, options) {
5727
+ return this.transport({
5728
+ method: "POST",
5729
+ path: `${this.base}/magic-link`,
5730
+ body: { email, redirect_url: options?.redirectUrl },
5731
+ skipAuth: true
5732
+ });
5733
+ }
5734
+ /**
5735
+ * Exchange a magic-link token for a session.
5736
+ *
5737
+ * Most applications never call this: following the emailed link hits
5738
+ * RaisinDB directly, which verifies and 302s to the redirect URL with the
5739
+ * tokens in the URL **fragment** (so they stay out of server logs and out
5740
+ * of the Referer header) — see {@link readTokensFromFragment}. Call this
5741
+ * only when handling the token yourself, and note it is single-use.
5742
+ */
5743
+ async verifyMagicLink(token) {
5744
+ return this.transport({
5745
+ method: "GET",
5746
+ path: `${this.base}/magic-link/verify?token=${encodeURIComponent(token)}`,
5747
+ skipAuth: true
5748
+ });
5749
+ }
5750
+ /** Sign in with email and password, where the repository enables it. */
5751
+ async login(email, password, options) {
5752
+ return this.transport({
5753
+ method: "POST",
5754
+ path: `${this.base}/login`,
5755
+ body: { email, password, remember_me: options?.rememberMe ?? false },
5756
+ skipAuth: true
5757
+ });
5758
+ }
5759
+ /** Create an account with email and password. */
5760
+ async register(email, password, options) {
5761
+ return this.transport({
5762
+ method: "POST",
5763
+ path: `${this.base}/register`,
5764
+ body: { email, password, display_name: options?.displayName },
5765
+ skipAuth: true
5766
+ });
5767
+ }
5768
+ /** Trade a refresh token for a fresh pair. */
5769
+ async refresh(refreshToken) {
5770
+ return this.transport({
5771
+ method: "POST",
5772
+ path: `${this.base}/refresh`,
5773
+ body: { refresh_token: refreshToken },
5774
+ skipAuth: true
5775
+ });
5776
+ }
5777
+ /**
5778
+ * Which sign-in methods to render.
5779
+ *
5780
+ * Ask rather than hard-code: magic link and password are per-repository
5781
+ * configuration, and a button for a disabled method is a dead end.
5782
+ */
5783
+ async providers() {
5784
+ return this.transport({
5785
+ method: "GET",
5786
+ path: `${this.base}/providers`,
5787
+ skipAuth: true
5788
+ });
5789
+ }
5790
+ /** Who the current token belongs to in this repository. */
5791
+ async me() {
5792
+ return this.transport({ method: "GET", path: `${this.base}/me` });
5793
+ }
5794
+ };
5795
+ function readTokensFromFragment(hashOrUrl) {
5796
+ const hash = hashOrUrl.includes("#") ? hashOrUrl.slice(hashOrUrl.indexOf("#") + 1) : hashOrUrl;
5797
+ if (!hash) return null;
5798
+ const params = new URLSearchParams(hash);
5799
+ const accessToken = params.get("access_token");
5800
+ if (!accessToken) return null;
5801
+ return { accessToken, refreshToken: params.get("refresh_token") };
5802
+ }
5803
+
5701
5804
  // src/http-client.ts
5702
5805
  var RaisinHttpClient = class extends EventEmitter {
5703
5806
  constructor(baseUrl, options = {}) {
@@ -6096,6 +6199,65 @@ var RaisinHttpClient = class extends EventEmitter {
6096
6199
  return this.authManager;
6097
6200
  }
6098
6201
  // ============================================================================
6202
+ // Identity Authentication
6203
+ // ============================================================================
6204
+ /**
6205
+ * Identity authentication (magic link, password, providers) for one
6206
+ * repository.
6207
+ *
6208
+ * Identities are per repository — their home nodes and roles live there — so
6209
+ * the repository is required rather than inferred from client state, which
6210
+ * would silently sign somebody into whichever one happened to be current.
6211
+ *
6212
+ * ```ts
6213
+ * const auth = client.auth('studio');
6214
+ * await auth.sendMagicLink('a@example.com', {
6215
+ * redirectUrl: 'https://app.example.com/account/callback',
6216
+ * });
6217
+ * // …on the callback route:
6218
+ * const tokens = readTokensFromFragment(window.location.hash);
6219
+ * if (tokens) client.setIdentityTokens(tokens.accessToken, tokens.refreshToken);
6220
+ * ```
6221
+ */
6222
+ auth(repository) {
6223
+ return new IdentityAuthApi(repository, async (options) => {
6224
+ const response = await this.request({
6225
+ method: options.method,
6226
+ path: options.path,
6227
+ body: options.body,
6228
+ skipAuth: options.skipAuth
6229
+ });
6230
+ return response.data;
6231
+ });
6232
+ }
6233
+ /**
6234
+ * Adopt an identity's tokens for every subsequent call on this client.
6235
+ *
6236
+ * Takes the loose form so it serves both callers: the whole result of a
6237
+ * sign-in, and the pair recovered from a redirect fragment (which carries no
6238
+ * identity object and may carry no refresh token).
6239
+ */
6240
+ setIdentityTokens(accessTokenOrResult, refreshToken) {
6241
+ if (typeof accessTokenOrResult === "string") {
6242
+ this.authManager.storage.setAccessToken(accessTokenOrResult);
6243
+ if (refreshToken) this.authManager.storage.setRefreshToken(refreshToken);
6244
+ return;
6245
+ }
6246
+ const result = accessTokenOrResult;
6247
+ this.authManager.setTokens({
6248
+ access_token: result.access_token,
6249
+ refresh_token: result.refresh_token,
6250
+ // The server reports an absolute expiry; AuthManager schedules from a
6251
+ // duration. Deriving it here keeps the refresh timer honest instead of
6252
+ // leaving it unset, which reads as "never expires".
6253
+ expires_in: Math.max(0, result.expires_at - Math.floor(Date.now() / 1e3))
6254
+ });
6255
+ }
6256
+ /** Forget the current identity's tokens. */
6257
+ clearIdentityTokens() {
6258
+ this.authManager.clear();
6259
+ }
6260
+ // ============================================================================
6099
6261
  // Upload Methods
6100
6262
  // ============================================================================
6101
6263
  /**
@@ -8932,6 +9094,7 @@ export {
8932
9094
  HttpFunctionsApi,
8933
9095
  HttpNodeTypes,
8934
9096
  HttpWorkspaceClient,
9097
+ IdentityAuthApi,
8935
9098
  InboxApi,
8936
9099
  LocalStorageTokenStorage,
8937
9100
  LogLevel,
@@ -9007,6 +9170,7 @@ export {
9007
9170
  logger,
9008
9171
  normalizeHomePath,
9009
9172
  projectPlansFromMessages,
9173
+ readTokensFromFragment,
9010
9174
  rowsToObjects,
9011
9175
  setLogLevel,
9012
9176
  sleep,