assembly-kit 0.0.5 → 0.0.7

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/CLAUDE.md CHANGED
@@ -126,6 +126,7 @@ token.companyId; // string | undefined
126
126
  token.internalUserId; // string | undefined
127
127
  token.isClientUser; // boolean
128
128
  token.isInternalUser; // boolean
129
+ token.isProxying; // boolean — internal user previewing as a client (both IDs present)
129
130
 
130
131
  const client = token.ensureIsClient(); // ClientTokenPayload (throws if not client)
131
132
  const internal = token.ensureIsInternalUser(); // InternalUserTokenPayload (throws if not internal)
package/README.md CHANGED
@@ -358,8 +358,9 @@ token.tokenId; // string | undefined — present in some marketplace tokens
358
358
  token.baseUrl; // string | undefined — overrides the API base URL if set
359
359
 
360
360
  // Identity checks
361
- token.isClientUser; // true if clientId + companyId are present
361
+ token.isClientUser; // true if clientId is present
362
362
  token.isInternalUser; // true if internalUserId is present
363
+ token.isProxying; // true if BOTH are present — internal user previewing as a client via CRM
363
364
 
364
365
  // Throwing guards — return narrowed payload type or throw AssemblyUnauthorizedError
365
366
  const clientPayload = token.ensureIsClient(); // ClientTokenPayload
