@sharedid-edge/core
The platform-neutral part of SharedID Edge: the request handler that sets the Prebid SharedID as a server-set first-party cookie, the consent checks, and the module interface. It uses only web-standard APIs (Request, Response, URL, crypto) and has no runtime dependencies, so every adapter bundles the same code.
Most publishers don't use this package directly: deploy one of the adapters instead (Cloudflare, Node.js, AWS Lambda). Use it to write an adapter for another platform, or a module.
Using it in code
ts
import { createHandler, resolveConfig } from '@sharedid-edge/core';
import { builtInModules } from '@sharedid-edge/modules';
const handler = createHandler({ config: resolveConfig(env), modules: builtInModules });
// Per request: the platform fills in what only it knows, such as the connecting address.
const response = await handler(request, { clientIp: '192.0.2.1', country: 'DE', isEU: true });resolveConfig(env)reads theSID_*settings (the Configuration reference) and throwsConfigErroron an invalid one.createHandler(options)returns(request, platform?) => Promise<Response>. It answers the routes underSID_BASE_PATHand returns a 404 for any other path, so send it only that path and serve the rest of the site as before.PlatformInfocarries what the platform knows about the visitor:clientIp,isEUand location fields. Fill location withlocationInfo, which drops empty and invalid values the same way on every platform. Only use data the platform itself sets; seepackages/adapters/AGENTS.md. Its optionaltrafficis the platform's own bot verdict (aTrafficReport, such as Cloudflare Bot Management's score), merged as sourceplatform.TrafficReport,TrafficSignal,mergeTrafficandskipsBotare the shared traffic signal (ortb2.device.ext.traffic): modules report withtrafficin their result and core merges the reports, most cautious first, on/v1and/sync(where onlySID_SKIP_BOTSuses them). See the spec's Traffic signal.parseCookies(header)reads aCookieheader (the first value of each name),cookieValues(header, name)every value of one name in header order, for cookies that may be duplicated acrossDomains (a host-only copy next to a domain one), andserializeCookie(name, value, options, date)writes aSet-Cookie.- For an adapter's plumbing around the handler:
splitHeaders(response.headers)gives eachSet-Cookieseparately (for platforms that keep one value per header name) and the other headers;logRequestFailure(error)logs a failed request without its message, which may hold request data;handlerOrMisconfigured(build, misconfigured)builds the handler, or logs aConfigErrorand returns your handler that answers every request with a 500;publicOriginFromEnv(env)readsSID_PUBLIC_ORIGINas an option;booleanFromEnv(value, fallback)accepts1/true/yes/onor0/false/no/off(case-insensitive, with surrounding whitespace ignored) and returnsfallbackfor missing, blank or unrecognized values;headerValue(headers, name)gives a trimmed header, orundefinedwhen it's blank;parseHeaderMap(value, setting, fields, example)parses a JSON setting that maps fields to header names (throwingConfigError), withisHeaderNamefor single names; andlocationWithEU(source)islocationInfoplusisEUfrom the country, for platforms that report no EU flag. defineModule,EdgeModule,ModuleContextandModuleRouteare the module interface (EdgeModule.routeschooses/v1,/syncor both); see Adding a module andpackages/modules/AGENTS.md.
The exact behaviour (routes, cookies, consent, responses) is in spec/SPEC.md, and the conformance suite checks it against every adapter.