@openpolicy/vite-auto-collect 0.0.20 → 0.0.22

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/dist/index.js CHANGED
@@ -5,6 +5,7 @@ import { parseSync } from "oxc-parser";
5
5
  const SDK_SPECIFIER = "@openpolicy/sdk";
6
6
  const COLLECTING_NAME = "collecting";
7
7
  const THIRD_PARTY_NAME = "thirdParty";
8
+ const IGNORE_NAME = "Ignore";
8
9
  /**
9
10
  * Extract `collecting()` and `thirdParty()` call metadata from a single source file.
10
11
  *
@@ -40,6 +41,7 @@ function extractFromFile(filename, code) {
40
41
  const program = result.program;
41
42
  const collectingNames = collectSdkBindings(program, COLLECTING_NAME);
42
43
  const thirdPartyNames = collectSdkBindings(program, THIRD_PARTY_NAME);
44
+ const ignoreNames = collectSdkBindings(program, IGNORE_NAME);
43
45
  if (collectingNames.size === 0 && thirdPartyNames.size === 0) return empty;
44
46
  const dataCollected = {};
45
47
  const thirdParties = [];
@@ -54,7 +56,7 @@ function extractFromFile(filename, code) {
54
56
  if (!args || args.length < 3) return;
55
57
  const category = extractStringLiteral(args[0]);
56
58
  if (category === null) return;
57
- const labels = extractLabelKeys(args[2]);
59
+ const labels = extractLabelKeys(args[2], ignoreNames);
58
60
  if (labels === null) return;
59
61
  const existing = dataCollected[category] ?? [];
60
62
  const seen = new Set(existing);
@@ -128,8 +130,13 @@ function extractStringLiteral(node) {
128
130
  * Extract the string values from a plain `{ fieldName: "Human Label" }`
129
131
  * object literal. Returns an array of label strings, deduped while
130
132
  * preserving insertion order. Returns `null` if the shape doesn't match.
133
+ *
134
+ * Properties whose value is an `Identifier` matching a tracked local name
135
+ * bound to the SDK's `Ignore` export are treated as explicit opt-outs and
136
+ * skipped silently — producing the same observable result as omitting the
137
+ * field from the record did before.
131
138
  */
