@knocklabs/client 0.14.11 → 0.15.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/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.15.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 2a0b3e2: Adds support for inline user `identify` calls when authenticating a user via the Knock client.
8
+ You can now pass a `user` object, for example `{ id: "123" }`, directly to the `authenticate` function.
9
+ Additional properties can also be included to update the user record, such as `{ id: "123", name: "Knock" }`.
10
+
11
+ This update also applies to `KnockProvider`, where you can now pass a `user` prop instead of a `userId` prop to achieve the same behavior.
12
+
3
13
  ## 0.14.11
4
14
 
5
15
  ### Patch Changes
package/dist/cjs/knock.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var u=Object.defineProperty;var c=(n,e,t)=>e in n?u(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t;var i=(n,e,t)=>c(n,typeof e!="symbol"?e+"":e,t);Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const l=require("jwt-decode"),d=require("./api.js"),f=require("./clients/feed/index.js"),p=require("./clients/messages/index.js"),k=require("./clients/ms-teams/index.js"),T=require("./clients/objects/index.js"),w=require("./clients/preferences/index.js"),g=require("./clients/slack/index.js"),x=require("./clients/users/index.js"),C="https://api.knock.app";class m{constructor(e,t={}){i(this,"host");i(this,"apiClient",null);i(this,"userId");i(this,"userToken");i(this,"logLevel");i(this,"tokenExpirationTimer",null);i(this,"feeds",new f.default(this));i(this,"objects",new T.default(this));i(this,"preferences",new w.default(this));i(this,"slack",new g.default(this));i(this,"msTeams",new k.default(this));i(this,"user",new x.default(this));i(this,"messages",new p.default(this));if(this.apiKey=e,this.host=t.host||C,this.logLevel=t.logLevel,this.log("Initialized Knock instance"),this.apiKey&&this.apiKey.startsWith("sk_"))throw new Error("[Knock] You are using your secret API key on the client. Please use the public key.")}client(){return this.apiClient||(this.apiClient=this.createApiClient()),this.apiClient}authenticate(e,t,s){let r=!1;this.apiClient&&(this.userId!==e||this.userToken!==t)&&(this.log("userId or userToken changed; reinitializing connections"),this.feeds.teardownInstances(),this.teardown(),r=!0),this.userId=e,this.userToken=t,this.log(`Authenticated with userId ${e}`),this.userToken&&(s==null?void 0:s.onUserTokenExpiring)instanceof Function&&this.maybeScheduleUserTokenExpiration(s.onUserTokenExpiring,s.timeBeforeExpirationInMs),r&&(this.apiClient=this.createApiClient(),this.feeds.reinitializeInstances(),this.log("Reinitialized real-time connections"))}failIfNotAuthenticated(){if(!this.isAuthenticated())throw new Error("Not authenticated. Please call `authenticate` first.")}isAuthenticated(e=!1){return e?!!(this.userId&&this.userToken):!!this.userId}teardown(){var e;this.tokenExpirationTimer&&clearTimeout(this.tokenExpirationTimer),(e=this.apiClient)!=null&&e.socket&&this.apiClient.socket.isConnected()&&this.apiClient.socket.disconnect()}log(e,t=!1){(this.logLevel==="debug"||t)&&console.log(`[Knock] ${e}`)}createApiClient(){return new d.default({apiKey:this.apiKey,host:this.host,userToken:this.userToken})}async maybeScheduleUserTokenExpiration(e,t=3e4){if(!this.userToken)return;const s=l.jwtDecode(this.userToken),r=(s.exp??0)*1e3,o=Date.now();if(r&&r>o){const h=r-t-o;this.tokenExpirationTimer=setTimeout(async()=>{const a=await e(this.userToken,s);typeof a=="string"&&this.authenticate(this.userId,a,{onUserTokenExpiring:e,timeBeforeExpirationInMs:t})},h)}}}exports.default=m;
1
+ "use strict";var h=Object.defineProperty;var r=(s,e,t)=>e in s?h(s,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):s[e]=t;var i=(s,e,t)=>r(s,typeof e!="symbol"?e+"":e,t);Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const d=require("jwt-decode"),f=require("./api.js"),k=require("./clients/feed/index.js"),T=require("./clients/messages/index.js"),g=require("./clients/ms-teams/index.js"),w=require("./clients/objects/index.js"),p=require("./clients/preferences/index.js"),x=require("./clients/slack/index.js"),y=require("./clients/users/index.js"),m="https://api.knock.app";class C{constructor(e,t={}){i(this,"host");i(this,"apiClient",null);i(this,"userId");i(this,"userToken");i(this,"logLevel");i(this,"tokenExpirationTimer",null);i(this,"feeds",new k.default(this));i(this,"objects",new w.default(this));i(this,"preferences",new p.default(this));i(this,"slack",new x.default(this));i(this,"msTeams",new g.default(this));i(this,"user",new y.default(this));i(this,"messages",new T.default(this));if(this.apiKey=e,this.host=t.host||m,this.logLevel=t.logLevel,this.log("Initialized Knock instance"),this.apiKey&&this.apiKey.startsWith("sk_"))throw new Error("[Knock] You are using your secret API key on the client. Please use the public key.")}client(){return this.apiClient||(this.apiClient=this.createApiClient()),this.apiClient}authenticate(e,t,n){let o=!1;const c=this.apiClient,a=this.getUserId(e);if(c&&(this.userId!==a||this.userToken!==t)&&(this.log("userId or userToken changed; reinitializing connections"),this.feeds.teardownInstances(),this.teardown(),o=!0),this.userId=a,this.userToken=t,this.log(`Authenticated with userId ${a}`),this.userToken&&(n==null?void 0:n.onUserTokenExpiring)instanceof Function&&this.maybeScheduleUserTokenExpiration(n.onUserTokenExpiring,n.timeBeforeExpirationInMs),o&&(this.apiClient=this.createApiClient(),this.feeds.reinitializeInstances(),this.log("Reinitialized real-time connections")),typeof e=="object"&&(e!=null&&e.id)){const{id:l,...u}=e;this.user.identify(u)}}failIfNotAuthenticated(){if(!this.isAuthenticated())throw new Error("Not authenticated. Please call `authenticate` first.")}isAuthenticated(e=!1){return e?!!(this.userId&&this.userToken):!!this.userId}teardown(){var e;this.tokenExpirationTimer&&clearTimeout(this.tokenExpirationTimer),(e=this.apiClient)!=null&&e.socket&&this.apiClient.socket.isConnected()&&this.apiClient.socket.disconnect()}log(e,t=!1){(this.logLevel==="debug"||t)&&console.log(`[Knock] ${e}`)}createApiClient(){return new f.default({apiKey:this.apiKey,host:this.host,userToken:this.userToken})}async maybeScheduleUserTokenExpiration(e,t=3e4){if(!this.userToken)return;const n=d.jwtDecode(this.userToken),o=(n.exp??0)*1e3,c=Date.now();if(o&&o>c){const a=o-t-c;this.tokenExpirationTimer=setTimeout(async()=>{const l=await e(this.userToken,n);typeof l=="string"&&this.authenticate(this.userId,l,{onUserTokenExpiring:e,timeBeforeExpirationInMs:t})},a)}}getUserId(e){if(typeof e=="string"||!e)return e;if(e!=null&&e.id)return e.id;throw new Error("`user` object must contain an `id` property")}}exports.default=C;
2
2
  //# sourceMappingURL=knock.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"knock.js","sources":["../../src/knock.ts"],"sourcesContent":["import { jwtDecode } from \"jwt-decode\";\n\nimport ApiClient from \"./api\";\nimport FeedClient from \"./clients/feed\";\nimport MessageClient from \"./clients/messages\";\nimport MsTeamsClient from \"./clients/ms-teams\";\nimport ObjectClient from \"./clients/objects\";\nimport Preferences from \"./clients/preferences\";\nimport SlackClient from \"./clients/slack\";\nimport UserClient from \"./clients/users\";\nimport {\n AuthenticateOptions,\n KnockOptions,\n LogLevel,\n UserTokenExpiringCallback,\n} from \"./interfaces\";\n\nconst DEFAULT_HOST = \"https://api.knock.app\";\n\nclass Knock {\n public host: string;\n private apiClient: ApiClient | null = null;\n public userId: string | undefined | null;\n public userToken?: string;\n public logLevel?: LogLevel;\n private tokenExpirationTimer: ReturnType<typeof setTimeout> | null = null;\n readonly feeds = new FeedClient(this);\n readonly objects = new ObjectClient(this);\n readonly preferences = new Preferences(this);\n readonly slack = new SlackClient(this);\n readonly msTeams = new MsTeamsClient(this);\n readonly user = new UserClient(this);\n readonly messages = new MessageClient(this);\n\n constructor(\n readonly apiKey: string,\n options: KnockOptions = {},\n ) {\n this.host = options.host || DEFAULT_HOST;\n this.logLevel = options.logLevel;\n\n this.log(\"Initialized Knock instance\");\n\n // Fail loudly if we're using the wrong API key\n if (this.apiKey && this.apiKey.startsWith(\"sk_\")) {\n throw new Error(\n \"[Knock] You are using your secret API key on the client. Please use the public key.\",\n );\n }\n }\n\n client() {\n // Initiate a new API client if we don't have one yet\n if (!this.apiClient) {\n this.apiClient = this.createApiClient();\n }\n\n return this.apiClient;\n }\n\n /*\n Authenticates the current user. In non-sandbox environments\n the userToken must be specified.\n */\n authenticate(\n userId: Knock[\"userId\"],\n userToken?: Knock[\"userToken\"],\n options?: AuthenticateOptions,\n ) {\n let reinitializeApi = false;\n const currentApiClient = this.apiClient;\n\n // If we've previously been initialized and the values have now changed, then we\n // need to reinitialize any stateful connections we have\n if (\n currentApiClient &&\n (this.userId !== userId || this.userToken !== userToken)\n ) {\n this.log(\"userId or userToken changed; reinitializing connections\");\n this.feeds.teardownInstances();\n this.teardown();\n reinitializeApi = true;\n }\n\n this.userId = userId;\n this.userToken = userToken;\n\n this.log(`Authenticated with userId ${userId}`);\n\n if (this.userToken && options?.onUserTokenExpiring instanceof Function) {\n this.maybeScheduleUserTokenExpiration(\n options.onUserTokenExpiring,\n options.timeBeforeExpirationInMs,\n );\n }\n\n // If we get the signal to reinitialize the api client, then we want to create a new client\n // and the reinitialize any existing feed real-time connections we have so everything continues\n // to work with the new credentials we've been given\n if (reinitializeApi) {\n this.apiClient = this.createApiClient();\n this.feeds.reinitializeInstances();\n this.log(\"Reinitialized real-time connections\");\n }\n\n return;\n }\n\n failIfNotAuthenticated() {\n if (!this.isAuthenticated()) {\n throw new Error(\"Not authenticated. Please call `authenticate` first.\");\n }\n }\n\n /*\n Returns whether or this Knock instance is authenticated. Passing `true` will check the presence\n of the userToken as well.\n */\n isAuthenticated(checkUserToken = false) {\n return checkUserToken ? !!(this.userId && this.userToken) : !!this.userId;\n }\n\n // Used to teardown any connected instances\n teardown() {\n if (this.tokenExpirationTimer) {\n clearTimeout(this.tokenExpirationTimer);\n }\n if (this.apiClient?.socket && this.apiClient.socket.isConnected()) {\n this.apiClient.socket.disconnect();\n }\n }\n\n log(message: string, force = false) {\n if (this.logLevel === \"debug\" || force) {\n console.log(`[Knock] ${message}`);\n }\n }\n\n /**\n * Initiates an API client\n */\n private createApiClient() {\n return new ApiClient({\n apiKey: this.apiKey,\n host: this.host,\n userToken: this.userToken,\n });\n }\n\n private async maybeScheduleUserTokenExpiration(\n callbackFn: UserTokenExpiringCallback,\n timeBeforeExpirationInMs: number = 30_000,\n ) {\n if (!this.userToken) return;\n\n const decoded = jwtDecode(this.userToken);\n const expiresAtMs = (decoded.exp ?? 0) * 1000;\n const nowMs = Date.now();\n\n // Expiration is in the future\n if (expiresAtMs && expiresAtMs > nowMs) {\n // Check how long until the token should be regenerated\n // | ----------------- | ----------------------- |\n // ^ now ^ expiration offset ^ expires at\n const msInFuture = expiresAtMs - timeBeforeExpirationInMs - nowMs;\n\n this.tokenExpirationTimer = setTimeout(async () => {\n const newToken = await callbackFn(this.userToken as string, decoded);\n\n // Reauthenticate which will handle reinitializing sockets\n if (typeof newToken === \"string\") {\n this.authenticate(this.userId!, newToken, {\n onUserTokenExpiring: callbackFn,\n timeBeforeExpirationInMs: timeBeforeExpirationInMs,\n });\n }\n }, msInFuture);\n }\n }\n}\n\nexport default Knock;\n"],"names":["DEFAULT_HOST","Knock","apiKey","options","__publicField","FeedClient","ObjectClient","Preferences","SlackClient","MsTeamsClient","UserClient","MessageClient","userId","userToken","reinitializeApi","checkUserToken","_a","message","force","ApiClient","callbackFn","timeBeforeExpirationInMs","decoded","jwtDecode","expiresAtMs","nowMs","msInFuture","newToken"],"mappings":"2lBAiBMA,EAAe,wBAErB,MAAMC,CAAM,CAeV,YACWC,EACTC,EAAwB,GACxB,CAjBKC,EAAA,aACCA,EAAA,iBAA8B,MAC/BA,EAAA,eACAA,EAAA,kBACAA,EAAA,iBACCA,EAAA,4BAA6D,MAC5DA,EAAA,aAAQ,IAAIC,EAAA,QAAW,IAAI,GAC3BD,EAAA,eAAU,IAAIE,EAAA,QAAa,IAAI,GAC/BF,EAAA,mBAAc,IAAIG,EAAA,QAAY,IAAI,GAClCH,EAAA,aAAQ,IAAII,EAAA,QAAY,IAAI,GAC5BJ,EAAA,eAAU,IAAIK,EAAA,QAAc,IAAI,GAChCL,EAAA,YAAO,IAAIM,EAAA,QAAW,IAAI,GAC1BN,EAAA,gBAAW,IAAIO,EAAA,QAAc,IAAI,GAYxC,GATS,KAAA,OAAAT,EAGJ,KAAA,KAAOC,EAAQ,MAAQH,EAC5B,KAAK,SAAWG,EAAQ,SAExB,KAAK,IAAI,4BAA4B,EAGjC,KAAK,QAAU,KAAK,OAAO,WAAW,KAAK,EAC7C,MAAM,IAAI,MACR,qFACF,CACF,CAGF,QAAS,CAEH,OAAC,KAAK,YACH,KAAA,UAAY,KAAK,gBAAgB,GAGjC,KAAK,SAAA,CAOd,aACES,EACAC,EACAV,EACA,CACA,IAAIW,EAAkB,GACG,KAAK,YAM3B,KAAK,SAAWF,GAAU,KAAK,YAAcC,KAE9C,KAAK,IAAI,yDAAyD,EAClE,KAAK,MAAM,kBAAkB,EAC7B,KAAK,SAAS,EACIC,EAAA,IAGpB,KAAK,OAASF,EACd,KAAK,UAAYC,EAEZ,KAAA,IAAI,6BAA6BD,CAAM,EAAE,EAE1C,KAAK,YAAaT,GAAA,YAAAA,EAAS,+BAA+B,UACvD,KAAA,iCACHA,EAAQ,oBACRA,EAAQ,wBACV,EAMEW,IACG,KAAA,UAAY,KAAK,gBAAgB,EACtC,KAAK,MAAM,sBAAsB,EACjC,KAAK,IAAI,qCAAqC,EAGhD,CAGF,wBAAyB,CACnB,GAAA,CAAC,KAAK,kBACF,MAAA,IAAI,MAAM,sDAAsD,CACxE,CAOF,gBAAgBC,EAAiB,GAAO,CAC/B,OAAAA,EAAiB,CAAC,EAAE,KAAK,QAAU,KAAK,WAAa,CAAC,CAAC,KAAK,MAAA,CAIrE,UAAW,OACL,KAAK,sBACP,aAAa,KAAK,oBAAoB,GAEpCC,EAAA,KAAK,YAAL,MAAAA,EAAgB,QAAU,KAAK,UAAU,OAAO,eAC7C,KAAA,UAAU,OAAO,WAAW,CACnC,CAGF,IAAIC,EAAiBC,EAAQ,GAAO,EAC9B,KAAK,WAAa,SAAWA,IACvB,QAAA,IAAI,WAAWD,CAAO,EAAE,CAClC,CAMM,iBAAkB,CACxB,OAAO,IAAIE,EAAAA,QAAU,CACnB,OAAQ,KAAK,OACb,KAAM,KAAK,KACX,UAAW,KAAK,SAAA,CACjB,CAAA,CAGH,MAAc,iCACZC,EACAC,EAAmC,IACnC,CACI,GAAA,CAAC,KAAK,UAAW,OAEf,MAAAC,EAAUC,EAAAA,UAAU,KAAK,SAAS,EAClCC,GAAeF,EAAQ,KAAO,GAAK,IACnCG,EAAQ,KAAK,IAAI,EAGnB,GAAAD,GAAeA,EAAcC,EAAO,CAIhC,MAAAC,EAAaF,EAAcH,EAA2BI,EAEvD,KAAA,qBAAuB,WAAW,SAAY,CACjD,MAAME,EAAW,MAAMP,EAAW,KAAK,UAAqBE,CAAO,EAG/D,OAAOK,GAAa,UACjB,KAAA,aAAa,KAAK,OAASA,EAAU,CACxC,oBAAqBP,EACrB,yBAAAC,CAAA,CACD,GAEFK,CAAU,CAAA,CACf,CAEJ"}
1
+ {"version":3,"file":"knock.js","sources":["../../src/knock.ts"],"sourcesContent":["import { jwtDecode } from \"jwt-decode\";\n\nimport ApiClient from \"./api\";\nimport FeedClient from \"./clients/feed\";\nimport MessageClient from \"./clients/messages\";\nimport MsTeamsClient from \"./clients/ms-teams\";\nimport ObjectClient from \"./clients/objects\";\nimport Preferences from \"./clients/preferences\";\nimport SlackClient from \"./clients/slack\";\nimport UserClient from \"./clients/users\";\nimport {\n AuthenticateOptions,\n KnockOptions,\n LogLevel,\n UserId,\n UserIdOrUserWithProperties,\n UserTokenExpiringCallback,\n} from \"./interfaces\";\n\nconst DEFAULT_HOST = \"https://api.knock.app\";\n\nclass Knock {\n public host: string;\n private apiClient: ApiClient | null = null;\n public userId: string | undefined | null;\n public userToken?: string;\n public logLevel?: LogLevel;\n private tokenExpirationTimer: ReturnType<typeof setTimeout> | null = null;\n readonly feeds = new FeedClient(this);\n readonly objects = new ObjectClient(this);\n readonly preferences = new Preferences(this);\n readonly slack = new SlackClient(this);\n readonly msTeams = new MsTeamsClient(this);\n readonly user = new UserClient(this);\n readonly messages = new MessageClient(this);\n\n constructor(\n readonly apiKey: string,\n options: KnockOptions = {},\n ) {\n this.host = options.host || DEFAULT_HOST;\n this.logLevel = options.logLevel;\n\n this.log(\"Initialized Knock instance\");\n\n // Fail loudly if we're using the wrong API key\n if (this.apiKey && this.apiKey.startsWith(\"sk_\")) {\n throw new Error(\n \"[Knock] You are using your secret API key on the client. Please use the public key.\",\n );\n }\n }\n\n client() {\n // Initiate a new API client if we don't have one yet\n if (!this.apiClient) {\n this.apiClient = this.createApiClient();\n }\n\n return this.apiClient;\n }\n\n /**\n * @deprecated Passing `userId` as a `string` is deprecated and will be removed in a future version.\n * Please pass a `user` object instead containing an `id` value.\n * example:\n * ```ts\n * knock.authenticate({ id: \"user_123\" });\n * ```\n */\n authenticate(\n userIdOrUserWithProperties: UserId,\n userToken?: Knock[\"userToken\"],\n options?: AuthenticateOptions,\n ): never;\n authenticate(\n userIdOrUserWithProperties: UserIdOrUserWithProperties,\n userToken?: Knock[\"userToken\"],\n options?: AuthenticateOptions,\n ): void;\n authenticate(\n userIdOrUserWithProperties: UserIdOrUserWithProperties,\n userToken?: Knock[\"userToken\"],\n options?: AuthenticateOptions,\n ) {\n let reinitializeApi = false;\n const currentApiClient = this.apiClient;\n const userId = this.getUserId(userIdOrUserWithProperties);\n\n // If we've previously been initialized and the values have now changed, then we\n // need to reinitialize any stateful connections we have\n if (\n currentApiClient &&\n (this.userId !== userId || this.userToken !== userToken)\n ) {\n this.log(\"userId or userToken changed; reinitializing connections\");\n this.feeds.teardownInstances();\n this.teardown();\n reinitializeApi = true;\n }\n\n this.userId = userId;\n this.userToken = userToken;\n\n this.log(`Authenticated with userId ${userId}`);\n\n if (this.userToken && options?.onUserTokenExpiring instanceof Function) {\n this.maybeScheduleUserTokenExpiration(\n options.onUserTokenExpiring,\n options.timeBeforeExpirationInMs,\n );\n }\n\n // If we get the signal to reinitialize the api client, then we want to create a new client\n // and the reinitialize any existing feed real-time connections we have so everything continues\n // to work with the new credentials we've been given\n if (reinitializeApi) {\n this.apiClient = this.createApiClient();\n this.feeds.reinitializeInstances();\n this.log(\"Reinitialized real-time connections\");\n }\n\n // Inline identify the user if we've been given an object with an id.\n if (\n typeof userIdOrUserWithProperties === \"object\" &&\n userIdOrUserWithProperties?.id\n ) {\n const { id, ...properties } = userIdOrUserWithProperties;\n this.user.identify(properties);\n }\n\n return;\n }\n\n failIfNotAuthenticated() {\n if (!this.isAuthenticated()) {\n throw new Error(\"Not authenticated. Please call `authenticate` first.\");\n }\n }\n\n /*\n Returns whether or this Knock instance is authenticated. Passing `true` will check the presence\n of the userToken as well.\n */\n isAuthenticated(checkUserToken = false) {\n return checkUserToken ? !!(this.userId && this.userToken) : !!this.userId;\n }\n\n // Used to teardown any connected instances\n teardown() {\n if (this.tokenExpirationTimer) {\n clearTimeout(this.tokenExpirationTimer);\n }\n if (this.apiClient?.socket && this.apiClient.socket.isConnected()) {\n this.apiClient.socket.disconnect();\n }\n }\n\n log(message: string, force = false) {\n if (this.logLevel === \"debug\" || force) {\n console.log(`[Knock] ${message}`);\n }\n }\n\n /**\n * Initiates an API client\n */\n private createApiClient() {\n return new ApiClient({\n apiKey: this.apiKey,\n host: this.host,\n userToken: this.userToken,\n });\n }\n\n private async maybeScheduleUserTokenExpiration(\n callbackFn: UserTokenExpiringCallback,\n timeBeforeExpirationInMs: number = 30_000,\n ) {\n if (!this.userToken) return;\n\n const decoded = jwtDecode(this.userToken);\n const expiresAtMs = (decoded.exp ?? 0) * 1000;\n const nowMs = Date.now();\n\n // Expiration is in the future\n if (expiresAtMs && expiresAtMs > nowMs) {\n // Check how long until the token should be regenerated\n // | ----------------- | ----------------------- |\n // ^ now ^ expiration offset ^ expires at\n const msInFuture = expiresAtMs - timeBeforeExpirationInMs - nowMs;\n\n this.tokenExpirationTimer = setTimeout(async () => {\n const newToken = await callbackFn(this.userToken as string, decoded);\n\n // Reauthenticate which will handle reinitializing sockets\n if (typeof newToken === \"string\") {\n this.authenticate(this.userId!, newToken, {\n onUserTokenExpiring: callbackFn,\n timeBeforeExpirationInMs: timeBeforeExpirationInMs,\n });\n }\n }, msInFuture);\n }\n }\n\n /**\n * Returns the user id from the given userIdOrUserWithProperties\n * @param userIdOrUserWithProperties - The user id or user object\n * @returns The user id\n * @throws {Error} If the user object does not contain an `id` property\n */\n private getUserId(userIdOrUserWithProperties: UserIdOrUserWithProperties) {\n if (\n typeof userIdOrUserWithProperties === \"string\" ||\n !userIdOrUserWithProperties\n ) {\n return userIdOrUserWithProperties;\n }\n\n if (userIdOrUserWithProperties?.id) {\n return userIdOrUserWithProperties.id;\n }\n\n throw new Error(\"`user` object must contain an `id` property\");\n }\n}\n\nexport default Knock;\n"],"names":["DEFAULT_HOST","Knock","apiKey","options","__publicField","FeedClient","ObjectClient","Preferences","SlackClient","MsTeamsClient","UserClient","MessageClient","userIdOrUserWithProperties","userToken","reinitializeApi","currentApiClient","userId","id","properties","checkUserToken","_a","message","force","ApiClient","callbackFn","timeBeforeExpirationInMs","decoded","jwtDecode","expiresAtMs","nowMs","msInFuture","newToken"],"mappings":"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"}
@@ -1,17 +1,17 @@
1
- var l = Object.defineProperty;
2
- var c = (n, e, t) => e in n ? l(n, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : n[e] = t;
3
- var i = (n, e, t) => c(n, typeof e != "symbol" ? e + "" : e, t);
4
- import { jwtDecode as u } from "jwt-decode";
5
- import p from "./api.mjs";
6
- import f from "./clients/feed/index.mjs";
7
- import k from "./clients/messages/index.mjs";
8
- import m from "./clients/ms-teams/index.mjs";
9
- import d from "./clients/objects/index.mjs";
10
- import T from "./clients/preferences/index.mjs";
11
- import C from "./clients/slack/index.mjs";
12
- import w from "./clients/users/index.mjs";
13
- const g = "https://api.knock.app";
14
- class v {
1
+ var r = Object.defineProperty;
2
+ var u = (s, e, t) => e in s ? r(s, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : s[e] = t;
3
+ var i = (s, e, t) => u(s, typeof e != "symbol" ? e + "" : e, t);
4
+ import { jwtDecode as f } from "jwt-decode";
5
+ import k from "./api.mjs";
6
+ import m from "./clients/feed/index.mjs";
7
+ import p from "./clients/messages/index.mjs";
8
+ import d from "./clients/ms-teams/index.mjs";
9
+ import T from "./clients/objects/index.mjs";
10
+ import g from "./clients/preferences/index.mjs";
11
+ import w from "./clients/slack/index.mjs";
12
+ import C from "./clients/users/index.mjs";
13
+ const y = "https://api.knock.app";
14
+ class S {
15
15
  constructor(e, t = {}) {
16
16
  i(this, "host");
17
17
  i(this, "apiClient", null);
@@ -19,14 +19,14 @@ class v {
19
19
  i(this, "userToken");
20
20
  i(this, "logLevel");
21
21
  i(this, "tokenExpirationTimer", null);
22
- i(this, "feeds", new f(this));
23
- i(this, "objects", new d(this));
24
- i(this, "preferences", new T(this));
25
- i(this, "slack", new C(this));
26
- i(this, "msTeams", new m(this));
27
- i(this, "user", new w(this));
28
- i(this, "messages", new k(this));
29
- if (this.apiKey = e, this.host = t.host || g, this.logLevel = t.logLevel, this.log("Initialized Knock instance"), this.apiKey && this.apiKey.startsWith("sk_"))
22
+ i(this, "feeds", new m(this));
23
+ i(this, "objects", new T(this));
24
+ i(this, "preferences", new g(this));
25
+ i(this, "slack", new w(this));
26
+ i(this, "msTeams", new d(this));
27
+ i(this, "user", new C(this));
28
+ i(this, "messages", new p(this));
29
+ if (this.apiKey = e, this.host = t.host || y, this.logLevel = t.logLevel, this.log("Initialized Knock instance"), this.apiKey && this.apiKey.startsWith("sk_"))
30
30
  throw new Error(
31
31
  "[Knock] You are using your secret API key on the client. Please use the public key."
32
32
  );
@@ -34,16 +34,16 @@ class v {
34
34
  client() {
35
35
  return this.apiClient || (this.apiClient = this.createApiClient()), this.apiClient;
36
36
  }
37
- /*
38
- Authenticates the current user. In non-sandbox environments
39
- the userToken must be specified.
40
- */
41
- authenticate(e, t, s) {
42
- let r = !1;
43
- this.apiClient && (this.userId !== e || this.userToken !== t) && (this.log("userId or userToken changed; reinitializing connections"), this.feeds.teardownInstances(), this.teardown(), r = !0), this.userId = e, this.userToken = t, this.log(`Authenticated with userId ${e}`), this.userToken && (s == null ? void 0 : s.onUserTokenExpiring) instanceof Function && this.maybeScheduleUserTokenExpiration(
44
- s.onUserTokenExpiring,
45
- s.timeBeforeExpirationInMs
46
- ), r && (this.apiClient = this.createApiClient(), this.feeds.reinitializeInstances(), this.log("Reinitialized real-time connections"));
37
+ authenticate(e, t, n) {
38
+ let o = !1;
39
+ const c = this.apiClient, a = this.getUserId(e);
40
+ if (c && (this.userId !== a || this.userToken !== t) && (this.log("userId or userToken changed; reinitializing connections"), this.feeds.teardownInstances(), this.teardown(), o = !0), this.userId = a, this.userToken = t, this.log(`Authenticated with userId ${a}`), this.userToken && (n == null ? void 0 : n.onUserTokenExpiring) instanceof Function && this.maybeScheduleUserTokenExpiration(
41
+ n.onUserTokenExpiring,
42
+ n.timeBeforeExpirationInMs
43
+ ), o && (this.apiClient = this.createApiClient(), this.feeds.reinitializeInstances(), this.log("Reinitialized real-time connections")), typeof e == "object" && (e != null && e.id)) {
44
+ const { id: h, ...l } = e;
45
+ this.user.identify(l);
46
+ }
47
47
  }
48
48
  failIfNotAuthenticated() {
49
49
  if (!this.isAuthenticated())
@@ -68,7 +68,7 @@ class v {
68
68
  * Initiates an API client
69
69
  */
70
70
  createApiClient() {
71
- return new p({
71
+ return new k({
72
72
  apiKey: this.apiKey,
73
73
  host: this.host,
74
74
  userToken: this.userToken
@@ -76,20 +76,33 @@ class v {
76
76
  }
77
77
  async maybeScheduleUserTokenExpiration(e, t = 3e4) {
78
78
  if (!this.userToken) return;
79
- const s = u(this.userToken), r = (s.exp ?? 0) * 1e3, o = Date.now();
80
- if (r && r > o) {
81
- const h = r - t - o;
79
+ const n = f(this.userToken), o = (n.exp ?? 0) * 1e3, c = Date.now();
80
+ if (o && o > c) {
81
+ const a = o - t - c;
82
82
  this.tokenExpirationTimer = setTimeout(async () => {
83
- const a = await e(this.userToken, s);
84
- typeof a == "string" && this.authenticate(this.userId, a, {
83
+ const h = await e(this.userToken, n);
84
+ typeof h == "string" && this.authenticate(this.userId, h, {
85
85
  onUserTokenExpiring: e,
86
86
  timeBeforeExpirationInMs: t
87
87
  });
88
- }, h);
88
+ }, a);
89
89
  }
90
90
  }
91
+ /**
92
+ * Returns the user id from the given userIdOrUserWithProperties
93
+ * @param userIdOrUserWithProperties - The user id or user object
94
+ * @returns The user id
95
+ * @throws {Error} If the user object does not contain an `id` property
96
+ */
97
+ getUserId(e) {
98
+ if (typeof e == "string" || !e)
99
+ return e;
100
+ if (e != null && e.id)
101
+ return e.id;
102
+ throw new Error("`user` object must contain an `id` property");
103
+ }
91
104
  }
92
105
  export {
93
- v as default
106
+ S as default
94
107
  };
95
108
  //# sourceMappingURL=knock.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"knock.mjs","sources":["../../src/knock.ts"],"sourcesContent":["import { jwtDecode } from \"jwt-decode\";\n\nimport ApiClient from \"./api\";\nimport FeedClient from \"./clients/feed\";\nimport MessageClient from \"./clients/messages\";\nimport MsTeamsClient from \"./clients/ms-teams\";\nimport ObjectClient from \"./clients/objects\";\nimport Preferences from \"./clients/preferences\";\nimport SlackClient from \"./clients/slack\";\nimport UserClient from \"./clients/users\";\nimport {\n AuthenticateOptions,\n KnockOptions,\n LogLevel,\n UserTokenExpiringCallback,\n} from \"./interfaces\";\n\nconst DEFAULT_HOST = \"https://api.knock.app\";\n\nclass Knock {\n public host: string;\n private apiClient: ApiClient | null = null;\n public userId: string | undefined | null;\n public userToken?: string;\n public logLevel?: LogLevel;\n private tokenExpirationTimer: ReturnType<typeof setTimeout> | null = null;\n readonly feeds = new FeedClient(this);\n readonly objects = new ObjectClient(this);\n readonly preferences = new Preferences(this);\n readonly slack = new SlackClient(this);\n readonly msTeams = new MsTeamsClient(this);\n readonly user = new UserClient(this);\n readonly messages = new MessageClient(this);\n\n constructor(\n readonly apiKey: string,\n options: KnockOptions = {},\n ) {\n this.host = options.host || DEFAULT_HOST;\n this.logLevel = options.logLevel;\n\n this.log(\"Initialized Knock instance\");\n\n // Fail loudly if we're using the wrong API key\n if (this.apiKey && this.apiKey.startsWith(\"sk_\")) {\n throw new Error(\n \"[Knock] You are using your secret API key on the client. Please use the public key.\",\n );\n }\n }\n\n client() {\n // Initiate a new API client if we don't have one yet\n if (!this.apiClient) {\n this.apiClient = this.createApiClient();\n }\n\n return this.apiClient;\n }\n\n /*\n Authenticates the current user. In non-sandbox environments\n the userToken must be specified.\n */\n authenticate(\n userId: Knock[\"userId\"],\n userToken?: Knock[\"userToken\"],\n options?: AuthenticateOptions,\n ) {\n let reinitializeApi = false;\n const currentApiClient = this.apiClient;\n\n // If we've previously been initialized and the values have now changed, then we\n // need to reinitialize any stateful connections we have\n if (\n currentApiClient &&\n (this.userId !== userId || this.userToken !== userToken)\n ) {\n this.log(\"userId or userToken changed; reinitializing connections\");\n this.feeds.teardownInstances();\n this.teardown();\n reinitializeApi = true;\n }\n\n this.userId = userId;\n this.userToken = userToken;\n\n this.log(`Authenticated with userId ${userId}`);\n\n if (this.userToken && options?.onUserTokenExpiring instanceof Function) {\n this.maybeScheduleUserTokenExpiration(\n options.onUserTokenExpiring,\n options.timeBeforeExpirationInMs,\n );\n }\n\n // If we get the signal to reinitialize the api client, then we want to create a new client\n // and the reinitialize any existing feed real-time connections we have so everything continues\n // to work with the new credentials we've been given\n if (reinitializeApi) {\n this.apiClient = this.createApiClient();\n this.feeds.reinitializeInstances();\n this.log(\"Reinitialized real-time connections\");\n }\n\n return;\n }\n\n failIfNotAuthenticated() {\n if (!this.isAuthenticated()) {\n throw new Error(\"Not authenticated. Please call `authenticate` first.\");\n }\n }\n\n /*\n Returns whether or this Knock instance is authenticated. Passing `true` will check the presence\n of the userToken as well.\n */\n isAuthenticated(checkUserToken = false) {\n return checkUserToken ? !!(this.userId && this.userToken) : !!this.userId;\n }\n\n // Used to teardown any connected instances\n teardown() {\n if (this.tokenExpirationTimer) {\n clearTimeout(this.tokenExpirationTimer);\n }\n if (this.apiClient?.socket && this.apiClient.socket.isConnected()) {\n this.apiClient.socket.disconnect();\n }\n }\n\n log(message: string, force = false) {\n if (this.logLevel === \"debug\" || force) {\n console.log(`[Knock] ${message}`);\n }\n }\n\n /**\n * Initiates an API client\n */\n private createApiClient() {\n return new ApiClient({\n apiKey: this.apiKey,\n host: this.host,\n userToken: this.userToken,\n });\n }\n\n private async maybeScheduleUserTokenExpiration(\n callbackFn: UserTokenExpiringCallback,\n timeBeforeExpirationInMs: number = 30_000,\n ) {\n if (!this.userToken) return;\n\n const decoded = jwtDecode(this.userToken);\n const expiresAtMs = (decoded.exp ?? 0) * 1000;\n const nowMs = Date.now();\n\n // Expiration is in the future\n if (expiresAtMs && expiresAtMs > nowMs) {\n // Check how long until the token should be regenerated\n // | ----------------- | ----------------------- |\n // ^ now ^ expiration offset ^ expires at\n const msInFuture = expiresAtMs - timeBeforeExpirationInMs - nowMs;\n\n this.tokenExpirationTimer = setTimeout(async () => {\n const newToken = await callbackFn(this.userToken as string, decoded);\n\n // Reauthenticate which will handle reinitializing sockets\n if (typeof newToken === \"string\") {\n this.authenticate(this.userId!, newToken, {\n onUserTokenExpiring: callbackFn,\n timeBeforeExpirationInMs: timeBeforeExpirationInMs,\n });\n }\n }, msInFuture);\n }\n }\n}\n\nexport default Knock;\n"],"names":["DEFAULT_HOST","Knock","apiKey","options","__publicField","FeedClient","ObjectClient","Preferences","SlackClient","MsTeamsClient","UserClient","MessageClient","userId","userToken","reinitializeApi","checkUserToken","_a","message","force","ApiClient","callbackFn","timeBeforeExpirationInMs","decoded","jwtDecode","expiresAtMs","nowMs","msInFuture","newToken"],"mappings":"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"}
1
+ {"version":3,"file":"knock.mjs","sources":["../../src/knock.ts"],"sourcesContent":["import { jwtDecode } from \"jwt-decode\";\n\nimport ApiClient from \"./api\";\nimport FeedClient from \"./clients/feed\";\nimport MessageClient from \"./clients/messages\";\nimport MsTeamsClient from \"./clients/ms-teams\";\nimport ObjectClient from \"./clients/objects\";\nimport Preferences from \"./clients/preferences\";\nimport SlackClient from \"./clients/slack\";\nimport UserClient from \"./clients/users\";\nimport {\n AuthenticateOptions,\n KnockOptions,\n LogLevel,\n UserId,\n UserIdOrUserWithProperties,\n UserTokenExpiringCallback,\n} from \"./interfaces\";\n\nconst DEFAULT_HOST = \"https://api.knock.app\";\n\nclass Knock {\n public host: string;\n private apiClient: ApiClient | null = null;\n public userId: string | undefined | null;\n public userToken?: string;\n public logLevel?: LogLevel;\n private tokenExpirationTimer: ReturnType<typeof setTimeout> | null = null;\n readonly feeds = new FeedClient(this);\n readonly objects = new ObjectClient(this);\n readonly preferences = new Preferences(this);\n readonly slack = new SlackClient(this);\n readonly msTeams = new MsTeamsClient(this);\n readonly user = new UserClient(this);\n readonly messages = new MessageClient(this);\n\n constructor(\n readonly apiKey: string,\n options: KnockOptions = {},\n ) {\n this.host = options.host || DEFAULT_HOST;\n this.logLevel = options.logLevel;\n\n this.log(\"Initialized Knock instance\");\n\n // Fail loudly if we're using the wrong API key\n if (this.apiKey && this.apiKey.startsWith(\"sk_\")) {\n throw new Error(\n \"[Knock] You are using your secret API key on the client. Please use the public key.\",\n );\n }\n }\n\n client() {\n // Initiate a new API client if we don't have one yet\n if (!this.apiClient) {\n this.apiClient = this.createApiClient();\n }\n\n return this.apiClient;\n }\n\n /**\n * @deprecated Passing `userId` as a `string` is deprecated and will be removed in a future version.\n * Please pass a `user` object instead containing an `id` value.\n * example:\n * ```ts\n * knock.authenticate({ id: \"user_123\" });\n * ```\n */\n authenticate(\n userIdOrUserWithProperties: UserId,\n userToken?: Knock[\"userToken\"],\n options?: AuthenticateOptions,\n ): never;\n authenticate(\n userIdOrUserWithProperties: UserIdOrUserWithProperties,\n userToken?: Knock[\"userToken\"],\n options?: AuthenticateOptions,\n ): void;\n authenticate(\n userIdOrUserWithProperties: UserIdOrUserWithProperties,\n userToken?: Knock[\"userToken\"],\n options?: AuthenticateOptions,\n ) {\n let reinitializeApi = false;\n const currentApiClient = this.apiClient;\n const userId = this.getUserId(userIdOrUserWithProperties);\n\n // If we've previously been initialized and the values have now changed, then we\n // need to reinitialize any stateful connections we have\n if (\n currentApiClient &&\n (this.userId !== userId || this.userToken !== userToken)\n ) {\n this.log(\"userId or userToken changed; reinitializing connections\");\n this.feeds.teardownInstances();\n this.teardown();\n reinitializeApi = true;\n }\n\n this.userId = userId;\n this.userToken = userToken;\n\n this.log(`Authenticated with userId ${userId}`);\n\n if (this.userToken && options?.onUserTokenExpiring instanceof Function) {\n this.maybeScheduleUserTokenExpiration(\n options.onUserTokenExpiring,\n options.timeBeforeExpirationInMs,\n );\n }\n\n // If we get the signal to reinitialize the api client, then we want to create a new client\n // and the reinitialize any existing feed real-time connections we have so everything continues\n // to work with the new credentials we've been given\n if (reinitializeApi) {\n this.apiClient = this.createApiClient();\n this.feeds.reinitializeInstances();\n this.log(\"Reinitialized real-time connections\");\n }\n\n // Inline identify the user if we've been given an object with an id.\n if (\n typeof userIdOrUserWithProperties === \"object\" &&\n userIdOrUserWithProperties?.id\n ) {\n const { id, ...properties } = userIdOrUserWithProperties;\n this.user.identify(properties);\n }\n\n return;\n }\n\n failIfNotAuthenticated() {\n if (!this.isAuthenticated()) {\n throw new Error(\"Not authenticated. Please call `authenticate` first.\");\n }\n }\n\n /*\n Returns whether or this Knock instance is authenticated. Passing `true` will check the presence\n of the userToken as well.\n */\n isAuthenticated(checkUserToken = false) {\n return checkUserToken ? !!(this.userId && this.userToken) : !!this.userId;\n }\n\n // Used to teardown any connected instances\n teardown() {\n if (this.tokenExpirationTimer) {\n clearTimeout(this.tokenExpirationTimer);\n }\n if (this.apiClient?.socket && this.apiClient.socket.isConnected()) {\n this.apiClient.socket.disconnect();\n }\n }\n\n log(message: string, force = false) {\n if (this.logLevel === \"debug\" || force) {\n console.log(`[Knock] ${message}`);\n }\n }\n\n /**\n * Initiates an API client\n */\n private createApiClient() {\n return new ApiClient({\n apiKey: this.apiKey,\n host: this.host,\n userToken: this.userToken,\n });\n }\n\n private async maybeScheduleUserTokenExpiration(\n callbackFn: UserTokenExpiringCallback,\n timeBeforeExpirationInMs: number = 30_000,\n ) {\n if (!this.userToken) return;\n\n const decoded = jwtDecode(this.userToken);\n const expiresAtMs = (decoded.exp ?? 0) * 1000;\n const nowMs = Date.now();\n\n // Expiration is in the future\n if (expiresAtMs && expiresAtMs > nowMs) {\n // Check how long until the token should be regenerated\n // | ----------------- | ----------------------- |\n // ^ now ^ expiration offset ^ expires at\n const msInFuture = expiresAtMs - timeBeforeExpirationInMs - nowMs;\n\n this.tokenExpirationTimer = setTimeout(async () => {\n const newToken = await callbackFn(this.userToken as string, decoded);\n\n // Reauthenticate which will handle reinitializing sockets\n if (typeof newToken === \"string\") {\n this.authenticate(this.userId!, newToken, {\n onUserTokenExpiring: callbackFn,\n timeBeforeExpirationInMs: timeBeforeExpirationInMs,\n });\n }\n }, msInFuture);\n }\n }\n\n /**\n * Returns the user id from the given userIdOrUserWithProperties\n * @param userIdOrUserWithProperties - The user id or user object\n * @returns The user id\n * @throws {Error} If the user object does not contain an `id` property\n */\n private getUserId(userIdOrUserWithProperties: UserIdOrUserWithProperties) {\n if (\n typeof userIdOrUserWithProperties === \"string\" ||\n !userIdOrUserWithProperties\n ) {\n return userIdOrUserWithProperties;\n }\n\n if (userIdOrUserWithProperties?.id) {\n return userIdOrUserWithProperties.id;\n }\n\n throw new Error(\"`user` object must contain an `id` property\");\n }\n}\n\nexport default Knock;\n"],"names":["DEFAULT_HOST","Knock","apiKey","options","__publicField","FeedClient","ObjectClient","Preferences","SlackClient","MsTeamsClient","UserClient","MessageClient","userIdOrUserWithProperties","userToken","reinitializeApi","currentApiClient","userId","id","properties","checkUserToken","_a","message","force","ApiClient","callbackFn","timeBeforeExpirationInMs","decoded","jwtDecode","expiresAtMs","nowMs","msInFuture","newToken"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { GenericData } from '@knocklabs/types';
2
2
  import { JwtPayload } from 'jwt-decode';
3
+ import { default as Knock } from './knock';
3
4
  export type LogLevel = "debug";
4
5
  export interface KnockOptions {
5
6
  host?: string;
@@ -63,4 +64,9 @@ export type RevokeAccessTokenInput = {
63
64
  tenant: string;
64
65
  knockChannelId: string;
65
66
  };
67
+ export type UserId = Knock["userId"];
68
+ export type UserWithProperties = {
69
+ id: UserId;
70
+ } & GenericData;
71
+ export type UserIdOrUserWithProperties = UserId | UserWithProperties;
66
72
  //# sourceMappingURL=interfaces.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../src/interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,MAAM,QAAQ,GAAG,OAAO,CAAC;AAE/B,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,WAAW;IAC1C,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,CAAC,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,WAAW,CAAC;AAE3C,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvE,MAAM,WAAW,QAAQ,CAAC,CAAC,GAAG,WAAW;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,SAAS,CAAC;IACrB,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;CAChB;AAED,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,WAAW;IAC1C,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,CAAC,CAAC;CACT;AAED,MAAM,MAAM,yBAAyB,GAAG,CACtC,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,UAAU,KACrB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;AAE5B,MAAM,WAAW,mBAAmB;IAClC,mBAAmB,CAAC,EAAE,yBAAyB,CAAC;IAChD,wBAAwB,CAAC,EAAE,MAAM,CAAC;CACnC;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,QAAQ,GAAG,YAAY,GAAG,WAAW,GAAG,QAAQ,CAAC;IACzD,cAAc,EAAE,MAAM,CAAC;IACvB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC"}
1
+ {"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../src/interfaces.ts"],"names":[],"mappings":"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"}
@@ -6,7 +6,7 @@ import { default as ObjectClient } from './clients/objects';
6
6
  import { default as Preferences } from './clients/preferences';
7
7
  import { default as SlackClient } from './clients/slack';
8
8
  import { default as UserClient } from './clients/users';
9
- import { AuthenticateOptions, KnockOptions, LogLevel } from './interfaces';
9
+ import { AuthenticateOptions, KnockOptions, LogLevel, UserId, UserIdOrUserWithProperties } from './interfaces';
10
10
  declare class Knock {
11
11
  readonly apiKey: string;
12
12
  host: string;
@@ -24,7 +24,16 @@ declare class Knock {
24
24
  readonly messages: MessageClient;
25
25
  constructor(apiKey: string, options?: KnockOptions);
26
26
  client(): ApiClient;
27
- authenticate(userId: Knock["userId"], userToken?: Knock["userToken"], options?: AuthenticateOptions): void;
27
+ /**
28
+ * @deprecated Passing `userId` as a `string` is deprecated and will be removed in a future version.
29
+ * Please pass a `user` object instead containing an `id` value.
30
+ * example:
31
+ * ```ts
32
+ * knock.authenticate({ id: "user_123" });
33
+ * ```
34
+ */
35
+ authenticate(userIdOrUserWithProperties: UserId, userToken?: Knock["userToken"], options?: AuthenticateOptions): never;
36
+ authenticate(userIdOrUserWithProperties: UserIdOrUserWithProperties, userToken?: Knock["userToken"], options?: AuthenticateOptions): void;
28
37
  failIfNotAuthenticated(): void;
29
38
  isAuthenticated(checkUserToken?: boolean): boolean;
30
39
  teardown(): void;
@@ -34,6 +43,13 @@ declare class Knock {
34
43
  */
35
44
  private createApiClient;
36
45
  private maybeScheduleUserTokenExpiration;
46
+ /**
47
+ * Returns the user id from the given userIdOrUserWithProperties
48
+ * @param userIdOrUserWithProperties - The user id or user object
49
+ * @returns The user id
50
+ * @throws {Error} If the user object does not contain an `id` property
51
+ */
52
+ private getUserId;
37
53
  }
38
54
  export default Knock;
39
55
  //# sourceMappingURL=knock.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"knock.d.ts","sourceRoot":"","sources":["../../src/knock.ts"],"names":[],"mappings":"AAEA,OAAO,SAAS,MAAM,OAAO,CAAC;AAC9B,OAAO,UAAU,MAAM,gBAAgB,CAAC;AACxC,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAC/C,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAC/C,OAAO,YAAY,MAAM,mBAAmB,CAAC;AAC7C,OAAO,WAAW,MAAM,uBAAuB,CAAC;AAChD,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAC1C,OAAO,UAAU,MAAM,iBAAiB,CAAC;AACzC,OAAO,EACL,mBAAmB,EACnB,YAAY,EACZ,QAAQ,EAET,MAAM,cAAc,CAAC;AAItB,cAAM,KAAK;IAgBP,QAAQ,CAAC,MAAM,EAAE,MAAM;IAflB,IAAI,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,SAAS,CAA0B;IACpC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAC3B,OAAO,CAAC,oBAAoB,CAA8C;IAC1E,QAAQ,CAAC,KAAK,aAAwB;IACtC,QAAQ,CAAC,OAAO,eAA0B;IAC1C,QAAQ,CAAC,WAAW,cAAyB;IAC7C,QAAQ,CAAC,KAAK,cAAyB;IACvC,QAAQ,CAAC,OAAO,gBAA2B;IAC3C,QAAQ,CAAC,IAAI,aAAwB;IACrC,QAAQ,CAAC,QAAQ,gBAA2B;gBAGjC,MAAM,EAAE,MAAM,EACvB,OAAO,GAAE,YAAiB;IAe5B,MAAM;IAaN,YAAY,CACV,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,EACvB,SAAS,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,EAC9B,OAAO,CAAC,EAAE,mBAAmB;IAyC/B,sBAAsB;IAUtB,eAAe,CAAC,cAAc,UAAQ;IAKtC,QAAQ;IASR,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,UAAQ;IAMlC;;OAEG;IACH,OAAO,CAAC,eAAe;YAQT,gCAAgC;CA8B/C;AAED,eAAe,KAAK,CAAC"}
1
+ {"version":3,"file":"knock.d.ts","sourceRoot":"","sources":["../../src/knock.ts"],"names":[],"mappings":"AAEA,OAAO,SAAS,MAAM,OAAO,CAAC;AAC9B,OAAO,UAAU,MAAM,gBAAgB,CAAC;AACxC,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAC/C,OAAO,aAAa,MAAM,oBAAoB,CAAC;AAC/C,OAAO,YAAY,MAAM,mBAAmB,CAAC;AAC7C,OAAO,WAAW,MAAM,uBAAuB,CAAC;AAChD,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAC1C,OAAO,UAAU,MAAM,iBAAiB,CAAC;AACzC,OAAO,EACL,mBAAmB,EACnB,YAAY,EACZ,QAAQ,EACR,MAAM,EACN,0BAA0B,EAE3B,MAAM,cAAc,CAAC;AAItB,cAAM,KAAK;IAgBP,QAAQ,CAAC,MAAM,EAAE,MAAM;IAflB,IAAI,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,SAAS,CAA0B;IACpC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IAC3B,OAAO,CAAC,oBAAoB,CAA8C;IAC1E,QAAQ,CAAC,KAAK,aAAwB;IACtC,QAAQ,CAAC,OAAO,eAA0B;IAC1C,QAAQ,CAAC,WAAW,cAAyB;IAC7C,QAAQ,CAAC,KAAK,cAAyB;IACvC,QAAQ,CAAC,OAAO,gBAA2B;IAC3C,QAAQ,CAAC,IAAI,aAAwB;IACrC,QAAQ,CAAC,QAAQ,gBAA2B;gBAGjC,MAAM,EAAE,MAAM,EACvB,OAAO,GAAE,YAAiB;IAe5B,MAAM;IASN;;;;;;;OAOG;IACH,YAAY,CACV,0BAA0B,EAAE,MAAM,EAClC,SAAS,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,EAC9B,OAAO,CAAC,EAAE,mBAAmB,GAC5B,KAAK;IACR,YAAY,CACV,0BAA0B,EAAE,0BAA0B,EACtD,SAAS,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,EAC9B,OAAO,CAAC,EAAE,mBAAmB,GAC5B,IAAI;IAuDP,sBAAsB;IAUtB,eAAe,CAAC,cAAc,UAAQ;IAKtC,QAAQ;IASR,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,UAAQ;IAMlC;;OAEG;IACH,OAAO,CAAC,eAAe;YAQT,gCAAgC;IA+B9C;;;;;OAKG;IACH,OAAO,CAAC,SAAS;CAclB;AAED,eAAe,KAAK,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knocklabs/client",
3
- "version": "0.14.11",
3
+ "version": "0.15.0",
4
4
  "description": "The clientside library for interacting with Knock",
5
5
  "homepage": "https://github.com/knocklabs/javascript/tree/main/packages/client",
6
6
  "author": "@knocklabs",
@@ -52,6 +52,7 @@
52
52
  "@babel/plugin-transform-runtime": "^7.25.4",
53
53
  "@babel/preset-env": "^7.27.1",
54
54
  "@babel/preset-typescript": "^7.27.0",
55
+ "@codecov/vite-plugin": "^1.9.1",
55
56
  "@types/jsonwebtoken": "^9.0.9",
56
57
  "@typescript-eslint/eslint-plugin": "^8.32.0",
57
58
  "@typescript-eslint/parser": "^8.32.1",
package/src/interfaces.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  import { GenericData } from "@knocklabs/types";
2
2
  import { JwtPayload } from "jwt-decode";
3
3
 
4
+ import Knock from "./knock";
5
+
4
6
  export type LogLevel = "debug";
5
7
 
6
8
  export interface KnockOptions {
@@ -76,3 +78,7 @@ export type RevokeAccessTokenInput = {
76
78
  tenant: string;
77
79
  knockChannelId: string;
78
80
  };
81
+
82
+ export type UserId = Knock["userId"];
83
+ export type UserWithProperties = { id: UserId } & GenericData;
84
+ export type UserIdOrUserWithProperties = UserId | UserWithProperties;
package/src/knock.ts CHANGED
@@ -12,6 +12,8 @@ import {
12
12
  AuthenticateOptions,
13
13
  KnockOptions,
14
14
  LogLevel,
15
+ UserId,
16
+ UserIdOrUserWithProperties,
15
17
  UserTokenExpiringCallback,
16
18
  } from "./interfaces";
17
19
 
@@ -58,17 +60,32 @@ class Knock {
58
60
  return this.apiClient;
59
61
  }
60
62
 
61
- /*
62
- Authenticates the current user. In non-sandbox environments
63
- the userToken must be specified.
64
- */
63
+ /**
64
+ * @deprecated Passing `userId` as a `string` is deprecated and will be removed in a future version.
65
+ * Please pass a `user` object instead containing an `id` value.
66
+ * example:
67
+ * ```ts
68
+ * knock.authenticate({ id: "user_123" });
69
+ * ```
70
+ */
71
+ authenticate(
72
+ userIdOrUserWithProperties: UserId,
73
+ userToken?: Knock["userToken"],
74
+ options?: AuthenticateOptions,
75
+ ): never;
76
+ authenticate(
77
+ userIdOrUserWithProperties: UserIdOrUserWithProperties,
78
+ userToken?: Knock["userToken"],
79
+ options?: AuthenticateOptions,
80
+ ): void;
65
81
  authenticate(
66
- userId: Knock["userId"],
82
+ userIdOrUserWithProperties: UserIdOrUserWithProperties,
67
83
  userToken?: Knock["userToken"],
68
84
  options?: AuthenticateOptions,
69
85
  ) {
70
86
  let reinitializeApi = false;
71
87
  const currentApiClient = this.apiClient;
88
+ const userId = this.getUserId(userIdOrUserWithProperties);
72
89
 
73
90
  // If we've previously been initialized and the values have now changed, then we
74
91
  // need to reinitialize any stateful connections we have
@@ -103,6 +120,15 @@ class Knock {
103
120
  this.log("Reinitialized real-time connections");
104
121
  }
105
122
 
123
+ // Inline identify the user if we've been given an object with an id.
124
+ if (
125
+ typeof userIdOrUserWithProperties === "object" &&
126
+ userIdOrUserWithProperties?.id
127
+ ) {
128
+ const { id, ...properties } = userIdOrUserWithProperties;
129
+ this.user.identify(properties);
130
+ }
131
+
106
132
  return;
107
133
  }
108
134
 
@@ -177,6 +203,27 @@ class Knock {
177
203
  }, msInFuture);
178
204
  }
179
205
  }
206
+
207
+ /**
208
+ * Returns the user id from the given userIdOrUserWithProperties
209
+ * @param userIdOrUserWithProperties - The user id or user object
210
+ * @returns The user id
211
+ * @throws {Error} If the user object does not contain an `id` property
212
+ */
213
+ private getUserId(userIdOrUserWithProperties: UserIdOrUserWithProperties) {
214
+ if (
215
+ typeof userIdOrUserWithProperties === "string" ||
216
+ !userIdOrUserWithProperties
217
+ ) {
218
+ return userIdOrUserWithProperties;
219
+ }
220
+
221
+ if (userIdOrUserWithProperties?.id) {
222
+ return userIdOrUserWithProperties.id;
223
+ }
224
+
225
+ throw new Error("`user` object must contain an `id` property");
226
+ }
180
227
  }
181
228
 
182
229
  export default Knock;