featuredrop 1.3.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/README.md +287 -760
  2. package/dist/adapters.cjs +1757 -0
  3. package/dist/adapters.cjs.map +1 -0
  4. package/dist/adapters.d.cts +744 -0
  5. package/dist/adapters.d.ts +744 -0
  6. package/dist/adapters.js +1745 -0
  7. package/dist/adapters.js.map +1 -0
  8. package/dist/admin.cjs +148 -32
  9. package/dist/admin.cjs.map +1 -1
  10. package/dist/admin.d.cts +14 -3
  11. package/dist/admin.d.ts +14 -3
  12. package/dist/admin.js +148 -32
  13. package/dist/admin.js.map +1 -1
  14. package/dist/bridges.cjs +134 -15
  15. package/dist/bridges.cjs.map +1 -1
  16. package/dist/bridges.d.cts +12 -5
  17. package/dist/bridges.d.ts +12 -5
  18. package/dist/bridges.js +114 -15
  19. package/dist/bridges.js.map +1 -1
  20. package/dist/ci.cjs +34 -0
  21. package/dist/ci.cjs.map +1 -1
  22. package/dist/ci.d.cts +5 -1
  23. package/dist/ci.d.ts +5 -1
  24. package/dist/ci.js +34 -1
  25. package/dist/ci.js.map +1 -1
  26. package/dist/cms.cjs +835 -0
  27. package/dist/cms.cjs.map +1 -0
  28. package/dist/cms.d.cts +236 -0
  29. package/dist/cms.d.ts +236 -0
  30. package/dist/cms.js +829 -0
  31. package/dist/cms.js.map +1 -0
  32. package/dist/featuredrop.cjs +23 -2
  33. package/dist/featuredrop.cjs.map +1 -1
  34. package/dist/flags.cjs +27 -7
  35. package/dist/flags.cjs.map +1 -1
  36. package/dist/flags.d.cts +14 -0
  37. package/dist/flags.d.ts +14 -0
  38. package/dist/flags.js +27 -7
  39. package/dist/flags.js.map +1 -1
  40. package/dist/index.cjs +52 -4460
  41. package/dist/index.cjs.map +1 -1
  42. package/dist/index.d.cts +1 -1340
  43. package/dist/index.d.ts +1 -1340
  44. package/dist/index.js +53 -4387
  45. package/dist/index.js.map +1 -1
  46. package/dist/markdown.cjs +257 -0
  47. package/dist/markdown.cjs.map +1 -0
  48. package/dist/markdown.d.cts +9 -0
  49. package/dist/markdown.d.ts +9 -0
  50. package/dist/markdown.js +234 -0
  51. package/dist/markdown.js.map +1 -0
  52. package/dist/preact.cjs +37 -12
  53. package/dist/preact.cjs.map +1 -1
  54. package/dist/preact.js +17 -12
  55. package/dist/preact.js.map +1 -1
  56. package/dist/react.cjs +37 -12
  57. package/dist/react.cjs.map +1 -1
  58. package/dist/react.js +17 -12
  59. package/dist/react.js.map +1 -1
  60. package/dist/renderer.cjs +503 -0
  61. package/dist/renderer.cjs.map +1 -0
  62. package/dist/renderer.d.cts +250 -0
  63. package/dist/renderer.d.ts +250 -0
  64. package/dist/renderer.js +501 -0
  65. package/dist/renderer.js.map +1 -0
  66. package/dist/rss.cjs +291 -0
  67. package/dist/rss.cjs.map +1 -0
  68. package/dist/rss.d.cts +158 -0
  69. package/dist/rss.d.ts +158 -0
  70. package/dist/rss.js +268 -0
  71. package/dist/rss.js.map +1 -0
  72. package/dist/vue.cjs +23 -2
  73. package/dist/vue.cjs.map +1 -1
  74. package/dist/vue.js +3 -2
  75. package/dist/vue.js.map +1 -1
  76. package/package.json +72 -6
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/dependencies.ts","../src/schema.ts","../src/changelog-as-code.ts","../src/cms.ts"],"names":["z","readdir","join","stat","readFile","relative","sep","writeFile","asString","entries"],"mappings":"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","file":"cms.cjs","sourcesContent":["import type { FeatureEntry, FeatureManifest } from \"./types\";\n\nfunction getDirectDependencies(feature: FeatureEntry): string[] {\n const dependsOn = feature.dependsOn;\n if (!dependsOn) return [];\n const seen = dependsOn.seen ?? [];\n const clicked = dependsOn.clicked ?? [];\n const dismissed = dependsOn.dismissed ?? [];\n const unique = new Set<string>();\n for (const id of [...seen, ...clicked, ...dismissed]) {\n if (id) unique.add(id);\n }\n return Array.from(unique);\n}\n\nexport function resolveDependencyOrder(manifest: FeatureManifest): string[] {\n const ids = new Set(manifest.map((feature) => feature.id));\n const outgoing = new Map<string, Set<string>>();\n const indegree = new Map<string, number>();\n\n for (const feature of manifest) {\n outgoing.set(feature.id, new Set());\n indegree.set(feature.id, 0);\n }\n\n for (const feature of manifest) {\n for (const dependencyId of getDirectDependencies(feature)) {\n if (!ids.has(dependencyId)) continue;\n const edges = outgoing.get(dependencyId);\n if (!edges || edges.has(feature.id)) continue;\n edges.add(feature.id);\n indegree.set(feature.id, (indegree.get(feature.id) ?? 0) + 1);\n }\n }\n\n const queue: string[] = [];\n for (const feature of manifest) {\n if ((indegree.get(feature.id) ?? 0) === 0) queue.push(feature.id);\n }\n\n const ordered: string[] = [];\n while (queue.length > 0) {\n const id = queue.shift();\n if (!id) continue;\n ordered.push(id);\n const edges = outgoing.get(id);\n if (!edges) continue;\n for (const nextId of edges) {\n const nextDegree = (indegree.get(nextId) ?? 0) - 1;\n indegree.set(nextId, nextDegree);\n if (nextDegree === 0) queue.push(nextId);\n }\n }\n\n // On cycles, append remaining IDs in original order to keep behavior stable.\n if (ordered.length < manifest.length) {\n const included = new Set(ordered);\n for (const feature of manifest) {\n if (included.has(feature.id)) continue;\n ordered.push(feature.id);\n }\n }\n\n return ordered;\n}\n\nexport function hasDependencyCycle(manifest: FeatureManifest): boolean {\n const ids = new Set(manifest.map((feature) => feature.id));\n const outgoing = new Map<string, Set<string>>();\n const indegree = new Map<string, number>();\n\n for (const feature of manifest) {\n outgoing.set(feature.id, new Set());\n indegree.set(feature.id, 0);\n }\n\n for (const feature of manifest) {\n for (const dependencyId of getDirectDependencies(feature)) {\n if (!ids.has(dependencyId)) continue;\n const edges = outgoing.get(dependencyId);\n if (!edges || edges.has(feature.id)) continue;\n edges.add(feature.id);\n indegree.set(feature.id, (indegree.get(feature.id) ?? 0) + 1);\n }\n }\n\n const queue: string[] = [];\n for (const feature of manifest) {\n if ((indegree.get(feature.id) ?? 0) === 0) queue.push(feature.id);\n }\n\n let visited = 0;\n while (queue.length > 0) {\n const id = queue.shift();\n if (!id) continue;\n visited += 1;\n const edges = outgoing.get(id);\n if (!edges) continue;\n for (const nextId of edges) {\n const nextDegree = (indegree.get(nextId) ?? 0) - 1;\n indegree.set(nextId, nextDegree);\n if (nextDegree === 0) queue.push(nextId);\n }\n }\n\n return visited !== manifest.length;\n}\n\nexport function sortFeaturesByDependencies(features: FeatureEntry[]): FeatureEntry[] {\n if (features.length <= 1) return [...features];\n const order = resolveDependencyOrder(features);\n const rank = new Map(order.map((id, index) => [id, index]));\n return [...features].sort((a, b) => {\n const ra = rank.get(a.id);\n const rb = rank.get(b.id);\n if (ra === undefined || rb === undefined) return 0;\n return ra - rb;\n });\n}\n","import { hasDependencyCycle } from \"./dependencies\";\nimport type { FeatureEntry, FeatureManifest } from \"./types\";\nimport { z } from \"zod\";\n\nexport interface ValidationIssue {\n path: string;\n message: string;\n code:\n | \"invalid_type\"\n | \"missing_required\"\n | \"invalid_value\"\n | \"invalid_date\"\n | \"duplicate_id\"\n | \"circular_dependency\";\n}\n\nexport interface ValidationResult {\n valid: boolean;\n errors: ValidationIssue[];\n}\n\nexport const featureEntryJsonSchema = {\n type: \"object\",\n required: [\"id\", \"label\", \"releasedAt\", \"showNewUntil\"],\n properties: {\n id: { type: \"string\" },\n label: { type: \"string\" },\n description: { type: \"string\" },\n releasedAt: { type: \"string\", format: \"date-time\" },\n showNewUntil: { type: \"string\", format: \"date-time\" },\n flagKey: { type: \"string\" },\n product: { type: \"string\" },\n url: { type: \"string\" },\n image: { type: \"string\" },\n type: { enum: [\"feature\", \"improvement\", \"fix\", \"breaking\"] },\n priority: { enum: [\"critical\", \"normal\", \"low\"] },\n cta: {\n type: \"object\",\n properties: {\n label: { type: \"string\" },\n url: { type: \"string\" },\n },\n },\n meta: { type: \"object\" },\n },\n} as const;\n\nexport const featureManifestJsonSchema = {\n type: \"array\",\n items: featureEntryJsonSchema,\n} as const;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction isValidDate(value: string): boolean {\n return Number.isFinite(new Date(value).getTime());\n}\n\nconst nonEmptyString = z.string().trim().min(1, \"must be a non-empty string\");\n\nconst isoDateString = nonEmptyString.refine(isValidDate, {\n message: \"must be a valid date\",\n params: { featuredropCode: \"invalid_date\" },\n});\n\nconst dependsOnSchema = z\n .object({\n seen: z.array(z.string()).optional(),\n clicked: z.array(z.string()).optional(),\n dismissed: z.array(z.string()).optional(),\n })\n .optional();\n\nconst ctaSchema = z\n .object({\n label: nonEmptyString,\n url: nonEmptyString,\n })\n .optional();\n\nexport const featureEntrySchema = z\n .object({\n id: nonEmptyString,\n label: nonEmptyString,\n releasedAt: isoDateString,\n showNewUntil: isoDateString,\n description: z.string().optional(),\n flagKey: z.string().optional(),\n product: z.string().optional(),\n url: z.string().optional(),\n image: z.string().optional(),\n type: z.enum([\"feature\", \"improvement\", \"fix\", \"breaking\"]).optional(),\n priority: z.enum([\"critical\", \"normal\", \"low\"]).optional(),\n cta: ctaSchema,\n meta: z.record(z.unknown()).optional(),\n dependsOn: dependsOnSchema,\n })\n .passthrough();\n\nexport const featureManifestSchema = z.array(featureEntrySchema);\n\nfunction toIssuePath(path: Array<string | number>): string {\n if (path.length === 0) return \"$\";\n let output = \"\";\n for (const part of path) {\n if (typeof part === \"number\") output += `[${part}]`;\n else output += output ? `.${part}` : part;\n }\n return output;\n}\n\nfunction mapZodIssue(issue: z.ZodIssue): ValidationIssue {\n const codeParam = (issue as { params?: Record<string, unknown> }).params?.featuredropCode;\n if (codeParam === \"invalid_date\") {\n return {\n path: toIssuePath(issue.path),\n message: issue.message,\n code: \"invalid_date\",\n };\n }\n if (issue.code === \"invalid_type\") {\n return {\n path: toIssuePath(issue.path),\n message: issue.message,\n code: issue.received === \"undefined\" ? \"missing_required\" : \"invalid_type\",\n };\n }\n return {\n path: toIssuePath(issue.path),\n message: issue.message,\n code: \"invalid_value\",\n };\n}\n\nconst UNSAFE_META_KEYS = new Set([\"__proto__\", \"constructor\", \"prototype\"]);\n\nfunction isSafeUrl(value: string): boolean {\n const normalized = value.trim();\n if (!normalized) return false;\n if (/^(\\/|\\.\\/|\\.\\.\\/|\\?|#)/.test(normalized)) return true;\n if (/^https?:\\/\\//i.test(normalized)) return true;\n return false;\n}\n\nfunction findUnsafeMetaPath(value: unknown, path = \"meta\"): string | null {\n if (Array.isArray(value)) {\n for (let index = 0; index < value.length; index++) {\n const nested = findUnsafeMetaPath(value[index], `${path}[${index}]`);\n if (nested) return nested;\n }\n return null;\n }\n\n if (!isRecord(value)) return null;\n for (const [key, nestedValue] of Object.entries(value)) {\n if (UNSAFE_META_KEYS.has(key)) {\n return `${path}.${key}`;\n }\n const nested = findUnsafeMetaPath(nestedValue, `${path}.${key}`);\n if (nested) return nested;\n }\n return null;\n}\n\nfunction validateFeatureEntry(raw: unknown, index: number): { entry?: FeatureEntry; issues: ValidationIssue[] } {\n if (!isRecord(raw)) {\n return {\n issues: [\n {\n path: `[${index}]`,\n message: \"Feature entry must be an object\",\n code: \"invalid_type\",\n },\n ],\n };\n }\n\n const parsed = featureEntrySchema.safeParse(raw);\n if (!parsed.success) {\n return {\n issues: parsed.error.issues.map((issue) => ({\n ...mapZodIssue(issue),\n path: `[${index}]${issue.path.length > 0 ? `.${toIssuePath(issue.path)}` : \"\"}`,\n })),\n };\n }\n\n return {\n issues: [],\n entry: parsed.data as FeatureEntry,\n };\n}\n\nexport function validateManifest(data: unknown): ValidationResult {\n const errors: ValidationIssue[] = [];\n if (!Array.isArray(data)) {\n return {\n valid: false,\n errors: [\n {\n path: \"$\",\n message: \"Manifest must be an array\",\n code: \"invalid_type\",\n },\n ],\n };\n }\n\n const entries: FeatureEntry[] = [];\n const seenIds = new Set<string>();\n data.forEach((item, index) => {\n const result = validateFeatureEntry(item, index);\n errors.push(...result.issues);\n if (!result.entry) return;\n if (seenIds.has(result.entry.id)) {\n errors.push({\n path: `[${index}].id`,\n message: `Duplicate feature id \"${result.entry.id}\"`,\n code: \"duplicate_id\",\n });\n return;\n }\n seenIds.add(result.entry.id);\n entries.push(result.entry);\n });\n\n if (entries.length > 0 && hasDependencyCycle(entries as FeatureManifest)) {\n errors.push({\n path: \"$\",\n message: \"Circular dependsOn relationship detected\",\n code: \"circular_dependency\",\n });\n }\n\n for (let index = 0; index < entries.length; index++) {\n const entry = entries[index];\n if (new Date(entry.showNewUntil).getTime() <= new Date(entry.releasedAt).getTime()) {\n errors.push({\n path: `[${index}].showNewUntil`,\n message: \"showNewUntil must be after releasedAt\",\n code: \"invalid_value\",\n });\n }\n\n if (entry.url && !isSafeUrl(entry.url)) {\n errors.push({\n path: `[${index}].url`,\n message: \"url must be http, https, or relative\",\n code: \"invalid_value\",\n });\n }\n\n if (entry.image && !isSafeUrl(entry.image)) {\n errors.push({\n path: `[${index}].image`,\n message: \"image must be http, https, or relative\",\n code: \"invalid_value\",\n });\n }\n\n if (entry.cta?.url && !isSafeUrl(entry.cta.url)) {\n errors.push({\n path: `[${index}].cta.url`,\n message: \"cta.url must be http, https, or relative\",\n code: \"invalid_value\",\n });\n }\n\n const unsafeMetaPath = findUnsafeMetaPath(entry.meta);\n if (unsafeMetaPath) {\n errors.push({\n path: `[${index}].${unsafeMetaPath}`,\n message: `meta contains unsafe key \"${unsafeMetaPath.split(\".\").pop()}\"`,\n code: \"invalid_value\",\n });\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n };\n}\n","import { readdir, readFile, stat, writeFile } from \"node:fs/promises\";\nimport { join, relative, sep } from \"node:path\";\nimport type { FeatureEntry } from \"./types\";\nimport { validateManifest } from \"./schema\";\n\ninterface ParseResult {\n frontmatter: Record<string, unknown>;\n body: string;\n}\n\nexport interface BuildManifestOptions {\n cwd?: string;\n pattern?: string;\n outFile?: string;\n}\n\nfunction parseScalar(raw: string): unknown {\n const value = raw.trim();\n if (!value) return \"\";\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n return value.slice(1, -1);\n }\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n if (value === \"null\") return null;\n if (/^-?\\d+(\\.\\d+)?$/.test(value)) return Number(value);\n if (value.startsWith(\"[\") && value.endsWith(\"]\")) {\n const inner = value.slice(1, -1).trim();\n if (!inner) return [];\n return inner.split(\",\").map((part) => String(parseScalar(part.trim())));\n }\n return value;\n}\n\nfunction parseFrontmatter(raw: string): Record<string, unknown> {\n const lines = raw.split(/\\r?\\n/);\n const root: Record<string, unknown> = {};\n const stack: Array<{ indent: number; value: Record<string, unknown> | unknown[] }> = [\n { indent: -1, value: root },\n ];\n\n const isArrayContext = (idx: number): boolean => {\n for (let i = idx + 1; i < lines.length; i++) {\n const line = lines[i];\n if (!line.trim()) continue;\n const indent = line.length - line.trimStart().length;\n if (indent <= (lines[idx].length - lines[idx].trimStart().length)) return false;\n return line.trimStart().startsWith(\"- \");\n }\n return false;\n };\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i];\n if (!line.trim() || line.trimStart().startsWith(\"#\")) continue;\n\n const indent = line.length - line.trimStart().length;\n const trimmed = line.trim();\n\n while (stack.length > 1 && indent <= stack[stack.length - 1].indent) {\n stack.pop();\n }\n\n const current = stack[stack.length - 1].value;\n\n if (trimmed.startsWith(\"- \")) {\n if (!Array.isArray(current)) {\n throw new Error(`Invalid frontmatter list at line ${i + 1}`);\n }\n const item = trimmed.slice(2).trim();\n current.push(parseScalar(item));\n continue;\n }\n\n const colon = trimmed.indexOf(\":\");\n if (colon === -1) {\n throw new Error(`Invalid frontmatter line ${i + 1}: ${trimmed}`);\n }\n\n const key = trimmed.slice(0, colon).trim();\n const rest = trimmed.slice(colon + 1).trim();\n\n if (Array.isArray(current)) {\n throw new Error(`Unexpected key in list at line ${i + 1}`);\n }\n\n if (!rest) {\n const container: Record<string, unknown> | unknown[] = isArrayContext(i) ? [] : {};\n current[key] = container;\n stack.push({ indent, value: container });\n continue;\n }\n\n current[key] = parseScalar(rest);\n }\n\n return root;\n}\n\nfunction splitFrontmatter(markdown: string): ParseResult {\n const normalized = markdown.replace(/\\r\\n/g, \"\\n\");\n if (!normalized.startsWith(\"---\\n\")) {\n return { frontmatter: {}, body: normalized.trim() };\n }\n\n const end = normalized.indexOf(\"\\n---\\n\", 4);\n if (end === -1) {\n throw new Error(\"Frontmatter block is not closed with ---\");\n }\n\n const fmRaw = normalized.slice(4, end);\n const body = normalized.slice(end + 5).trim();\n return {\n frontmatter: parseFrontmatter(fmRaw),\n body,\n };\n}\n\nfunction asString(value: unknown, field: string, source: string): string {\n if (typeof value !== \"string\" || !value.trim()) {\n throw new Error(`${source}: \"${field}\" must be a non-empty string`);\n }\n return value;\n}\n\nfunction asOptionalObject(value: unknown, field: string, source: string): Record<string, unknown> | undefined {\n if (value === undefined) return undefined;\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new Error(`${source}: \"${field}\" must be an object`);\n }\n return value as Record<string, unknown>;\n}\n\nexport function parseFeatureFile(markdown: string, source = \"feature.md\"): FeatureEntry {\n const { frontmatter, body } = splitFrontmatter(markdown);\n\n const entry: FeatureEntry = {\n id: asString(frontmatter.id, \"id\", source),\n label: asString(frontmatter.label, \"label\", source),\n releasedAt: asString(frontmatter.releasedAt, \"releasedAt\", source),\n showNewUntil: asString(frontmatter.showNewUntil, \"showNewUntil\", source),\n description: body || undefined,\n };\n\n if (frontmatter.sidebarKey !== undefined) entry.sidebarKey = asString(frontmatter.sidebarKey, \"sidebarKey\", source);\n if (frontmatter.category !== undefined) entry.category = asString(frontmatter.category, \"category\", source);\n if (frontmatter.product !== undefined) entry.product = asString(frontmatter.product, \"product\", source);\n if (frontmatter.url !== undefined) entry.url = asString(frontmatter.url, \"url\", source);\n if (frontmatter.flagKey !== undefined) entry.flagKey = asString(frontmatter.flagKey, \"flagKey\", source);\n if (frontmatter.image !== undefined) entry.image = asString(frontmatter.image, \"image\", source);\n if (frontmatter.publishAt !== undefined) entry.publishAt = asString(frontmatter.publishAt, \"publishAt\", source);\n if (frontmatter.version !== undefined) {\n if (typeof frontmatter.version === \"string\" || typeof frontmatter.version === \"object\") {\n entry.version = frontmatter.version as FeatureEntry[\"version\"];\n } else {\n throw new Error(`${source}: \"version\" must be a string or object`);\n }\n }\n if (frontmatter.type !== undefined) {\n const type = asString(frontmatter.type, \"type\", source);\n if (![\"feature\", \"improvement\", \"fix\", \"breaking\"].includes(type)) {\n throw new Error(`${source}: invalid \"type\" value \"${type}\"`);\n }\n entry.type = type as FeatureEntry[\"type\"];\n }\n if (frontmatter.priority !== undefined) {\n const priority = asString(frontmatter.priority, \"priority\", source);\n if (![\"critical\", \"normal\", \"low\"].includes(priority)) {\n throw new Error(`${source}: invalid \"priority\" value \"${priority}\"`);\n }\n entry.priority = priority as FeatureEntry[\"priority\"];\n }\n\n const cta = asOptionalObject(frontmatter.cta, \"cta\", source);\n if (cta) {\n entry.cta = {\n label: asString(cta.label, \"cta.label\", source),\n url: asString(cta.url, \"cta.url\", source),\n };\n }\n\n const audience = asOptionalObject(frontmatter.audience, \"audience\", source);\n if (audience) {\n const parsedAudience: FeatureEntry[\"audience\"] = {};\n for (const field of [\"plan\", \"role\", \"region\"] as const) {\n const value = audience[field];\n if (value !== undefined) {\n if (!Array.isArray(value) || value.some((item) => typeof item !== \"string\")) {\n throw new Error(`${source}: \"audience.${field}\" must be string[]`);\n }\n parsedAudience[field] = value;\n }\n }\n if (audience.custom !== undefined) {\n if (!audience.custom || typeof audience.custom !== \"object\" || Array.isArray(audience.custom)) {\n throw new Error(`${source}: \"audience.custom\" must be an object`);\n }\n parsedAudience.custom = audience.custom as Record<string, unknown>;\n }\n entry.audience = parsedAudience;\n }\n\n return entry;\n}\n\nfunction normalizePattern(pattern: string): { baseDir: string; ext: string } {\n const normalized = pattern.replaceAll(\"\\\\\", \"/\");\n if (normalized.endsWith(\"/**/*.md\")) {\n return {\n baseDir: normalized.slice(0, -\"/**/*.md\".length),\n ext: \".md\",\n };\n }\n throw new Error(`Unsupported pattern \"${pattern}\". Use \"features/**/*.md\" style patterns.`);\n}\n\nasync function collectFiles(dir: string, ext: string): Promise<string[]> {\n const out: string[] = [];\n async function walk(current: string): Promise<void> {\n let entries;\n try {\n entries = await readdir(current, { withFileTypes: true });\n } catch {\n return;\n }\n for (const entry of entries) {\n const fullPath = join(current, entry.name);\n if (entry.isDirectory()) {\n await walk(fullPath);\n continue;\n }\n if (entry.isFile() && entry.name.endsWith(ext)) {\n out.push(fullPath);\n }\n }\n }\n await walk(dir);\n return out.sort();\n}\n\nexport async function buildManifestFromPattern(options: BuildManifestOptions = {}): Promise<FeatureEntry[]> {\n const cwd = options.cwd ?? process.cwd();\n const pattern = options.pattern ?? \"features/**/*.md\";\n const { baseDir, ext } = normalizePattern(pattern);\n const baseAbs = join(cwd, baseDir);\n\n const stats = await stat(baseAbs).catch(() => null);\n if (!stats || !stats.isDirectory()) {\n throw new Error(`Pattern base directory does not exist: ${baseDir}`);\n }\n\n const files = await collectFiles(baseAbs, ext);\n const entries: FeatureEntry[] = [];\n const seenIds = new Set<string>();\n\n for (const file of files) {\n const content = await readFile(file, \"utf8\");\n const source = relative(cwd, file).split(sep).join(\"/\");\n const entry = parseFeatureFile(content, source);\n if (seenIds.has(entry.id)) {\n throw new Error(`Duplicate feature id \"${entry.id}\" found at ${source}`);\n }\n seenIds.add(entry.id);\n entries.push(entry);\n }\n\n if (options.outFile) {\n const outPath = join(cwd, options.outFile);\n await writeFile(outPath, `${JSON.stringify(entries, null, 2)}\\n`, \"utf8\");\n }\n\n return entries;\n}\n\nexport async function validateFeatureFiles(options: BuildManifestOptions = {}): Promise<void> {\n const entries = await buildManifestFromPattern(options);\n const result = validateManifest(entries);\n if (!result.valid) {\n const message = result.errors\n .map((issue) => `${issue.path}: ${issue.message}`)\n .join(\"; \");\n throw new Error(`Manifest validation failed: ${message}`);\n }\n}\n","import { buildManifestFromPattern, parseFeatureFile } from \"./changelog-as-code\";\nimport { validateManifest } from \"./schema\";\nimport type { FeatureEntry } from \"./types\";\n\ntype CMSFieldResolver = string | ((record: unknown) => unknown);\n\nexport interface CMSFieldMapping {\n id?: CMSFieldResolver;\n label?: CMSFieldResolver;\n description?: CMSFieldResolver;\n releasedAt?: CMSFieldResolver;\n showNewUntil?: CMSFieldResolver;\n sidebarKey?: CMSFieldResolver;\n category?: CMSFieldResolver;\n product?: CMSFieldResolver;\n flagKey?: CMSFieldResolver;\n url?: CMSFieldResolver;\n image?: CMSFieldResolver;\n publishAt?: CMSFieldResolver;\n type?: CMSFieldResolver;\n priority?: CMSFieldResolver;\n ctaLabel?: CMSFieldResolver;\n ctaUrl?: CMSFieldResolver;\n}\n\nexport interface CMSAdapter {\n load: () => Promise<FeatureEntry[]>;\n}\n\ninterface NormalizedCMSFieldMapping {\n id: CMSFieldResolver;\n label: CMSFieldResolver;\n releasedAt: CMSFieldResolver;\n showNewUntil: CMSFieldResolver;\n description?: CMSFieldResolver;\n sidebarKey?: CMSFieldResolver;\n category?: CMSFieldResolver;\n product?: CMSFieldResolver;\n flagKey?: CMSFieldResolver;\n url?: CMSFieldResolver;\n image?: CMSFieldResolver;\n publishAt?: CMSFieldResolver;\n type?: CMSFieldResolver;\n priority?: CMSFieldResolver;\n ctaLabel?: CMSFieldResolver;\n ctaUrl?: CMSFieldResolver;\n}\n\ninterface CMSAdapterBaseOptions {\n fieldMapping?: CMSFieldMapping;\n /** Throw when mapped entries are invalid. Default false (invalid entries are dropped). */\n strictValidation?: boolean;\n}\n\nconst DEFAULT_FIELDS: NormalizedCMSFieldMapping = {\n id: \"id\",\n label: \"label\",\n releasedAt: \"releasedAt\",\n showNewUntil: \"showNewUntil\",\n description: \"description\",\n sidebarKey: \"sidebarKey\",\n category: \"category\",\n product: \"product\",\n flagKey: \"flagKey\",\n url: \"url\",\n image: \"image\",\n publishAt: \"publishAt\",\n type: \"type\",\n priority: \"priority\",\n ctaLabel: \"cta.label\",\n ctaUrl: \"cta.url\",\n};\n\ninterface ContentfulAdapterOptions extends CMSAdapterBaseOptions {\n spaceId: string;\n accessToken: string;\n contentType: string;\n environment?: string;\n locale?: string;\n limit?: number;\n}\n\ninterface SanityAdapterOptions extends CMSAdapterBaseOptions {\n projectId: string;\n dataset: string;\n query: string;\n token?: string;\n apiVersion?: string;\n}\n\ninterface StrapiAdapterOptions extends CMSAdapterBaseOptions {\n baseUrl: string;\n endpoint?: string;\n token?: string;\n query?: string;\n}\n\ninterface NotionAdapterOptions extends CMSAdapterBaseOptions {\n databaseId: string;\n token: string;\n notionVersion?: string;\n filter?: Record<string, unknown>;\n sorts?: Array<Record<string, unknown>>;\n}\n\ninterface MarkdownAdapterFile {\n source?: string;\n markdown: string;\n}\n\ninterface MarkdownAdapterOptions extends CMSAdapterBaseOptions {\n pattern?: string;\n cwd?: string;\n entries?: MarkdownAdapterFile[];\n}\n\nfunction getByPath(record: unknown, path: string): unknown {\n const parts = path.split(\".\").filter(Boolean);\n let cursor: unknown = record;\n for (const part of parts) {\n if (!cursor || typeof cursor !== \"object\") return undefined;\n cursor = (cursor as Record<string, unknown>)[part];\n }\n return cursor;\n}\n\nfunction normalizeLocalizedValue(value: unknown): unknown {\n if (value && typeof value === \"object\" && !Array.isArray(value)) {\n const objectValue = value as Record<string, unknown>;\n const keys = Object.keys(objectValue);\n if (keys.length === 1) {\n const nested = objectValue[keys[0]];\n if (\n typeof nested === \"string\" ||\n typeof nested === \"number\" ||\n typeof nested === \"boolean\" ||\n nested == null\n ) {\n return nested;\n }\n }\n }\n return value;\n}\n\nfunction resolveField(record: unknown, resolver?: CMSFieldResolver): unknown {\n if (!resolver) return undefined;\n if (typeof resolver === \"function\") return resolver(record);\n return normalizeLocalizedValue(getByPath(record, resolver));\n}\n\nfunction asString(value: unknown): string | undefined {\n if (typeof value === \"string\") {\n const trimmed = value.trim();\n return trimmed ? trimmed : undefined;\n }\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n return undefined;\n}\n\nfunction normalizeFieldMapping(\n defaults: NormalizedCMSFieldMapping,\n overrides?: CMSFieldMapping,\n): NormalizedCMSFieldMapping {\n return {\n ...defaults,\n ...overrides,\n };\n}\n\nfunction validateMappedEntries(\n entries: FeatureEntry[],\n options?: CMSAdapterBaseOptions,\n): FeatureEntry[] {\n const strictValidation = options?.strictValidation ?? false;\n const validEntries: FeatureEntry[] = [];\n const seenIds = new Set<string>();\n const errors: string[] = [];\n\n for (const entry of entries) {\n if (seenIds.has(entry.id)) {\n errors.push(`${entry.id}: duplicate id`);\n continue;\n }\n seenIds.add(entry.id);\n\n const validation = validateManifest([entry]);\n if (validation.valid) {\n validEntries.push(entry);\n continue;\n }\n const reason = validation.errors\n .map((error) => `${error.path} ${error.message}`)\n .join(\"; \");\n errors.push(`${entry.id}: ${reason}`);\n }\n\n if (errors.length > 0) {\n if (strictValidation) {\n throw new Error(`[featuredrop] CMS mapping validation failed: ${errors.join(\" | \")}`);\n }\n if (typeof process !== \"undefined\" && process.env.NODE_ENV !== \"production\") {\n console.warn(`[featuredrop] Skipped ${errors.length} invalid CMS entries.`);\n }\n }\n\n return validEntries;\n}\n\nfunction mapRecordToFeatureEntry(\n record: unknown,\n mapping: NormalizedCMSFieldMapping,\n): FeatureEntry | null {\n const id = asString(resolveField(record, mapping.id));\n const label = asString(resolveField(record, mapping.label));\n const releasedAt = asString(resolveField(record, mapping.releasedAt));\n const showNewUntil = asString(resolveField(record, mapping.showNewUntil));\n\n if (!id || !label || !releasedAt || !showNewUntil) return null;\n\n const entry: FeatureEntry = {\n id,\n label,\n releasedAt,\n showNewUntil,\n };\n\n const description = asString(resolveField(record, mapping.description));\n if (description) entry.description = description;\n\n const sidebarKey = asString(resolveField(record, mapping.sidebarKey));\n if (sidebarKey) entry.sidebarKey = sidebarKey;\n\n const category = asString(resolveField(record, mapping.category));\n if (category) entry.category = category;\n\n const product = asString(resolveField(record, mapping.product));\n if (product) entry.product = product;\n\n const flagKey = asString(resolveField(record, mapping.flagKey));\n if (flagKey) entry.flagKey = flagKey;\n\n const url = asString(resolveField(record, mapping.url));\n if (url) entry.url = url;\n\n const image = asString(resolveField(record, mapping.image));\n if (image) entry.image = image;\n\n const publishAt = asString(resolveField(record, mapping.publishAt));\n if (publishAt) entry.publishAt = publishAt;\n\n const type = asString(resolveField(record, mapping.type));\n if (type && [\"feature\", \"improvement\", \"fix\", \"breaking\"].includes(type)) {\n entry.type = type as FeatureEntry[\"type\"];\n }\n\n const priority = asString(resolveField(record, mapping.priority));\n if (priority && [\"critical\", \"normal\", \"low\"].includes(priority)) {\n entry.priority = priority as FeatureEntry[\"priority\"];\n }\n\n const ctaLabel = asString(resolveField(record, mapping.ctaLabel));\n const ctaUrl = asString(resolveField(record, mapping.ctaUrl));\n if (ctaLabel && ctaUrl) {\n entry.cta = { label: ctaLabel, url: ctaUrl };\n }\n\n return entry;\n}\n\nasync function fetchJson<T>(\n input: string,\n init?: RequestInit,\n): Promise<T> {\n const response = await fetch(input, init);\n if (!response.ok) {\n throw new Error(`[featuredrop] CMS request failed (${response.status}) for ${input}`);\n }\n return response.json() as Promise<T>;\n}\n\nexport class ContentfulAdapter implements CMSAdapter {\n private readonly options: ContentfulAdapterOptions;\n\n constructor(options: ContentfulAdapterOptions) {\n this.options = options;\n }\n\n async load(): Promise<FeatureEntry[]> {\n const environment = this.options.environment ?? \"master\";\n const params = new URLSearchParams({\n content_type: this.options.contentType,\n limit: String(this.options.limit ?? 1000),\n });\n if (this.options.locale) {\n params.set(\"locale\", this.options.locale);\n }\n const url =\n `https://cdn.contentful.com/spaces/${encodeURIComponent(this.options.spaceId)}`\n + `/environments/${encodeURIComponent(environment)}/entries?${params.toString()}`;\n\n const payload = await fetchJson<{ items?: unknown[] }>(url, {\n headers: {\n Authorization: `Bearer ${this.options.accessToken}`,\n },\n });\n\n const mapping = normalizeFieldMapping(\n {\n ...DEFAULT_FIELDS,\n id: \"sys.id\",\n label: \"fields.label\",\n description: \"fields.description\",\n releasedAt: \"fields.releasedAt\",\n showNewUntil: \"fields.showNewUntil\",\n sidebarKey: \"fields.sidebarKey\",\n category: \"fields.category\",\n product: \"fields.product\",\n flagKey: \"fields.flagKey\",\n url: \"fields.url\",\n image: \"fields.image\",\n publishAt: \"fields.publishAt\",\n type: \"fields.type\",\n priority: \"fields.priority\",\n ctaLabel: \"fields.ctaLabel\",\n ctaUrl: \"fields.ctaUrl\",\n },\n this.options.fieldMapping,\n );\n\n const entries = (payload.items ?? [])\n .map((item) => mapRecordToFeatureEntry(item, mapping))\n .filter((entry): entry is FeatureEntry => entry !== null);\n return validateMappedEntries(entries, this.options);\n }\n}\n\nexport class SanityAdapter implements CMSAdapter {\n private readonly options: SanityAdapterOptions;\n\n constructor(options: SanityAdapterOptions) {\n this.options = options;\n }\n\n async load(): Promise<FeatureEntry[]> {\n const version = this.options.apiVersion ?? \"v2023-10-01\";\n const queryParam = encodeURIComponent(this.options.query);\n const url = `https://${encodeURIComponent(this.options.projectId)}.api.sanity.io/${version}/data/query/${encodeURIComponent(this.options.dataset)}?query=${queryParam}`;\n\n const headers: Record<string, string> = {};\n if (this.options.token) {\n headers.Authorization = `Bearer ${this.options.token}`;\n }\n\n const payload = await fetchJson<{ result?: unknown[] }>(url, {\n headers,\n });\n\n const mapping = normalizeFieldMapping(\n {\n ...DEFAULT_FIELDS,\n id: \"_id\",\n },\n this.options.fieldMapping,\n );\n\n const entries = (payload.result ?? [])\n .map((item) => mapRecordToFeatureEntry(item, mapping))\n .filter((entry): entry is FeatureEntry => entry !== null);\n return validateMappedEntries(entries, this.options);\n }\n}\n\nexport class StrapiAdapter implements CMSAdapter {\n private readonly options: StrapiAdapterOptions;\n\n constructor(options: StrapiAdapterOptions) {\n this.options = options;\n }\n\n async load(): Promise<FeatureEntry[]> {\n const endpoint = this.options.endpoint ?? \"/api/features\";\n const base = this.options.baseUrl.replace(/\\/+$/, \"\");\n const query = this.options.query ? `?${this.options.query}` : \"\";\n const url = `${base}${endpoint}${query}`;\n\n const headers: Record<string, string> = {};\n if (this.options.token) {\n headers.Authorization = `Bearer ${this.options.token}`;\n }\n\n const payload = await fetchJson<{ data?: unknown[] }>(url, { headers });\n const mapping = normalizeFieldMapping(DEFAULT_FIELDS, this.options.fieldMapping);\n\n const entries = (payload.data ?? [])\n .map((item) => {\n if (!item || typeof item !== \"object\") return null;\n const record = item as Record<string, unknown>;\n const attributes = record.attributes;\n if (attributes && typeof attributes === \"object\") {\n return mapRecordToFeatureEntry(\n { id: record.id, ...(attributes as Record<string, unknown>) },\n mapping,\n );\n }\n return mapRecordToFeatureEntry(record, mapping);\n })\n .filter((entry): entry is FeatureEntry => entry !== null);\n return validateMappedEntries(entries, this.options);\n }\n}\n\nfunction notionPropertyToValue(property: unknown): unknown {\n if (!property || typeof property !== \"object\") return undefined;\n const typed = property as Record<string, unknown>;\n const type = typed.type;\n if (typeof type !== \"string\") return undefined;\n\n const value = typed[type];\n if (type === \"title\" || type === \"rich_text\") {\n if (!Array.isArray(value)) return undefined;\n return value\n .map((item) => {\n if (!item || typeof item !== \"object\") return \"\";\n return asString((item as Record<string, unknown>).plain_text) ?? \"\";\n })\n .join(\"\")\n .trim();\n }\n if (type === \"select\") {\n if (!value || typeof value !== \"object\") return undefined;\n return asString((value as Record<string, unknown>).name);\n }\n if (type === \"multi_select\") {\n if (!Array.isArray(value)) return undefined;\n return value\n .map((item) => (item && typeof item === \"object\"\n ? asString((item as Record<string, unknown>).name)\n : undefined))\n .filter((item): item is string => Boolean(item));\n }\n if (type === \"date\") {\n if (!value || typeof value !== \"object\") return undefined;\n return asString((value as Record<string, unknown>).start);\n }\n if (type === \"number\" || type === \"url\" || type === \"email\" || type === \"phone_number\") {\n return value;\n }\n if (type === \"checkbox\") {\n return value === true ? \"true\" : value === false ? \"false\" : undefined;\n }\n return undefined;\n}\n\nfunction flattenNotionPage(page: unknown): Record<string, unknown> {\n if (!page || typeof page !== \"object\") return {};\n const record = page as Record<string, unknown>;\n const properties = record.properties;\n const flattened: Record<string, unknown> = {\n id: record.id,\n };\n\n if (properties && typeof properties === \"object\") {\n Object.entries(properties as Record<string, unknown>).forEach(([key, value]) => {\n flattened[key] = notionPropertyToValue(value);\n });\n }\n\n return flattened;\n}\n\nexport class NotionAdapter implements CMSAdapter {\n private readonly options: NotionAdapterOptions;\n\n constructor(options: NotionAdapterOptions) {\n this.options = options;\n }\n\n async load(): Promise<FeatureEntry[]> {\n const body: Record<string, unknown> = {};\n if (this.options.filter) body.filter = this.options.filter;\n if (this.options.sorts) body.sorts = this.options.sorts;\n\n const payload = await fetchJson<{ results?: unknown[] }>(\n `https://api.notion.com/v1/databases/${encodeURIComponent(this.options.databaseId)}/query`,\n {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.options.token}`,\n \"Notion-Version\": this.options.notionVersion ?? \"2022-06-28\",\n },\n body: JSON.stringify(body),\n },\n );\n\n const mapping = normalizeFieldMapping(DEFAULT_FIELDS, this.options.fieldMapping);\n\n const entries = (payload.results ?? [])\n .map((page) => mapRecordToFeatureEntry(flattenNotionPage(page), mapping))\n .filter((entry): entry is FeatureEntry => entry !== null);\n return validateMappedEntries(entries, this.options);\n }\n}\n\nexport class MarkdownAdapter implements CMSAdapter {\n private readonly options: MarkdownAdapterOptions;\n\n constructor(options: MarkdownAdapterOptions = {}) {\n this.options = options;\n }\n\n async load(): Promise<FeatureEntry[]> {\n if (this.options.pattern) {\n const entries = await buildManifestFromPattern({\n cwd: this.options.cwd,\n pattern: this.options.pattern,\n });\n return validateMappedEntries(entries, this.options);\n }\n\n const entries = this.options.entries ?? [];\n const mapped = entries.map((entry, index) => {\n const source = entry.source ?? `feature-${index + 1}.md`;\n return parseFeatureFile(entry.markdown, source);\n });\n return validateMappedEntries(mapped, this.options);\n }\n}\n"]}
package/dist/cms.d.cts ADDED
@@ -0,0 +1,236 @@
1
+ /** Entry type label — determines default icon/color in UI */
2
+ type FeatureType = "feature" | "improvement" | "fix" | "breaking";
3
+ /** Priority level for announcements */
4
+ type FeaturePriority = "critical" | "normal" | "low";
5
+ /** Call-to-action for a feature entry */
6
+ interface FeatureCTA {
7
+ /** Button/link label */
8
+ label: string;
9
+ /** URL to navigate to */
10
+ url: string;
11
+ }
12
+ /** Variant-level overrides for A/B announcement testing */
13
+ interface FeatureVariant {
14
+ /** Optional variant-specific label override */
15
+ label?: string;
16
+ /** Optional variant-specific description override */
17
+ description?: string;
18
+ /** Optional variant-specific image override */
19
+ image?: string;
20
+ /** Optional variant-specific CTA override */
21
+ cta?: FeatureCTA;
22
+ /** Optional variant-specific metadata overrides */
23
+ meta?: Record<string, unknown>;
24
+ }
25
+ /** Audience targeting rule — determines which user segments see a feature */
26
+ interface AudienceRule {
27
+ /** Plans that should see this feature (e.g. ["pro", "enterprise"]) */
28
+ plan?: string[];
29
+ /** Roles that should see this feature (e.g. ["admin", "editor"]) */
30
+ role?: string[];
31
+ /** Regions that should see this feature (e.g. ["us", "eu"]) */
32
+ region?: string[];
33
+ /** Arbitrary key-value pairs for custom matching logic */
34
+ custom?: Record<string, unknown>;
35
+ }
36
+ /** Dependency gates for progressive feature discovery */
37
+ interface FeatureDependencies {
38
+ /** Features the user must have seen before this one can surface */
39
+ seen?: string[];
40
+ /** Features the user must have clicked before this one can surface */
41
+ clicked?: string[];
42
+ /** Features the user must have dismissed before this one can surface */
43
+ dismissed?: string[];
44
+ }
45
+ /** Runtime context used by trigger evaluation */
46
+ interface TriggerContext {
47
+ /** Current app route/path */
48
+ path?: string;
49
+ /** Named events observed in this session */
50
+ events?: ReadonlySet<string>;
51
+ /** Named milestone flags reached in this session */
52
+ milestones?: ReadonlySet<string>;
53
+ /** Usage counters keyed by event/pattern name */
54
+ usage?: Record<string, number>;
55
+ /** Session elapsed time in milliseconds */
56
+ elapsedMs?: number;
57
+ /** Scroll completion percentage (0-100) */
58
+ scrollPercent?: number;
59
+ /** Optional additional trigger context */
60
+ metadata?: Record<string, unknown>;
61
+ }
62
+ type FeatureTrigger = {
63
+ type: "page";
64
+ match: string | RegExp;
65
+ } | {
66
+ type: "usage";
67
+ event: string;
68
+ minActions?: number;
69
+ } | {
70
+ type: "time";
71
+ minSeconds: number;
72
+ } | {
73
+ type: "milestone";
74
+ event: string;
75
+ } | {
76
+ type: "frustration";
77
+ pattern: string;
78
+ threshold?: number;
79
+ } | {
80
+ type: "scroll";
81
+ minPercent?: number;
82
+ } | {
83
+ type: "custom";
84
+ evaluate: (context: TriggerContext) => boolean;
85
+ };
86
+ /** A single feature entry in the manifest */
87
+ interface FeatureEntry {
88
+ /** Unique identifier for the feature */
89
+ id: string;
90
+ /** Human-readable label (e.g. "Decision Journal") */
91
+ label: string;
92
+ /** Optional longer description (supports markdown in UI components) */
93
+ description?: string;
94
+ /**
95
+ * Semantic version targeting.
96
+ * If provided as an object, requires `appVersion` to be supplied to the provider/helpers.
97
+ * - introduced: earliest app version that includes this feature
98
+ * - showNewUntil: stop showing "new" once appVersion reaches this
99
+ * - deprecatedAt: hide feature for app versions at or above this (optional safety)
100
+ * - showIn: range string, e.g. ">=2.5.0 <3.0.0"
101
+ */
102
+ version?: string | {
103
+ introduced?: string;
104
+ showNewUntil?: string;
105
+ deprecatedAt?: string;
106
+ showIn?: string;
107
+ };
108
+ /** ISO date when this feature was released */
109
+ releasedAt: string;
110
+ /** ISO date after which the "new" badge should stop showing */
111
+ showNewUntil: string;
112
+ /** Optional key to match navigation items (e.g. "/journal", "settings") */
113
+ sidebarKey?: string;
114
+ /** Optional grouping category (e.g. "ai", "billing", "core") */
115
+ category?: string;
116
+ /** Optional product scope (`"*"`, `"askverdict"`, etc.) for multi-product manifests */
117
+ product?: string;
118
+ /** Optional URL to link to (e.g. docs page, changelog entry) */
119
+ url?: string;
120
+ /** Optional feature flag key; requires a flag bridge to evaluate */
121
+ flagKey?: string;
122
+ /** Entry type — determines default icon/color in UI components */
123
+ type?: FeatureType;
124
+ /** Priority level — critical entries get special treatment in UI */
125
+ priority?: FeaturePriority;
126
+ /** Optional image/screenshot URL */
127
+ image?: string;
128
+ /** Optional call-to-action button */
129
+ cta?: FeatureCTA;
130
+ /** ISO date — entry is hidden until this date (scheduled publishing) */
131
+ publishAt?: string;
132
+ /** Optional arbitrary metadata */
133
+ meta?: Record<string, unknown>;
134
+ /** A/B variants keyed by variant name (e.g. control, treatment_a) */
135
+ variants?: Record<string, FeatureVariant>;
136
+ /** Percentage split per variant (same order as variants object keys) */
137
+ variantSplit?: number[];
138
+ /** Audience targeting — if set, only matching users see this feature */
139
+ audience?: AudienceRule;
140
+ /** Dependency requirements (progressive disclosure sequencing) */
141
+ dependsOn?: FeatureDependencies;
142
+ /** Contextual trigger rule */
143
+ trigger?: FeatureTrigger;
144
+ }
145
+
146
+ type CMSFieldResolver = string | ((record: unknown) => unknown);
147
+ interface CMSFieldMapping {
148
+ id?: CMSFieldResolver;
149
+ label?: CMSFieldResolver;
150
+ description?: CMSFieldResolver;
151
+ releasedAt?: CMSFieldResolver;
152
+ showNewUntil?: CMSFieldResolver;
153
+ sidebarKey?: CMSFieldResolver;
154
+ category?: CMSFieldResolver;
155
+ product?: CMSFieldResolver;
156
+ flagKey?: CMSFieldResolver;
157
+ url?: CMSFieldResolver;
158
+ image?: CMSFieldResolver;
159
+ publishAt?: CMSFieldResolver;
160
+ type?: CMSFieldResolver;
161
+ priority?: CMSFieldResolver;
162
+ ctaLabel?: CMSFieldResolver;
163
+ ctaUrl?: CMSFieldResolver;
164
+ }
165
+ interface CMSAdapter {
166
+ load: () => Promise<FeatureEntry[]>;
167
+ }
168
+ interface CMSAdapterBaseOptions {
169
+ fieldMapping?: CMSFieldMapping;
170
+ /** Throw when mapped entries are invalid. Default false (invalid entries are dropped). */
171
+ strictValidation?: boolean;
172
+ }
173
+ interface ContentfulAdapterOptions extends CMSAdapterBaseOptions {
174
+ spaceId: string;
175
+ accessToken: string;
176
+ contentType: string;
177
+ environment?: string;
178
+ locale?: string;
179
+ limit?: number;
180
+ }
181
+ interface SanityAdapterOptions extends CMSAdapterBaseOptions {
182
+ projectId: string;
183
+ dataset: string;
184
+ query: string;
185
+ token?: string;
186
+ apiVersion?: string;
187
+ }
188
+ interface StrapiAdapterOptions extends CMSAdapterBaseOptions {
189
+ baseUrl: string;
190
+ endpoint?: string;
191
+ token?: string;
192
+ query?: string;
193
+ }
194
+ interface NotionAdapterOptions extends CMSAdapterBaseOptions {
195
+ databaseId: string;
196
+ token: string;
197
+ notionVersion?: string;
198
+ filter?: Record<string, unknown>;
199
+ sorts?: Array<Record<string, unknown>>;
200
+ }
201
+ interface MarkdownAdapterFile {
202
+ source?: string;
203
+ markdown: string;
204
+ }
205
+ interface MarkdownAdapterOptions extends CMSAdapterBaseOptions {
206
+ pattern?: string;
207
+ cwd?: string;
208
+ entries?: MarkdownAdapterFile[];
209
+ }
210
+ declare class ContentfulAdapter implements CMSAdapter {
211
+ private readonly options;
212
+ constructor(options: ContentfulAdapterOptions);
213
+ load(): Promise<FeatureEntry[]>;
214
+ }
215
+ declare class SanityAdapter implements CMSAdapter {
216
+ private readonly options;
217
+ constructor(options: SanityAdapterOptions);
218
+ load(): Promise<FeatureEntry[]>;
219
+ }
220
+ declare class StrapiAdapter implements CMSAdapter {
221
+ private readonly options;
222
+ constructor(options: StrapiAdapterOptions);
223
+ load(): Promise<FeatureEntry[]>;
224
+ }
225
+ declare class NotionAdapter implements CMSAdapter {
226
+ private readonly options;
227
+ constructor(options: NotionAdapterOptions);
228
+ load(): Promise<FeatureEntry[]>;
229
+ }
230
+ declare class MarkdownAdapter implements CMSAdapter {
231
+ private readonly options;
232
+ constructor(options?: MarkdownAdapterOptions);
233
+ load(): Promise<FeatureEntry[]>;
234
+ }
235
+
236
+ export { type CMSAdapter, type CMSFieldMapping, ContentfulAdapter, MarkdownAdapter, NotionAdapter, SanityAdapter, StrapiAdapter };
package/dist/cms.d.ts ADDED
@@ -0,0 +1,236 @@
1
+ /** Entry type label — determines default icon/color in UI */
2
+ type FeatureType = "feature" | "improvement" | "fix" | "breaking";
3
+ /** Priority level for announcements */
4
+ type FeaturePriority = "critical" | "normal" | "low";
5
+ /** Call-to-action for a feature entry */
6
+ interface FeatureCTA {
7
+ /** Button/link label */
8
+ label: string;
9
+ /** URL to navigate to */
10
+ url: string;
11
+ }
12
+ /** Variant-level overrides for A/B announcement testing */
13
+ interface FeatureVariant {
14
+ /** Optional variant-specific label override */
15
+ label?: string;
16
+ /** Optional variant-specific description override */
17
+ description?: string;
18
+ /** Optional variant-specific image override */
19
+ image?: string;
20
+ /** Optional variant-specific CTA override */
21
+ cta?: FeatureCTA;
22
+ /** Optional variant-specific metadata overrides */
23
+ meta?: Record<string, unknown>;
24
+ }
25
+ /** Audience targeting rule — determines which user segments see a feature */
26
+ interface AudienceRule {
27
+ /** Plans that should see this feature (e.g. ["pro", "enterprise"]) */
28
+ plan?: string[];
29
+ /** Roles that should see this feature (e.g. ["admin", "editor"]) */
30
+ role?: string[];
31
+ /** Regions that should see this feature (e.g. ["us", "eu"]) */
32
+ region?: string[];
33
+ /** Arbitrary key-value pairs for custom matching logic */
34
+ custom?: Record<string, unknown>;
35
+ }
36
+ /** Dependency gates for progressive feature discovery */
37
+ interface FeatureDependencies {
38
+ /** Features the user must have seen before this one can surface */
39
+ seen?: string[];
40
+ /** Features the user must have clicked before this one can surface */
41
+ clicked?: string[];
42
+ /** Features the user must have dismissed before this one can surface */
43
+ dismissed?: string[];
44
+ }
45
+ /** Runtime context used by trigger evaluation */
46
+ interface TriggerContext {
47
+ /** Current app route/path */
48
+ path?: string;
49
+ /** Named events observed in this session */
50
+ events?: ReadonlySet<string>;
51
+ /** Named milestone flags reached in this session */
52
+ milestones?: ReadonlySet<string>;
53
+ /** Usage counters keyed by event/pattern name */
54
+ usage?: Record<string, number>;
55
+ /** Session elapsed time in milliseconds */
56
+ elapsedMs?: number;
57
+ /** Scroll completion percentage (0-100) */
58
+ scrollPercent?: number;
59
+ /** Optional additional trigger context */
60
+ metadata?: Record<string, unknown>;
61
+ }
62
+ type FeatureTrigger = {
63
+ type: "page";
64
+ match: string | RegExp;
65
+ } | {
66
+ type: "usage";
67
+ event: string;
68
+ minActions?: number;
69
+ } | {
70
+ type: "time";
71
+ minSeconds: number;
72
+ } | {
73
+ type: "milestone";
74
+ event: string;
75
+ } | {
76
+ type: "frustration";
77
+ pattern: string;
78
+ threshold?: number;
79
+ } | {
80
+ type: "scroll";
81
+ minPercent?: number;
82
+ } | {
83
+ type: "custom";
84
+ evaluate: (context: TriggerContext) => boolean;
85
+ };
86
+ /** A single feature entry in the manifest */
87
+ interface FeatureEntry {
88
+ /** Unique identifier for the feature */
89
+ id: string;
90
+ /** Human-readable label (e.g. "Decision Journal") */
91
+ label: string;
92
+ /** Optional longer description (supports markdown in UI components) */
93
+ description?: string;
94
+ /**
95
+ * Semantic version targeting.
96
+ * If provided as an object, requires `appVersion` to be supplied to the provider/helpers.
97
+ * - introduced: earliest app version that includes this feature
98
+ * - showNewUntil: stop showing "new" once appVersion reaches this
99
+ * - deprecatedAt: hide feature for app versions at or above this (optional safety)
100
+ * - showIn: range string, e.g. ">=2.5.0 <3.0.0"
101
+ */
102
+ version?: string | {
103
+ introduced?: string;
104
+ showNewUntil?: string;
105
+ deprecatedAt?: string;
106
+ showIn?: string;
107
+ };
108
+ /** ISO date when this feature was released */
109
+ releasedAt: string;
110
+ /** ISO date after which the "new" badge should stop showing */
111
+ showNewUntil: string;
112
+ /** Optional key to match navigation items (e.g. "/journal", "settings") */
113
+ sidebarKey?: string;
114
+ /** Optional grouping category (e.g. "ai", "billing", "core") */
115
+ category?: string;
116
+ /** Optional product scope (`"*"`, `"askverdict"`, etc.) for multi-product manifests */
117
+ product?: string;
118
+ /** Optional URL to link to (e.g. docs page, changelog entry) */
119
+ url?: string;
120
+ /** Optional feature flag key; requires a flag bridge to evaluate */
121
+ flagKey?: string;
122
+ /** Entry type — determines default icon/color in UI components */
123
+ type?: FeatureType;
124
+ /** Priority level — critical entries get special treatment in UI */
125
+ priority?: FeaturePriority;
126
+ /** Optional image/screenshot URL */
127
+ image?: string;
128
+ /** Optional call-to-action button */
129
+ cta?: FeatureCTA;
130
+ /** ISO date — entry is hidden until this date (scheduled publishing) */
131
+ publishAt?: string;
132
+ /** Optional arbitrary metadata */
133
+ meta?: Record<string, unknown>;
134
+ /** A/B variants keyed by variant name (e.g. control, treatment_a) */
135
+ variants?: Record<string, FeatureVariant>;
136
+ /** Percentage split per variant (same order as variants object keys) */
137
+ variantSplit?: number[];
138
+ /** Audience targeting — if set, only matching users see this feature */
139
+ audience?: AudienceRule;
140
+ /** Dependency requirements (progressive disclosure sequencing) */
141
+ dependsOn?: FeatureDependencies;
142
+ /** Contextual trigger rule */
143
+ trigger?: FeatureTrigger;
144
+ }
145
+
146
+ type CMSFieldResolver = string | ((record: unknown) => unknown);
147
+ interface CMSFieldMapping {
148
+ id?: CMSFieldResolver;
149
+ label?: CMSFieldResolver;
150
+ description?: CMSFieldResolver;
151
+ releasedAt?: CMSFieldResolver;
152
+ showNewUntil?: CMSFieldResolver;
153
+ sidebarKey?: CMSFieldResolver;
154
+ category?: CMSFieldResolver;
155
+ product?: CMSFieldResolver;
156
+ flagKey?: CMSFieldResolver;
157
+ url?: CMSFieldResolver;
158
+ image?: CMSFieldResolver;
159
+ publishAt?: CMSFieldResolver;
160
+ type?: CMSFieldResolver;
161
+ priority?: CMSFieldResolver;
162
+ ctaLabel?: CMSFieldResolver;
163
+ ctaUrl?: CMSFieldResolver;
164
+ }
165
+ interface CMSAdapter {
166
+ load: () => Promise<FeatureEntry[]>;
167
+ }
168
+ interface CMSAdapterBaseOptions {
169
+ fieldMapping?: CMSFieldMapping;
170
+ /** Throw when mapped entries are invalid. Default false (invalid entries are dropped). */
171
+ strictValidation?: boolean;
172
+ }
173
+ interface ContentfulAdapterOptions extends CMSAdapterBaseOptions {
174
+ spaceId: string;
175
+ accessToken: string;
176
+ contentType: string;
177
+ environment?: string;
178
+ locale?: string;
179
+ limit?: number;
180
+ }
181
+ interface SanityAdapterOptions extends CMSAdapterBaseOptions {
182
+ projectId: string;
183
+ dataset: string;
184
+ query: string;
185
+ token?: string;
186
+ apiVersion?: string;
187
+ }
188
+ interface StrapiAdapterOptions extends CMSAdapterBaseOptions {
189
+ baseUrl: string;
190
+ endpoint?: string;
191
+ token?: string;
192
+ query?: string;
193
+ }
194
+ interface NotionAdapterOptions extends CMSAdapterBaseOptions {
195
+ databaseId: string;
196
+ token: string;
197
+ notionVersion?: string;
198
+ filter?: Record<string, unknown>;
199
+ sorts?: Array<Record<string, unknown>>;
200
+ }
201
+ interface MarkdownAdapterFile {
202
+ source?: string;
203
+ markdown: string;
204
+ }
205
+ interface MarkdownAdapterOptions extends CMSAdapterBaseOptions {
206
+ pattern?: string;
207
+ cwd?: string;
208
+ entries?: MarkdownAdapterFile[];
209
+ }
210
+ declare class ContentfulAdapter implements CMSAdapter {
211
+ private readonly options;
212
+ constructor(options: ContentfulAdapterOptions);
213
+ load(): Promise<FeatureEntry[]>;
214
+ }
215
+ declare class SanityAdapter implements CMSAdapter {
216
+ private readonly options;
217
+ constructor(options: SanityAdapterOptions);
218
+ load(): Promise<FeatureEntry[]>;
219
+ }
220
+ declare class StrapiAdapter implements CMSAdapter {
221
+ private readonly options;
222
+ constructor(options: StrapiAdapterOptions);
223
+ load(): Promise<FeatureEntry[]>;
224
+ }
225
+ declare class NotionAdapter implements CMSAdapter {
226
+ private readonly options;
227
+ constructor(options: NotionAdapterOptions);
228
+ load(): Promise<FeatureEntry[]>;
229
+ }
230
+ declare class MarkdownAdapter implements CMSAdapter {
231
+ private readonly options;
232
+ constructor(options?: MarkdownAdapterOptions);
233
+ load(): Promise<FeatureEntry[]>;
234
+ }
235
+
236
+ export { type CMSAdapter, type CMSFieldMapping, ContentfulAdapter, MarkdownAdapter, NotionAdapter, SanityAdapter, StrapiAdapter };