@genkit-ai/core
Version:
Genkit AI framework core libraries.
1 lines • 5.18 kB
Source Map (JSON)
{"version":3,"sources":["../src/context.ts"],"sourcesContent":["/**\n * Copyright 2024 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { runInActionRuntimeContext } from './action.js';\nimport { getAsyncContext } from './async-context.js';\nimport { UserFacingError } from './error.js';\n\nconst contextAlsKey = 'core.auth.context';\n\n/**\n * Action side channel data, like auth and other invocation context infromation provided by the invoker.\n */\nexport interface ActionContext {\n /** Information about the currently authenticated user if provided. */\n auth?: Record<string, any>;\n [additionalContext: string]: any;\n}\n\n/**\n * Execute the provided function in the runtime context. Call {@link getFlowContext()} anywhere\n * within the async call stack to retrieve the context. If context object is undefined, this function\n * is a no op passthrough, the function will be invoked as is.\n */\nexport function runWithContext<R>(\n context: ActionContext | undefined,\n fn: () => R\n): R {\n if (context === undefined) {\n return fn();\n }\n return getAsyncContext().run(contextAlsKey, context, () =>\n runInActionRuntimeContext(fn)\n );\n}\n\n/**\n * Gets the runtime context of the current flow.\n */\nexport function getContext(): ActionContext | undefined {\n return getAsyncContext().getStore<ActionContext>(contextAlsKey);\n}\n\n/**\n * A universal type that request handling extensions (e.g. express, next) can map their request to.\n * This allows ContextProviders to build consistent interfacese on any web framework.\n * Headers must be lowercase to ensure portability.\n */\nexport interface RequestData<T = any> {\n method: 'GET' | 'PUT' | 'POST' | 'DELETE' | 'OPTIONS' | 'QUERY';\n headers: Record<string, string>;\n input: T;\n}\n\n/**\n * Middleware can read request data and add information to the context that will\n * be passed to the Action. If middleware throws an error, that error will fail\n * the request and the Action will not be invoked. Expected cases should return a\n * UserFacingError, which allows the request handler to know what data is safe to\n * return to end users.\n *\n * Middleware can provide validation in addition to parsing. For example, an auth\n * middleware can have policies for validating auth in addition to passing auth context\n * to the Action.\n */\nexport type ContextProvider<\n C extends ActionContext = ActionContext,\n T = any,\n> = (request: RequestData<T>) => C | Promise<C>;\n\nexport interface ApiKeyContext extends ActionContext {\n auth: {\n apiKey: string | undefined;\n };\n}\n\nexport function apiKey(\n policy: (context: ApiKeyContext) => void | Promise<void>\n): ContextProvider<ApiKeyContext>;\nexport function apiKey(value?: string): ContextProvider<ApiKeyContext>;\nexport function apiKey(\n valueOrPolicy?: ((context: ApiKeyContext) => void | Promise<void>) | string\n): ContextProvider<ApiKeyContext> {\n return async (request: RequestData): Promise<ApiKeyContext> => {\n const context: ApiKeyContext = {\n auth: { apiKey: request.headers['authorization'] },\n };\n if (typeof valueOrPolicy === 'string') {\n if (!context.auth?.apiKey) {\n console.error('THROWING UNAUTHENTICATED');\n throw new UserFacingError('UNAUTHENTICATED', 'Unauthenticated');\n }\n if (context.auth?.apiKey != valueOrPolicy) {\n console.error('Throwing PERMISSION_DENIED');\n throw new UserFacingError('PERMISSION_DENIED', 'Permission Denied');\n }\n } else if (typeof valueOrPolicy === 'function') {\n await valueOrPolicy(context);\n } else if (typeof valueOrPolicy !== 'undefined') {\n throw new Error(\n `Invalid type ${typeof valueOrPolicy} passed to apiKey()`\n );\n }\n return context;\n };\n}\n"],"mappings":"AAgBA,SAAS,iCAAiC;AAC1C,SAAS,uBAAuB;AAChC,SAAS,uBAAuB;AAEhC,MAAM,gBAAgB;AAgBf,SAAS,eACd,SACA,IACG;AACH,MAAI,YAAY,QAAW;AACzB,WAAO,GAAG;AAAA,EACZ;AACA,SAAO,gBAAgB,EAAE;AAAA,IAAI;AAAA,IAAe;AAAA,IAAS,MACnD,0BAA0B,EAAE;AAAA,EAC9B;AACF;AAKO,SAAS,aAAwC;AACtD,SAAO,gBAAgB,EAAE,SAAwB,aAAa;AAChE;AAuCO,SAAS,OACd,eACgC;AAChC,SAAO,OAAO,YAAiD;AAC7D,UAAM,UAAyB;AAAA,MAC7B,MAAM,EAAE,QAAQ,QAAQ,QAAQ,eAAe,EAAE;AAAA,IACnD;AACA,QAAI,OAAO,kBAAkB,UAAU;AACrC,UAAI,CAAC,QAAQ,MAAM,QAAQ;AACzB,gBAAQ,MAAM,0BAA0B;AACxC,cAAM,IAAI,gBAAgB,mBAAmB,iBAAiB;AAAA,MAChE;AACA,UAAI,QAAQ,MAAM,UAAU,eAAe;AACzC,gBAAQ,MAAM,4BAA4B;AAC1C,cAAM,IAAI,gBAAgB,qBAAqB,mBAAmB;AAAA,MACpE;AAAA,IACF,WAAW,OAAO,kBAAkB,YAAY;AAC9C,YAAM,cAAc,OAAO;AAAA,IAC7B,WAAW,OAAO,kBAAkB,aAAa;AAC/C,YAAM,IAAI;AAAA,QACR,gBAAgB,OAAO,aAAa;AAAA,MACtC;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;","names":[]}