contextkit-sdk 0.1.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/README.md +120 -0
- package/dist/index.cjs +646 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +524 -0
- package/dist/index.d.ts +524 -0
- package/dist/index.js +604 -0
- package/dist/index.js.map +1 -0
- package/package.json +73 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/pkce.ts","../src/types.ts","../src/user.ts","../src/client.ts","../src/webhooks.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Every failure the SDK raises is a ContextKitError. Subclasses tell the\n * caller what to DO, which is the only reason to distinguish them:\n *\n * TokenRevokedError → the user must reconnect; stop retrying\n * RateLimitedError → wait `retryAfterSeconds`, then retry\n * TimeoutError / NetworkError → transient; retry with backoff\n * ValidationError / ScopeError / NotFoundError → caller bug or stale id; do not retry\n *\n * \"unknown\" answers are NOT errors. They come back as values.\n */\nexport class ContextKitError extends Error {\n readonly code: string;\n readonly status: number | null;\n readonly body: unknown;\n\n constructor(message: string, code: string, status: number | null = null, body: unknown = null) {\n super(message);\n this.name = new.target.name;\n this.code = code;\n this.status = status;\n this.body = body;\n }\n}\n\n/** 400 — the request shape was wrong. `messages` is what the API said. */\nexport class ValidationError extends ContextKitError {\n readonly messages: string[];\n constructor(messages: string[], body: unknown) {\n super(messages.join(\"; \") || \"validation failed\", \"validation\", 400, body);\n this.messages = messages;\n }\n}\n\n/** 401 that a refresh could not fix, or a refresh that itself failed. The\n * grant is gone (revoked, expired, app deactivated, or the refresh token\n * was replayed). Send the user back through the connect flow. */\nexport class TokenRevokedError extends ContextKitError {\n constructor(message = \"grant is no longer valid; the user must reconnect\", body: unknown = null) {\n super(message, \"token_revoked\", 401, body);\n }\n}\n\n/** 403 — the grant does not carry the scope this call needs. */\nexport class ScopeError extends ContextKitError {\n constructor(message: string, body: unknown) {\n super(message, \"scope\", 403, body);\n }\n}\n\n/** 404 — unshared and nonexistent are deliberately the same answer. */\nexport class NotFoundError extends ContextKitError {\n constructor(message: string, body: unknown) {\n super(message, \"not_found\", 404, body);\n }\n}\n\n/** 429 — per-app budget or rate limit. Honour `retryAfterSeconds`. */\nexport class RateLimitedError extends ContextKitError {\n readonly retryAfterSeconds: number | null;\n constructor(message: string, retryAfterSeconds: number | null, body: unknown) {\n super(message, \"rate_limited\", 429, body);\n this.retryAfterSeconds = retryAfterSeconds;\n }\n}\n\n/** Any other non-2xx. */\nexport class ApiError extends ContextKitError {\n constructor(message: string, status: number, body: unknown) {\n super(message, \"api\", status, body);\n }\n}\n\nexport class TimeoutError extends ContextKitError {\n constructor(url: string, timeoutMs: number) {\n super(`request to ${url} timed out after ${timeoutMs}ms`, \"timeout\");\n }\n}\n\nexport class NetworkError extends ContextKitError {\n override readonly cause: unknown;\n constructor(url: string, cause: unknown) {\n super(`request to ${url} failed: ${describe(cause)}`, \"network\");\n this.cause = cause;\n }\n}\n\n/** A webhook delivery that failed signature or freshness checks. */\nexport class WebhookVerificationError extends ContextKitError {\n constructor(detail: string) {\n super(detail, \"webhook_verification\");\n }\n}\n\nfunction describe(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n","import {\n ApiError,\n NetworkError,\n NotFoundError,\n RateLimitedError,\n ScopeError,\n TimeoutError,\n ValidationError,\n} from \"./errors.js\";\n\nexport type FetchLike = (\n input: string,\n init: {\n method: string;\n headers: Record<string, string>;\n body?: string;\n signal: AbortSignal;\n },\n) => Promise<{\n status: number;\n headers: { get(name: string): string | null };\n text(): Promise<string>;\n}>;\n\nexport interface HttpOptions {\n fetchImpl: FetchLike;\n timeoutMs: number;\n userAgent: string;\n}\n\nexport interface HttpRequest {\n method: \"GET\" | \"POST\" | \"PUT\" | \"PATCH\" | \"DELETE\";\n url: string;\n headers?: Record<string, string>;\n body?: unknown;\n /** 401 handling is the caller's job (it needs to refresh); everything\n * else is mapped here. */\n query?: Record<string, string | number | undefined>;\n}\n\nexport interface HttpResponse<T> {\n status: number;\n data: T;\n headers: { get(name: string): string | null };\n}\n\n/** Thrown for 401 only, so the auth layer can decide whether to refresh. */\nexport class UnauthorizedSignal extends Error {\n readonly body: unknown;\n constructor(body: unknown) {\n super(\"unauthorized\");\n this.body = body;\n }\n}\n\nexport async function request<T>(opts: HttpOptions, req: HttpRequest): Promise<HttpResponse<T>> {\n const url = withQuery(req.url, req.query);\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), opts.timeoutMs);\n\n let status: number;\n let text: string;\n let headers: { get(name: string): string | null };\n try {\n const res = await opts.fetchImpl(url, {\n method: req.method,\n headers: {\n \"accept\": \"application/json\",\n \"user-agent\": opts.userAgent,\n ...(req.body !== undefined ? { \"content-type\": \"application/json\" } : {}),\n ...(req.headers ?? {}),\n },\n ...(req.body !== undefined ? { body: JSON.stringify(req.body) } : {}),\n signal: controller.signal,\n });\n status = res.status;\n headers = res.headers;\n text = await res.text();\n } catch (err) {\n if (controller.signal.aborted) throw new TimeoutError(url, opts.timeoutMs);\n throw new NetworkError(url, err);\n } finally {\n clearTimeout(timer);\n }\n\n const data = parseJson(text);\n if (status >= 200 && status < 300) return { status, data: data as T, headers };\n\n const message = errorMessage(data, status);\n switch (status) {\n case 400:\n throw new ValidationError(errorMessages(data), data);\n case 401:\n throw new UnauthorizedSignal(data);\n case 403:\n throw new ScopeError(message, data);\n case 404:\n throw new NotFoundError(message, data);\n case 429:\n throw new RateLimitedError(message, retryAfter(headers.get(\"retry-after\")), data);\n default:\n throw new ApiError(message, status, data);\n }\n}\n\nfunction withQuery(url: string, query: HttpRequest[\"query\"]): string {\n if (!query) return url;\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(query)) {\n if (value !== undefined) params.set(key, String(value));\n }\n const qs = params.toString();\n return qs ? `${url}?${qs}` : url;\n}\n\nfunction parseJson(text: string): unknown {\n if (!text) return null;\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n\n/** Nest's default error body is { statusCode, message: string | string[], error }. */\nfunction errorMessages(data: unknown): string[] {\n if (data && typeof data === \"object\" && \"message\" in data) {\n const m = (data as { message: unknown }).message;\n if (Array.isArray(m)) return m.map(String);\n if (typeof m === \"string\") return [m];\n }\n return [];\n}\n\nfunction errorMessage(data: unknown, status: number): string {\n const messages = errorMessages(data);\n return messages.length ? messages.join(\"; \") : `HTTP ${status}`;\n}\n\nfunction retryAfter(header: string | null): number | null {\n if (!header) return null;\n const n = Number(header);\n return Number.isFinite(n) && n >= 0 ? n : null;\n}\n","import { createHash, randomBytes } from \"node:crypto\";\n\n/** 43-character base64url verifier (32 random bytes), the RFC 7636 minimum. */\nexport function generateCodeVerifier(): string {\n return base64url(randomBytes(32));\n}\n\n/** S256 challenge for a verifier — the only method the API accepts. */\nexport function codeChallenge(verifier: string): string {\n return base64url(createHash(\"sha256\").update(verifier, \"utf8\").digest());\n}\n\n/** 32 random bytes as base64url; use as the OAuth `state`. */\nexport function generateState(): string {\n return base64url(randomBytes(32));\n}\n\nfunction base64url(buf: Buffer): string {\n return buf.toString(\"base64\").replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\");\n}\n","/**\n * Wire types. These mirror the ContextKit API field-for-field: request\n * parameters are snake_case on the wire (the SDK accepts camelCase and\n * translates), response bodies are returned as the API sends them.\n */\n\nexport const APP_SCOPES = [\n // standard — answers, not data\n \"location.verify.zone\",\n \"location.place.current\",\n \"location.place.presence\",\n \"location.visits.read\",\n \"location.lookup.place\",\n \"location.rules.place\",\n \"location.rules.zone\",\n \"location.places.watch\",\n // sensitive — raw coordinates\n \"location.latest.read\",\n \"location.history.read\",\n \"location.lookup\",\n] as const;\nexport type AppScope = (typeof APP_SCOPES)[number];\n\nexport const SENSITIVE_SCOPES: readonly AppScope[] = [\n \"location.latest.read\",\n \"location.history.read\",\n \"location.lookup\",\n];\n\nexport function isAppScope(value: string): value is AppScope {\n return (APP_SCOPES as readonly string[]).includes(value);\n}\n\n/** Limits the API enforces; the SDK checks them before sending. */\nexport const MIN_ZONE_RADIUS_M = 100;\nexport const MAX_ZONE_RADIUS_M = 10_000;\nexport const MIN_MAX_AGE_S = 60;\nexport const MAX_MAX_AGE_S = 86_400;\nexport const DEFAULT_MAX_AGE_S = 900;\nexport const MIN_DWELL_MINUTES = 5;\nexport const MAX_DWELL_MINUTES = 720;\nexport const MIN_EVENT_AGE_S = 30;\nexport const MAX_EVENT_AGE_S = 3600;\n\n// ---------------------------------------------------------------------------\n// Tokens\n\n/** Raw body of POST /v1/oauth/token. */\nexport interface TokenResponse {\n access_token: string;\n token_type: \"Bearer\";\n expires_in: number;\n refresh_token: string;\n refresh_token_expires_at: string | null;\n scope: string;\n /** Pairwise per-app user id. Present once the API ships it; optional until then. */\n sub?: string;\n}\n\n/** What the integrator persists per user. Refresh tokens ROTATE: every\n * refresh returns a new one and invalidates the old, so store what\n * `onTokens` hands you or the next refresh fails. */\nexport interface TokenSet {\n accessToken: string;\n /** Epoch milliseconds when `accessToken` stops working. */\n accessTokenExpiresAt: number;\n refreshToken: string;\n /** ISO timestamp of the grant's horizon, or null for no expiry. */\n refreshTokenExpiresAt: string | null;\n scopes: AppScope[];\n sub: string | null;\n}\n\n// ---------------------------------------------------------------------------\n// Answers (standard tier)\n\nexport type UnknownReason = \"stale\" | \"no_data\" | \"boundary\";\n\nexport interface PlaceRef {\n id: string;\n label: string;\n kind: string | null;\n}\n\nexport interface ZoneAnswer {\n state: \"inside\" | \"outside\" | \"unknown\";\n reason: UnknownReason | null;\n asOf: string | null;\n ageSeconds: number | null;\n}\n\nexport interface CurrentPlaceAnswer {\n place: PlaceRef | null;\n state: \"at_place\" | \"no_place\" | \"unknown\";\n reason: UnknownReason | null;\n asOf: string | null;\n ageSeconds: number | null;\n}\n\nexport interface PresenceAnswer {\n state: \"yes\" | \"no\" | \"unknown\";\n reason: UnknownReason | null;\n asOf: string | null;\n ageSeconds: number | null;\n}\n\nexport interface SharedPlaceRef {\n id: string;\n label: string;\n kind: string | null;\n}\n\nexport interface SharedPlaceList {\n /** Bumps whenever the set of places shared with this app changes. */\n version: number;\n places: SharedPlaceRef[];\n}\n\n// ---------------------------------------------------------------------------\n// Visits\n\nexport interface Visit {\n arrival: string;\n /** null while the visit is still open. */\n departure: string | null;\n place: PlaceRef;\n}\n\nexport interface VisitsPage {\n visits: Visit[];\n nextCursor: string | null;\n}\n\nexport interface PlaceLookup {\n place: PlaceRef | null;\n matched: boolean;\n asOf: string | null;\n deltaSeconds: number | null;\n}\n\n// ---------------------------------------------------------------------------\n// Raw points (sensitive tier)\n\nexport const LOCATION_SOURCES = [\"slc\", \"visit\", \"precise\"] as const;\nexport type LocationSource = (typeof LOCATION_SOURCES)[number];\n\nexport interface LocationPoint {\n id: string;\n /** When the fix was measured. ISO8601 UTC. */\n timestamp: string;\n lat: number;\n lon: number;\n horizontalAccuracy?: number;\n altitude?: number;\n speed?: number;\n course?: number;\n source: LocationSource;\n visitArrival?: string;\n visitDeparture?: string;\n batteryLevel?: number;\n deviceId?: string;\n}\n\nexport interface PointsPage {\n points: LocationPoint[];\n nextCursor?: string;\n}\n\nexport interface LatestPoint {\n point: LocationPoint;\n ageSeconds: number;\n}\n\nexport interface PointAt {\n point: LocationPoint;\n deltaSeconds: number;\n}\n\nexport interface DaysWithData {\n /** \"YYYY-MM-DD\" in the requested timezone. */\n days: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Rules + subscriptions\n\nexport type RuleType = \"enter\" | \"exit\" | \"dwell\";\n\nexport type RuleTarget =\n | { place_id: string; label: string }\n | { lat: number; lon: number; radius_m: number; label: string };\n\nexport interface RuleSummary {\n id: string;\n type: RuleType;\n target: RuleTarget;\n dwell_minutes: number | null;\n max_event_age_s: number | null;\n webhook_url: string;\n disabled_at: string | null;\n created_at: string;\n}\n\n/** Returned once, at creation. Sign-verify every delivery with it. */\nexport type CreatedRule = RuleSummary & { secret: string };\n\nexport const CONNECTION_EVENTS = [\"places.changed\"] as const;\nexport type ConnectionEventName = (typeof CONNECTION_EVENTS)[number];\n\nexport interface SubscriptionSummary {\n id: string;\n events: string[];\n webhook_url: string;\n disabled_at: string | null;\n created_at: string;\n}\n\nexport type CreatedSubscription = SubscriptionSummary & { secret: string };\n\n// ---------------------------------------------------------------------------\n// Webhook bodies\n\nexport interface RuleWebhookEvent {\n event_id: string;\n rule_id: string;\n grant_id: string;\n /** \"place.enter\" | \"place.exit\" | \"place.dwell\" | \"zone.enter\" | ... */\n type: string;\n occurred_at: string;\n target: { place_id?: string; label: string };\n}\n\nexport interface ConnectionWebhookEvent {\n event_id: string;\n subscription_id: string;\n grant_id: string;\n type: ConnectionEventName;\n occurred_at: string;\n places_version: number;\n}\n\nexport type WebhookEvent = RuleWebhookEvent | ConnectionWebhookEvent;\n\nexport function isRuleEvent(event: WebhookEvent): event is RuleWebhookEvent {\n return \"rule_id\" in event;\n}\n\nexport function isConnectionEvent(event: WebhookEvent): event is ConnectionWebhookEvent {\n return \"subscription_id\" in event;\n}\n","import { TokenRevokedError } from \"./errors.js\";\nimport { type HttpOptions, type HttpRequest, UnauthorizedSignal, request } from \"./http.js\";\nimport {\n type CreatedRule,\n type CreatedSubscription,\n type CurrentPlaceAnswer,\n type ConnectionEventName,\n type DaysWithData,\n type LatestPoint,\n type LocationSource,\n MAX_MAX_AGE_S,\n MAX_ZONE_RADIUS_M,\n MIN_MAX_AGE_S,\n MIN_ZONE_RADIUS_M,\n type PlaceLookup,\n type PointAt,\n type PointsPage,\n type PresenceAnswer,\n type RuleSummary,\n type RuleType,\n type SharedPlaceList,\n type SubscriptionSummary,\n type TokenSet,\n type VisitsPage,\n type ZoneAnswer,\n} from \"./types.js\";\n\n/** The minimum a caller must hold per user. A full TokenSet is accepted. */\nexport interface UserTokens {\n refreshToken: string;\n accessToken?: string;\n /** Epoch ms. Without it the first call refreshes. */\n accessTokenExpiresAt?: number;\n}\n\nexport interface UserClientOptions {\n /**\n * Called every time tokens change (after a refresh). PERSIST THEM: refresh\n * tokens rotate, and the old one is dead the moment this fires. Awaited;\n * a throw here fails the call that triggered the refresh.\n */\n onTokens?: (tokens: TokenSet) => void | Promise<void>;\n}\n\n/** Refresh this many ms before expiry rather than racing the clock. */\nconst EXPIRY_SKEW_MS = 30_000;\n\nexport interface VerifyZoneParams {\n lat: number;\n lon: number;\n /** 100–10 000. Smaller zones are a triangulation tool, not a question. */\n radiusM: number;\n /** 3–80 chars; shown to the user in their access log. */\n label: string;\n /** How stale a fix may be and still count. 60–86 400, default 900. */\n maxAgeS?: number;\n}\n\nexport interface VisitsListParams {\n from?: string;\n to?: string;\n /** 1–500 */\n limit?: number;\n cursor?: string;\n}\n\nexport interface RangeParams {\n from: string;\n to: string;\n deviceId?: string;\n source?: LocationSource;\n /** 1–5000 */\n limit?: number;\n cursor?: string;\n}\n\ninterface BaseRuleParams {\n type: RuleType;\n /** 5–720; only for `dwell`. */\n dwellMinutes?: number;\n /** 30–3600; deliveries older than this are abandoned, not retried. */\n maxEventAgeS?: number;\n /** https only. */\n webhookUrl: string;\n}\n\nexport interface CreatePlaceRuleParams extends BaseRuleParams {\n placeId: string;\n}\n\nexport interface CreateZoneRuleParams extends BaseRuleParams {\n lat: number;\n lon: number;\n radiusM: number;\n label: string;\n}\n\n/**\n * All calls for one connected user. Handles access-token refresh: refreshes\n * before expiry, retries once on 401, and raises TokenRevokedError when a\n * refresh fails — at which point the user must reconnect.\n */\nexport class UserClient {\n private tokens: UserTokens;\n private refreshing: Promise<TokenSet> | null = null;\n\n constructor(\n private readonly http: HttpOptions,\n private readonly apiBaseUrl: string,\n private readonly refreshImpl: (refreshToken: string) => Promise<TokenSet>,\n tokens: UserTokens,\n private readonly options: UserClientOptions,\n ) {\n if (!tokens.refreshToken) throw new Error(\"forUser: refreshToken is required\");\n this.tokens = { ...tokens };\n }\n\n /** The tokens this client currently holds. */\n currentTokens(): Readonly<UserTokens> {\n return this.tokens;\n }\n\n readonly answers = {\n /** Is the user inside this circle right now? \"unknown\" is a value. */\n verifyZone: async (params: VerifyZoneParams): Promise<ZoneAnswer> => {\n assertRange(\"radiusM\", params.radiusM, MIN_ZONE_RADIUS_M, MAX_ZONE_RADIUS_M);\n if (params.maxAgeS !== undefined)\n assertRange(\"maxAgeS\", params.maxAgeS, MIN_MAX_AGE_S, MAX_MAX_AGE_S);\n return this.call<ZoneAnswer>({\n method: \"POST\",\n url: \"/v1/answers/verify-zone\",\n body: {\n lat: params.lat,\n lon: params.lon,\n radius_m: params.radiusM,\n label: params.label,\n ...(params.maxAgeS !== undefined ? { max_age_s: params.maxAgeS } : {}),\n },\n });\n },\n\n /** Which of the places shared with this app is the user at, if any? */\n currentPlace: (params: { maxAgeS?: number } = {}): Promise<CurrentPlaceAnswer> =>\n this.call<CurrentPlaceAnswer>({\n method: \"GET\",\n url: \"/v1/answers/current-place\",\n query: { max_age_s: params.maxAgeS },\n }),\n\n /** The places the user chose to share with this app. Cache by `version`. */\n places: (): Promise<SharedPlaceList> =>\n this.call<SharedPlaceList>({ method: \"GET\", url: \"/v1/answers/places\" }),\n\n /** Is the user at this shared place right now? */\n presence: (placeId: string, params: { maxAgeS?: number } = {}): Promise<PresenceAnswer> =>\n this.call<PresenceAnswer>({\n method: \"GET\",\n url: `/v1/answers/places/${encodeURIComponent(placeId)}/presence`,\n query: { max_age_s: params.maxAgeS },\n }),\n };\n\n readonly visits = {\n /** Stays at shared places, newest first. Follow `nextCursor`. */\n list: (params: VisitsListParams = {}): Promise<VisitsPage> =>\n this.call<VisitsPage>({\n method: \"GET\",\n url: \"/v1/visits\",\n query: { from: params.from, to: params.to, limit: params.limit, cursor: params.cursor },\n }),\n\n /** Which shared place was the user at, at this instant? */\n lookupPlace: (params: { at: string; toleranceS?: number }): Promise<PlaceLookup> =>\n this.call<PlaceLookup>({\n method: \"GET\",\n url: \"/v1/lookup/place\",\n query: { at: params.at, tolerance_s: params.toleranceS },\n }),\n };\n\n /** Sensitive tier: raw coordinates. Needs the location.*.read / lookup scopes. */\n readonly locations = {\n range: (params: RangeParams): Promise<PointsPage> =>\n this.call<PointsPage>({\n method: \"GET\",\n url: \"/v1/locations/timerange\",\n query: {\n from: params.from,\n to: params.to,\n device_id: params.deviceId,\n source: params.source,\n limit: params.limit,\n cursor: params.cursor,\n },\n }),\n\n /** Which calendar days (in `tz`) have any points. */\n days: (params: { from: string; to: string; tz: string }): Promise<DaysWithData> =>\n this.call<DaysWithData>({\n method: \"GET\",\n url: \"/v1/locations/days\",\n query: { from: params.from, to: params.to, tz: params.tz },\n }),\n\n latest: (): Promise<LatestPoint> =>\n this.call<LatestPoint>({ method: \"GET\", url: \"/v1/locations/latest\" }),\n\n /** The point nearest `at`, within `toleranceS`. 404 if none. */\n at: (params: { at: string; toleranceS?: number; source?: LocationSource }): Promise<PointAt> =>\n this.call<PointAt>({\n method: \"GET\",\n url: \"/v1/locations/lookup\",\n query: { at: params.at, tolerance_s: params.toleranceS, source: params.source },\n }),\n };\n\n readonly rules = {\n /** Fire a webhook when the user enters / exits / dwells at a shared place.\n * The returned `secret` is shown once; keep it to verify deliveries. */\n createPlace: (params: CreatePlaceRuleParams): Promise<CreatedRule> =>\n this.call<CreatedRule>({\n method: \"POST\",\n url: \"/v1/rules/place\",\n body: { place_id: params.placeId, ...ruleBody(params) },\n }),\n\n createZone: async (params: CreateZoneRuleParams): Promise<CreatedRule> => {\n assertRange(\"radiusM\", params.radiusM, MIN_ZONE_RADIUS_M, MAX_ZONE_RADIUS_M);\n return this.call<CreatedRule>({\n method: \"POST\",\n url: \"/v1/rules/zone\",\n body: {\n lat: params.lat,\n lon: params.lon,\n radius_m: params.radiusM,\n label: params.label,\n ...ruleBody(params),\n },\n });\n },\n\n /** Every rule this app holds for the user, place and zone alike. */\n list: (): Promise<RuleSummary[]> =>\n this.call<RuleSummary[]>({ method: \"GET\", url: \"/v1/rules/place\" }),\n\n deletePlace: (ruleId: string): Promise<void> =>\n this.call<void>({ method: \"DELETE\", url: `/v1/rules/place/${encodeURIComponent(ruleId)}` }),\n\n deleteZone: (ruleId: string): Promise<void> =>\n this.call<void>({ method: \"DELETE\", url: `/v1/rules/zone/${encodeURIComponent(ruleId)}` }),\n };\n\n readonly subscriptions = {\n /** One subscription per grant; registering again replaces it and mints a\n * new secret. */\n register: (params: {\n events: readonly ConnectionEventName[];\n webhookUrl: string;\n }): Promise<CreatedSubscription> =>\n this.call<CreatedSubscription>({\n method: \"POST\",\n url: \"/v1/subscriptions\",\n body: { events: [...params.events], webhook_url: params.webhookUrl },\n }),\n\n get: (): Promise<SubscriptionSummary | null> =>\n this.call<SubscriptionSummary | null>({ method: \"GET\", url: \"/v1/subscriptions\" }),\n\n remove: (subscriptionId: string): Promise<void> =>\n this.call<void>({\n method: \"DELETE\",\n url: `/v1/subscriptions/${encodeURIComponent(subscriptionId)}`,\n }),\n };\n\n // -------------------------------------------------------------------------\n\n private async call<T>(req: Omit<HttpRequest, \"headers\">): Promise<T> {\n let accessToken = await this.accessToken();\n try {\n return await this.send<T>(req, accessToken);\n } catch (err) {\n if (!(err instanceof UnauthorizedSignal)) throw err;\n }\n // One retry after a forced refresh; a second 401 means the grant is gone.\n accessToken = (await this.refresh()).accessToken;\n try {\n return await this.send<T>(req, accessToken);\n } catch (err) {\n if (err instanceof UnauthorizedSignal) throw new TokenRevokedError(undefined, err.body);\n throw err;\n }\n }\n\n private async send<T>(req: Omit<HttpRequest, \"headers\">, accessToken: string): Promise<T> {\n const res = await request<T>(this.http, {\n ...req,\n url: `${this.apiBaseUrl}${req.url}`,\n headers: { authorization: `Bearer ${accessToken}` },\n });\n return res.data;\n }\n\n private async accessToken(): Promise<string> {\n const { accessToken, accessTokenExpiresAt } = this.tokens;\n if (accessToken && accessTokenExpiresAt && accessTokenExpiresAt - EXPIRY_SKEW_MS > Date.now()) {\n return accessToken;\n }\n return (await this.refresh()).accessToken;\n }\n\n /** Single-flight: concurrent calls share one refresh, because the second\n * use of a rotated refresh token is treated as replay and kills the grant. */\n private refresh(): Promise<TokenSet> {\n if (!this.refreshing) {\n this.refreshing = this.refreshImpl(this.tokens.refreshToken)\n .then(async (next) => {\n this.tokens = {\n refreshToken: next.refreshToken,\n accessToken: next.accessToken,\n accessTokenExpiresAt: next.accessTokenExpiresAt,\n };\n if (this.options.onTokens) await this.options.onTokens(next);\n return next;\n })\n .finally(() => {\n this.refreshing = null;\n });\n }\n return this.refreshing;\n }\n}\n\nfunction ruleBody(params: BaseRuleParams): Record<string, unknown> {\n return {\n type: params.type,\n webhook_url: params.webhookUrl,\n ...(params.dwellMinutes !== undefined ? { dwell_minutes: params.dwellMinutes } : {}),\n ...(params.maxEventAgeS !== undefined ? { max_event_age_s: params.maxEventAgeS } : {}),\n };\n}\n\nfunction assertRange(name: string, value: number, min: number, max: number): void {\n if (!Number.isInteger(value) || value < min || value > max) {\n throw new RangeError(`${name} must be an integer between ${min} and ${max}, got ${value}`);\n }\n}\n","import { TokenRevokedError, ValidationError } from \"./errors.js\";\nimport { type FetchLike, type HttpOptions, UnauthorizedSignal, request } from \"./http.js\";\nimport { codeChallenge } from \"./pkce.js\";\nimport { type AppScope, type TokenResponse, type TokenSet, isAppScope } from \"./types.js\";\nimport { UserClient, type UserClientOptions, type UserTokens } from \"./user.js\";\n\nexport const DEFAULT_API_BASE_URL = \"https://api.contextkit.com\";\nexport const DEFAULT_AUTHORIZE_BASE_URL = \"https://contextkit.com\";\nexport const DEFAULT_TIMEOUT_MS = 10_000;\n\ndeclare const __SDK_VERSION__: string | undefined;\nconst VERSION = typeof __SDK_VERSION__ === \"string\" ? __SDK_VERSION__ : \"dev\";\n\nexport interface ContextKitOptions {\n /** The app's client id (a UUID) from the developer portal. */\n clientId: string;\n /** The app's client secret. Server-side only — never ship this to a browser. */\n clientSecret: string;\n /** Defaults to https://api.contextkit.com */\n apiBaseUrl?: string;\n /** Where users are sent to consent. Defaults to https://contextkit.com */\n authorizeBaseUrl?: string;\n /** Per-request timeout. Defaults to 10s. */\n timeoutMs?: number;\n /** Injectable for tests; defaults to global fetch (Node 20+). */\n fetch?: FetchLike;\n}\n\nexport interface AuthorizeUrlParams {\n /** Must be one of the redirect URIs registered for the app. */\n redirectUri: string;\n scopes: readonly AppScope[];\n /** Opaque, unguessable, bound to the user's session. Echoed back on the\n * redirect; refuse the callback if it does not match. */\n state: string;\n /** Keep the verifier in the user's session; the challenge is derived here. */\n codeVerifier: string;\n /** Your own id for this user. Stored on the grant and shown to you in the\n * portal's Users tab. Optional; never shown to the user. */\n externalUserId?: string;\n}\n\nexport interface ExchangeCodeParams {\n code: string;\n codeVerifier: string;\n redirectUri: string;\n}\n\n/**\n * One instance per app. Holds the client credentials and builds per-user\n * handles with `forUser`.\n */\nexport class ContextKit {\n readonly clientId: string;\n readonly apiBaseUrl: string;\n readonly authorizeBaseUrl: string;\n private readonly clientSecret: string;\n private readonly http: HttpOptions;\n\n constructor(options: ContextKitOptions) {\n if (!options.clientId) throw new Error(\"ContextKit: clientId is required\");\n if (!options.clientSecret) throw new Error(\"ContextKit: clientSecret is required\");\n this.clientId = options.clientId;\n this.clientSecret = options.clientSecret;\n this.apiBaseUrl = stripSlash(options.apiBaseUrl ?? DEFAULT_API_BASE_URL);\n this.authorizeBaseUrl = stripSlash(options.authorizeBaseUrl ?? DEFAULT_AUTHORIZE_BASE_URL);\n const fetchImpl = options.fetch ?? (globalThis.fetch as unknown as FetchLike | undefined);\n if (!fetchImpl) throw new Error(\"ContextKit: no fetch available; pass options.fetch\");\n this.http = {\n fetchImpl,\n timeoutMs: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n userAgent: `contextkit-sdk/${VERSION} node/${process.versions.node}`,\n };\n }\n\n /** The URL to send the user to. */\n authorizeUrl(params: AuthorizeUrlParams): string {\n if (params.scopes.length === 0) throw new Error(\"authorizeUrl: at least one scope is required\");\n for (const scope of params.scopes) {\n if (!isAppScope(scope)) throw new Error(`authorizeUrl: unknown scope \"${String(scope)}\"`);\n }\n if (!params.state) throw new Error(\"authorizeUrl: state is required\");\n if (params.codeVerifier.length < 43 || params.codeVerifier.length > 128) {\n throw new Error(\n \"authorizeUrl: codeVerifier must be 43–128 characters (see generateCodeVerifier)\",\n );\n }\n const url = new URL(`${this.authorizeBaseUrl}/authorize`);\n url.searchParams.set(\"client_id\", this.clientId);\n url.searchParams.set(\"redirect_uri\", params.redirectUri);\n url.searchParams.set(\"scope\", params.scopes.join(\" \"));\n url.searchParams.set(\"code_challenge\", codeChallenge(params.codeVerifier));\n url.searchParams.set(\"code_challenge_method\", \"S256\");\n url.searchParams.set(\"state\", params.state);\n if (params.externalUserId) url.searchParams.set(\"external_user_id\", params.externalUserId);\n return url.toString();\n }\n\n /** Callback step: trade the code for tokens. Persist the result per user. */\n async exchangeCode(params: ExchangeCodeParams): Promise<TokenSet> {\n return this.token({\n grantType: \"authorization_code\",\n code: params.code,\n codeVerifier: params.codeVerifier,\n redirectUri: params.redirectUri,\n });\n }\n\n /**\n * Refresh explicitly. `forUser` does this for you; call it directly only\n * for a scheduled refresh. Refresh tokens rotate — persist the new set.\n */\n async refresh(refreshToken: string): Promise<TokenSet> {\n return this.token({ grantType: \"refresh_token\", refreshToken });\n }\n\n /** A handle that makes calls as one connected user. */\n forUser(tokens: UserTokens, options: UserClientOptions = {}): UserClient {\n return new UserClient(this.http, this.apiBaseUrl, (rt) => this.refresh(rt), tokens, options);\n }\n\n private async token(body: Record<string, string>): Promise<TokenSet> {\n let res: { data: TokenResponse };\n try {\n res = await request<TokenResponse>(this.http, {\n method: \"POST\",\n url: `${this.apiBaseUrl}/v1/oauth/token`,\n body: { clientId: this.clientId, clientSecret: this.clientSecret, ...body },\n });\n } catch (err) {\n // The token endpoint answers a dead refresh token or a bad code with\n // 400/401. Both mean \"start over\", so both become TokenRevokedError.\n if (err instanceof UnauthorizedSignal) throw new TokenRevokedError(undefined, err.body);\n if (err instanceof ValidationError && body.grantType === \"refresh_token\") {\n throw new TokenRevokedError(err.message, err.body);\n }\n throw err;\n }\n return toTokenSet(res.data);\n }\n}\n\nexport function toTokenSet(raw: TokenResponse, now = Date.now()): TokenSet {\n return {\n accessToken: raw.access_token,\n accessTokenExpiresAt: now + raw.expires_in * 1000,\n refreshToken: raw.refresh_token,\n refreshTokenExpiresAt: raw.refresh_token_expires_at ?? null,\n scopes: raw.scope.split(\" \").filter(isAppScope),\n sub: raw.sub ?? null,\n };\n}\n\nfunction stripSlash(url: string): string {\n return url.replace(/\\/+$/, \"\");\n}\n","import { createHmac, timingSafeEqual } from \"node:crypto\";\nimport { WebhookVerificationError } from \"./errors.js\";\nimport type { WebhookEvent } from \"./types.js\";\n\n/**\n * ContextKit signs every delivery Stripe-style:\n * X-ContextKit-Signature: t=<unix seconds>,v1=<hex hmac-sha256(secret, `${t}.${body}`)>\n * Retries are re-signed, so a receiver never needs a window wider than\n * realistic clock skew. This must agree byte-for-byte with the API's\n * webhook-delivery.service.ts and the Explorer relay's signature.ts.\n */\nexport const RECOMMENDED_TOLERANCE_S = 60;\nexport const MAX_TOLERANCE_S = 300;\nexport const SIGNATURE_HEADER = \"x-contextkit-signature\";\n\n/** Something that remembers event ids it has already accepted. Needed for\n * replay protection across your own retries or a duplicated delivery. */\nexport interface ReplayGuard {\n /** Return true if this id was already seen; otherwise record it. */\n seen(eventId: string, occurredAtMs: number): boolean | Promise<boolean>;\n}\n\nexport interface VerifyWebhookParams {\n /** The EXACT bytes received. Re-serialising a parsed body breaks the HMAC. */\n rawBody: Buffer | string;\n /** The X-ContextKit-Signature header value. */\n signature: string | string[] | undefined;\n /** The secret returned when the rule or subscription was created. */\n secret: string;\n /** Seconds of clock skew to allow. Default 60, max 300. */\n toleranceS?: number;\n replayGuard?: ReplayGuard;\n /** Injectable clock, epoch ms. */\n now?: number;\n}\n\n/**\n * Verify a delivery and return its parsed event. Throws\n * WebhookVerificationError on any failure — respond 400 and do NOT act.\n */\nexport async function verifyWebhook(params: VerifyWebhookParams): Promise<WebhookEvent> {\n const header = Array.isArray(params.signature) ? params.signature[0] : params.signature;\n if (!header) throw new WebhookVerificationError(`missing ${SIGNATURE_HEADER} header`);\n const parsed = parseSignatureHeader(header);\n if (!parsed) throw new WebhookVerificationError(\"malformed signature header\");\n\n const toleranceS = Math.min(params.toleranceS ?? RECOMMENDED_TOLERANCE_S, MAX_TOLERANCE_S);\n const nowS = Math.floor((params.now ?? Date.now()) / 1000);\n const skew = nowS - parsed.timestamp;\n if (Math.abs(skew) > toleranceS) {\n throw new WebhookVerificationError(`timestamp ${skew}s outside ${toleranceS}s tolerance`);\n }\n\n const body = Buffer.isBuffer(params.rawBody)\n ? params.rawBody\n : Buffer.from(params.rawBody, \"utf8\");\n const expected = signPayload(body, parsed.timestamp, params.secret);\n if (!parsed.signatures.some((candidate) => constantTimeEquals(candidate, expected))) {\n throw new WebhookVerificationError(\"no v1 signature matched — wrong secret or tampered body\");\n }\n\n const event = parseEvent(body);\n if (params.replayGuard) {\n const occurredAtMs = Date.parse(event.occurred_at);\n if (await params.replayGuard.seen(event.event_id, occurredAtMs)) {\n throw new WebhookVerificationError(`event ${event.event_id} already processed`);\n }\n }\n return event;\n}\n\n/** Build the header for a body — for tests and for simulating deliveries. */\nexport function signWebhook(body: Buffer | string, secret: string, atMs = Date.now()): string {\n const t = Math.floor(atMs / 1000);\n const buf = Buffer.isBuffer(body) ? body : Buffer.from(body, \"utf8\");\n return `t=${t},v1=${signPayload(buf, t, secret)}`;\n}\n\nexport function parseSignatureHeader(\n header: string,\n): { timestamp: number; signatures: string[] } | null {\n let timestamp: number | null = null;\n const signatures: string[] = [];\n for (const part of header.split(\",\")) {\n const eq = part.indexOf(\"=\");\n if (eq === -1) return null;\n const key = part.slice(0, eq).trim();\n const value = part.slice(eq + 1).trim();\n if (key === \"t\") {\n const n = Number(value);\n if (!Number.isFinite(n)) return null;\n timestamp = n;\n } else if (key === \"v1\") {\n signatures.push(value.toLowerCase());\n }\n // Unknown keys are ignored so a future v2 does not break v1 receivers.\n }\n if (timestamp === null || signatures.length === 0) return null;\n return { timestamp, signatures };\n}\n\n/**\n * A process-local replay guard. Fine for a single instance; behind more than\n * one replica, back `ReplayGuard` with something shared (Redis SET NX EX).\n */\nexport class InMemoryReplayGuard implements ReplayGuard {\n private readonly ids = new Map<string, number>();\n constructor(private readonly ttlMs = 10 * 60_000) {}\n\n seen(eventId: string, _occurredAtMs: number): boolean {\n const now = Date.now();\n for (const [id, at] of this.ids) if (now - at > this.ttlMs) this.ids.delete(id);\n if (this.ids.has(eventId)) return true;\n this.ids.set(eventId, now);\n return false;\n }\n}\n\nfunction signPayload(body: Buffer, timestamp: number, secret: string): string {\n return createHmac(\"sha256\", secret)\n .update(Buffer.concat([Buffer.from(`${timestamp}.`, \"utf8\"), body]))\n .digest(\"hex\");\n}\n\nfunction parseEvent(body: Buffer): WebhookEvent {\n let data: unknown;\n try {\n data = JSON.parse(body.toString(\"utf8\"));\n } catch {\n throw new WebhookVerificationError(\"body is not JSON\");\n }\n if (\n !data ||\n typeof data !== \"object\" ||\n typeof (data as { event_id?: unknown }).event_id !== \"string\" ||\n typeof (data as { occurred_at?: unknown }).occurred_at !== \"string\" ||\n typeof (data as { type?: unknown }).type !== \"string\"\n ) {\n throw new WebhookVerificationError(\"body is not a ContextKit event\");\n }\n return data as WebhookEvent;\n}\n\nfunction constantTimeEquals(a: string, b: string): boolean {\n const left = Buffer.from(a, \"utf8\");\n const right = Buffer.from(b, \"utf8\");\n if (left.length !== right.length) return false;\n return timingSafeEqual(left, right);\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "contextkit-sdk",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Node.js SDK for ContextKit — ask scoped questions about a user's location without holding their coordinates.",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/tinbee/contextkit-sdk-node.git"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://docs.contextkit.com",
|
|
11
|
+
"keywords": [
|
|
12
|
+
"contextkit",
|
|
13
|
+
"location",
|
|
14
|
+
"geofence",
|
|
15
|
+
"privacy",
|
|
16
|
+
"oauth",
|
|
17
|
+
"sdk"
|
|
18
|
+
],
|
|
19
|
+
"type": "module",
|
|
20
|
+
"main": "./dist/index.cjs",
|
|
21
|
+
"module": "./dist/index.js",
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"import": {
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"default": "./dist/index.js"
|
|
28
|
+
},
|
|
29
|
+
"require": {
|
|
30
|
+
"types": "./dist/index.d.cts",
|
|
31
|
+
"default": "./dist/index.cjs"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"files": [
|
|
36
|
+
"dist",
|
|
37
|
+
"README.md"
|
|
38
|
+
],
|
|
39
|
+
"sideEffects": false,
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=20"
|
|
42
|
+
},
|
|
43
|
+
"packageManager": "pnpm@11.1.3",
|
|
44
|
+
"scripts": {
|
|
45
|
+
"build": "tsup",
|
|
46
|
+
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
47
|
+
"lint": "tsc --noEmit -p tsconfig.json",
|
|
48
|
+
"test": "jest",
|
|
49
|
+
"format": "prettier --write .",
|
|
50
|
+
"format:check": "prettier --check .",
|
|
51
|
+
"prepare": "husky",
|
|
52
|
+
"prepublishOnly": "pnpm typecheck && pnpm test && pnpm build"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@types/jest": "^29.5.14",
|
|
56
|
+
"@types/node": "^22.15.0",
|
|
57
|
+
"husky": "^9.1.7",
|
|
58
|
+
"jest": "^29.7.0",
|
|
59
|
+
"lint-staged": "^16.4.0",
|
|
60
|
+
"prettier": "^3.8.2",
|
|
61
|
+
"ts-jest": "^29.2.5",
|
|
62
|
+
"tsup": "^8.5.0",
|
|
63
|
+
"typescript": "^5.9.2"
|
|
64
|
+
},
|
|
65
|
+
"lint-staged": {
|
|
66
|
+
"*.{ts,tsx,js,jsx,cjs,mjs}": [
|
|
67
|
+
"prettier --write"
|
|
68
|
+
],
|
|
69
|
+
"*.{json,md,yml,yaml}": [
|
|
70
|
+
"prettier --write"
|
|
71
|
+
]
|
|
72
|
+
}
|
|
73
|
+
}
|