@isomorph.ai/app-sdk 1.9.0 → 1.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/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { type IsomorphUserRole } from './user-role.js';
2
+ export type { IsomorphUserRole } from './user-role.js';
1
3
  export type IsomorphErrorCategory = 'AUTH_REQUIRED' | 'FORBIDDEN' | 'NOT_FOUND' | 'CONFLICT' | 'VALIDATION_FAILED' | 'RATE_LIMITED' | 'UNAVAILABLE' | 'INTERNAL';
2
4
  export declare class IsomorphError extends Error {
3
5
  readonly category: IsomorphErrorCategory;
@@ -18,6 +20,14 @@ export interface IsomorphUser {
18
20
  * enforced before your code runs.
19
21
  */
20
22
  groups: string[];
23
+ /**
24
+ * What the person may do on the company's app platform: a `'builder'`
25
+ * builds and deploys apps, a `'member'` uses them. Show builders what only
26
+ * they need (a debug panel, a "deploy" hint); never gate data on it — that
27
+ * is a row rule's job, where `current_setting('harbour.user_role', true)`
28
+ * carries the same value.
29
+ */
30
+ role: IsomorphUserRole;
21
31
  appUser?: unknown;
22
32
  }
23
33
  export interface IsomorphResult<T> {
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { validateIntegrationExecuteInput } from './integration-execute-input-rules.js';
2
2
  import { userGroups } from './user-groups.js';
3
+ import { userRole } from './user-role.js';
3
4
  export class IsomorphError extends Error {
4
5
  category;
5
6
  requestId;
@@ -417,8 +418,9 @@ export function createClient(options = {}) {
417
418
  };
418
419
  // The gateway's answer becomes an IsomorphUser in place: the same object
419
420
  // must reach every caller (the API-host refresh below relies on it).
420
- const withGroups = (user) => {
421
+ const normalizeUser = (user) => {
421
422
  user.groups = userGroups(user.groups);
423
+ user.role = userRole(user.role);
422
424
  return user;
423
425
  };
424
426
  const transport = new Transport(options, () => notifyIdentity(null));
@@ -429,7 +431,7 @@ export function createClient(options = {}) {
429
431
  refreshesStarted += 1;
430
432
  refreshInFlight = transport.json(IDENTITY_PATH)
431
433
  .then((answer) => {
432
- const user = answer === null ? null : withGroups(answer);
434
+ const user = answer === null ? null : normalizeUser(answer);
433
435
  // A user answered by the API host's context refresh was announced by
434
436
  // that refresh already (it is the same object): once is enough.
435
437
  if (user === null || user !== currentUser)
@@ -480,7 +482,7 @@ export function createClient(options = {}) {
480
482
  const user = (await response.json())?.data;
481
483
  if (typeof user?.id !== 'string')
482
484
  return false;
483
- notifyIdentity(withGroups(user), true);
485
+ notifyIdentity(normalizeUser(user), true);
484
486
  return user;
485
487
  })
486
488
  .catch(() => false)
package/dist/runtime.d.ts CHANGED
@@ -10,7 +10,7 @@ export declare const GET_RUN_ACTION = "isomorph-jobs-get";
10
10
  export declare const CANCEL_RUN_ACTION = "isomorph-jobs-cancel";
11
11
  export interface ActionContext {
12
12
  signal: AbortSignal;
13
- user: Pick<IsomorphUser, 'id' | 'email' | 'groups'>;
13
+ user: Pick<IsomorphUser, 'id' | 'email' | 'groups' | 'role'>;
14
14
  tenant: string;
15
15
  app: string;
16
16
  requestId: string;
package/dist/runtime.js CHANGED
@@ -57,6 +57,7 @@ import { join, resolve } from 'node:path';
57
57
  import { pathToFileURL } from 'node:url';
58
58
  import { createClient, IsomorphError } from './index.js';
59
59
  import { userGroupsFromHeader } from './user-groups.js';
60
+ import { userRole } from './user-role.js';
60
61
  const actionIdentity = new AsyncLocalStorage();
61
62
  const identityKey = Symbol.for('isomorph.actionIdentity');
62
63
  globalThis[identityKey] = () => actionIdentity.getStore();
@@ -515,6 +516,7 @@ export class Runtime {
515
516
  id: header(request, 'X-Harbour-Verified-User-ID'),
516
517
  email: header(request, 'X-Harbour-Verified-User-Email'),
517
518
  groups: userGroupsFromHeader(header(request, 'X-Harbour-Verified-User-Groups')),
519
+ role: userRole(header(request, 'X-Harbour-Verified-User-Role')),
518
520
  };
519
521
  const streams = header(request, 'accept').toLowerCase().includes(PROGRESS_MEDIA_TYPE);
520
522
  let steps = 0;
@@ -0,0 +1,2 @@
1
+ export type IsomorphUserRole = 'builder' | 'member';
2
+ export declare function userRole(value: unknown): IsomorphUserRole;
@@ -0,0 +1,3 @@
1
+ export function userRole(value) {
2
+ return value === 'builder' ? 'builder' : 'member';
3
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@isomorph.ai/app-sdk",
3
- "version": "1.9.0",
3
+ "version": "1.10.0",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",