132
- function extractLabelKeys(node) {
139
+ function extractLabelKeys(node, ignoreNames) {
133
140
  if (!node || node.type !== "ObjectExpression") return null;
134
141
  const properties = node.properties;
135
142
  if (!properties) return null;
@@ -138,10 +145,14 @@ function extractLabelKeys(node) {
138
145
  for (const prop of properties) {
139
146
  if (prop.type !== "Property") continue;
140
147
  const val = prop.value;
141
- if (!val || val.type !== "Literal" || typeof val.value !== "string") continue;
142
- if (seen.has(val.value)) continue;
143
- seen.add(val.value);
144
- labels.push(val.value);
148
+ if (!val) continue;
149
+ if (val.type === "Literal" && typeof val.value === "string") {
150
+ if (seen.has(val.value)) continue;
151
+ seen.add(val.value);
152
+ labels.push(val.value);
153
+ continue;
154
+ }
155
+ if (val.type === "Identifier" && typeof val.name === "string" && ignoreNames.has(val.name)) {}
145
156
  }
146
157
  return labels;
147
158
  }
@@ -479,6 +490,15 @@ function autoCollect(options = {}) {
479
490
  return {
480
491
  name: "openpolicy-auto-collect",
481
492
  enforce: "pre",
493
+ config() {
494
+ return {
495
+ optimizeDeps: { exclude: ["@openpolicy/sdk"] },
496
+ ssr: {
497
+ optimizeDeps: { exclude: ["@openpolicy/sdk"] },
498
+ noExternal: ["@openpolicy/sdk"]
499
+ }
500
+ };
501
+ },
482
502
  configResolved(config) {
483
503
  resolvedRoot = config.root;
484
504
  resolvedSrcDir = resolve(config.root, srcDirOpt);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/analyse.ts","../src/known-packages.ts","../src/scan.ts","../src/index.ts"],"sourcesContent":["import { parseSync } from \"oxc-parser\";\n\nconst SDK_SPECIFIER = \"@openpolicy/sdk\";\nconst COLLECTING_NAME = \"collecting\";\nconst THIRD_PARTY_NAME = \"thirdParty\";\n\ntype AnyNode = { type: string; [key: string]: unknown };\n\nexport type ThirdPartyEntry = {\n\tname: string;\n\tpurpose: string;\n\tpolicyUrl: string;\n};\n\nexport type ExtractResult = {\n\tdataCollected: Record<string, string[]>;\n\tthirdParties: ThirdPartyEntry[];\n};\n\n/**\n * Extract `collecting()` and `thirdParty()` call metadata from a single source file.\n *\n * Returns an `ExtractResult` with `dataCollected` (category → labels) and\n * `thirdParties` (array of third-party entries). Files with no matching calls\n * — or that fail to parse — return empty defaults.\n *\n * The analyser runs in two phases:\n * 1. Collect local names bound to `collecting` / `thirdParty` imported from\n * `@openpolicy/sdk` (handles renamed imports, skips type-only imports,\n * ignores look-alikes imported from other modules).\n * 2. Walk the program body and inspect every `CallExpression` whose callee\n * is one of those tracked local names.\n */\nexport function extractFromFile(filename: string, code: string): ExtractResult {\n\tconst empty: ExtractResult = { dataCollected: {}, thirdParties: [] };\n\tlet result: ReturnType<typeof parseSync>;\n\ttry {\n\t\tresult = parseSync(filename, code);\n\t} catch {\n\t\tconsole.warn(`[openpolicy-auto-collect] parse error in ${filename}`);\n\t\treturn empty;\n\t}\n\n\tif (result.errors.length > 0) {\n\t\t// Hard parse failures only — oxc reports recoverable errors but still\n\t\t// produces a usable AST, so we keep going and let the walker decide.\n\t\tconst fatal = result.errors.some((e) => e.severity === (\"Error\" as never));\n\t\tif (fatal) {\n\t\t\tconsole.warn(`[openpolicy-auto-collect] parse error in ${filename}`);\n\t\t\treturn empty;\n\t\t}\n\t}\n\n\tconst program = result.program as unknown as AnyNode;\n\tconst collectingNames = collectSdkBindings(program, COLLECTING_NAME);\n\tconst thirdPartyNames = collectSdkBindings(program, THIRD_PARTY_NAME);\n\tif (collectingNames.size === 0 && thirdPartyNames.size === 0) return empty;\n\n\tconst dataCollected: Record<string, string[]> = {};\n\tconst thirdParties: ThirdPartyEntry[] = [];\n\tconst seenThirdParties = new Set<string>();\n\n\twalk(program, (node) => {\n\t\tif (node.type !== \"CallExpression\") return;\n\t\tconst callee = node.callee as AnyNode | undefined;\n\t\tif (!callee || callee.type !== \"Identifier\") return;\n\t\tconst calleeName = callee.name as string;\n\t\tconst args = node.arguments as AnyNode[] | undefined;\n\n\t\tif (collectingNames.has(calleeName)) {\n\t\t\tif (!args || args.length < 3) return;\n\t\t\tconst category = extractStringLiteral(args[0]);\n\t\t\tif (category === null) return;\n\t\t\tconst labels = extractLabelKeys(args[2]);\n\t\t\tif (labels === null) return;\n\t\t\tconst existing = dataCollected[category] ?? [];\n\t\t\tconst seen = new Set(existing);\n\t\t\tfor (const label of labels) {\n\t\t\t\tif (!seen.has(label)) {\n\t\t\t\t\texisting.push(label);\n\t\t\t\t\tseen.add(label);\n\t\t\t\t}\n\t\t\t}\n\t\t\tdataCollected[category] = existing;\n\t\t} else if (thirdPartyNames.has(calleeName)) {\n\t\t\tif (!args || args.length < 3) return;\n\t\t\tconst name = extractStringLiteral(args[0]);\n\t\t\tif (name === null) return;\n\t\t\tconst purpose = extractStringLiteral(args[1]);\n\t\t\tif (purpose === null) return;\n\t\t\tconst policyUrl = extractStringLiteral(args[2]);\n\t\t\tif (policyUrl === null) return;\n\t\t\t// Deduplicate by name — first occurrence wins (files walked in sorted order)\n\t\t\tif (seenThirdParties.has(name)) return;\n\t\t\tseenThirdParties.add(name);\n\t\t\tthirdParties.push({ name, purpose, policyUrl });\n\t\t}\n\t});\n\n\treturn { dataCollected, thirdParties };\n}\n\n/**\n * Walk `ImportDeclaration` nodes and return the local names bound to the given\n * `exportName` imported from `@openpolicy/sdk`. Skips type-only imports and\n * specifiers whose imported name doesn't match.\n */\nfunction collectSdkBindings(program: AnyNode, exportName: string): Set<string> {\n\tconst names = new Set<string>();\n\tconst body = program.body as AnyNode[] | undefined;\n\tif (!body) return names;\n\tfor (const node of body) {\n\t\tif (node.type !== \"ImportDeclaration\") continue;\n\t\tif ((node.importKind as string | undefined) === \"type\") continue;\n\t\tconst source = node.source as AnyNode | undefined;\n\t\tif (!source || source.value !== SDK_SPECIFIER) continue;\n\t\tconst specifiers = node.specifiers as AnyNode[] | undefined;\n\t\tif (!specifiers) continue;\n\t\tfor (const spec of specifiers) {\n\t\t\tif (spec.type !== \"ImportSpecifier\") continue;\n\t\t\tif ((spec.importKind as string | undefined) === \"type\") continue;\n\t\t\tconst imported = spec.imported as AnyNode | undefined;\n\t\t\tif (!imported) continue;\n\t\t\t// ESTree allows either an Identifier (name) or a string Literal (value)\n\t\t\t// for the imported binding (e.g. `import { \"foo\" as bar }`).\n\t\t\tconst importedName =\n\t\t\t\timported.type === \"Identifier\"\n\t\t\t\t\t? (imported.name as string | undefined)\n\t\t\t\t\t: imported.type === \"Literal\"\n\t\t\t\t\t\t? typeof imported.value === \"string\"\n\t\t\t\t\t\t\t? imported.value\n\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t: undefined;\n\t\t\tif (importedName !== exportName) continue;\n\t\t\tconst local = spec.local as AnyNode | undefined;\n\t\t\tif (!local || local.type !== \"Identifier\") continue;\n\t\t\tnames.add(local.name as string);\n\t\t}\n\t}\n\treturn names;\n}\n\n/**\n * If `node` is a string `Literal`, return its string value. Otherwise\n * return `null` so the caller silently skips the call.\n */\nfunction extractStringLiteral(node: AnyNode | undefined): string | null {\n\tif (!node) return null;\n\tif (node.type !== \"Literal\") return null;\n\tif (typeof node.value !== \"string\") return null;\n\treturn node.value;\n}\n\n/**\n * Extract the string values from a plain `{ fieldName: \"Human Label\" }`\n * object literal. Returns an array of label strings, deduped while\n * preserving insertion order. Returns `null` if the shape doesn't match.\n */\nfunction extractLabelKeys(node: AnyNode | undefined): string[] | null {\n\tif (!node || node.type !== \"ObjectExpression\") return null;\n\tconst properties = node.properties as AnyNode[] | undefined;\n\tif (!properties) return null;\n\n\tconst labels: string[] = [];\n\tconst seen = new Set<string>();\n\tfor (const prop of properties) {\n\t\tif (prop.type !== \"Property\") continue; // drop SpreadElement silently\n\t\tconst val = prop.value as AnyNode | undefined;\n\t\tif (!val || val.type !== \"Literal\" || typeof val.value !== \"string\")\n\t\t\tcontinue;\n\t\tif (seen.has(val.value)) continue;\n\t\tseen.add(val.value);\n\t\tlabels.push(val.value);\n\t}\n\treturn labels;\n}\n\n/**\n * Recursive AST walker. Visits every `AnyNode` (depth-first) reachable\n * through array / nested-object children and invokes `visit` on each.\n */\nfunction walk(node: AnyNode, visit: (node: AnyNode) => void): void {\n\tvisit(node);\n\tfor (const key of Object.keys(node)) {\n\t\tif (key === \"parent\") continue;\n\t\tconst value = node[key];\n\t\tif (Array.isArray(value)) {\n\t\t\tfor (const item of value) {\n\t\t\t\tif (item && typeof item === \"object\" && typeof item.type === \"string\") {\n\t\t\t\t\twalk(item as AnyNode, visit);\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (\n\t\t\tvalue &&\n\t\t\ttypeof value === \"object\" &&\n\t\t\ttypeof (value as { type?: unknown }).type === \"string\"\n\t\t) {\n\t\t\twalk(value as AnyNode, visit);\n\t\t}\n\t}\n}\n","import type { ThirdPartyEntry } from \"./analyse\";\n\n/**\n * Registry of known npm packages mapped to their ThirdPartyEntry metadata.\n * Multiple package names can point to the same service — deduplication by\n * `ThirdPartyEntry.name` is handled at merge time in the caller.\n */\nexport const KNOWN_PACKAGES: ReadonlyMap<string, ThirdPartyEntry> = new Map([\n\t[\n\t\t\"stripe\",\n\t\t{\n\t\t\tname: \"Stripe\",\n\t\t\tpurpose: \"Payment processing\",\n\t\t\tpolicyUrl: \"https://stripe.com/privacy\",\n\t\t},\n\t],\n\t[\n\t\t\"@stripe/stripe-js\",\n\t\t{\n\t\t\tname: \"Stripe\",\n\t\t\tpurpose: \"Payment processing\",\n\t\t\tpolicyUrl: \"https://stripe.com/privacy\",\n\t\t},\n\t],\n\t[\n\t\t\"braintree\",\n\t\t{\n\t\t\tname: \"Braintree\",\n\t\t\tpurpose: \"Payment processing\",\n\t\t\tpolicyUrl:\n\t\t\t\t\"https://www.braintreepayments.com/legal/braintree-privacy-policy\",\n\t\t},\n\t],\n\t[\n\t\t\"@braintree/browser-drop-in\",\n\t\t{\n\t\t\tname: \"Braintree\",\n\t\t\tpurpose: \"Payment processing\",\n\t\t\tpolicyUrl:\n\t\t\t\t\"https://www.braintreepayments.com/legal/braintree-privacy-policy\",\n\t\t},\n\t],\n\t[\n\t\t\"@sentry/browser\",\n\t\t{\n\t\t\tname: \"Sentry\",\n\t\t\tpurpose: \"Error tracking\",\n\t\t\tpolicyUrl: \"https://sentry.io/privacy/\",\n\t\t},\n\t],\n\t[\n\t\t\"@sentry/node\",\n\t\t{\n\t\t\tname: \"Sentry\",\n\t\t\tpurpose: \"Error tracking\",\n\t\t\tpolicyUrl: \"https://sentry.io/privacy/\",\n\t\t},\n\t],\n\t[\n\t\t\"@sentry/nextjs\",\n\t\t{\n\t\t\tname: \"Sentry\",\n\t\t\tpurpose: \"Error tracking\",\n\t\t\tpolicyUrl: \"https://sentry.io/privacy/\",\n\t\t},\n\t],\n\t[\n\t\t\"@sentry/react\",\n\t\t{\n\t\t\tname: \"Sentry\",\n\t\t\tpurpose: \"Error tracking\",\n\t\t\tpolicyUrl: \"https://sentry.io/privacy/\",\n\t\t},\n\t],\n\t[\n\t\t\"@sentry/vue\",\n\t\t{\n\t\t\tname: \"Sentry\",\n\t\t\tpurpose: \"Error tracking\",\n\t\t\tpolicyUrl: \"https://sentry.io/privacy/\",\n\t\t},\n\t],\n\t[\n\t\t\"@datadog/browser-rum\",\n\t\t{\n\t\t\tname: \"Datadog\",\n\t\t\tpurpose: \"Monitoring\",\n\t\t\tpolicyUrl: \"https://www.datadoghq.com/legal/privacy/\",\n\t\t},\n\t],\n\t[\n\t\t\"dd-trace\",\n\t\t{\n\t\t\tname: \"Datadog\",\n\t\t\tpurpose: \"Monitoring\",\n\t\t\tpolicyUrl: \"https://www.datadoghq.com/legal/privacy/\",\n\t\t},\n\t],\n\t[\n\t\t\"posthog-js\",\n\t\t{\n\t\t\tname: \"PostHog\",\n\t\t\tpurpose: \"Product analytics\",\n\t\t\tpolicyUrl: \"https://posthog.com/privacy\",\n\t\t},\n\t],\n\t[\n\t\t\"posthog-node\",\n\t\t{\n\t\t\tname: \"PostHog\",\n\t\t\tpurpose: \"Product analytics\",\n\t\t\tpolicyUrl: \"https://posthog.com/privacy\",\n\t\t},\n\t],\n\t[\n\t\t\"mixpanel-browser\",\n\t\t{\n\t\t\tname: \"Mixpanel\",\n\t\t\tpurpose: \"Product analytics\",\n\t\t\tpolicyUrl: \"https://mixpanel.com/legal/privacy-policy/\",\n\t\t},\n\t],\n\t[\n\t\t\"@segment/analytics-next\",\n\t\t{\n\t\t\tname: \"Segment\",\n\t\t\tpurpose: \"Customer data platform\",\n\t\t\tpolicyUrl: \"https://www.twilio.com/en-us/legal/privacy\",\n\t\t},\n\t],\n\t[\n\t\t\"@amplitude/analytics-browser\",\n\t\t{\n\t\t\tname: \"Amplitude\",\n\t\t\tpurpose: \"Product analytics\",\n\t\t\tpolicyUrl: \"https://amplitude.com/privacy\",\n\t\t},\n\t],\n\t[\n\t\t\"amplitude-js\",\n\t\t{\n\t\t\tname: \"Amplitude\",\n\t\t\tpurpose: \"Product analytics\",\n\t\t\tpolicyUrl: \"https://amplitude.com/privacy\",\n\t\t},\n\t],\n\t[\n\t\t\"@vercel/analytics\",\n\t\t{\n\t\t\tname: \"Vercel Analytics\",\n\t\t\tpurpose: \"Web analytics\",\n\t\t\tpolicyUrl: \"https://vercel.com/legal/privacy-policy\",\n\t\t},\n\t],\n\t[\n\t\t\"plausible-tracker\",\n\t\t{\n\t\t\tname: \"Plausible\",\n\t\t\tpurpose: \"Web analytics\",\n\t\t\tpolicyUrl: \"https://plausible.io/privacy\",\n\t\t},\n\t],\n\t[\n\t\t\"logrocket\",\n\t\t{\n\t\t\tname: \"LogRocket\",\n\t\t\tpurpose: \"Session recording\",\n\t\t\tpolicyUrl: \"https://logrocket.com/privacy/\",\n\t\t},\n\t],\n\t[\n\t\t\"@hotjar/browser\",\n\t\t{\n\t\t\tname: \"Hotjar\",\n\t\t\tpurpose: \"Session recording\",\n\t\t\tpolicyUrl: \"https://www.hotjar.com/legal/policies/privacy/\",\n\t\t},\n\t],\n\t[\n\t\t\"resend\",\n\t\t{\n\t\t\tname: \"Resend\",\n\t\t\tpurpose: \"Transactional email\",\n\t\t\tpolicyUrl: \"https://resend.com/legal/privacy-policy\",\n\t\t},\n\t],\n\t[\n\t\t\"@sendgrid/mail\",\n\t\t{\n\t\t\tname: \"SendGrid\",\n\t\t\tpurpose: \"Transactional email\",\n\t\t\tpolicyUrl: \"https://www.twilio.com/en-us/legal/privacy\",\n\t\t},\n\t],\n\t[\n\t\t\"intercom-client\",\n\t\t{\n\t\t\tname: \"Intercom\",\n\t\t\tpurpose: \"Customer messaging\",\n\t\t\tpolicyUrl: \"https://www.intercom.com/legal/privacy\",\n\t\t},\n\t],\n\t[\n\t\t\"@intercom/messenger-js-sdk\",\n\t\t{\n\t\t\tname: \"Intercom\",\n\t\t\tpurpose: \"Customer messaging\",\n\t\t\tpolicyUrl: \"https://www.intercom.com/legal/privacy\",\n\t\t},\n\t],\n]);\n","import type { Dirent } from \"node:fs\";\nimport { readdir } from \"node:fs/promises\";\nimport { extname, join } from \"node:path\";\n\nconst DEFAULT_IGNORES: ReadonlySet<string> = new Set([\n\t\"node_modules\",\n\t\"dist\",\n\t\".git\",\n\t\".next\",\n\t\".output\",\n\t\".svelte-kit\",\n\t\".cache\",\n]);\n\n/**\n * Recursively walks `root`, returning absolute paths of every regular file\n * whose extension is in `extensions`. Directories whose basename appears in\n * the built-in ignore list (or the extra `ignore` argument) are skipped\n * entirely.\n *\n * Missing roots resolve to an empty array — the plugin must not throw if the\n * user's `srcDir` hasn't been created yet.\n */\nexport async function walkSources(\n\troot: string,\n\textensions: readonly string[],\n\tignore: readonly string[] = [],\n): Promise<string[]> {\n\tconst ignored = new Set<string>([...DEFAULT_IGNORES, ...ignore]);\n\tconst exts = new Set(extensions);\n\tconst results: string[] = [];\n\n\tasync function walk(dir: string): Promise<void> {\n\t\tlet entries: Dirent[];\n\t\ttry {\n\t\t\tentries = (await readdir(dir, { withFileTypes: true })) as Dirent[];\n\t\t} catch (err) {\n\t\t\tconst code = (err as NodeJS.ErrnoException).code;\n\t\t\tif (code === \"ENOENT\" || code === \"ENOTDIR\") return;\n\t\t\tthrow err;\n\t\t}\n\t\tfor (const entry of entries) {\n\t\t\tif (ignored.has(entry.name)) continue;\n\t\t\tconst full = join(dir, entry.name);\n\t\t\tif (entry.isDirectory()) {\n\t\t\t\tawait walk(full);\n\t\t\t} else if (entry.isFile() && exts.has(extname(entry.name))) {\n\t\t\t\tresults.push(full);\n\t\t\t}\n\t\t}\n\t}\n\n\tawait walk(root);\n\tresults.sort();\n\treturn results;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { relative, resolve } from \"node:path\";\nimport type { Plugin, ViteDevServer } from \"vite\";\nimport { extractFromFile, type ThirdPartyEntry } from \"./analyse\";\nimport { KNOWN_PACKAGES } from \"./known-packages\";\nimport { walkSources } from \"./scan\";\n\nexport type AutoCollectOptions = {\n\t/**\n\t * Directory walked for `collecting()` calls. Resolved relative to the\n\t * Vite project root. Defaults to `\"src\"`.\n\t */\n\tsrcDir?: string;\n\t/**\n\t * File extensions scanned. Defaults to `[\".ts\", \".tsx\"]`.\n\t */\n\textensions?: string[];\n\t/**\n\t * Extra directory names skipped during the walk. Appended to the built-in\n\t * defaults (`node_modules`, `dist`, `.git`, `.next`, `.output`,\n\t * `.svelte-kit`, `.cache`).\n\t */\n\tignore?: string[];\n\n\tthirdParties?: {\n\t\tusePackageJson?: boolean;\n\t};\n};\n\n/**\n * Marker returned from `resolveId` so `load` can recognise a hit. The leading\n * NUL prefix is the Rollup/Vite convention for virtual IDs so other plugins\n * leave it alone.\n */\nconst RESOLVED_VIRTUAL_ID = \"\\0virtual:openpolicy/auto-collected\";\n\n/**\n * Matches any path that lives inside the `@openpolicy/sdk` package, whether\n * it's resolved via a workspace symlink (`.../packages/sdk/...`) or a\n * published `node_modules` install (`.../@openpolicy/sdk/...`). Used to scope\n * the `./auto-collected` relative-import interception to the SDK itself.\n */\nconst SDK_PATH_PATTERN = /[\\\\/](?:@openpolicy[\\\\/]sdk|packages[\\\\/]sdk)[\\\\/]/;\n\n/**\n * Matches the relative specifier the SDK uses for its own internal\n * `./auto-collected` import. Both the source form (`./auto-collected`) and\n * the published dist form (`./auto-collected.js`) need to be intercepted:\n * the former applies when consumers resolve the SDK via its workspace\n * source, the latter when resolving against `dist/` with the separate\n * `auto-collected.js` chunk.\n */\nconst AUTO_COLLECTED_SPECIFIER = /^\\.\\/auto-collected(?:\\.js)?$/;\n\n/**\n * Vite plugin that scans source files for `@openpolicy/sdk` `collecting()`\n * calls at the start of each build and inlines the discovered categories into\n * the SDK's `dataCollected` sentinel.\n *\n * Internally the plugin intercepts `@openpolicy/sdk`'s own relative import of\n * `./auto-collected` and redirects it to a virtual module whose body is a\n * literal `export const dataCollected = { ... }`. Because the replacement\n * becomes part of the consumer's own module graph, the scanned data survives\n * any downstream bundler boundary (e.g. nitro's SSR output), which a shared\n * module-level registry would not.\n */\nexport function autoCollect(options: AutoCollectOptions = {}): Plugin {\n\tconst srcDirOpt = options.srcDir ?? \"src\";\n\tconst extensions = options.extensions ?? [\".ts\", \".tsx\"];\n\tconst ignore = options.ignore ?? [];\n\tconst usePackageJsonOpt = options.thirdParties?.usePackageJson ?? false;\n\tlet resolvedRoot: string;\n\tlet resolvedSrcDir: string;\n\tlet scanned: {\n\t\tdataCollected: Record<string, string[]>;\n\t\tthirdParties: ThirdPartyEntry[];\n\t} = { dataCollected: {}, thirdParties: [] };\n\n\tasync function detectFromPackageJson(\n\t\troot: string,\n\t): Promise<ThirdPartyEntry[]> {\n\t\tlet raw: string;\n\t\ttry {\n\t\t\traw = await readFile(resolve(root, \"package.json\"), \"utf8\");\n\t\t} catch {\n\t\t\treturn [];\n\t\t}\n\t\tlet pkg: {\n\t\t\tdependencies?: Record<string, string>;\n\t\t\tdevDependencies?: Record<string, string>;\n\t\t};\n\t\ttry {\n\t\t\tpkg = JSON.parse(raw) as typeof pkg;\n\t\t} catch {\n\t\t\treturn [];\n\t\t}\n\t\tconst allDeps = {\n\t\t\t...pkg.dependencies,\n\t\t\t...pkg.devDependencies,\n\t\t};\n\t\tconst entries: ThirdPartyEntry[] = [];\n\t\tconst seenNames = new Set<string>();\n\t\tfor (const pkgName of Object.keys(allDeps)) {\n\t\t\tconst entry = KNOWN_PACKAGES.get(pkgName);\n\t\t\tif (entry && !seenNames.has(entry.name)) {\n\t\t\t\tseenNames.add(entry.name);\n\t\t\t\tentries.push(entry);\n\t\t\t}\n\t\t}\n\t\treturn entries;\n\t}\n\n\tasync function scanAndMerge(): Promise<typeof scanned> {\n\t\tconst files = await walkSources(resolvedSrcDir, extensions, ignore);\n\t\tconst mergedData: Record<string, string[]> = {};\n\t\tconst mergedParties: ThirdPartyEntry[] = [];\n\t\tconst seenParties = new Set<string>();\n\t\tfor (const file of files) {\n\t\t\tlet code: string;\n\t\t\ttry {\n\t\t\t\tcode = await readFile(file, \"utf8\");\n\t\t\t} catch {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst extracted = extractFromFile(file, code);\n\t\t\tfor (const [category, labels] of Object.entries(\n\t\t\t\textracted.dataCollected,\n\t\t\t)) {\n\t\t\t\tconst existing = mergedData[category] ?? [];\n\t\t\t\tconst seen = new Set(existing);\n\t\t\t\tfor (const label of labels) {\n\t\t\t\t\tif (!seen.has(label)) {\n\t\t\t\t\t\texisting.push(label);\n\t\t\t\t\t\tseen.add(label);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tmergedData[category] = existing;\n\t\t\t}\n\t\t\tfor (const entry of extracted.thirdParties) {\n\t\t\t\tif (!seenParties.has(entry.name)) {\n\t\t\t\t\tseenParties.add(entry.name);\n\t\t\t\t\tmergedParties.push(entry);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (usePackageJsonOpt) {\n\t\t\tconst pkgEntries = await detectFromPackageJson(resolvedRoot);\n\t\t\tfor (const entry of pkgEntries) {\n\t\t\t\tif (!seenParties.has(entry.name)) {\n\t\t\t\t\tseenParties.add(entry.name);\n\t\t\t\t\tmergedParties.push(entry);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn { dataCollected: mergedData, thirdParties: mergedParties };\n\t}\n\n\t/**\n\t * Returns true when `file` lives inside `resolvedSrcDir` and has one of\n\t * the tracked extensions. Used by the dev-server watcher to skip events\n\t * for unrelated files (configs, public assets, other packages, etc.).\n\t */\n\tfunction isTrackedSource(file: string): boolean {\n\t\tconst rel = relative(resolvedSrcDir, file);\n\t\tif (!rel || rel.startsWith(\"..\")) return false;\n\t\treturn extensions.some((ext) => file.endsWith(ext));\n\t}\n\n\t/**\n\t * Re-runs the scan and, if anything changed, invalidates the virtual\n\t * module and triggers a full page reload. A full reload is used because\n\t * `dataCollected` is spread into the policy config at module-evaluation\n\t * time and the result is captured by the React tree as a prop — there's\n\t * no clean way to hot-swap it in place.\n\t */\n\tasync function rescanAndRefresh(server: ViteDevServer): Promise<void> {\n\t\tconst next = await scanAndMerge();\n\t\tif (JSON.stringify(next) === JSON.stringify(scanned)) return;\n\t\tscanned = next;\n\t\tconst mod = server.moduleGraph.getModuleById(RESOLVED_VIRTUAL_ID);\n\t\tif (mod) server.moduleGraph.invalidateModule(mod);\n\t\tserver.ws.send({ type: \"full-reload\" });\n\t}\n\n\treturn {\n\t\tname: \"openpolicy-auto-collect\",\n\t\tenforce: \"pre\",\n\t\tconfigResolved(config) {\n\t\t\tresolvedRoot = config.root;\n\t\t\tresolvedSrcDir = resolve(config.root, srcDirOpt);\n\t\t},\n\t\tasync buildStart() {\n\t\t\tscanned = await scanAndMerge();\n\t\t},\n\t\tconfigureServer(server) {\n\t\t\t// Make sure chokidar watches the whole src tree, not just files\n\t\t\t// already in the module graph. Without this, creating a brand-new\n\t\t\t// source file that nothing imports yet wouldn't fire a watcher\n\t\t\t// event — the very case we most need to re-scan on.\n\t\t\tserver.watcher.add(resolvedSrcDir);\n\n\t\t\tconst handler = async (file: string): Promise<void> => {\n\t\t\t\tif (!isTrackedSource(file)) return;\n\t\t\t\t// Surface errors via the logger but don't rethrow — an\n\t\t\t\t// unhandled rejection would crash the watcher process.\n\t\t\t\ttry {\n\t\t\t\t\tawait rescanAndRefresh(server);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tserver.config.logger.error(\n\t\t\t\t\t\t`[openpolicy-auto-collect] rescan failed: ${error}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tserver.watcher.on(\"change\", handler);\n\t\t\tserver.watcher.on(\"add\", handler);\n\t\t\tserver.watcher.on(\"unlink\", handler);\n\t\t},\n\t\tasync resolveId(source, importer, resolveOptions) {\n\t\t\tif (!importer || !AUTO_COLLECTED_SPECIFIER.test(source)) return null;\n\t\t\t// Defer to Vite's resolver first so we only redirect when the\n\t\t\t// relative specifier actually points inside @openpolicy/sdk.\n\t\t\tconst resolved = await this.resolve(source, importer, {\n\t\t\t\t...resolveOptions,\n\t\t\t\tskipSelf: true,\n\t\t\t});\n\t\t\tif (!resolved) return null;\n\t\t\tif (!SDK_PATH_PATTERN.test(resolved.id)) return null;\n\t\t\treturn RESOLVED_VIRTUAL_ID;\n\t\t},\n\t\tload(id) {\n\t\t\tif (id !== RESOLVED_VIRTUAL_ID) return null;\n\t\t\treturn (\n\t\t\t\t`export const dataCollected = ${JSON.stringify(\n\t\t\t\t\tscanned.dataCollected,\n\t\t\t\t)};\\n` +\n\t\t\t\t`export const thirdParties = ${JSON.stringify(scanned.thirdParties)};\\n`\n\t\t\t);\n\t\t},\n\t};\n}\n"],"mappings":"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,CACC,gBACA;EACC,MAAM;EACN,SAAS;EACT,WAAW;EACX,CACD;CACD,CACC,oBACA;EACC,MAAM;EACN,SAAS;EACT,WAAW;EACX,CACD;CACD,CACC,2BACA;EACC,MAAM;EACN,SAAS;EACT,WAAW;EACX,CACD;CACD,CACC,gCACA;EACC,MAAM;EACN,SAAS;EACT,WAAW;EACX,CACD;CACD,CACC,gBACA;EACC,MAAM;EACN,SAAS;EACT,WAAW;EACX,CACD;CACD,CACC,qBACA;EACC,MAAM;EACN,SAAS;EACT,WAAW;EACX,CACD;CACD,CACC,qBACA;EACC,MAAM;EACN,SAAS;EACT,WAAW;EACX,CACD;CACD,CACC,aACA;EACC,MAAM;EACN,SAAS;EACT,WAAW;EACX,CACD;CACD,CACC,mBACA;EACC,MAAM;EACN,SAAS;EACT,WAAW;EACX,CACD;CACD,CACC,UACA;EACC,MAAM;EACN,SAAS;EACT,WAAW;EACX,CACD;CACD,CACC,kBACA;EACC,MAAM;EACN,SAAS;EACT,WAAW;EACX,CACD;CACD,CACC,mBACA;EACC,MAAM;EACN,SAAS;EACT,WAAW;EACX,CACD;CACD,CACC,8BACA;EACC,MAAM;EACN,SAAS;EACT,WAAW;EACX,CACD;CACD,CAAC;;;AC9MF,MAAM,kBAAuC,IAAI,IAAI;CACpD;CACA;CACA;CACA;CACA;CACA;CACA;CACA,CAAC;;;;;;;;;;AAWF,eAAsB,YACrB,MACA,YACA,SAA4B,EAAE,EACV;CACpB,MAAM,UAAU,IAAI,IAAY,CAAC,GAAG,iBAAiB,GAAG,OAAO,CAAC;CAChE,MAAM,OAAO,IAAI,IAAI,WAAW;CAChC,MAAM,UAAoB,EAAE;CAE5B,eAAe,KAAK,KAA4B;EAC/C,IAAI;AACJ,MAAI;AACH,aAAW,MAAM,QAAQ,KAAK,EAAE,eAAe,MAAM,CAAC;WAC9C,KAAK;GACb,MAAM,OAAQ,IAA8B;AAC5C,OAAI,SAAS,YAAY,SAAS,UAAW;AAC7C,SAAM;;AAEP,OAAK,MAAM,SAAS,SAAS;AAC5B,OAAI,QAAQ,IAAI,MAAM,KAAK,CAAE;GAC7B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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/analyse.ts","../src/known-packages.ts","../src/scan.ts","../src/index.ts"],"sourcesContent":["import { parseSync } from \"oxc-parser\";\n\nconst SDK_SPECIFIER = \"@openpolicy/sdk\";\nconst COLLECTING_NAME = \"collecting\";\nconst THIRD_PARTY_NAME = \"thirdParty\";\nconst IGNORE_NAME = \"Ignore\";\n\ntype AnyNode = { type: string; [key: string]: unknown };\n\nexport type ThirdPartyEntry = {\n\tname: string;\n\tpurpose: string;\n\tpolicyUrl: string;\n};\n\nexport type ExtractResult = {\n\tdataCollected: Record<string, string[]>;\n\tthirdParties: ThirdPartyEntry[];\n};\n\n/**\n * Extract `collecting()` and `thirdParty()` call metadata from a single source file.\n *\n * Returns an `ExtractResult` with `dataCollected` (category → labels) and\n * `thirdParties` (array of third-party entries). Files with no matching calls\n * — or that fail to parse — return empty defaults.\n *\n * The analyser runs in two phases:\n * 1. Collect local names bound to `collecting` / `thirdParty` imported from\n * `@openpolicy/sdk` (handles renamed imports, skips type-only imports,\n * ignores look-alikes imported from other modules).\n * 2. Walk the program body and inspect every `CallExpression` whose callee\n * is one of those tracked local names.\n */\nexport function extractFromFile(filename: string, code: string): ExtractResult {\n\tconst empty: ExtractResult = { dataCollected: {}, thirdParties: [] };\n\tlet result: ReturnType<typeof parseSync>;\n\ttry {\n\t\tresult = parseSync(filename, code);\n\t} catch {\n\t\tconsole.warn(`[openpolicy-auto-collect] parse error in ${filename}`);\n\t\treturn empty;\n\t}\n\n\tif (result.errors.length > 0) {\n\t\t// Hard parse failures only — oxc reports recoverable errors but still\n\t\t// produces a usable AST, so we keep going and let the walker decide.\n\t\tconst fatal = result.errors.some((e) => e.severity === (\"Error\" as never));\n\t\tif (fatal) {\n\t\t\tconsole.warn(`[openpolicy-auto-collect] parse error in ${filename}`);\n\t\t\treturn empty;\n\t\t}\n\t}\n\n\tconst program = result.program as unknown as AnyNode;\n\tconst collectingNames = collectSdkBindings(program, COLLECTING_NAME);\n\tconst thirdPartyNames = collectSdkBindings(program, THIRD_PARTY_NAME);\n\tconst ignoreNames = collectSdkBindings(program, IGNORE_NAME);\n\tif (collectingNames.size === 0 && thirdPartyNames.size === 0) return empty;\n\n\tconst dataCollected: Record<string, string[]> = {};\n\tconst thirdParties: ThirdPartyEntry[] = [];\n\tconst seenThirdParties = new Set<string>();\n\n\twalk(program, (node) => {\n\t\tif (node.type !== \"CallExpression\") return;\n\t\tconst callee = node.callee as AnyNode | undefined;\n\t\tif (!callee || callee.type !== \"Identifier\") return;\n\t\tconst calleeName = callee.name as string;\n\t\tconst args = node.arguments as AnyNode[] | undefined;\n\n\t\tif (collectingNames.has(calleeName)) {\n\t\t\tif (!args || args.length < 3) return;\n\t\t\tconst category = extractStringLiteral(args[0]);\n\t\t\tif (category === null) return;\n\t\t\tconst labels = extractLabelKeys(args[2], ignoreNames);\n\t\t\tif (labels === null) return;\n\t\t\tconst existing = dataCollected[category] ?? [];\n\t\t\tconst seen = new Set(existing);\n\t\t\tfor (const label of labels) {\n\t\t\t\tif (!seen.has(label)) {\n\t\t\t\t\texisting.push(label);\n\t\t\t\t\tseen.add(label);\n\t\t\t\t}\n\t\t\t}\n\t\t\tdataCollected[category] = existing;\n\t\t} else if (thirdPartyNames.has(calleeName)) {\n\t\t\tif (!args || args.length < 3) return;\n\t\t\tconst name = extractStringLiteral(args[0]);\n\t\t\tif (name === null) return;\n\t\t\tconst purpose = extractStringLiteral(args[1]);\n\t\t\tif (purpose === null) return;\n\t\t\tconst policyUrl = extractStringLiteral(args[2]);\n\t\t\tif (policyUrl === null) return;\n\t\t\t// Deduplicate by name — first occurrence wins (files walked in sorted order)\n\t\t\tif (seenThirdParties.has(name)) return;\n\t\t\tseenThirdParties.add(name);\n\t\t\tthirdParties.push({ name, purpose, policyUrl });\n\t\t}\n\t});\n\n\treturn { dataCollected, thirdParties };\n}\n\n/**\n * Walk `ImportDeclaration` nodes and return the local names bound to the given\n * `exportName` imported from `@openpolicy/sdk`. Skips type-only imports and\n * specifiers whose imported name doesn't match.\n */\nfunction collectSdkBindings(program: AnyNode, exportName: string): Set<string> {\n\tconst names = new Set<string>();\n\tconst body = program.body as AnyNode[] | undefined;\n\tif (!body) return names;\n\tfor (const node of body) {\n\t\tif (node.type !== \"ImportDeclaration\") continue;\n\t\tif ((node.importKind as string | undefined) === \"type\") continue;\n\t\tconst source = node.source as AnyNode | undefined;\n\t\tif (!source || source.value !== SDK_SPECIFIER) continue;\n\t\tconst specifiers = node.specifiers as AnyNode[] | undefined;\n\t\tif (!specifiers) continue;\n\t\tfor (const spec of specifiers) {\n\t\t\tif (spec.type !== \"ImportSpecifier\") continue;\n\t\t\tif ((spec.importKind as string | undefined) === \"type\") continue;\n\t\t\tconst imported = spec.imported as AnyNode | undefined;\n\t\t\tif (!imported) continue;\n\t\t\t// ESTree allows either an Identifier (name) or a string Literal (value)\n\t\t\t// for the imported binding (e.g. `import { \"foo\" as bar }`).\n\t\t\tconst importedName =\n\t\t\t\timported.type === \"Identifier\"\n\t\t\t\t\t? (imported.name as string | undefined)\n\t\t\t\t\t: imported.type === \"Literal\"\n\t\t\t\t\t\t? typeof imported.value === \"string\"\n\t\t\t\t\t\t\t? imported.value\n\t\t\t\t\t\t\t: undefined\n\t\t\t\t\t\t: undefined;\n\t\t\tif (importedName !== exportName) continue;\n\t\t\tconst local = spec.local as AnyNode | undefined;\n\t\t\tif (!local || local.type !== \"Identifier\") continue;\n\t\t\tnames.add(local.name as string);\n\t\t}\n\t}\n\treturn names;\n}\n\n/**\n * If `node` is a string `Literal`, return its string value. Otherwise\n * return `null` so the caller silently skips the call.\n */\nfunction extractStringLiteral(node: AnyNode | undefined): string | null {\n\tif (!node) return null;\n\tif (node.type !== \"Literal\") return null;\n\tif (typeof node.value !== \"string\") return null;\n\treturn node.value;\n}\n\n/**\n * Extract the string values from a plain `{ fieldName: \"Human Label\" }`\n * object literal. Returns an array of label strings, deduped while\n * preserving insertion order. Returns `null` if the shape doesn't match.\n *\n * Properties whose value is an `Identifier` matching a tracked local name\n * bound to the SDK's `Ignore` export are treated as explicit opt-outs and\n * skipped silently — producing the same observable result as omitting the\n * field from the record did before.\n */\nfunction extractLabelKeys(\n\tnode: AnyNode | undefined,\n\tignoreNames: Set<string>,\n): string[] | null {\n\tif (!node || node.type !== \"ObjectExpression\") return null;\n\tconst properties = node.properties as AnyNode[] | undefined;\n\tif (!properties) return null;\n\n\tconst labels: string[] = [];\n\tconst seen = new Set<string>();\n\tfor (const prop of properties) {\n\t\tif (prop.type !== \"Property\") continue; // drop SpreadElement silently\n\t\tconst val = prop.value as AnyNode | undefined;\n\t\tif (!val) continue;\n\t\tif (val.type === \"Literal\" && typeof val.value === \"string\") {\n\t\t\tif (seen.has(val.value)) continue;\n\t\t\tseen.add(val.value);\n\t\t\tlabels.push(val.value);\n\t\t\tcontinue;\n\t\t}\n\t\tif (\n\t\t\tval.type === \"Identifier\" &&\n\t\t\ttypeof val.name === \"string\" &&\n\t\t\tignoreNames.has(val.name as string)\n\t\t) {\n\t\t}\n\t\t// Any other value (template literals, variable references, etc.) is\n\t\t// skipped silently to preserve the analyser's conservative posture.\n\t}\n\treturn labels;\n}\n\n/**\n * Recursive AST walker. Visits every `AnyNode` (depth-first) reachable\n * through array / nested-object children and invokes `visit` on each.\n */\nfunction walk(node: AnyNode, visit: (node: AnyNode) => void): void {\n\tvisit(node);\n\tfor (const key of Object.keys(node)) {\n\t\tif (key === \"parent\") continue;\n\t\tconst value = node[key];\n\t\tif (Array.isArray(value)) {\n\t\t\tfor (const item of value) {\n\t\t\t\tif (item && typeof item === \"object\" && typeof item.type === \"string\") {\n\t\t\t\t\twalk(item as AnyNode, visit);\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (\n\t\t\tvalue &&\n\t\t\ttypeof value === \"object\" &&\n\t\t\ttypeof (value as { type?: unknown }).type === \"string\"\n\t\t) {\n\t\t\twalk(value as AnyNode, visit);\n\t\t}\n\t}\n}\n","import type { ThirdPartyEntry } from \"./analyse\";\n\n/**\n * Registry of known npm packages mapped to their ThirdPartyEntry metadata.\n * Multiple package names can point to the same service — deduplication by\n * `ThirdPartyEntry.name` is handled at merge time in the caller.\n */\nexport const KNOWN_PACKAGES: ReadonlyMap<string, ThirdPartyEntry> = new Map([\n\t[\n\t\t\"stripe\",\n\t\t{\n\t\t\tname: \"Stripe\",\n\t\t\tpurpose: \"Payment processing\",\n\t\t\tpolicyUrl: \"https://stripe.com/privacy\",\n\t\t},\n\t],\n\t[\n\t\t\"@stripe/stripe-js\",\n\t\t{\n\t\t\tname: \"Stripe\",\n\t\t\tpurpose: \"Payment processing\",\n\t\t\tpolicyUrl: \"https://stripe.com/privacy\",\n\t\t},\n\t],\n\t[\n\t\t\"braintree\",\n\t\t{\n\t\t\tname: \"Braintree\",\n\t\t\tpurpose: \"Payment processing\",\n\t\t\tpolicyUrl:\n\t\t\t\t\"https://www.braintreepayments.com/legal/braintree-privacy-policy\",\n\t\t},\n\t],\n\t[\n\t\t\"@braintree/browser-drop-in\",\n\t\t{\n\t\t\tname: \"Braintree\",\n\t\t\tpurpose: \"Payment processing\",\n\t\t\tpolicyUrl:\n\t\t\t\t\"https://www.braintreepayments.com/legal/braintree-privacy-policy\",\n\t\t},\n\t],\n\t[\n\t\t\"@sentry/browser\",\n\t\t{\n\t\t\tname: \"Sentry\",\n\t\t\tpurpose: \"Error tracking\",\n\t\t\tpolicyUrl: \"https://sentry.io/privacy/\",\n\t\t},\n\t],\n\t[\n\t\t\"@sentry/node\",\n\t\t{\n\t\t\tname: \"Sentry\",\n\t\t\tpurpose: \"Error tracking\",\n\t\t\tpolicyUrl: \"https://sentry.io/privacy/\",\n\t\t},\n\t],\n\t[\n\t\t\"@sentry/nextjs\",\n\t\t{\n\t\t\tname: \"Sentry\",\n\t\t\tpurpose: \"Error tracking\",\n\t\t\tpolicyUrl: \"https://sentry.io/privacy/\",\n\t\t},\n\t],\n\t[\n\t\t\"@sentry/react\",\n\t\t{\n\t\t\tname: \"Sentry\",\n\t\t\tpurpose: \"Error tracking\",\n\t\t\tpolicyUrl: \"https://sentry.io/privacy/\",\n\t\t},\n\t],\n\t[\n\t\t\"@sentry/vue\",\n\t\t{\n\t\t\tname: \"Sentry\",\n\t\t\tpurpose: \"Error tracking\",\n\t\t\tpolicyUrl: \"https://sentry.io/privacy/\",\n\t\t},\n\t],\n\t[\n\t\t\"@datadog/browser-rum\",\n\t\t{\n\t\t\tname: \"Datadog\",\n\t\t\tpurpose: \"Monitoring\",\n\t\t\tpolicyUrl: \"https://www.datadoghq.com/legal/privacy/\",\n\t\t},\n\t],\n\t[\n\t\t\"dd-trace\",\n\t\t{\n\t\t\tname: \"Datadog\",\n\t\t\tpurpose: \"Monitoring\",\n\t\t\tpolicyUrl: \"https://www.datadoghq.com/legal/privacy/\",\n\t\t},\n\t],\n\t[\n\t\t\"posthog-js\",\n\t\t{\n\t\t\tname: \"PostHog\",\n\t\t\tpurpose: \"Product analytics\",\n\t\t\tpolicyUrl: \"https://posthog.com/privacy\",\n\t\t},\n\t],\n\t[\n\t\t\"posthog-node\",\n\t\t{\n\t\t\tname: \"PostHog\",\n\t\t\tpurpose: \"Product analytics\",\n\t\t\tpolicyUrl: \"https://posthog.com/privacy\",\n\t\t},\n\t],\n\t[\n\t\t\"mixpanel-browser\",\n\t\t{\n\t\t\tname: \"Mixpanel\",\n\t\t\tpurpose: \"Product analytics\",\n\t\t\tpolicyUrl: \"https://mixpanel.com/legal/privacy-policy/\",\n\t\t},\n\t],\n\t[\n\t\t\"@segment/analytics-next\",\n\t\t{\n\t\t\tname: \"Segment\",\n\t\t\tpurpose: \"Customer data platform\",\n\t\t\tpolicyUrl: \"https://www.twilio.com/en-us/legal/privacy\",\n\t\t},\n\t],\n\t[\n\t\t\"@amplitude/analytics-browser\",\n\t\t{\n\t\t\tname: \"Amplitude\",\n\t\t\tpurpose: \"Product analytics\",\n\t\t\tpolicyUrl: \"https://amplitude.com/privacy\",\n\t\t},\n\t],\n\t[\n\t\t\"amplitude-js\",\n\t\t{\n\t\t\tname: \"Amplitude\",\n\t\t\tpurpose: \"Product analytics\",\n\t\t\tpolicyUrl: \"https://amplitude.com/privacy\",\n\t\t},\n\t],\n\t[\n\t\t\"@vercel/analytics\",\n\t\t{\n\t\t\tname: \"Vercel Analytics\",\n\t\t\tpurpose: \"Web analytics\",\n\t\t\tpolicyUrl: \"https://vercel.com/legal/privacy-policy\",\n\t\t},\n\t],\n\t[\n\t\t\"plausible-tracker\",\n\t\t{\n\t\t\tname: \"Plausible\",\n\t\t\tpurpose: \"Web analytics\",\n\t\t\tpolicyUrl: \"https://plausible.io/privacy\",\n\t\t},\n\t],\n\t[\n\t\t\"logrocket\",\n\t\t{\n\t\t\tname: \"LogRocket\",\n\t\t\tpurpose: \"Session recording\",\n\t\t\tpolicyUrl: \"https://logrocket.com/privacy/\",\n\t\t},\n\t],\n\t[\n\t\t\"@hotjar/browser\",\n\t\t{\n\t\t\tname: \"Hotjar\",\n\t\t\tpurpose: \"Session recording\",\n\t\t\tpolicyUrl: \"https://www.hotjar.com/legal/policies/privacy/\",\n\t\t},\n\t],\n\t[\n\t\t\"resend\",\n\t\t{\n\t\t\tname: \"Resend\",\n\t\t\tpurpose: \"Transactional email\",\n\t\t\tpolicyUrl: \"https://resend.com/legal/privacy-policy\",\n\t\t},\n\t],\n\t[\n\t\t\"@sendgrid/mail\",\n\t\t{\n\t\t\tname: \"SendGrid\",\n\t\t\tpurpose: \"Transactional email\",\n\t\t\tpolicyUrl: \"https://www.twilio.com/en-us/legal/privacy\",\n\t\t},\n\t],\n\t[\n\t\t\"intercom-client\",\n\t\t{\n\t\t\tname: \"Intercom\",\n\t\t\tpurpose: \"Customer messaging\",\n\t\t\tpolicyUrl: \"https://www.intercom.com/legal/privacy\",\n\t\t},\n\t],\n\t[\n\t\t\"@intercom/messenger-js-sdk\",\n\t\t{\n\t\t\tname: \"Intercom\",\n\t\t\tpurpose: \"Customer messaging\",\n\t\t\tpolicyUrl: \"https://www.intercom.com/legal/privacy\",\n\t\t},\n\t],\n]);\n","import type { Dirent } from \"node:fs\";\nimport { readdir } from \"node:fs/promises\";\nimport { extname, join } from \"node:path\";\n\nconst DEFAULT_IGNORES: ReadonlySet<string> = new Set([\n\t\"node_modules\",\n\t\"dist\",\n\t\".git\",\n\t\".next\",\n\t\".output\",\n\t\".svelte-kit\",\n\t\".cache\",\n]);\n\n/**\n * Recursively walks `root`, returning absolute paths of every regular file\n * whose extension is in `extensions`. Directories whose basename appears in\n * the built-in ignore list (or the extra `ignore` argument) are skipped\n * entirely.\n *\n * Missing roots resolve to an empty array — the plugin must not throw if the\n * user's `srcDir` hasn't been created yet.\n */\nexport async function walkSources(\n\troot: string,\n\textensions: readonly string[],\n\tignore: readonly string[] = [],\n): Promise<string[]> {\n\tconst ignored = new Set<string>([...DEFAULT_IGNORES, ...ignore]);\n\tconst exts = new Set(extensions);\n\tconst results: string[] = [];\n\n\tasync function walk(dir: string): Promise<void> {\n\t\tlet entries: Dirent[];\n\t\ttry {\n\t\t\tentries = (await readdir(dir, { withFileTypes: true })) as Dirent[];\n\t\t} catch (err) {\n\t\t\tconst code = (err as NodeJS.ErrnoException).code;\n\t\t\tif (code === \"ENOENT\" || code === \"ENOTDIR\") return;\n\t\t\tthrow err;\n\t\t}\n\t\tfor (const entry of entries) {\n\t\t\tif (ignored.has(entry.name)) continue;\n\t\t\tconst full = join(dir, entry.name);\n\t\t\tif (entry.isDirectory()) {\n\t\t\t\tawait walk(full);\n\t\t\t} else if (entry.isFile() && exts.has(extname(entry.name))) {\n\t\t\t\tresults.push(full);\n\t\t\t}\n\t\t}\n\t}\n\n\tawait walk(root);\n\tresults.sort();\n\treturn results;\n}\n","import { readFile } from \"node:fs/promises\";\nimport { relative, resolve } from \"node:path\";\nimport type { Plugin, ViteDevServer } from \"vite\";\nimport { extractFromFile, type ThirdPartyEntry } from \"./analyse\";\nimport { KNOWN_PACKAGES } from \"./known-packages\";\nimport { walkSources } from \"./scan\";\n\nexport type AutoCollectOptions = {\n\t/**\n\t * Directory walked for `collecting()` calls. Resolved relative to the\n\t * Vite project root. Defaults to `\"src\"`.\n\t */\n\tsrcDir?: string;\n\t/**\n\t * File extensions scanned. Defaults to `[\".ts\", \".tsx\"]`.\n\t */\n\textensions?: string[];\n\t/**\n\t * Extra directory names skipped during the walk. Appended to the built-in\n\t * defaults (`node_modules`, `dist`, `.git`, `.next`, `.output`,\n\t * `.svelte-kit`, `.cache`).\n\t */\n\tignore?: string[];\n\n\tthirdParties?: {\n\t\tusePackageJson?: boolean;\n\t};\n};\n\n/**\n * Marker returned from `resolveId` so `load` can recognise a hit. The leading\n * NUL prefix is the Rollup/Vite convention for virtual IDs so other plugins\n * leave it alone.\n */\nconst RESOLVED_VIRTUAL_ID = \"\\0virtual:openpolicy/auto-collected\";\n\n/**\n * Matches any path that lives inside the `@openpolicy/sdk` package, whether\n * it's resolved via a workspace symlink (`.../packages/sdk/...`) or a\n * published `node_modules` install (`.../@openpolicy/sdk/...`). Used to scope\n * the `./auto-collected` relative-import interception to the SDK itself.\n */\nconst SDK_PATH_PATTERN = /[\\\\/](?:@openpolicy[\\\\/]sdk|packages[\\\\/]sdk)[\\\\/]/;\n\n/**\n * Matches the relative specifier the SDK uses for its own internal\n * `./auto-collected` import. Both the source form (`./auto-collected`) and\n * the published dist form (`./auto-collected.js`) need to be intercepted:\n * the former applies when consumers resolve the SDK via its workspace\n * source, the latter when resolving against `dist/` with the separate\n * `auto-collected.js` chunk.\n */\nconst AUTO_COLLECTED_SPECIFIER = /^\\.\\/auto-collected(?:\\.js)?$/;\n\n/**\n * Vite plugin that scans source files for `@openpolicy/sdk` `collecting()`\n * calls at the start of each build and inlines the discovered categories into\n * the SDK's `dataCollected` sentinel.\n *\n * Internally the plugin intercepts `@openpolicy/sdk`'s own relative import of\n * `./auto-collected` and redirects it to a virtual module whose body is a\n * literal `export const dataCollected = { ... }`. Because the replacement\n * becomes part of the consumer's own module graph, the scanned data survives\n * any downstream bundler boundary (e.g. nitro's SSR output), which a shared\n * module-level registry would not.\n */\nexport function autoCollect(options: AutoCollectOptions = {}): Plugin {\n\tconst srcDirOpt = options.srcDir ?? \"src\";\n\tconst extensions = options.extensions ?? [\".ts\", \".tsx\"];\n\tconst ignore = options.ignore ?? [];\n\tconst usePackageJsonOpt = options.thirdParties?.usePackageJson ?? false;\n\tlet resolvedRoot: string;\n\tlet resolvedSrcDir: string;\n\tlet scanned: {\n\t\tdataCollected: Record<string, string[]>;\n\t\tthirdParties: ThirdPartyEntry[];\n\t} = { dataCollected: {}, thirdParties: [] };\n\n\tasync function detectFromPackageJson(\n\t\troot: string,\n\t): Promise<ThirdPartyEntry[]> {\n\t\tlet raw: string;\n\t\ttry {\n\t\t\traw = await readFile(resolve(root, \"package.json\"), \"utf8\");\n\t\t} catch {\n\t\t\treturn [];\n\t\t}\n\t\tlet pkg: {\n\t\t\tdependencies?: Record<string, string>;\n\t\t\tdevDependencies?: Record<string, string>;\n\t\t};\n\t\ttry {\n\t\t\tpkg = JSON.parse(raw) as typeof pkg;\n\t\t} catch {\n\t\t\treturn [];\n\t\t}\n\t\tconst allDeps = {\n\t\t\t...pkg.dependencies,\n\t\t\t...pkg.devDependencies,\n\t\t};\n\t\tconst entries: ThirdPartyEntry[] = [];\n\t\tconst seenNames = new Set<string>();\n\t\tfor (const pkgName of Object.keys(allDeps)) {\n\t\t\tconst entry = KNOWN_PACKAGES.get(pkgName);\n\t\t\tif (entry && !seenNames.has(entry.name)) {\n\t\t\t\tseenNames.add(entry.name);\n\t\t\t\tentries.push(entry);\n\t\t\t}\n\t\t}\n\t\treturn entries;\n\t}\n\n\tasync function scanAndMerge(): Promise<typeof scanned> {\n\t\tconst files = await walkSources(resolvedSrcDir, extensions, ignore);\n\t\tconst mergedData: Record<string, string[]> = {};\n\t\tconst mergedParties: ThirdPartyEntry[] = [];\n\t\tconst seenParties = new Set<string>();\n\t\tfor (const file of files) {\n\t\t\tlet code: string;\n\t\t\ttry {\n\t\t\t\tcode = await readFile(file, \"utf8\");\n\t\t\t} catch {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst extracted = extractFromFile(file, code);\n\t\t\tfor (const [category, labels] of Object.entries(\n\t\t\t\textracted.dataCollected,\n\t\t\t)) {\n\t\t\t\tconst existing = mergedData[category] ?? [];\n\t\t\t\tconst seen = new Set(existing);\n\t\t\t\tfor (const label of labels) {\n\t\t\t\t\tif (!seen.has(label)) {\n\t\t\t\t\t\texisting.push(label);\n\t\t\t\t\t\tseen.add(label);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tmergedData[category] = existing;\n\t\t\t}\n\t\t\tfor (const entry of extracted.thirdParties) {\n\t\t\t\tif (!seenParties.has(entry.name)) {\n\t\t\t\t\tseenParties.add(entry.name);\n\t\t\t\t\tmergedParties.push(entry);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (usePackageJsonOpt) {\n\t\t\tconst pkgEntries = await detectFromPackageJson(resolvedRoot);\n\t\t\tfor (const entry of pkgEntries) {\n\t\t\t\tif (!seenParties.has(entry.name)) {\n\t\t\t\t\tseenParties.add(entry.name);\n\t\t\t\t\tmergedParties.push(entry);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn { dataCollected: mergedData, thirdParties: mergedParties };\n\t}\n\n\t/**\n\t * Returns true when `file` lives inside `resolvedSrcDir` and has one of\n\t * the tracked extensions. Used by the dev-server watcher to skip events\n\t * for unrelated files (configs, public assets, other packages, etc.).\n\t */\n\tfunction isTrackedSource(file: string): boolean {\n\t\tconst rel = relative(resolvedSrcDir, file);\n\t\tif (!rel || rel.startsWith(\"..\")) return false;\n\t\treturn extensions.some((ext) => file.endsWith(ext));\n\t}\n\n\t/**\n\t * Re-runs the scan and, if anything changed, invalidates the virtual\n\t * module and triggers a full page reload. A full reload is used because\n\t * `dataCollected` is spread into the policy config at module-evaluation\n\t * time and the result is captured by the React tree as a prop — there's\n\t * no clean way to hot-swap it in place.\n\t */\n\tasync function rescanAndRefresh(server: ViteDevServer): Promise<void> {\n\t\tconst next = await scanAndMerge();\n\t\tif (JSON.stringify(next) === JSON.stringify(scanned)) return;\n\t\tscanned = next;\n\t\tconst mod = server.moduleGraph.getModuleById(RESOLVED_VIRTUAL_ID);\n\t\tif (mod) server.moduleGraph.invalidateModule(mod);\n\t\tserver.ws.send({ type: \"full-reload\" });\n\t}\n\n\treturn {\n\t\tname: \"openpolicy-auto-collect\",\n\t\tenforce: \"pre\",\n\t\t/**\n\t\t * Opt `@openpolicy/sdk` out of Vite's dep pre-bundler so our `resolveId`/\n\t\t * `load` hooks get a chance to intercept the SDK's internal\n\t\t * `./auto-collected.js` relative import in dev mode. Without this, esbuild\n\t\t * resolves that import during pre-bundling and inlines the empty fallback\n\t\t * from `auto-collected.ts` into the optimised dep bundle, which is why\n\t\t * `dataCollected` / `thirdParties` came out empty under `vite dev`\n\t\t * (OSS-7 / #57). `vite build` is unaffected because Rollup runs the whole\n\t\t * graph through the plugin pipeline. The SDK has no runtime deps of its\n\t\t * own, so excluding it from pre-bundling is cheap. Applied to both the\n\t\t * browser and the SSR dep optimizer for frameworks like TanStack Start /\n\t\t * Nitro (see `examples/tanstack/vite.config.ts`).\n\t\t *\n\t\t * Also pin the SDK to `ssr.noExternal` so Vite bundles it into the SSR\n\t\t * output instead of externalising it. Workspace packages resolved from\n\t\t * `node_modules` are externalised by default in SSR builds; Node's ESM\n\t\t * loader then resolves the SDK's internal `./auto-collected.js` to the\n\t\t * empty fallback at runtime, bypassing the plugin's `resolveId` hook\n\t\t * entirely. That asymmetry caused `dataCollected` / `thirdParties` to\n\t\t * arrive empty for server-side consumers such as `@openpolicy/plus`'s\n\t\t * `client.consent()` called from server functions, and produced a\n\t\t * hydration flash of empty privacy data (OP-170). Bundling the SDK\n\t\t * server-side routes its internal imports through the plugin pipeline\n\t\t * the same way they already go through it on the client.\n\t\t */\n\t\tconfig() {\n\t\t\treturn {\n\t\t\t\toptimizeDeps: { exclude: [\"@openpolicy/sdk\"] },\n\t\t\t\tssr: {\n\t\t\t\t\toptimizeDeps: { exclude: [\"@openpolicy/sdk\"] },\n\t\t\t\t\tnoExternal: [\"@openpolicy/sdk\"],\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t\tconfigResolved(config) {\n\t\t\tresolvedRoot = config.root;\n\t\t\tresolvedSrcDir = resolve(config.root, srcDirOpt);\n\t\t},\n\t\tasync buildStart() {\n\t\t\tscanned = await scanAndMerge();\n\t\t},\n\t\tconfigureServer(server) {\n\t\t\t// Make sure chokidar watches the whole src tree, not just files\n\t\t\t// already in the module graph. Without this, creating a brand-new\n\t\t\t// source file that nothing imports yet wouldn't fire a watcher\n\t\t\t// event — the very case we most need to re-scan on.\n\t\t\tserver.watcher.add(resolvedSrcDir);\n\n\t\t\tconst handler = async (file: string): Promise<void> => {\n\t\t\t\tif (!isTrackedSource(file)) return;\n\t\t\t\t// Surface errors via the logger but don't rethrow — an\n\t\t\t\t// unhandled rejection would crash the watcher process.\n\t\t\t\ttry {\n\t\t\t\t\tawait rescanAndRefresh(server);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tserver.config.logger.error(\n\t\t\t\t\t\t`[openpolicy-auto-collect] rescan failed: ${error}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tserver.watcher.on(\"change\", handler);\n\t\t\tserver.watcher.on(\"add\", handler);\n\t\t\tserver.watcher.on(\"unlink\", handler);\n\t\t},\n\t\tasync resolveId(source, importer, resolveOptions) {\n\t\t\tif (!importer || !AUTO_COLLECTED_SPECIFIER.test(source)) return null;\n\t\t\t// Defer to Vite's resolver first so we only redirect when the\n\t\t\t// relative specifier actually points inside @openpolicy/sdk.\n\t\t\tconst resolved = await this.resolve(source, importer, {\n\t\t\t\t...resolveOptions,\n\t\t\t\tskipSelf: true,\n\t\t\t});\n\t\t\tif (!resolved) return null;\n\t\t\tif (!SDK_PATH_PATTERN.test(resolved.id)) return null;\n\t\t\treturn RESOLVED_VIRTUAL_ID;\n\t\t},\n\t\tload(id) {\n\t\t\tif (id !== RESOLVED_VIRTUAL_ID) return null;\n\t\t\treturn (\n\t\t\t\t`export const dataCollected = ${JSON.stringify(\n\t\t\t\t\tscanned.dataCollected,\n\t\t\t\t)};\\n` +\n\t\t\t\t`export const thirdParties = ${JSON.stringify(scanned.thirdParties)};\\n`\n\t\t\t);\n\t\t},\n\t};\n}\n"],"mappings":"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CC,MAAM;EACN,SAAS;EACT,WAAW;EACX,CACD;CACD,CACC,YACA;EACC,MAAM;EACN,SAAS;EACT,WAAW;EACX,CACD;CACD,CACC,cACA;EACC,MAAM;EACN,SAAS;EACT,WAAW;EACX,CACD;CACD,CACC,gBACA;EACC,MAAM;EACN,SAAS;EACT,WAAW;EACX,CACD;CACD,CACC,oBACA;EACC,MAAM;EACN,SAAS;EACT,WAAW;EACX,CACD;CACD,CACC,2BACA;EACC,MAAM;EACN,SAAS;EACT,WAAW;EACX,CACD;CACD,CACC,gCACA;EACC,MAAM;EACN,SAAS;EACT,WAAW;EACX,CACD;CACD,CACC,gBACA;EACC,MAAM;EACN,SAAS;EACT,WAAW;EACX,CACD;CACD,CACC,qBACA;EACC,MAAM;EACN,SAAS;EACT,WAAW;EACX,CACD;CACD,CACC,qBACA;EACC,MAAM;EACN,SAAS;EACT,WAAW;EACX,CACD;CACD,CACC,aACA;EACC,MAAM;EACN,SAAS;EACT,WAAW;EACX,CACD;CACD,CACC,mBACA;EACC,MAAM;EACN,SAAS;EACT,WAAW;EACX,CACD;CACD,CACC,UACA;EACC,MAAM;EACN,SAAS;EACT,WAAW;EACX,CACD;CACD,CACC,kBACA;EACC,MAAM;EACN,SAAS;EACT,WAAW;EACX,CACD;CACD,CACC,mBACA;EACC,MAAM;EACN,SAAS;EACT,WAAW;EACX,CACD;CACD,CACC,8BACA;EACC,MAAM;EACN,SAAS;EACT,WAAW;EACX,CACD;CACD,CAAC;;;AC9MF,MAAM,kBAAuC,IAAI,IAAI;CACpD;CACA;CACA;CACA;CACA;CACA;CACA;CACA,CAAC;;;;;;;;;;AAWF,eAAsB,YACrB,MACA,YACA,SAA4B,EAAE,EACV;CACpB,MAAM,UAAU,IAAI,IAAY,CAAC,GAAG,iBAAiB,GAAG,OAAO,CAAC;CAChE,MAAM,OAAO,IAAI,IAAI,WAAW;CAChC,MAAM,UAAoB,EAAE;CAE5B,eAAe,KAAK,KAA4B;EAC/C,IAAI;AACJ,MAAI;AACH,aAAW,MAAM,QAAQ,KAAK,EAAE,eAAe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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openpolicy/vite-auto-collect",
3
- "version": "0.0.20",
3
+ "version": "0.0.22",
4
4
  "type": "module",
5
5
  "description": "Vite plugin that scans source files for @openpolicy/sdk collecting() calls and populates autoCollected() at build time",
6
6
  "license": "GPL-3.0-only",