@@ -69,6 +69,12 @@ declare class AssemblyToken {
69
69
  get isClientUser(): boolean;
70
70
  /** `true` when the token belongs to an internal (team member) user. */
71
71
  get isInternalUser(): boolean;
72
+ /**
73
+ * `true` when an internal user is proxying as a client (CRM "preview as client"):
74
+ * both `internalUserId` and `clientId` are present. Both `isClientUser` and
75
+ * `isInternalUser` are also `true` in this case — branch on this getter first.
76
+ */
77
+ get isProxying(): boolean;
72
78
  /**
73
79
  * Assert that the token belongs to a client user and return the narrowed payload.
74
80
  * @throws {AssemblyUnauthorizedError} If the token does not represent a client user.
@@ -85,6 +85,14 @@ var AssemblyToken = class AssemblyToken {
85
85
  return this.payload.internalUserId !== void 0;
86
86
  }
87
87
  /**
88
+ * `true` when an internal user is proxying as a client (CRM "preview as client"):
89
+ * both `internalUserId` and `clientId` are present. Both `isClientUser` and
90
+ * `isInternalUser` are also `true` in this case — branch on this getter first.
91
+ */
92
+ get isProxying() {
93
+ return this.payload.internalUserId !== void 0 && this.payload.clientId !== void 0;
94
+ }
95
+ /**
88
96
  * Assert that the token belongs to a client user and return the narrowed payload.
89
97
  * @throws {AssemblyUnauthorizedError} If the token does not represent a client user.
90
98
  */
@@ -1 +1 @@
1
- {"version":3,"file":"assembly-token.mjs","names":["#store"],"sources":["../../src/token/assembly-token.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport { AssemblyInvalidTokenError } from \"src/errors/invalid-token\";\nimport { AssemblyNoTokenError } from \"src/errors/no-token\";\nimport { AssemblyUnauthorizedError } from \"src/errors/unauthorized\";\nimport type { TokenPayload } from \"src/schemas/shared/token\";\n\nimport { decrypt, validatePayload } from \"./parse\";\n\n/** A token payload that identifies a client (portal) user. */\nexport interface ClientTokenPayload extends TokenPayload {\n clientId: string;\n companyId?: string;\n}\n\n/** A token payload that identifies an internal (team member) user. */\nexport interface InternalUserTokenPayload extends TokenPayload {\n internalUserId: string;\n}\n\n/**\n * Decrypts and validates an Assembly token, exposing the payload with\n * convenience getters for identity checks and compound key building.\n *\n * Use `AssemblyToken.run()` to store a request-scoped instance via\n * `AsyncLocalStorage`, then retrieve it anywhere with `AssemblyToken.current()`.\n * This is safe for Vercel fluid compute — no shared state across requests.\n *\n * @example\n * ```ts\n * // Request-scoped (recommended for serverless)\n * const t = AssemblyToken.new({ token: encryptedHex, apiKey });\n * const same = AssemblyToken.new({ token: encryptedHex, apiKey }); // returns the same instance\n *\n * // Direct instantiation (always creates a new instance)\n * const token = new AssemblyToken({ token: encryptedHex, apiKey });\n * ```\n *\n * @throws {AssemblyNoTokenError} If `token` is nullish or empty.\n * @throws {AssemblyInvalidTokenError} If decryption, JSON parsing, or schema validation fails.\n */\nexport class AssemblyToken {\n static readonly #store: AsyncLocalStorage<AssemblyToken> = new AsyncLocalStorage<AssemblyToken>();\n\n readonly currentToken: string;\n readonly payload: TokenPayload;\n\n constructor({ token, apiKey }: { token: unknown; apiKey: string }) {\n if (token === undefined || token === null || token === \"\") {\n throw new AssemblyNoTokenError();\n }\n\n if (typeof token !== \"string\") {\n throw new AssemblyInvalidTokenError({\n message: `Expected token to be a string, got ${typeof token}`,\n });\n }\n\n this.currentToken = token;\n this.payload = validatePayload(decrypt({ apiKey, token }));\n }\n\n /**\n * Get or create a request-scoped `AssemblyToken` instance via `AsyncLocalStorage`.\n * Returns the existing instance if one exists with the same token. If the token\n * differs, a new instance is created and replaces the previous one.\n *\n * @returns The `AssemblyToken` instance for the current async context.\n */\n static new(options: { token: unknown; apiKey: string }): AssemblyToken {\n const existing = AssemblyToken.#store.getStore();\n if (existing && existing.currentToken === options.token) {\n return existing;\n }\n const instance = new AssemblyToken(options);\n AssemblyToken.#store.enterWith(instance);\n return instance;\n }\n\n /** The workspace ID embedded in the token. Always present. */\n get workspaceId(): string {\n return this.payload.workspaceId;\n }\n\n /** The token ID, if present (used in marketplace compound keys). */\n get tokenId(): string | undefined {\n return this.payload.tokenId;\n }\n\n /** The API base URL override, if present. */\n get baseUrl(): string | undefined {\n return this.payload.baseUrl;\n }\n\n /** The client (portal user) ID, if present. */\n get clientId(): string | undefined {\n return this.payload.clientId;\n }\n\n /** The company ID associated with the client, if present. */\n get companyId(): string | undefined {\n return this.payload.companyId;\n }\n\n /** The internal (team member) user ID, if present. */\n get internalUserId(): string | undefined {\n return this.payload.internalUserId;\n }\n\n /** `true` when the token belongs to a client (portal) user. */\n get isClientUser(): boolean {\n return this.payload.clientId !== undefined;\n }\n\n /** `true` when the token belongs to an internal (team member) user. */\n get isInternalUser(): boolean {\n return this.payload.internalUserId !== undefined;\n }\n\n /**\n * Assert that the token belongs to a client user and return the narrowed payload.\n * @throws {AssemblyUnauthorizedError} If the token does not represent a client user.\n */\n ensureIsClient(): ClientTokenPayload {\n if (!this.isClientUser) {\n throw new AssemblyUnauthorizedError({\n message:\n \"This operation requires a client token (clientId), but the token does not contain a clientId\",\n });\n }\n return this.payload as ClientTokenPayload;\n }\n\n /**\n * Assert that the token belongs to an internal (team member) user and return the narrowed payload.\n * @throws {AssemblyUnauthorizedError} If the token does not represent an internal user.\n */\n ensureIsInternalUser(): InternalUserTokenPayload {\n if (!this.isInternalUser) {\n throw new AssemblyUnauthorizedError({\n message:\n \"This operation requires an internal user token (internalUserId), but the token does not contain an internalUserId\",\n });\n }\n return this.payload as InternalUserTokenPayload;\n }\n\n /**\n * Build the compound API key sent in the `X-API-Key` header.\n *\n * - With `tokenId`: `{workspaceId}/{apiKey}/{tokenId}`\n * - Without `tokenId`: `{workspaceId}/{apiKey}`\n */\n buildCompoundKey({ apiKey }: { apiKey: string }): string {\n if (this.payload.tokenId) {\n return `${this.payload.workspaceId}/${apiKey}/${this.payload.tokenId}`;\n }\n return `${this.payload.workspaceId}/${apiKey}`;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAyCA,IAAa,gBAAb,MAAa,cAAc;CACzB,QAAA,QAA2D,IAAI,mBAAkC;CAEjG;CACA;CAEA,YAAY,EAAE,OAAO,UAA8C;AACjE,MAAI,UAAU,KAAA,KAAa,UAAU,QAAQ,UAAU,GACrD,OAAM,IAAI,sBAAsB;AAGlC,MAAI,OAAO,UAAU,SACnB,OAAM,IAAI,0BAA0B,EAClC,SAAS,sCAAsC,OAAO,SACvD,CAAC;AAGJ,OAAK,eAAe;AACpB,OAAK,UAAU,gBAAgB,QAAQ;GAAE;GAAQ;GAAO,CAAC,CAAC;;;;;;;;;CAU5D,OAAO,IAAI,SAA4D;EACrE,MAAM,WAAW,eAAA,MAAqB,UAAU;AAChD,MAAI,YAAY,SAAS,iBAAiB,QAAQ,MAChD,QAAO;EAET,MAAM,WAAW,IAAI,cAAc,QAAQ;AAC3C,iBAAA,MAAqB,UAAU,SAAS;AACxC,SAAO;;;CAIT,IAAI,cAAsB;AACxB,SAAO,KAAK,QAAQ;;;CAItB,IAAI,UAA8B;AAChC,SAAO,KAAK,QAAQ;;;CAItB,IAAI,UAA8B;AAChC,SAAO,KAAK,QAAQ;;;CAItB,IAAI,WAA+B;AACjC,SAAO,KAAK,QAAQ;;;CAItB,IAAI,YAAgC;AAClC,SAAO,KAAK,QAAQ;;;CAItB,IAAI,iBAAqC;AACvC,SAAO,KAAK,QAAQ;;;CAItB,IAAI,eAAwB;AAC1B,SAAO,KAAK,QAAQ,aAAa,KAAA;;;CAInC,IAAI,iBAA0B;AAC5B,SAAO,KAAK,QAAQ,mBAAmB,KAAA;;;;;;CAOzC,iBAAqC;AACnC,MAAI,CAAC,KAAK,aACR,OAAM,IAAI,0BAA0B,EAClC,SACE,gGACH,CAAC;AAEJ,SAAO,KAAK;;;;;;CAOd,uBAAiD;AAC/C,MAAI,CAAC,KAAK,eACR,OAAM,IAAI,0BAA0B,EAClC,SACE,qHACH,CAAC;AAEJ,SAAO,KAAK;;;;;;;;CASd,iBAAiB,EAAE,UAAsC;AACvD,MAAI,KAAK,QAAQ,QACf,QAAO,GAAG,KAAK,QAAQ,YAAY,GAAG,OAAO,GAAG,KAAK,QAAQ;AAE/D,SAAO,GAAG,KAAK,QAAQ,YAAY,GAAG"}
1
+ {"version":3,"file":"assembly-token.mjs","names":["#store"],"sources":["../../src/token/assembly-token.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\n\nimport { AssemblyInvalidTokenError } from \"src/errors/invalid-token\";\nimport { AssemblyNoTokenError } from \"src/errors/no-token\";\nimport { AssemblyUnauthorizedError } from \"src/errors/unauthorized\";\nimport type { TokenPayload } from \"src/schemas/shared/token\";\n\nimport { decrypt, validatePayload } from \"./parse\";\n\n/** A token payload that identifies a client (portal) user. */\nexport interface ClientTokenPayload extends TokenPayload {\n clientId: string;\n companyId?: string;\n}\n\n/** A token payload that identifies an internal (team member) user. */\nexport interface InternalUserTokenPayload extends TokenPayload {\n internalUserId: string;\n}\n\n/**\n * Decrypts and validates an Assembly token, exposing the payload with\n * convenience getters for identity checks and compound key building.\n *\n * Use `AssemblyToken.run()` to store a request-scoped instance via\n * `AsyncLocalStorage`, then retrieve it anywhere with `AssemblyToken.current()`.\n * This is safe for Vercel fluid compute — no shared state across requests.\n *\n * @example\n * ```ts\n * // Request-scoped (recommended for serverless)\n * const t = AssemblyToken.new({ token: encryptedHex, apiKey });\n * const same = AssemblyToken.new({ token: encryptedHex, apiKey }); // returns the same instance\n *\n * // Direct instantiation (always creates a new instance)\n * const token = new AssemblyToken({ token: encryptedHex, apiKey });\n * ```\n *\n * @throws {AssemblyNoTokenError} If `token` is nullish or empty.\n * @throws {AssemblyInvalidTokenError} If decryption, JSON parsing, or schema validation fails.\n */\nexport class AssemblyToken {\n static readonly #store: AsyncLocalStorage<AssemblyToken> = new AsyncLocalStorage<AssemblyToken>();\n\n readonly currentToken: string;\n readonly payload: TokenPayload;\n\n constructor({ token, apiKey }: { token: unknown; apiKey: string }) {\n if (token === undefined || token === null || token === \"\") {\n throw new AssemblyNoTokenError();\n }\n\n if (typeof token !== \"string\") {\n throw new AssemblyInvalidTokenError({\n message: `Expected token to be a string, got ${typeof token}`,\n });\n }\n\n this.currentToken = token;\n this.payload = validatePayload(decrypt({ apiKey, token }));\n }\n\n /**\n * Get or create a request-scoped `AssemblyToken` instance via `AsyncLocalStorage`.\n * Returns the existing instance if one exists with the same token. If the token\n * differs, a new instance is created and replaces the previous one.\n *\n * @returns The `AssemblyToken` instance for the current async context.\n */\n static new(options: { token: unknown; apiKey: string }): AssemblyToken {\n const existing = AssemblyToken.#store.getStore();\n if (existing && existing.currentToken === options.token) {\n return existing;\n }\n const instance = new AssemblyToken(options);\n AssemblyToken.#store.enterWith(instance);\n return instance;\n }\n\n /** The workspace ID embedded in the token. Always present. */\n get workspaceId(): string {\n return this.payload.workspaceId;\n }\n\n /** The token ID, if present (used in marketplace compound keys). */\n get tokenId(): string | undefined {\n return this.payload.tokenId;\n }\n\n /** The API base URL override, if present. */\n get baseUrl(): string | undefined {\n return this.payload.baseUrl;\n }\n\n /** The client (portal user) ID, if present. */\n get clientId(): string | undefined {\n return this.payload.clientId;\n }\n\n /** The company ID associated with the client, if present. */\n get companyId(): string | undefined {\n return this.payload.companyId;\n }\n\n /** The internal (team member) user ID, if present. */\n get internalUserId(): string | undefined {\n return this.payload.internalUserId;\n }\n\n /** `true` when the token belongs to a client (portal) user. */\n get isClientUser(): boolean {\n return this.payload.clientId !== undefined;\n }\n\n /** `true` when the token belongs to an internal (team member) user. */\n get isInternalUser(): boolean {\n return this.payload.internalUserId !== undefined;\n }\n\n /**\n * `true` when an internal user is proxying as a client (CRM \"preview as client\"):\n * both `internalUserId` and `clientId` are present. Both `isClientUser` and\n * `isInternalUser` are also `true` in this case — branch on this getter first.\n */\n get isProxying(): boolean {\n return this.payload.internalUserId !== undefined && this.payload.clientId !== undefined;\n }\n\n /**\n * Assert that the token belongs to a client user and return the narrowed payload.\n * @throws {AssemblyUnauthorizedError} If the token does not represent a client user.\n */\n ensureIsClient(): ClientTokenPayload {\n if (!this.isClientUser) {\n throw new AssemblyUnauthorizedError({\n message:\n \"This operation requires a client token (clientId), but the token does not contain a clientId\",\n });\n }\n return this.payload as ClientTokenPayload;\n }\n\n /**\n * Assert that the token belongs to an internal (team member) user and return the narrowed payload.\n * @throws {AssemblyUnauthorizedError} If the token does not represent an internal user.\n */\n ensureIsInternalUser(): InternalUserTokenPayload {\n if (!this.isInternalUser) {\n throw new AssemblyUnauthorizedError({\n message:\n \"This operation requires an internal user token (internalUserId), but the token does not contain an internalUserId\",\n });\n }\n return this.payload as InternalUserTokenPayload;\n }\n\n /**\n * Build the compound API key sent in the `X-API-Key` header.\n *\n * - With `tokenId`: `{workspaceId}/{apiKey}/{tokenId}`\n * - Without `tokenId`: `{workspaceId}/{apiKey}`\n */\n buildCompoundKey({ apiKey }: { apiKey: string }): string {\n if (this.payload.tokenId) {\n return `${this.payload.workspaceId}/${apiKey}/${this.payload.tokenId}`;\n }\n return `${this.payload.workspaceId}/${apiKey}`;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAyCA,IAAa,gBAAb,MAAa,cAAc;CACzB,QAAA,QAA2D,IAAI,mBAAkC;CAEjG;CACA;CAEA,YAAY,EAAE,OAAO,UAA8C;AACjE,MAAI,UAAU,KAAA,KAAa,UAAU,QAAQ,UAAU,GACrD,OAAM,IAAI,sBAAsB;AAGlC,MAAI,OAAO,UAAU,SACnB,OAAM,IAAI,0BAA0B,EAClC,SAAS,sCAAsC,OAAO,SACvD,CAAC;AAGJ,OAAK,eAAe;AACpB,OAAK,UAAU,gBAAgB,QAAQ;GAAE;GAAQ;GAAO,CAAC,CAAC;;;;;;;;;CAU5D,OAAO,IAAI,SAA4D;EACrE,MAAM,WAAW,eAAA,MAAqB,UAAU;AAChD,MAAI,YAAY,SAAS,iBAAiB,QAAQ,MAChD,QAAO;EAET,MAAM,WAAW,IAAI,cAAc,QAAQ;AAC3C,iBAAA,MAAqB,UAAU,SAAS;AACxC,SAAO;;;CAIT,IAAI,cAAsB;AACxB,SAAO,KAAK,QAAQ;;;CAItB,IAAI,UAA8B;AAChC,SAAO,KAAK,QAAQ;;;CAItB,IAAI,UAA8B;AAChC,SAAO,KAAK,QAAQ;;;CAItB,IAAI,WAA+B;AACjC,SAAO,KAAK,QAAQ;;;CAItB,IAAI,YAAgC;AAClC,SAAO,KAAK,QAAQ;;;CAItB,IAAI,iBAAqC;AACvC,SAAO,KAAK,QAAQ;;;CAItB,IAAI,eAAwB;AAC1B,SAAO,KAAK,QAAQ,aAAa,KAAA;;;CAInC,IAAI,iBAA0B;AAC5B,SAAO,KAAK,QAAQ,mBAAmB,KAAA;;;;;;;CAQzC,IAAI,aAAsB;AACxB,SAAO,KAAK,QAAQ,mBAAmB,KAAA,KAAa,KAAK,QAAQ,aAAa,KAAA;;;;;;CAOhF,iBAAqC;AACnC,MAAI,CAAC,KAAK,aACR,OAAM,IAAI,0BAA0B,EAClC,SACE,gGACH,CAAC;AAEJ,SAAO,KAAK;;;;;;CAOd,uBAAiD;AAC/C,MAAI,CAAC,KAAK,eACR,OAAM,IAAI,0BAA0B,EAClC,SACE,qHACH,CAAC;AAEJ,SAAO,KAAK;;;;;;;;CASd,iBAAiB,EAAE,UAAsC;AACvD,MAAI,KAAK,QAAQ,QACf,QAAO,GAAG,KAAK,QAAQ,YAAY,GAAG,OAAO,GAAG,KAAK,QAAQ;AAE/D,SAAO,GAAG,KAAK,QAAQ,YAAY,GAAG"}
package/dist/version.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  //#region src/version.ts
2
2
  /** SDK version string sent with every API request. */
3
- const SDK_VERSION = "2.0.8";
3
+ const SDK_VERSION = "0.0.7";
4
4
  //#endregion
5
5
  export { SDK_VERSION };
6
6
 
@@ -1 +1 @@
1
- {"version":3,"file":"version.mjs","names":[],"sources":["../src/version.ts"],"sourcesContent":["/** SDK version string sent with every API request. */\nexport const SDK_VERSION: string = \"2.0.8\";\n"],"mappings":";;AACA,MAAa,cAAsB"}
1
+ {"version":3,"file":"version.mjs","names":[],"sources":["../src/version.ts"],"sourcesContent":["/** SDK version string sent with every API request. */\nexport const SDK_VERSION: string = \"0.0.7\"; // x-release-please-version\n"],"mappings":";;AACA,MAAa,cAAsB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "assembly-kit",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "description": "TypeScript SDK for the Assembly platform",
5
5
  "homepage": "https://github.com/madebyoutside/assembly-kit#readme",
6
6
  "bugs": {
@@ -34,7 +34,6 @@
34
34
  "dev": "vp pack --watch",
35
35
  "test": "vp test",
36
36
  "check": "vp check",
37
- "release": "bumpp --commit --push --tag",
38
37
  "prepublishOnly": "vp run build",
39
38
  "prepare": "vp config"
40
39
  },
@@ -47,7 +46,6 @@
47
46
  "@types/node": "^25.6.0",
48
47
  "@types/react": "^19.2.14",
49
48
  "@typescript/native-preview": "7.0.0-dev.20260505.1",
50
- "bumpp": "^11.0.1",
51
49
  "pino": "^10.3.1",
52
50
  "pino-pretty": "^13.1.2",
53
51
  "react": "^19.2.5",