@c-rex/api 0.1.14

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/cookies.ts","../../constants/src/index.ts","../src/OIDC.ts","../src/rpc.ts","../../services/src/baseService.ts","../../utils/src/utils.ts","../../utils/src/classMerge.ts","../../utils/src/params.ts","../../utils/src/renditions.ts","../../services/src/transforms/documentTypes.ts","../../services/src/transforms/information.ts","../../services/src/informationUnits.ts","../../services/src/language.ts","../../services/src/transforms/topics.ts"],"sourcesContent":["//Do not export logger.ts. Logger must be exported as an another entrypoint on package.json\nexport * from \"./cookies\";\nexport * from \"./OIDC\";\nexport * from \"./rpc\";\n","import { NextRequest, NextResponse } from 'next/server';\nimport { cookies } from 'next/headers';\nimport { DEFAULT_COOKIE_LIMIT } from '@c-rex/constants';\n\n/**\n * Retrieves a cookie value by key from the request\n * @param {NextRequest} req - The Next.js request object\n * @returns {Promise<NextResponse>} JSON response containing the cookie key-value pair or error\n */\nexport const getCookieFromServer = async (req: NextRequest): Promise<NextResponse> => {\n const key = req.nextUrl.searchParams.get('key');\n if (!key) return NextResponse.json({ error: 'Missing key' }, { status: 400 });\n\n const value = cookies().get(key);\n const response = NextResponse.json({ key, value: value?.value || null });\n\n return response;\n}\n\n/**\n * Sets a cookie with the specified key, value and options\n * @param {NextRequest} req - The Next.js request object\n * @returns {Promise<NextResponse>} JSON response indicating success or error\n * @throws {Error} If key or value are missing in the request body\n */\nexport const saveCookie = async (req: NextRequest): Promise<NextResponse> => {\n const { key, value, maxAge: maxAgeAux } = await req.json();\n let maxAge = maxAgeAux;\n\n if (!key || value === undefined) {\n return NextResponse.json({ error: 'Missing key or value' }, { status: 400 });\n }\n\n if (maxAge === undefined) {\n maxAge = DEFAULT_COOKIE_LIMIT\n }\n\n const response = NextResponse.json({ success: true });\n\n response.cookies.set({\n name: key,\n value: value,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n path: '/',\n maxAge: maxAge,\n });\n\n return response\n};","export const ALL = \"*\"\n\nexport const LOG_CATEGORIES = [\n \"NoLicense\",\n \"Scenario\",\n \"Favorites\",\n \"Subscription\",\n \"Share\",\n \"Document\",\n \"Search\",\n \"History\",\n \"Notification\",\n \"UserProfile\",\n] as const;\n\nexport const LOG_LEVELS = {\n critical: 2,\n error: 3,\n warning: 4,\n info: 6,\n debug: 7,\n} as const;\n\nexport const RESULT_VIEW_STYLES = [\n \"cards\",\n \"table\",\n \"table-with-images\",\n] as const;\n\nexport const API = {\n MAX_RETRY: 3,\n API_TIMEOUT: 10000,\n RETRY_DELAY: 500,\n API_HEADERS: {\n \"content-Type\": \"application/json\",\n },\n};\n\nexport const SDK_CONFIG_KEY = \"crex-sdk-config\";\n\nexport const CONTENT_LANG_KEY = \"CONTENT_LANG_KEY\";\n\nexport const AVAILABLE_CONTENT_LANG_KEY = \"AVAILABLE_CONTENT_LANG_KEY\";\n\nexport const UI_LANG_KEY = \"UI_LANG_KEY\";\n\nexport const FLAGS_BY_LANG = {\n \"en\": \"US\",\n \"de\": \"DE\",\n};\n\nexport const DEFAULT_LANG = \"en-US\";\n\nexport const EN_LANG = \"en\";\n\nexport const UI_LANG_OPTIONS = [\"en-us\", \"de-de\"];\n\nexport const TOPICS_TYPE_AND_LINK = \"topics\";\nexport const BLOG_TYPE_AND_LINK = \"blog\";\nexport const DOCUMENTS_TYPE_AND_LINK = \"documents\";\n\nexport const TOPIC = \"TOPIC\";\nexport const DOCUMENT = \"DOCUMENT\";\nexport const PACKAGE = \"PACKAGE\";\nexport const FRAGMENT = \"FRAGMENT\";\n\nexport const RESULT_TYPES = {\n TOPIC: TOPIC,\n DOCUMENT: DOCUMENT,\n PACKAGE: PACKAGE,\n FRAGMENT: FRAGMENT\n} as const;\n\nexport const FILES_EXTENSIONS = {\n PDF: \"application/pdf\",\n HTML: \"text/html\",\n} as const;\n\nexport const DEFAULT_COOKIE_LIMIT = 30 * 24 * 60 * 60 * 1000; // 30 days in milliseconds\n\nexport const ICONS_BY_FILE_EXTENSION = {\n \"application/pdf\": \"FaFilePdf\",\n} as const;\n\nexport const DEFAULT_ICON = \"file\";\n\nexport const CREX_TOKEN_HEADER_KEY = \"crex-token\";\n\nexport const WILD_CARD_OPTIONS = {\n BOTH: \"BOTH\",\n END: \"END\",\n START: \"START\",\n NONE: \"NONE\",\n} as const;\n\nexport const OPERATOR_OPTIONS = {\n AND: \"AND\",\n OR: \"OR\",\n} as const;\n\nexport const ARTICLE_PAGE_LAYOUT = {\n BLOG: \"BLOG\",\n DOCUMENT: \"DOCUMENT\",\n} as const;\n\nexport const DEVICE_OPTIONS = {\n MOBILE: \"mobile\",\n TABLET: \"tablet\",\n DESKTOP: \"desktop\",\n}\nexport const BREAKPOINTS = {\n sm: 640,\n md: 768,\n lg: 1024,\n xl: 1280,\n \"2xl\": 1536,\n};\n\nexport const MARKER_COLORS = [\n \"red-500\",\n \"orange-500\",\n \"yellow-400\",\n \"green-500\",\n \"teal-500\",\n \"blue-500\",\n \"sky-500\",\n \"purple-500\",\n \"pink-500\",\n \"gray-500\",\n \"neutral-800\",\n \"cyan-500\",\n \"lime-500\",\n \"amber-500\",\n \"indigo-500\",\n];","import { NextResponse } from 'next/server';\nimport { CREX_TOKEN_HEADER_KEY } from '@c-rex/constants';\nimport { getIssuerMetadata, getToken } from '@c-rex/core/OIDC';\nimport { CrexSDK } from '@c-rex/core/sdk';\n\n/**\n * Retrieves an access token using client credentials flow from the configured OIDC provider\n * \n * @returns NextResponse with success status or error message\n * @throws Error if token retrieval fails\n */\nexport const getTokenMethod = async (): Promise<NextResponse> => {\n try {\n const { token, expiresAt, error } = await getToken();\n\n if (error) {\n return NextResponse.json({ error }, { status: 500 });\n }\n\n const response = NextResponse.json({ token: token });\n\n response.cookies.set({\n name: CREX_TOKEN_HEADER_KEY,\n value: token,\n httpOnly: true,\n secure: process.env.NODE_ENV === 'production',\n sameSite: 'lax',\n path: '/',\n expires: expiresAt ? new Date(expiresAt * 1000) : undefined\n });\n\n return response;\n\n } catch (error) {\n return NextResponse.json({ error: String(error) }, { status: 500 });\n }\n}\n\nexport const discoverIssuerMethod = async (): Promise<NextResponse> => {\n try {\n const metadata = await getIssuerMetadata();\n const sdk = new CrexSDK();\n const config = sdk.getServerConfig();\n sdk.updateConfigProp('OIDC', {\n ...config.OIDC,\n issuerMetadata: metadata\n });\n\n const response = NextResponse.json({ issuerMetadata: metadata });\n\n return response;\n\n } catch (error) {\n return NextResponse.json({ error: String(error) }, { status: 500 });\n }\n}\n","import { CrexLogger } from '@c-rex/core/logger';\nimport { InformationUnitsService, LanguageService } from '@c-rex/services';\nimport { NextRequest, NextResponse } from 'next/server';\n\n/**\n * Registry of available services that can be called via RPC.\n */\nconst serviceRegistry = {\n InformationUnitsService,\n CrexLogger,\n LanguageService\n};\n\n/**\n * Interface for RPC payload.\n */\ntype RpcPayload = {\n method: string;\n params: any;\n};\n\n/**\n * Handles POST requests for RPC (Remote Procedure Call) functionality.\n * Allows calling methods on registered services with parameters.\n * \n * @param req - The Next.js request object containing the RPC payload\n * @returns A JSON response with the result of the method call, or an error if the service or method is not found\n */\nexport const POST = async (req: NextRequest) => {\n try {\n const { method, params }: RpcPayload = await req.json();\n const [serviceName, methodName] = method.split('.');\n const ServiceClass = serviceRegistry[serviceName as keyof typeof serviceRegistry];\n\n if (!ServiceClass) {\n return NextResponse.json({ error: `Service '${serviceName}' not found` }, { status: 404 });\n }\n\n const serviceInstance = new ServiceClass();\n const handler = (serviceInstance as any)[methodName as any];\n\n if (typeof handler !== 'function') {\n return NextResponse.json({ error: `Method '${methodName}' not found on '${serviceName}'` }, { status: 404 });\n }\n\n const result = await handler.call(serviceInstance, params);\n return NextResponse.json({ data: result });\n } catch (error) {\n const logger = new CrexLogger()\n logger.log({\n level: \"error\",\n message: `RPC.POST error: ${error}`\n })\n return NextResponse.json({ error: String(error) }, { status: 500 });\n }\n}\n","import { CrexApi } from \"@c-rex/core/requests\";\nimport { QueryParams } from \"@c-rex/types\";\nimport { generateQueryParams } from \"@c-rex/utils\";\nimport { Method } from \"axios\";\n\n/**\n * Base service class that provides common functionality for API interactions.\n * All specific service classes extend this base class.\n */\nexport class BaseService {\n protected api: CrexApi;\n private endpoint: string;\n\n /**\n * Creates a new instance of BaseService.\n * \n * @param endpoint - The API endpoint URL for this service\n */\n constructor(endpoint: string) {\n this.api = new CrexApi();\n this.endpoint = endpoint;\n }\n\n /**\n * Makes an API request to the specified endpoint.\n * \n * @param options - Request configuration options\n * @param options.path - Optional path to append to the endpoint\n * @param options.params - Optional query parameters to include in the request\n * @param options.method - HTTP method to use (defaults to 'get')\n * @param options.transformer - Optional function to transform the response data\n * @returns The response data, optionally transformed\n * @throws Error if the API request fails\n */\n protected async request<T>({\n path = \"\",\n method = \"get\",\n params = [],\n headers = {},\n transformer = (response: any) => response,\n }: {\n path?: string,\n method?: Method,\n params?: QueryParams[],\n headers?: any,\n transformer?: (data: any) => T,\n }): Promise<T> {\n\n let url = `${this.endpoint}${path}`;\n\n const queryParams = generateQueryParams(params);\n if (queryParams.length > 0) {\n url += `?${queryParams}`;\n }\n\n const response = await this.api.execute({\n url,\n method,\n headers,\n })\n\n return await transformer(response);\n }\n}\n\n","import { FLAGS_BY_LANG } from \"@c-rex/constants\";\nimport { AvailableVersionsInterface, informationUnitsResponseItem } from \"@c-rex/interfaces\";\n\n/**\n * Retrieves the country code associated with a given language code.\n * @param lang - The language code to look up (e.g., \"en-US\")\n * @returns The corresponding country code, or the original language code if not found\n */\nexport const getCountryCodeByLang = (lang: string): string => {\n const mappedKeys = Object.keys(FLAGS_BY_LANG);\n\n if (!mappedKeys.includes(lang)) {\n return lang\n }\n\n type LangKey = keyof typeof FLAGS_BY_LANG;\n const country = FLAGS_BY_LANG[lang as LangKey]\n\n return country\n}\n\nexport const formatDateToLocale = (date: string, locale: string): string => {\n if (typeof date !== 'string' || !date) {\n return date;\n }\n\n const dateAux = new Date(date);\n return new Intl.DateTimeFormat(locale, {\n day: '2-digit',\n month: 'long',\n year: 'numeric'\n }).format(dateAux);\n}\n\nexport const createAvailableVersionList = (\n versions: informationUnitsResponseItem[],\n articleLang: string,\n type: string\n): AvailableVersionsInterface[] => {\n\n const availableVersions = versions.map(item => {\n return {\n shortId: item.shortId,\n active: item.language === articleLang,\n lang: item.language,\n country: item.language.split(\"-\")[1],\n link: `/${type}/${item.shortId}`,\n }\n }).sort((a, b) => {\n if (a.lang < b.lang) return -1;\n if (a.lang > b.lang) return 1;\n return 0;\n }) as AvailableVersionsInterface[];\n\n return availableVersions;\n}","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merges multiple class values into a single string using clsx and tailwind-merge.\n * Useful for conditionally applying Tailwind CSS classes.\n * @param inputs - Any number of class values (strings, objects, arrays, etc.)\n * @returns A merged string of class names optimized for Tailwind CSS\n */\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import { QueryParams } from '@c-rex/types';\n\n/**\n * Creates an array of parameter objects from a list of field values.\n * @param fieldsList - Array of field values to transform into parameter objects\n * @param key - The key to use for each parameter object (defaults to \"Fields\")\n * @returns An array of objects with key-value pairs\n */\nexport const createParams = (fieldsList: string[], key: string = \"Fields\") => {\n if (!fieldsList || fieldsList.length === 0) {\n return [];\n }\n\n return fieldsList.map((item) => ({\n key: key,\n value: item,\n }));\n}\n\n/**\n * Generates a URL query string from an array of parameter objects.\n * @param params - Array of QueryParams objects containing key-value pairs\n * @returns A URL-encoded query string\n */\nexport const generateQueryParams = (params: QueryParams[]): string => {\n const queryParams = params\n .map((param) => `${encodeURIComponent(param.key)}=${encodeURIComponent(param.value)}`)\n .join(\"&\");\n return queryParams;\n};\n","import { informationUnitsRenditions } from \"@c-rex/interfaces\";\nimport { DocumentsType } from \"@c-rex/types\";\n\n\nexport const getFileRenditions = ({ renditions }: { renditions: informationUnitsRenditions[] }): DocumentsType => {\n if (renditions == undefined || renditions.length == 0) {\n return {};\n }\n\n const filteredRenditions = renditions.filter(\n (item) => item.format != \"application/xhtml+xml\" && item.format != \"application/json\" && item.format != \"application/llm+xml\"\n );\n\n if (filteredRenditions.length == 0 || filteredRenditions[0] == undefined) {\n return {};\n }\n\n const result: {\n [key: string]: {\n view: string;\n download: string;\n }\n } = {}\n\n filteredRenditions.forEach((item) => {\n const key = item.format\n\n if (result[key] == undefined) {\n result[key] = {\n view: \"\",\n download: \"\"\n }\n }\n\n result[key].download = item.links.filter((link) => link.rel == \"download\")[0]?.href\n result[key].view = item.links.filter((link) => link.rel == \"view\")[0]?.href\n })\n\n return result\n}","import { CONTENT_LANG_KEY } from \"@c-rex/constants\";\nimport { CrexSDK } from \"@c-rex/core/sdk\";\nimport { DefaultRequest } from \"@c-rex/interfaces\";\nimport { DocumentTypesItem } from \"@c-rex/interfaces\";\nimport { cookies } from \"next/headers\";\n\nexport const transformDocumentTypes = async (data: DefaultRequest<DocumentTypesItem>) => {\n const labels: { shortId: string, label: string }[] = [];\n const sdk = new CrexSDK();\n const config = sdk.getClientConfig();\n const contentLanguage = cookies().get(CONTENT_LANG_KEY)?.value || config.languageSwitcher.default;\n const language = contentLanguage.split(\"-\")[0];\n\n data.items.forEach((documentItem) => {\n const label = documentItem.labels.find((item) => item.language.toLowerCase() === language.toLowerCase());\n\n labels.push({\n shortId: documentItem.shortId,\n label: label ? label.value : \"\"\n })\n });\n\n return labels;\n};\n","import { CONTENT_LANG_KEY, EN_LANG, RESULT_TYPES } from \"@c-rex/constants\";\nimport {\n DefaultRequest,\n informationUnitsResponse,\n informationUnitsItems,\n} from \"@c-rex/interfaces\";\nimport { cookies } from 'next/headers';\nimport { getFileRenditions } from \"@c-rex/utils\";\nimport { CrexLogger } from '@c-rex/core/logger';\nimport { AutocompleteSuggestion } from \"@c-rex/interfaces\";\nimport { informationUnitsResponseItem } from \"@c-rex/interfaces\";\nimport { CrexSDK } from \"@c-rex/core/sdk\";\n\nexport const transformInformationUnits = async (data: DefaultRequest<informationUnitsItems>): Promise<informationUnitsResponse> => {\n const logger = new CrexLogger()\n const sdk = new CrexSDK();\n const frontEndConfig = sdk.getClientConfig();\n const backEndConfig = sdk.getServerConfig();\n const filteredTags: any = {}\n\n const items: informationUnitsResponseItem[] = data.items.map((item) => {\n const type = item.class.labels.filter((item) => item.language === EN_LANG)[0].value.toUpperCase();\n const files = getFileRenditions({ renditions: item?.renditions });\n\n let link = `/topics/${item.shortId}`;\n\n if (frontEndConfig.results.articlePageLayout == \"BLOG\") {\n link = `/blog/${item.shortId}`\n } else if (type == RESULT_TYPES.DOCUMENT) {\n link = `/documents/${item.shortId}`;\n }\n\n let title = \"NO TITLE\"\n if (item.titles) {\n title = item.titles[0].value;\n } else if (item.labels) {\n title = item.labels[0].value;\n }\n\n let language = \"NO LANGUAGE\"\n if (item.languages.length > 0) {\n language = item.languages[0];\n }\n\n let versionOf: string[] = []\n if (item?.versionOf && item.versionOf?.labels) {\n versionOf = item.versionOf.labels.map(item => item.language).filter((value) => value !== undefined);\n }\n\n return {\n language: language,\n title: title,\n type: type,\n localeType: \"\",\n revision: item.revision,\n shortId: item.shortId,\n multipleVersions: versionOf,\n disabled: frontEndConfig.results.disabledResults.includes(type as any),\n link: link,\n files\n }\n });\n\n if (data.tags) {\n const contentLang = (cookies().get(CONTENT_LANG_KEY)?.value || EN_LANG).toLowerCase()\n const splittedContentLang = contentLang.split(\"-\")[0];\n\n for (const [key, value] of Object.entries(data.tags)) {\n\n if (!value || !value.items || value.items.length === 0) {\n continue;\n }\n if (!backEndConfig.search.tags.includes(key)) {\n continue;\n }\n\n const aux = value.items.map(item => {\n if (item?.shortId === undefined) return null\n if (Number(item.hits) === 0) return null\n if (item?.labels === undefined || item?.labels.length === 0) {\n logger.log({\n level: \"warning\",\n message: `No labels on item with id ${item.shortId} from category ${key}`\n })\n return null;\n }\n\n let label = \"\"\n\n for (const labelItem of item.labels) {\n if (labelItem.language === undefined) {\n logger.log({\n level: \"info\",\n message: `No language on label ${labelItem.value} from category ${key}`\n })\n label = labelItem.value\n break;\n }\n\n if (labelItem.language.toLowerCase() === contentLang || labelItem.language.toLowerCase() === splittedContentLang) {\n label = labelItem.value\n break;\n }\n\n label = labelItem.value\n\n //TODO: fallback in english\n }\n\n return {\n hits: item.hits,\n total: item.total,\n label: label,\n active: false,\n shortId: item.shortId,\n }\n }).filter((item) => item !== null)\n\n if (aux.length === 0) {\n continue;\n }\n\n filteredTags[key] = aux;\n }\n }\n\n return {\n tags: filteredTags,\n items: items,\n pageInfo: data.pageInfo,\n };\n};\n\nexport const transformSuggestions = (data: AutocompleteSuggestion, query: string) => {\n const suggestions: string[] = []\n const comparableList: string[] = []\n\n data.suggestions.forEach((item) => {\n suggestions.push(item.value);\n comparableList.push(item.value.toLowerCase())\n })\n\n if (!comparableList.includes(query.toLowerCase())) {\n return [query, ...suggestions];\n }\n\n return suggestions\n}","import {\n AutocompleteSuggestion,\n informationUnitsResponse,\n informationUnitsItems,\n} from \"@c-rex/interfaces\";\nimport { transformInformationUnits, transformSuggestions } from \"./transforms/information\";\nimport { createParams } from \"@c-rex/utils\";\nimport { BaseService } from \"./baseService\";\nimport { OperatorType, WildCardType } from \"@c-rex/types\";\nimport { OPERATOR_OPTIONS, WILD_CARD_OPTIONS } from \"@c-rex/constants\";\n\n/**\n * Service for interacting with information units in the API.\n * Provides methods to retrieve and search information units.\n */\nexport class InformationUnitsService extends BaseService {\n constructor() {\n super(\"InformationUnits/\");\n }\n\n /**\n * Retrieves a list of information units based on specified criteria.\n * \n * @param options - Options for filtering and paginating the information units list\n * @param options.queries - Optional search query string\n * @param options.page - Optional page number for pagination (defaults to 1)\n * @param options.fields - Optional array of fields to include in the response\n * @param options.filters - Optional array of filter strings to apply\n * @param options.languages - Optional array of language codes to filter by\n * @returns A promise that resolves to the information units response\n * @throws Error if the API request fails\n */\n public async getList({\n queries = \"\",\n page = 1,\n fields = [],\n filters = [],\n tags = [],\n restrict = [],\n languages = [],\n wildcard = WILD_CARD_OPTIONS.BOTH,\n operator = OPERATOR_OPTIONS.AND,\n like = false,\n }: {\n queries?: string,\n page?: number,\n filters?: string[],\n restrict?: string[],\n fields?: string[],\n tags?: string[],\n languages?: string[],\n wildcard?: WildCardType,\n operator?: OperatorType,\n like?: boolean,\n }): Promise<informationUnitsResponse> {\n const remainFields = createParams(fields, \"Fields\");\n const remainFilters = createParams(filters, \"Filter\");\n const restrictions = createParams(restrict, \"Restrict\");\n const remainTags = createParams(tags, \"Tags\");\n\n const params = [\n { key: \"pageSize\", value: \"12\" },\n { key: \"wildcard\", value: wildcard.toLowerCase() },\n { key: \"PageNumber\", value: page.toString() },\n { key: \"Operator\", value: operator },\n { key: \"Like\", value: like.toString() },\n ...remainTags,\n ...remainFields,\n ...remainFilters,\n ...restrictions\n ];\n\n if (languages.length > 0) {\n const languageParam = `VALUES ?lang { ${languages.map(lang => `\"${lang}\"`).join(\" \")} } ?s iirds:language ?lang .`\n params.push({ key: \"sparqlWhere\", value: languageParam });\n }\n if (queries.length > 0) {\n params.push(\n { key: \"Query\", value: queries },\n );\n }\n\n return await this.request({\n params: params,\n transformer: transformInformationUnits\n });\n }\n\n /**\n * Retrieves a specific information unit by its ID.\n * Includes renditions, directory nodes, version information, titles, languages, and labels.\n * \n * @param options - Options for retrieving the information unit\n * @param options.id - The unique identifier of the information unit\n * @returns A promise that resolves to the information unit data\n * @throws Error if the API request fails\n */\n public async getItem({ id, shouldGetAllFields = false }: { id: string, shouldGetAllFields?: boolean }): Promise<informationUnitsItems> {\n const params = []\n\n if (!shouldGetAllFields) {\n params.push(\n { key: \"Fields\", value: \"renditions\" },\n { key: \"Fields\", value: \"directoryNodes\" },\n { key: \"Fields\", value: \"versionOf\" },\n { key: \"Fields\", value: \"titles\" },\n { key: \"Fields\", value: \"languages\" },\n { key: \"Fields\", value: \"labels\" },\n { key: \"Fields\", value: \"packages\" },\n { key: \"Fields\", value: \"created\" },\n { key: \"Fields\", value: \"revision\" },\n );\n }\n\n return await this.request({\n path: id,\n params,\n });\n }\n\n /**\n * Retrieves autocomplete suggestions based on a query prefix.\n * \n * @param options - Options for retrieving suggestions\n * @param options.query - The query prefix to get suggestions for\n * @param options.language - The language of the suggestions\n * @returns A promise that resolves to an array of suggestion strings\n * @throws Error if the API request fails\n */\n public async getSuggestions(\n { query, language }: { query: string, language: string }\n ): Promise<string[]> {\n return await this.request({\n path: 'Suggestions',\n params: [\n { key: \"prefix\", value: query },\n { key: \"lang\", value: language },\n ],\n transformer: (data: AutocompleteSuggestion) => transformSuggestions(data, query)\n });\n }\n}\n","import { LanguageAndCountries } from \"@c-rex/interfaces\";\nimport { BaseService } from \"./baseService\";\nimport { getCountryCodeByLang } from \"@c-rex/utils\";\nimport { CrexSDK } from \"@c-rex/core/sdk\";\n\n/**\n * Service for interacting with language-related functionality in the API.\n * Provides methods to retrieve language and country information.\n */\nexport class LanguageService extends BaseService {\n constructor() {\n const sdk = new CrexSDK();\n const configs = sdk.getClientConfig();\n super(configs.languageSwitcher.endpoint);\n }\n\n /**\n * Retrieves a list of available languages and their associated countries.\n * Transforms the API response to include language code, country code, and original value.\n * \n * @returns A promise that resolves to an array of language and country objects\n * @throws Error if the API request fails\n */\n public async getLanguagesAndCountries(): Promise<LanguageAndCountries[]> {\n return await this.request({\n transformer: (data: { value: string; score: number }[]) => {\n const countryCodeList = data.map((item) => {\n /*\n api -> en, en-US\n default -> en-US. Then use EN-US \n\n api -> en\n default -> en-US. Then use EN\n */\n //should be abble to handle this items: en-US, en, pt, pt-PT, pt-BR \n\n const splittedValue = item.value.split(\"-\")\n const lang = splittedValue[0]\n let country = splittedValue[0]\n\n if (splittedValue.length > 1) {\n country = splittedValue[1]\n } else {\n country = getCountryCodeByLang(lang)\n }\n\n return {\n country: country,\n lang: lang,\n value: item.value,\n }\n })\n\n return countryCodeList.sort((a, b) => {\n return a.value.localeCompare(b.value)\n })\n },\n });\n }\n}\n","import { EN_LANG, RESULT_TYPES, UI_LANG_KEY } from \"@c-rex/constants\";\nimport { DefaultRequest, TopicsRequestItem, DefaultResponse, TopicsResponseItem } from \"@c-rex/interfaces\";\nimport { cookies } from 'next/headers';\nimport { CrexLogger } from '@c-rex/core/logger';\nimport { formatDateToLocale } from \"@c-rex/utils\";\nimport { CrexSDK } from \"@c-rex/core/sdk\";\n\nexport const transformTopics = async (data: DefaultRequest<TopicsRequestItem>): Promise<DefaultResponse<TopicsResponseItem, null>> => {\n const logger = new CrexLogger()\n const sdk = new CrexSDK();\n const config = sdk.getClientConfig();\n const uiLang = (cookies().get(UI_LANG_KEY)?.value || config.languageSwitcher.default).toLowerCase()\n\n const items = data.items.map(item => {\n const type = item.class.labels.filter((item) => item.language === EN_LANG)[0].value.toUpperCase();\n\n let link = `/topics/${item.shortId}`;\n\n if (config.results.articlePageLayout == \"BLOG\") {\n link = `/blog/${item.shortId}`\n } else if (type == RESULT_TYPES.DOCUMENT) {\n link = `/documents/${item.shortId}`;\n }\n\n let title = \"NO TITLE\"\n let language = \"NO LANGUAGE\"\n\n try {\n if (item.titles) {\n title = item.titles[0].value\n language = item.titles[0].language\n } else {\n title = item.labels[0].value\n language = item.labels[0].language\n }\n } catch {\n logger.log({\n level: \"error\",\n message: `No label or title on item ${item.shortId}`\n })\n }\n\n let renditionUrl = \"\"\n const renditions = item.renditions.filter(item => item.format == \"application/xhtml+xml\");\n if (renditions.length > 0 || renditions[0] !== undefined) {\n const filteredLinks = renditions[0].links.filter((renditionItem) => renditionItem.rel == \"view\");\n if (filteredLinks.length > 0 || filteredLinks[0] !== undefined) {\n renditionUrl = filteredLinks[0].href;\n };\n };\n\n let categoryType = type\n if (item.applicableForTypes && item.applicableForTypes.length > 0) {\n const splittedContentLang = uiLang.split(\"-\")[0];\n categoryType = item.applicableForTypes[0].labels.find(item => item.language === splittedContentLang)?.value || categoryType;\n }\n\n return {\n language: language,\n title: title,\n type: categoryType,\n localeType: \"\",\n shortId: item.shortId,\n created: formatDateToLocale(item.created, uiLang),\n disabled: config.results.disabledResults.includes(type as any),\n link: link,\n renditionUrl: renditionUrl,\n image: null,\n description: null,\n }\n })\n\n return {\n tags: null,\n items: items,\n pageInfo: data.pageInfo,\n };\n};\n"],"mappings":"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","names":["import_server","import_logger","import_sdk","import_headers","import_headers","import_sdk","item","import_sdk","import_headers","import_logger","import_sdk","import_server"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,522 @@
1
+ // src/cookies.ts
2
+ import { NextResponse } from "next/server";
3
+ import { cookies } from "next/headers";
4
+
5
+ // ../constants/src/index.ts
6
+ var CONTENT_LANG_KEY = "CONTENT_LANG_KEY";
7
+ var FLAGS_BY_LANG = {
8
+ "en": "US",
9
+ "de": "DE"
10
+ };
11
+ var EN_LANG = "en";
12
+ var TOPIC = "TOPIC";
13
+ var DOCUMENT = "DOCUMENT";
14
+ var PACKAGE = "PACKAGE";
15
+ var FRAGMENT = "FRAGMENT";
16
+ var RESULT_TYPES = {
17
+ TOPIC,
18
+ DOCUMENT,
19
+ PACKAGE,
20
+ FRAGMENT
21
+ };
22
+ var DEFAULT_COOKIE_LIMIT = 30 * 24 * 60 * 60 * 1e3;
23
+ var CREX_TOKEN_HEADER_KEY = "crex-token";
24
+ var WILD_CARD_OPTIONS = {
25
+ BOTH: "BOTH",
26
+ END: "END",
27
+ START: "START",
28
+ NONE: "NONE"
29
+ };
30
+ var OPERATOR_OPTIONS = {
31
+ AND: "AND",
32
+ OR: "OR"
33
+ };
34
+
35
+ // src/cookies.ts
36
+ var getCookieFromServer = async (req) => {
37
+ const key = req.nextUrl.searchParams.get("key");
38
+ if (!key) return NextResponse.json({ error: "Missing key" }, { status: 400 });
39
+ const value = cookies().get(key);
40
+ const response = NextResponse.json({ key, value: value?.value || null });
41
+ return response;
42
+ };
43
+ var saveCookie = async (req) => {
44
+ const { key, value, maxAge: maxAgeAux } = await req.json();
45
+ let maxAge = maxAgeAux;
46
+ if (!key || value === void 0) {
47
+ return NextResponse.json({ error: "Missing key or value" }, { status: 400 });
48
+ }
49
+ if (maxAge === void 0) {
50
+ maxAge = DEFAULT_COOKIE_LIMIT;
51
+ }
52
+ const response = NextResponse.json({ success: true });
53
+ response.cookies.set({
54
+ name: key,
55
+ value,
56
+ secure: process.env.NODE_ENV === "production",
57
+ sameSite: "lax",
58
+ path: "/",
59
+ maxAge
60
+ });
61
+ return response;
62
+ };
63
+
64
+ // src/OIDC.ts
65
+ import { NextResponse as NextResponse2 } from "next/server";
66
+ import { getIssuerMetadata, getToken } from "@c-rex/core/OIDC";
67
+ import { CrexSDK } from "@c-rex/core/sdk";
68
+ var getTokenMethod = async () => {
69
+ try {
70
+ const { token, expiresAt, error } = await getToken();
71
+ if (error) {
72
+ return NextResponse2.json({ error }, { status: 500 });
73
+ }
74
+ const response = NextResponse2.json({ token });
75
+ response.cookies.set({
76
+ name: CREX_TOKEN_HEADER_KEY,
77
+ value: token,
78
+ httpOnly: true,
79
+ secure: process.env.NODE_ENV === "production",
80
+ sameSite: "lax",
81
+ path: "/",
82
+ expires: expiresAt ? new Date(expiresAt * 1e3) : void 0
83
+ });
84
+ return response;
85
+ } catch (error) {
86
+ return NextResponse2.json({ error: String(error) }, { status: 500 });
87
+ }
88
+ };
89
+ var discoverIssuerMethod = async () => {
90
+ try {
91
+ const metadata = await getIssuerMetadata();
92
+ const sdk = new CrexSDK();
93
+ const config = sdk.getServerConfig();
94
+ sdk.updateConfigProp("OIDC", {
95
+ ...config.OIDC,
96
+ issuerMetadata: metadata
97
+ });
98
+ const response = NextResponse2.json({ issuerMetadata: metadata });
99
+ return response;
100
+ } catch (error) {
101
+ return NextResponse2.json({ error: String(error) }, { status: 500 });
102
+ }
103
+ };
104
+
105
+ // src/rpc.ts
106
+ import { CrexLogger as CrexLogger3 } from "@c-rex/core/logger";
107
+
108
+ // ../services/src/baseService.ts
109
+ import { CrexApi } from "@c-rex/core/requests";
110
+
111
+ // ../utils/src/utils.ts
112
+ var getCountryCodeByLang = (lang) => {
113
+ const mappedKeys = Object.keys(FLAGS_BY_LANG);
114
+ if (!mappedKeys.includes(lang)) {
115
+ return lang;
116
+ }
117
+ const country = FLAGS_BY_LANG[lang];
118
+ return country;
119
+ };
120
+
121
+ // ../utils/src/classMerge.ts
122
+ import { clsx } from "clsx";
123
+ import { twMerge } from "tailwind-merge";
124
+
125
+ // ../utils/src/params.ts
126
+ var createParams = (fieldsList, key = "Fields") => {
127
+ if (!fieldsList || fieldsList.length === 0) {
128
+ return [];
129
+ }
130
+ return fieldsList.map((item) => ({
131
+ key,
132
+ value: item
133
+ }));
134
+ };
135
+ var generateQueryParams = (params) => {
136
+ const queryParams = params.map((param) => `${encodeURIComponent(param.key)}=${encodeURIComponent(param.value)}`).join("&");
137
+ return queryParams;
138
+ };
139
+
140
+ // ../utils/src/renditions.ts
141
+ var getFileRenditions = ({ renditions }) => {
142
+ if (renditions == void 0 || renditions.length == 0) {
143
+ return {};
144
+ }
145
+ const filteredRenditions = renditions.filter(
146
+ (item) => item.format != "application/xhtml+xml" && item.format != "application/json" && item.format != "application/llm+xml"
147
+ );
148
+ if (filteredRenditions.length == 0 || filteredRenditions[0] == void 0) {
149
+ return {};
150
+ }
151
+ const result = {};
152
+ filteredRenditions.forEach((item) => {
153
+ const key = item.format;
154
+ if (result[key] == void 0) {
155
+ result[key] = {
156
+ view: "",
157
+ download: ""
158
+ };
159
+ }
160
+ result[key].download = item.links.filter((link) => link.rel == "download")[0]?.href;
161
+ result[key].view = item.links.filter((link) => link.rel == "view")[0]?.href;
162
+ });
163
+ return result;
164
+ };
165
+
166
+ // ../services/src/baseService.ts
167
+ var BaseService = class {
168
+ api;
169
+ endpoint;
170
+ /**
171
+ * Creates a new instance of BaseService.
172
+ *
173
+ * @param endpoint - The API endpoint URL for this service
174
+ */
175
+ constructor(endpoint) {
176
+ this.api = new CrexApi();
177
+ this.endpoint = endpoint;
178
+ }
179
+ /**
180
+ * Makes an API request to the specified endpoint.
181
+ *
182
+ * @param options - Request configuration options
183
+ * @param options.path - Optional path to append to the endpoint
184
+ * @param options.params - Optional query parameters to include in the request
185
+ * @param options.method - HTTP method to use (defaults to 'get')
186
+ * @param options.transformer - Optional function to transform the response data
187
+ * @returns The response data, optionally transformed
188
+ * @throws Error if the API request fails
189
+ */
190
+ async request({
191
+ path = "",
192
+ method = "get",
193
+ params = [],
194
+ headers = {},
195
+ transformer = (response) => response
196
+ }) {
197
+ let url = `${this.endpoint}${path}`;
198
+ const queryParams = generateQueryParams(params);
199
+ if (queryParams.length > 0) {
200
+ url += `?${queryParams}`;
201
+ }
202
+ const response = await this.api.execute({
203
+ url,
204
+ method,
205
+ headers
206
+ });
207
+ return await transformer(response);
208
+ }
209
+ };
210
+
211
+ // ../services/src/transforms/documentTypes.ts
212
+ import { CrexSDK as CrexSDK2 } from "@c-rex/core/sdk";
213
+ import { cookies as cookies2 } from "next/headers";
214
+
215
+ // ../services/src/transforms/information.ts
216
+ import { cookies as cookies3 } from "next/headers";
217
+ import { CrexLogger } from "@c-rex/core/logger";
218
+ import { CrexSDK as CrexSDK3 } from "@c-rex/core/sdk";
219
+ var transformInformationUnits = async (data) => {
220
+ const logger = new CrexLogger();
221
+ const sdk = new CrexSDK3();
222
+ const frontEndConfig = sdk.getClientConfig();
223
+ const backEndConfig = sdk.getServerConfig();
224
+ const filteredTags = {};
225
+ const items = data.items.map((item) => {
226
+ const type = item.class.labels.filter((item2) => item2.language === EN_LANG)[0].value.toUpperCase();
227
+ const files = getFileRenditions({ renditions: item?.renditions });
228
+ let link = `/topics/${item.shortId}`;
229
+ if (frontEndConfig.results.articlePageLayout == "BLOG") {
230
+ link = `/blog/${item.shortId}`;
231
+ } else if (type == RESULT_TYPES.DOCUMENT) {
232
+ link = `/documents/${item.shortId}`;
233
+ }
234
+ let title = "NO TITLE";
235
+ if (item.titles) {
236
+ title = item.titles[0].value;
237
+ } else if (item.labels) {
238
+ title = item.labels[0].value;
239
+ }
240
+ let language = "NO LANGUAGE";
241
+ if (item.languages.length > 0) {
242
+ language = item.languages[0];
243
+ }
244
+ let versionOf = [];
245
+ if (item?.versionOf && item.versionOf?.labels) {
246
+ versionOf = item.versionOf.labels.map((item2) => item2.language).filter((value) => value !== void 0);
247
+ }
248
+ return {
249
+ language,
250
+ title,
251
+ type,
252
+ localeType: "",
253
+ revision: item.revision,
254
+ shortId: item.shortId,
255
+ multipleVersions: versionOf,
256
+ disabled: frontEndConfig.results.disabledResults.includes(type),
257
+ link,
258
+ files
259
+ };
260
+ });
261
+ if (data.tags) {
262
+ const contentLang = (cookies3().get(CONTENT_LANG_KEY)?.value || EN_LANG).toLowerCase();
263
+ const splittedContentLang = contentLang.split("-")[0];
264
+ for (const [key, value] of Object.entries(data.tags)) {
265
+ if (!value || !value.items || value.items.length === 0) {
266
+ continue;
267
+ }
268
+ if (!backEndConfig.search.tags.includes(key)) {
269
+ continue;
270
+ }
271
+ const aux = value.items.map((item) => {
272
+ if (item?.shortId === void 0) return null;
273
+ if (Number(item.hits) === 0) return null;
274
+ if (item?.labels === void 0 || item?.labels.length === 0) {
275
+ logger.log({
276
+ level: "warning",
277
+ message: `No labels on item with id ${item.shortId} from category ${key}`
278
+ });
279
+ return null;
280
+ }
281
+ let label = "";
282
+ for (const labelItem of item.labels) {
283
+ if (labelItem.language === void 0) {
284
+ logger.log({
285
+ level: "info",
286
+ message: `No language on label ${labelItem.value} from category ${key}`
287
+ });
288
+ label = labelItem.value;
289
+ break;
290
+ }
291
+ if (labelItem.language.toLowerCase() === contentLang || labelItem.language.toLowerCase() === splittedContentLang) {
292
+ label = labelItem.value;
293
+ break;
294
+ }
295
+ label = labelItem.value;
296
+ }
297
+ return {
298
+ hits: item.hits,
299
+ total: item.total,
300
+ label,
301
+ active: false,
302
+ shortId: item.shortId
303
+ };
304
+ }).filter((item) => item !== null);
305
+ if (aux.length === 0) {
306
+ continue;
307
+ }
308
+ filteredTags[key] = aux;
309
+ }
310
+ }
311
+ return {
312
+ tags: filteredTags,
313
+ items,
314
+ pageInfo: data.pageInfo
315
+ };
316
+ };
317
+ var transformSuggestions = (data, query) => {
318
+ const suggestions = [];
319
+ const comparableList = [];
320
+ data.suggestions.forEach((item) => {
321
+ suggestions.push(item.value);
322
+ comparableList.push(item.value.toLowerCase());
323
+ });
324
+ if (!comparableList.includes(query.toLowerCase())) {
325
+ return [query, ...suggestions];
326
+ }
327
+ return suggestions;
328
+ };
329
+
330
+ // ../services/src/informationUnits.ts
331
+ var InformationUnitsService = class extends BaseService {
332
+ constructor() {
333
+ super("InformationUnits/");
334
+ }
335
+ /**
336
+ * Retrieves a list of information units based on specified criteria.
337
+ *
338
+ * @param options - Options for filtering and paginating the information units list
339
+ * @param options.queries - Optional search query string
340
+ * @param options.page - Optional page number for pagination (defaults to 1)
341
+ * @param options.fields - Optional array of fields to include in the response
342
+ * @param options.filters - Optional array of filter strings to apply
343
+ * @param options.languages - Optional array of language codes to filter by
344
+ * @returns A promise that resolves to the information units response
345
+ * @throws Error if the API request fails
346
+ */
347
+ async getList({
348
+ queries = "",
349
+ page = 1,
350
+ fields = [],
351
+ filters = [],
352
+ tags = [],
353
+ restrict = [],
354
+ languages = [],
355
+ wildcard = WILD_CARD_OPTIONS.BOTH,
356
+ operator = OPERATOR_OPTIONS.AND,
357
+ like = false
358
+ }) {
359
+ const remainFields = createParams(fields, "Fields");
360
+ const remainFilters = createParams(filters, "Filter");
361
+ const restrictions = createParams(restrict, "Restrict");
362
+ const remainTags = createParams(tags, "Tags");
363
+ const params = [
364
+ { key: "pageSize", value: "12" },
365
+ { key: "wildcard", value: wildcard.toLowerCase() },
366
+ { key: "PageNumber", value: page.toString() },
367
+ { key: "Operator", value: operator },
368
+ { key: "Like", value: like.toString() },
369
+ ...remainTags,
370
+ ...remainFields,
371
+ ...remainFilters,
372
+ ...restrictions
373
+ ];
374
+ if (languages.length > 0) {
375
+ const languageParam = `VALUES ?lang { ${languages.map((lang) => `"${lang}"`).join(" ")} } ?s iirds:language ?lang .`;
376
+ params.push({ key: "sparqlWhere", value: languageParam });
377
+ }
378
+ if (queries.length > 0) {
379
+ params.push(
380
+ { key: "Query", value: queries }
381
+ );
382
+ }
383
+ return await this.request({
384
+ params,
385
+ transformer: transformInformationUnits
386
+ });
387
+ }
388
+ /**
389
+ * Retrieves a specific information unit by its ID.
390
+ * Includes renditions, directory nodes, version information, titles, languages, and labels.
391
+ *
392
+ * @param options - Options for retrieving the information unit
393
+ * @param options.id - The unique identifier of the information unit
394
+ * @returns A promise that resolves to the information unit data
395
+ * @throws Error if the API request fails
396
+ */
397
+ async getItem({ id, shouldGetAllFields = false }) {
398
+ const params = [];
399
+ if (!shouldGetAllFields) {
400
+ params.push(
401
+ { key: "Fields", value: "renditions" },
402
+ { key: "Fields", value: "directoryNodes" },
403
+ { key: "Fields", value: "versionOf" },
404
+ { key: "Fields", value: "titles" },
405
+ { key: "Fields", value: "languages" },
406
+ { key: "Fields", value: "labels" },
407
+ { key: "Fields", value: "packages" },
408
+ { key: "Fields", value: "created" },
409
+ { key: "Fields", value: "revision" }
410
+ );
411
+ }
412
+ return await this.request({
413
+ path: id,
414
+ params
415
+ });
416
+ }
417
+ /**
418
+ * Retrieves autocomplete suggestions based on a query prefix.
419
+ *
420
+ * @param options - Options for retrieving suggestions
421
+ * @param options.query - The query prefix to get suggestions for
422
+ * @param options.language - The language of the suggestions
423
+ * @returns A promise that resolves to an array of suggestion strings
424
+ * @throws Error if the API request fails
425
+ */
426
+ async getSuggestions({ query, language }) {
427
+ return await this.request({
428
+ path: "Suggestions",
429
+ params: [
430
+ { key: "prefix", value: query },
431
+ { key: "lang", value: language }
432
+ ],
433
+ transformer: (data) => transformSuggestions(data, query)
434
+ });
435
+ }
436
+ };
437
+
438
+ // ../services/src/language.ts
439
+ import { CrexSDK as CrexSDK4 } from "@c-rex/core/sdk";
440
+ var LanguageService = class extends BaseService {
441
+ constructor() {
442
+ const sdk = new CrexSDK4();
443
+ const configs = sdk.getClientConfig();
444
+ super(configs.languageSwitcher.endpoint);
445
+ }
446
+ /**
447
+ * Retrieves a list of available languages and their associated countries.
448
+ * Transforms the API response to include language code, country code, and original value.
449
+ *
450
+ * @returns A promise that resolves to an array of language and country objects
451
+ * @throws Error if the API request fails
452
+ */
453
+ async getLanguagesAndCountries() {
454
+ return await this.request({
455
+ transformer: (data) => {
456
+ const countryCodeList = data.map((item) => {
457
+ const splittedValue = item.value.split("-");
458
+ const lang = splittedValue[0];
459
+ let country = splittedValue[0];
460
+ if (splittedValue.length > 1) {
461
+ country = splittedValue[1];
462
+ } else {
463
+ country = getCountryCodeByLang(lang);
464
+ }
465
+ return {
466
+ country,
467
+ lang,
468
+ value: item.value
469
+ };
470
+ });
471
+ return countryCodeList.sort((a, b) => {
472
+ return a.value.localeCompare(b.value);
473
+ });
474
+ }
475
+ });
476
+ }
477
+ };
478
+
479
+ // ../services/src/transforms/topics.ts
480
+ import { cookies as cookies4 } from "next/headers";
481
+ import { CrexLogger as CrexLogger2 } from "@c-rex/core/logger";
482
+ import { CrexSDK as CrexSDK5 } from "@c-rex/core/sdk";
483
+
484
+ // src/rpc.ts
485
+ import { NextResponse as NextResponse3 } from "next/server";
486
+ var serviceRegistry = {
487
+ InformationUnitsService,
488
+ CrexLogger: CrexLogger3,
489
+ LanguageService
490
+ };
491
+ var POST = async (req) => {
492
+ try {
493
+ const { method, params } = await req.json();
494
+ const [serviceName, methodName] = method.split(".");
495
+ const ServiceClass = serviceRegistry[serviceName];
496
+ if (!ServiceClass) {
497
+ return NextResponse3.json({ error: `Service '${serviceName}' not found` }, { status: 404 });
498
+ }
499
+ const serviceInstance = new ServiceClass();
500
+ const handler = serviceInstance[methodName];
501
+ if (typeof handler !== "function") {
502
+ return NextResponse3.json({ error: `Method '${methodName}' not found on '${serviceName}'` }, { status: 404 });
503
+ }
504
+ const result = await handler.call(serviceInstance, params);
505
+ return NextResponse3.json({ data: result });
506
+ } catch (error) {
507
+ const logger = new CrexLogger3();
508
+ logger.log({
509
+ level: "error",
510
+ message: `RPC.POST error: ${error}`
511
+ });
512
+ return NextResponse3.json({ error: String(error) }, { status: 500 });
513
+ }
514
+ };
515
+ export {
516
+ POST,
517
+ discoverIssuerMethod,
518
+ getCookieFromServer,
519
+ getTokenMethod,
520
+ saveCookie
521
+ };
522
+ //# sourceMappingURL=index.mjs.map