@clearlaunch/sdk 0.2.0 → 0.3.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.
package/README.md ADDED
@@ -0,0 +1,136 @@
1
+ # @clearlaunch/sdk
2
+
3
+ One project key, every ClearLaunch surface — release notes, user guides, and
4
+ feedback/ticketing — on your own site.
5
+
6
+ ```bash
7
+ npm install @clearlaunch/sdk @clearlaunch/core
8
+ ```
9
+
10
+ ```js
11
+ import { clearSDK } from '@clearlaunch/sdk';
12
+
13
+ const cl = clearSDK({ projectKey: 'pk_…' });
14
+
15
+ cl.versions.mount('#whats-new'); // release notes
16
+ cl.guides.mount({ target: '#docs' }); // published user guides
17
+ cl.ticketing.mount({ service: 'dealership' }); // feedback / bug reports
18
+ ```
19
+
20
+ Or without a build step:
21
+
22
+ ```html
23
+ <script src="https://unpkg.com/@clearlaunch/sdk/dist/clearlaunch.js"></script>
24
+ <script>
25
+ const cl = ClearLaunch.init({ projectKey: 'pk_…' });
26
+ cl.versions.mount('#whats-new');
27
+ </script>
28
+ ```
29
+
30
+ This build inlines every capability, so there is nothing else to install. Pin a
31
+ version in production — `@clearlaunch/sdk@0.3.0` — rather than tracking latest.
32
+
33
+ ## One credential
34
+
35
+ You pass a single `pk_` project key. The guide slug and feedback token the
36
+ sub-packages need are resolved server-side and returned in the SDK config, so
37
+ callers never handle them. Both were already public — guide slugs appear in
38
+ `/docs/:slug` URLs — so this exposes nothing new.
39
+
40
+ The key is publishable: it identifies a project and grants only the read and
41
+ submit operations these widgets perform.
42
+
43
+ ## Capabilities are opt-in
44
+
45
+ Each capability lives in its own package, declared as an **optional peer**, so a
46
+ docs site isn't forced to ship a ticketing inbox.
47
+
48
+ | Capability | Package | Install if you use |
49
+ |---|---|---|
50
+ | `cl.versions` | `@clearlaunch/versions` | release notes |
51
+ | `cl.guides` | `@clearlaunch/guide-sdk` | published guides |
52
+ | `cl.ticketing` | `@clearlaunch/feedback` | feedback / bug reports |
53
+
54
+ `@clearlaunch/core` is required. Accessors are lazy — touching `cl.ticketing` is
55
+ what resolves and mounts it, so an unused capability costs nothing at runtime.
56
+
57
+ Reaching for a capability whose package isn't installed throws a message naming
58
+ the exact package rather than a bare `undefined`.
59
+
60
+ ### If your bundler can't resolve optional peers
61
+
62
+ Bundlers resolve `import` statically, so some will fail the build on an optional
63
+ peer that isn't present. Register the module yourself:
64
+
65
+ ```js
66
+ import * as feedback from '@clearlaunch/feedback';
67
+ import { register, clearSDK } from '@clearlaunch/sdk';
68
+
69
+ register('@clearlaunch/feedback', feedback);
70
+ const cl = clearSDK({ projectKey: 'pk_…' });
71
+ ```
72
+
73
+ ## API
74
+
75
+ ### `clearSDK(config)` → `ClearLaunchClient`
76
+
77
+ Also exported as `init`, and as `ClearLaunch.init` for the script-tag build.
78
+
79
+ | Option | Type | Notes |
80
+ |---|---|---|
81
+ | `projectKey` | `string` | Required. Your `pk_…` key. |
82
+ | `apiUrl` | `string` | Defaults to `https://api.clearlaunch.ai`. |
83
+
84
+ ### `cl.ticketing`
85
+
86
+ ```js
87
+ const widget = await cl.ticketing.mount({ service: 'dealership' });
88
+ widget.open('bug');
89
+ ```
90
+
91
+ `mount(options?)` returns a widget with `open(type?)`, `close()`, `destroy()`.
92
+
93
+ Useful options: `service` (the touchpoint this widget sits on — stored on the
94
+ submission and the resulting card, so feedback can be filtered by surface),
95
+ `trigger`, `theme`, `types`, `defaultType`, `user`, `metadata`, `text`, and the
96
+ `onSubmit` / `onError` / `onOpen` / `onClose` callbacks.
97
+
98
+ `services()` lists the touchpoints declared on the project, for building your own
99
+ picker. `enabled()` reports whether feedback is switched on.
100
+
101
+ > `service` must be one of the services declared on the project.
102
+
103
+ ### `cl.guides`
104
+
105
+ ```js
106
+ await cl.guides.mount({ target: '#docs' });
107
+ ```
108
+
109
+ `mount(options?)` renders a published guide into `options.target`, defaulting to
110
+ the project's first published guide unless you pass a `slug`.
111
+
112
+ `slugs()` lists every published guide; `defaultSlug()` returns the one a bare
113
+ `mount()` would open.
114
+
115
+ ### `cl.versions`
116
+
117
+ ```js
118
+ cl.versions.mount('#whats-new');
119
+ ```
120
+
121
+ Renders published release notes. See `@clearlaunch/versions` for its options.
122
+
123
+ ### `cl.config`
124
+
125
+ The resolved project config — name, theme, and which widgets are enabled.
126
+ Fetched once and shared across capabilities.
127
+
128
+ ## TypeScript
129
+
130
+ Types ship with the package. The capability option and widget types are
131
+ re-exported, so you can annotate without depending on the sub-packages directly.
132
+
133
+ ## Links
134
+
135
+ - [ClearLaunch](https://clearlaunch.ai)
136
+ - [Documentation](https://clearlaunch.ai/docs)
@@ -0,0 +1,2 @@
1
+ export * from './index';
2
+ export { default } from './index';
@@ -1,39 +1,7 @@
1
- "use strict";var l=Object.defineProperty;var w=Object.getOwnPropertyDescriptor;var C=Object.getOwnPropertyNames;var b=Object.prototype.hasOwnProperty;var x=(e,t)=>{for(var r in t)l(e,r,{get:t[r],enumerable:!0})},y=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of C(t))!b.call(e,o)&&o!==r&&l(e,o,{get:()=>t[o],enumerable:!(n=w(t,o))||n.enumerable});return e};var h=e=>y(l({},"__esModule",{value:!0}),e);var T={};x(T,{ClearLaunch:()=>v,default:()=>R,init:()=>f});module.exports=h(T);var k="https://api.clearlaunch.com";function a(e){let t=document.createElement("div");return t.textContent=e,t.innerHTML}function d(e,t){if(document.getElementById(e))return;let r=document.createElement("style");r.id=e,r.textContent=t,document.head.appendChild(r)}function p(e){return typeof e=="string"?document.querySelector(e):e}function g(e){if(!(e!=null&&e.projectKey))throw new Error("ClearLaunch: projectKey is required");let r=`${(e.apiUrl||k).replace(/\/$/,"")}/api/v1/public/sdk/${encodeURIComponent(e.projectKey)}`,n=null;async function o(c){let s=await fetch(`${r}/${c.replace(/^\//,"")}`);if(!s.ok)throw new Error(`ClearLaunch: request to ${c} failed (${s.status})`);return s.json()}function _(){return n||(n=o("config").catch(()=>({projectName:"",widgets:{versions:!0}}))),n}return{projectKey:e.projectKey,sdkBase:r,get:o,config:_}}var u=`
2
- .cl-vw { --cl-vw-accent: #6366f1; --cl-vw-radius: 12px;
3
- font-family: var(--cl-vw-font, inherit); color: #1f2430; }
4
- .cl-vw * { box-sizing: border-box; }
5
- .cl-vw__empty { padding: 24px; text-align: center; color: #8891a5; font-size: 14px; }
6
- .cl-vw__release { padding: 16px 0; border-bottom: 1px solid #eceef3; }
7
- .cl-vw__release:last-child { border-bottom: 0; }
8
- .cl-vw__head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 8px; }
9
- .cl-vw__ver {
10
- font-weight: 700; font-size: 15px; color: #fff; background: var(--cl-vw-accent);
11
- padding: 2px 9px; border-radius: 999px; letter-spacing: -0.01em;
12
- }
13
- .cl-vw__date { font-size: 12px; color: #8891a5; }
14
- .cl-vw__group { margin: 10px 0 0; }
15
- .cl-vw__group-label {
16
- font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em;
17
- font-weight: 700; color: #6b7280; margin-bottom: 4px;
18
- }
19
- .cl-vw__group--breaking .cl-vw__group-label { color: #dc2626; }
20
- .cl-vw__list { margin: 0; padding-left: 18px; }
21
- .cl-vw__list li { font-size: 13px; line-height: 1.55; color: #374151; margin: 2px 0; }
22
- @media (prefers-color-scheme: dark) {
23
- .cl-vw { color: #e5e7eb; }
24
- .cl-vw__release { border-bottom-color: #2a2f3a; }
25
- .cl-vw__date, .cl-vw__group-label { color: #9aa3b2; }
26
- .cl-vw__list li { color: #cbd2de; }
27
- }
28
- `;function S(e){if(!e)return"";let t=new Date(e);return isNaN(t.getTime())?"":t.toLocaleDateString(void 0,{year:"numeric",month:"short",day:"numeric"})}function i(e,t,r=""){if(!(t!=null&&t.length))return"";let n=t.map(o=>`<li>${a(o)}</li>`).join("");return`<div class="cl-vw__group ${r}"><div class="cl-vw__group-label">${e}</div><ul class="cl-vw__list">${n}</ul></div>`}function P(e,t){if(!t.length){e.innerHTML='<div class="cl-vw"><div class="cl-vw__empty">No releases yet.</div></div>';return}let r=t.map(n=>`
29
- <div class="cl-vw__release">
30
- <div class="cl-vw__head">
31
- <span class="cl-vw__ver">v${a(n.version)}</span>
32
- <span class="cl-vw__date">${S(n.publishedAt)}</span>
33
- </div>
34
- ${i("Breaking changes",n.notes.breaking,"cl-vw__group--breaking")}
35
- ${i("New features",n.notes.features)}
36
- ${i("Enhancements",n.notes.enhancements)}
37
- ${i("Fixes",n.notes.bugFixes)}
38
- </div>`).join("");e.innerHTML=`<div class="cl-vw">${r}</div>`}function m(e){async function t(){return(await e.get("releases")).releases||[]}return{list:t,async mount(r){let n=p(r);if(!n)throw new Error(`ClearLaunch versions: mount target not found: ${String(r)}`);d("cl-vw-styles",u);try{P(n,await t())}catch{n.innerHTML=`<div class="cl-vw"><div class="cl-vw__empty">Couldn't load release notes.</div></div>`}}}}function f(e){let t=g(e);return{projectKey:t.projectKey,versions:m(t)}}var v={init:f},R=v;
1
+ "use strict";var l=Object.defineProperty;var y=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var T=Object.prototype.hasOwnProperty;var v=(n,t)=>{for(var i in t)l(n,i,{get:t[i],enumerable:!0})},w=(n,t,i,e)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of b(t))!T.call(n,r)&&r!==i&&l(n,r,{get:()=>t[r],enumerable:!(e=y(t,r))||e.enumerable});return n};var x=n=>w(l({},"__esModule",{value:!0}),n);var S={};v(S,{ClearLaunch:()=>h,clearSDK:()=>g,default:()=>E,init:()=>k,register:()=>C});module.exports=x(S);var j="https://api.clearlaunch.ai";function p(n){if(!(n!=null&&n.projectKey))throw new Error("ClearLaunch: projectKey is required");let i=`${(n.apiUrl||j).replace(/\/$/,"")}/api/v1/public/sdk/${encodeURIComponent(n.projectKey)}`,e=null;async function r(o){let c=await fetch(`${i}/${o.replace(/^\//,"")}`);if(!c.ok)throw new Error(`ClearLaunch: request to ${o} failed (${c.status})`);return c.json()}function s(){return e||(e=r("config").catch(()=>({projectName:"",widgets:{versions:!0}}))),e}return{projectKey:n.projectKey,sdkBase:i,get:r,config:s}}var m=new Map;function C(n,t){m.set(n,t)}function u(n,t){throw new Error(`[clearlaunch] The "${t}" capability needs ${n}, which isn't installed.
2
+ Install it: npm install ${n}
3
+ Or, if your bundler can't resolve optional peers, register it yourself:
4
+ import * as mod from '${n}';
5
+ import { register } from '@clearlaunch/sdk';
6
+ register('${n}', mod);`)}function d(n){let t=m.get(n);if(t)return t;try{let i=typeof module!="undefined"&&typeof require=="function"?require:void 0;if(i)return i(n)}catch{}return null}function P(n,t){async function i(){let e=await n.config();return e.feedback&&e.feedback.enabled?e.feedback:null}return{async enabled(){return!!await i()},async services(){var r;let e=await i();return(r=e==null?void 0:e.services)!=null?r:[]},async mount(e={}){var a,f;let r=await i();if(!r)throw new Error("[clearlaunch] Feedback is not enabled for this project. Turn it on in ClearLaunch \u2192 project \u2192 Feedback.");let s=d("@clearlaunch/feedback");if(s!=null&&s.mountFeedback||u("@clearlaunch/feedback","ticketing"),e.service&&((a=r.services)!=null&&a.length)&&!r.services.includes(e.service))throw new Error(`[clearlaunch] service "${e.service}" is not declared on this project. Declared: ${r.services.join(", ")}. Add it in ClearLaunch \u2192 project \u2192 Feedback.`);let{service:o,...c}=e;return s.mountFeedback({...c,...o?{service:o}:(f=r.services)!=null&&f.length?{services:r.services}:{},token:r.token,...t?{apiUrl:t}:{}})}}}function R(n,t){async function i(){var r;return(r=(await n.config()).guides)!=null?r:{slugs:[],default:void 0}}return{async slugs(){var e;return(e=(await i()).slugs)!=null?e:[]},async defaultSlug(){return(await i()).default},async mount(e={}){var c,a;let r=await i(),s=(c=e.slug)!=null?c:r.default;if(!s)throw new Error("[clearlaunch] This project has no published guide. Publish one in ClearLaunch \u2192 project \u2192 Guides, or pass an explicit `slug`.");if(e.slug&&((a=r.slugs)!=null&&a.length)&&!r.slugs.includes(e.slug))throw new Error(`[clearlaunch] guide "${e.slug}" is not published on this project. Published: ${r.slugs.join(", ")}.`);let o=d("@clearlaunch/guide-sdk");return o!=null&&o.init||u("@clearlaunch/guide-sdk","guides"),o.init({slug:s,...e.target?{target:e.target}:{},...t?{apiUrl:t}:{}})}}}function g(n){let t=p(n),i=null,e=null,r=null;return{projectKey:t.projectKey,core:t,config:()=>t.config(),get versions(){if(!i){let o=d("@clearlaunch/versions");o!=null&&o.createVersions||u("@clearlaunch/versions","versions"),i=o.createVersions(t)}return i},get guides(){return e||(e=R(t,n.apiUrl)),e},get ticketing(){return r||(r=P(t,n.apiUrl)),r},get feedback(){return this.ticketing}}}var k=g,h={init:k,clearSDK:g,register:C},E=h;
39
7
  //# sourceMappingURL=clearlaunch.cjs.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/index.ts", "../../clearsdk-core/src/index.ts", "../../clearsdk-versions/src/styles.ts", "../../clearsdk-versions/src/index.ts"],
4
- "sourcesContent": ["/**\n * @clearlaunch/sdk \u2014 the all-in-one bundle for the CDN script tag.\n *\n * This is the batteries-included entry: one <script> gives you\n * window.ClearLaunch.init({ projectKey }) with every widget attached. Under the\n * hood it composes the modular packages (@clearlaunch/core + the widget\n * packages), so apps that prefer smaller bundles can install those directly:\n *\n * import { createCore } from '@clearlaunch/core';\n * import { createVersions } from '@clearlaunch/versions';\n * const core = createCore({ projectKey });\n * const versions = createVersions(core);\n */\nimport { createCore, type ClearCoreConfig } from '@clearlaunch/core';\nimport { createVersions, type VersionsWidget, type PublicRelease } from '@clearlaunch/versions';\n\nexport type { ClearCoreConfig, VersionsWidget, PublicRelease };\n\nexport interface ClearLaunchClient {\n readonly projectKey: string;\n readonly versions: VersionsWidget;\n}\n\nexport function init(config: ClearCoreConfig): ClearLaunchClient {\n const core = createCore(config);\n return {\n projectKey: core.projectKey,\n versions: createVersions(core),\n };\n}\n\nexport const ClearLaunch = { init };\nexport default ClearLaunch;\n", "/**\n * @clearlaunch/core \u2014 the shared foundation every ClearLaunch widget builds on.\n *\n * One public project key (`pk_\u2026`) identifies the project in the browser. Core\n * owns the API base, the fetch client, the remote SDK config (which widgets are\n * enabled + theme), and a small style-injection helper. Widget packages\n * (@clearlaunch/versions, /guides, /feedback) receive a ClearCoreClient and\n * attach themselves to it.\n */\n\nexport interface ClearCoreConfig {\n /** The project's public key (pk_\u2026). Safe to ship in the browser. */\n projectKey: string;\n /** Override the API base. Defaults to the hosted ClearLaunch API. */\n apiUrl?: string;\n}\n\nexport interface SdkTheme {\n primaryColor?: string;\n fontFamily?: string;\n borderRadius?: string;\n logoUrl?: string;\n}\n\nexport interface SdkRemoteConfig {\n projectName: string;\n widgets: { versions?: boolean; guides?: boolean; feedback?: boolean };\n theme?: SdkTheme;\n}\n\nexport interface ClearCoreClient {\n readonly projectKey: string;\n /** Absolute base for this project's public SDK routes:\n * `${apiUrl}/api/v1/public/sdk/${projectKey}` */\n readonly sdkBase: string;\n /** GET a JSON path relative to sdkBase (e.g. 'releases', 'config'). */\n get<T = unknown>(path: string): Promise<T>;\n /** Cached remote config (widgets enabled + theme). Fetched once. */\n config(): Promise<SdkRemoteConfig>;\n}\n\nconst DEFAULT_API_URL = 'https://api.clearlaunch.com';\n\n/** Escape untrusted text before inserting into innerHTML. Shared by widgets. */\nexport function esc(s: string): string {\n const d = document.createElement('div');\n d.textContent = s;\n return d.innerHTML;\n}\n\n/** Inject a stylesheet once, keyed by id. Shared by widgets. */\nexport function injectStyles(id: string, css: string): void {\n if (document.getElementById(id)) return;\n const style = document.createElement('style');\n style.id = id;\n style.textContent = css;\n document.head.appendChild(style);\n}\n\n/** Resolve a selector-or-element mount target. */\nexport function resolveTarget(target: string | HTMLElement): HTMLElement | null {\n return typeof target === 'string' ? document.querySelector<HTMLElement>(target) : target;\n}\n\nexport function createCore(config: ClearCoreConfig): ClearCoreClient {\n if (!config?.projectKey) throw new Error('ClearLaunch: projectKey is required');\n const apiUrl = (config.apiUrl || DEFAULT_API_URL).replace(/\\/$/, '');\n const sdkBase = `${apiUrl}/api/v1/public/sdk/${encodeURIComponent(config.projectKey)}`;\n\n let configPromise: Promise<SdkRemoteConfig> | null = null;\n\n async function get<T>(path: string): Promise<T> {\n const res = await fetch(`${sdkBase}/${path.replace(/^\\//, '')}`);\n if (!res.ok) throw new Error(`ClearLaunch: request to ${path} failed (${res.status})`);\n return res.json() as Promise<T>;\n }\n\n function configOnce(): Promise<SdkRemoteConfig> {\n if (!configPromise) {\n configPromise = get<SdkRemoteConfig>('config').catch(() => ({\n projectName: '',\n widgets: { versions: true },\n } as SdkRemoteConfig));\n }\n return configPromise;\n }\n\n return {\n projectKey: config.projectKey,\n sdkBase,\n get,\n config: configOnce,\n };\n}\n", "/** Self-contained widget CSS, namespaced under .cl-vw so it never leaks into\n * or inherits from the host page. Theme values are injected via CSS vars. */\nexport const VERSIONS_CSS = `\n.cl-vw { --cl-vw-accent: #6366f1; --cl-vw-radius: 12px;\n font-family: var(--cl-vw-font, inherit); color: #1f2430; }\n.cl-vw * { box-sizing: border-box; }\n.cl-vw__empty { padding: 24px; text-align: center; color: #8891a5; font-size: 14px; }\n.cl-vw__release { padding: 16px 0; border-bottom: 1px solid #eceef3; }\n.cl-vw__release:last-child { border-bottom: 0; }\n.cl-vw__head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 8px; }\n.cl-vw__ver {\n font-weight: 700; font-size: 15px; color: #fff; background: var(--cl-vw-accent);\n padding: 2px 9px; border-radius: 999px; letter-spacing: -0.01em;\n}\n.cl-vw__date { font-size: 12px; color: #8891a5; }\n.cl-vw__group { margin: 10px 0 0; }\n.cl-vw__group-label {\n font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em;\n font-weight: 700; color: #6b7280; margin-bottom: 4px;\n}\n.cl-vw__group--breaking .cl-vw__group-label { color: #dc2626; }\n.cl-vw__list { margin: 0; padding-left: 18px; }\n.cl-vw__list li { font-size: 13px; line-height: 1.55; color: #374151; margin: 2px 0; }\n@media (prefers-color-scheme: dark) {\n .cl-vw { color: #e5e7eb; }\n .cl-vw__release { border-bottom-color: #2a2f3a; }\n .cl-vw__date, .cl-vw__group-label { color: #9aa3b2; }\n .cl-vw__list li { color: #cbd2de; }\n}\n`;\n", "import type { ClearCoreClient } from '@clearlaunch/core';\nimport { esc, injectStyles, resolveTarget } from '@clearlaunch/core';\nimport { VERSIONS_CSS } from './styles';\n\nexport interface ReleaseNotesPublic {\n features: string[];\n enhancements: string[];\n bugFixes: string[];\n breaking: string[];\n}\n\nexport interface PublicRelease {\n version: string;\n publishedAt?: string;\n notes: ReleaseNotesPublic;\n html?: string;\n}\n\nexport interface VersionsWidget {\n /** Render the version-history panel into a container (selector or element). */\n mount(target: string | HTMLElement): Promise<void>;\n /** Fetch releases without rendering (for a custom UI). */\n list(): Promise<PublicRelease[]>;\n}\n\nfunction fmtDate(iso?: string): string {\n if (!iso) return '';\n const d = new Date(iso);\n return isNaN(d.getTime()) ? '' : d.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' });\n}\n\nfunction group(label: string, items: string[], modifier = ''): string {\n if (!items?.length) return '';\n const li = items.map(i => `<li>${esc(i)}</li>`).join('');\n return `<div class=\"cl-vw__group ${modifier}\"><div class=\"cl-vw__group-label\">${label}</div><ul class=\"cl-vw__list\">${li}</ul></div>`;\n}\n\nfunction render(el: HTMLElement, releases: PublicRelease[]): void {\n if (!releases.length) {\n el.innerHTML = `<div class=\"cl-vw\"><div class=\"cl-vw__empty\">No releases yet.</div></div>`;\n return;\n }\n const body = releases.map(r => `\n <div class=\"cl-vw__release\">\n <div class=\"cl-vw__head\">\n <span class=\"cl-vw__ver\">v${esc(r.version)}</span>\n <span class=\"cl-vw__date\">${fmtDate(r.publishedAt)}</span>\n </div>\n ${group('Breaking changes', r.notes.breaking, 'cl-vw__group--breaking')}\n ${group('New features', r.notes.features)}\n ${group('Enhancements', r.notes.enhancements)}\n ${group('Fixes', r.notes.bugFixes)}\n </div>`).join('');\n el.innerHTML = `<div class=\"cl-vw\">${body}</div>`;\n}\n\n/** Attach a versions widget to a core client. */\nexport function createVersions(core: ClearCoreClient): VersionsWidget {\n async function list(): Promise<PublicRelease[]> {\n const data = await core.get<{ releases: PublicRelease[] }>('releases');\n return data.releases || [];\n }\n return {\n list,\n async mount(target) {\n const el = resolveTarget(target);\n if (!el) throw new Error(`ClearLaunch versions: mount target not found: ${String(target)}`);\n injectStyles('cl-vw-styles', VERSIONS_CSS);\n try {\n render(el, await list());\n } catch {\n el.innerHTML = `<div class=\"cl-vw\"><div class=\"cl-vw__empty\">Couldn't load release notes.</div></div>`;\n }\n },\n };\n}\n"],
5
- "mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,iBAAAE,EAAA,YAAAC,EAAA,SAAAC,IAAA,eAAAC,EAAAL,GCyCA,IAAMM,EAAkB,8BAGjB,SAASC,EAAIC,EAAmB,CACrC,IAAMC,EAAI,SAAS,cAAc,KAAK,EACtC,OAAAA,EAAE,YAAcD,EACTC,EAAE,SACX,CAGO,SAASC,EAAaC,EAAYC,EAAmB,CAC1D,GAAI,SAAS,eAAeD,CAAE,EAAG,OACjC,IAAME,EAAQ,SAAS,cAAc,OAAO,EAC5CA,EAAM,GAAKF,EACXE,EAAM,YAAcD,EACpB,SAAS,KAAK,YAAYC,CAAK,CACjC,CAGO,SAASC,EAAcC,EAAkD,CAC9E,OAAO,OAAOA,GAAW,SAAW,SAAS,cAA2BA,CAAM,EAAIA,CACpF,CAEO,SAASC,EAAWC,EAA0C,CACnE,GAAI,EAACA,GAAA,MAAAA,EAAQ,YAAY,MAAM,IAAI,MAAM,qCAAqC,EAE9E,IAAMC,EAAU,IADAD,EAAO,QAAUX,GAAiB,QAAQ,MAAO,EAAE,CAC1C,sBAAsB,mBAAmBW,EAAO,UAAU,CAAC,GAEhFE,EAAiD,KAErD,eAAeC,EAAOC,EAA0B,CAC9C,IAAMC,EAAM,MAAM,MAAM,GAAGJ,CAAO,IAAIG,EAAK,QAAQ,MAAO,EAAE,CAAC,EAAE,EAC/D,GAAI,CAACC,EAAI,GAAI,MAAM,IAAI,MAAM,2BAA2BD,CAAI,YAAYC,EAAI,MAAM,GAAG,EACrF,OAAOA,EAAI,KAAK,CAClB,CAEA,SAASC,GAAuC,CAC9C,OAAKJ,IACHA,EAAgBC,EAAqB,QAAQ,EAAE,MAAM,KAAO,CAC1D,YAAa,GACb,QAAS,CAAE,SAAU,EAAK,CAC5B,EAAqB,GAEhBD,CACT,CAEA,MAAO,CACL,WAAYF,EAAO,WACnB,QAAAC,EACA,IAAAE,EACA,OAAQG,CACV,CACF,CC3FO,IAAMC,EAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;ECuB5B,SAASC,EAAQC,EAAsB,CACrC,GAAI,CAACA,EAAK,MAAO,GACjB,IAAMC,EAAI,IAAI,KAAKD,CAAG,EACtB,OAAO,MAAMC,EAAE,QAAQ,CAAC,EAAI,GAAKA,EAAE,mBAAmB,OAAW,CAAE,KAAM,UAAW,MAAO,QAAS,IAAK,SAAU,CAAC,CACtH,CAEA,SAASC,EAAMC,EAAeC,EAAiBC,EAAW,GAAY,CACpE,GAAI,EAACD,GAAA,MAAAA,EAAO,QAAQ,MAAO,GAC3B,IAAME,EAAKF,EAAM,IAAIG,GAAK,OAAOC,EAAID,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EACvD,MAAO,4BAA4BF,CAAQ,qCAAqCF,CAAK,iCAAiCG,CAAE,aAC1H,CAEA,SAASG,EAAOC,EAAiBC,EAAiC,CAChE,GAAI,CAACA,EAAS,OAAQ,CACpBD,EAAG,UAAY,4EACf,MACF,CACA,IAAME,EAAOD,EAAS,IAAIE,GAAK;AAAA;AAAA;AAAA,oCAGGL,EAAIK,EAAE,OAAO,CAAC;AAAA,oCACdd,EAAQc,EAAE,WAAW,CAAC;AAAA;AAAA,QAElDX,EAAM,mBAAoBW,EAAE,MAAM,SAAU,wBAAwB,CAAC;AAAA,QACrEX,EAAM,eAAgBW,EAAE,MAAM,QAAQ,CAAC;AAAA,QACvCX,EAAM,eAAgBW,EAAE,MAAM,YAAY,CAAC;AAAA,QAC3CX,EAAM,QAASW,EAAE,MAAM,QAAQ,CAAC;AAAA,WAC7B,EAAE,KAAK,EAAE,EAClBH,EAAG,UAAY,sBAAsBE,CAAI,QAC3C,CAGO,SAASE,EAAeC,EAAuC,CACpE,eAAeC,GAAiC,CAE9C,OADa,MAAMD,EAAK,IAAmC,UAAU,GACzD,UAAY,CAAC,CAC3B,CACA,MAAO,CACL,KAAAC,EACA,MAAM,MAAMC,EAAQ,CAClB,IAAMP,EAAKQ,EAAcD,CAAM,EAC/B,GAAI,CAACP,EAAI,MAAM,IAAI,MAAM,iDAAiD,OAAOO,CAAM,CAAC,EAAE,EAC1FE,EAAa,eAAgBC,CAAY,EACzC,GAAI,CACFX,EAAOC,EAAI,MAAMM,EAAK,CAAC,CACzB,MAAQ,CACNN,EAAG,UAAY,uFACjB,CACF,CACF,CACF,CHpDO,SAASW,EAAKC,EAA4C,CAC/D,IAAMC,EAAOC,EAAWF,CAAM,EAC9B,MAAO,CACL,WAAYC,EAAK,WACjB,SAAUE,EAAeF,CAAI,CAC/B,CACF,CAEO,IAAMG,EAAc,CAAE,KAAAL,CAAK,EAC3BM,EAAQD",
6
- "names": ["index_exports", "__export", "ClearLaunch", "index_default", "init", "__toCommonJS", "DEFAULT_API_URL", "esc", "s", "d", "injectStyles", "id", "css", "style", "resolveTarget", "target", "createCore", "config", "sdkBase", "configPromise", "get", "path", "res", "configOnce", "VERSIONS_CSS", "fmtDate", "iso", "d", "group", "label", "items", "modifier", "li", "i", "esc", "render", "el", "releases", "body", "r", "createVersions", "core", "list", "target", "resolveTarget", "injectStyles", "VERSIONS_CSS", "init", "config", "core", "createCore", "createVersions", "ClearLaunch", "index_default"]
3
+ "sources": ["../src/index.ts", "../../clearsdk-core/src/index.ts"],
4
+ "sourcesContent": ["/**\r\n * @clearlaunch/sdk \u2014 one project key, every ClearLaunch surface.\r\n *\r\n * import { clearSDK } from '@clearlaunch/sdk';\r\n * const cl = clearSDK({ projectKey: 'pk_\u2026' });\r\n *\r\n * cl.versions.mount('#whats-new'); // release notes\r\n * cl.guides.mount({ target: '#docs' }); // published user guides\r\n * cl.ticketing.mount({ service: 'dealership' }); // feedback / bug reports\r\n *\r\n * ## How composition works\r\n *\r\n * Each capability lives in its own package so a docs site isn't forced to ship\r\n * a ticketing inbox. They are declared as OPTIONAL peer dependencies: install\r\n * only what you use, and the accessor for anything missing throws a message\r\n * naming the exact package to install rather than a bare `undefined`.\r\n *\r\n * Accessors are lazy \u2014 touching `cl.ticketing` is what resolves and mounts it,\r\n * so an unused capability costs nothing at runtime. The bundled CDN build\r\n * inlines all of them (see build.mjs), so the script tag keeps working with no\r\n * install step.\r\n *\r\n * ## One credential\r\n *\r\n * Sub-packages historically needed their own identifiers: a guide slug, a `fb_`\r\n * feedback token. Both are already public \u2014 guide slugs appear in /docs/:slug\r\n * URLs and the feedback token is served by the widget-config route \u2014 so the\r\n * server resolves them from the `pk_` key and returns them in the SDK config\r\n * (ADR feeb30c5). Callers pass one key and never see the others.\r\n */\r\nimport { createCore, type ClearCoreClient, type ClearCoreConfig, type SdkRemoteConfig } from '@clearlaunch/core';\r\nimport type { VersionsWidget, PublicRelease } from '@clearlaunch/versions';\r\nimport type { FeedbackType, FeedbackTheme, TriggerConfig } from '@clearlaunch/feedback';\r\n\r\nexport type {\r\n ClearCoreConfig, SdkRemoteConfig, VersionsWidget, PublicRelease,\r\n FeedbackType, FeedbackTheme, TriggerConfig,\r\n};\r\n\r\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n * Optional peer resolution\r\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\r\n\r\n/**\r\n * Modules the host app supplied by hand.\r\n *\r\n * Bundlers resolve `import` statically, so a truly optional dependency can't be\r\n * `await import`ed without the bundler either erroring or emitting a chunk for\r\n * a package that may not exist. Callers in that situation register the module\r\n * themselves; the CDN build registers all three at startup.\r\n */\r\nconst registry = new Map<string, unknown>();\r\n\r\n/** Supply a capability module explicitly, bypassing package resolution. */\r\nexport function register(pkg: string, mod: unknown): void {\r\n registry.set(pkg, mod);\r\n}\r\n\r\nfunction missing(pkg: string, capability: string): never {\r\n throw new Error(\r\n `[clearlaunch] The \"${capability}\" capability needs ${pkg}, which isn't installed.\\n` +\r\n ` Install it: npm install ${pkg}\\n` +\r\n ` Or, if your bundler can't resolve optional peers, register it yourself:\\n` +\r\n ` import * as mod from '${pkg}';\\n` +\r\n ` import { register } from '@clearlaunch/sdk';\\n` +\r\n ` register('${pkg}', mod);`,\r\n );\r\n}\r\n\r\n/**\r\n * Resolve an optional peer, preferring an explicit registration.\r\n *\r\n * The `require` path covers CJS/Node; the registry covers bundlers. We never\r\n * throw from resolution itself \u2014 the caller decides, so the error names the\r\n * capability the user actually asked for.\r\n */\r\nfunction resolve<T>(pkg: string): T | null {\r\n const registered = registry.get(pkg);\r\n if (registered) return registered as T;\r\n try {\r\n // Hidden from bundlers on purpose: a literal require() of an optional peer\r\n // makes webpack/vite fail the build when it isn't installed.\r\n const req: ((id: string) => unknown) | undefined =\r\n typeof module !== 'undefined' && typeof require === 'function' ? require : undefined;\r\n if (req) return req(pkg) as T;\r\n } catch {\r\n /* not installed, or not a CJS context \u2014 fall through to null */\r\n }\r\n return null;\r\n}\r\n\r\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n * Ticketing\r\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\r\n\r\n/**\r\n * Options for the ticketing widget.\r\n *\r\n * `token` is deliberately absent \u2014 it is resolved from the project key. Every\r\n * other option is passed through to @clearlaunch/feedback.\r\n */\r\nexport interface TicketingMountOptions {\r\n /**\r\n * Touchpoint this widget is embedded on (\"dealership\", \"admin\", \u2026). Stored on\r\n * the submission and the resulting card, so feedback can be filtered by\r\n * surface. Must be one of the services declared on the project.\r\n */\r\n service?: string;\r\n trigger?: TriggerConfig;\r\n theme?: FeedbackTheme;\r\n types?: FeedbackType[];\r\n defaultType?: FeedbackType;\r\n source?: string;\r\n user?: { email?: string; name?: string };\r\n metadata?: Record<string, string>;\r\n text?: Record<string, string>;\r\n onSubmit?: (result: { submissionId: string }) => void;\r\n onError?: (err: Error) => void;\r\n onOpen?: () => void;\r\n onClose?: () => void;\r\n}\r\n\r\nexport interface TicketingWidget {\r\n open(type?: FeedbackType): void;\r\n close(): void;\r\n destroy(): void;\r\n}\r\n\r\nexport interface Ticketing {\r\n /**\r\n * Mount the feedback trigger + dialog. Resolves once the project config has\r\n * supplied the feedback token.\r\n */\r\n mount(options?: TicketingMountOptions): Promise<TicketingWidget>;\r\n /** Touchpoints declared on the project, for building your own picker. */\r\n services(): Promise<string[]>;\r\n /** Whether feedback is switched on for this project. */\r\n enabled(): Promise<boolean>;\r\n}\r\n\r\nfunction createTicketing(core: ClearCoreClient, apiUrl?: string): Ticketing {\r\n async function feedbackConfig() {\r\n const cfg = await core.config();\r\n return cfg.feedback && cfg.feedback.enabled ? cfg.feedback : null;\r\n }\r\n\r\n return {\r\n async enabled() {\r\n return !!(await feedbackConfig());\r\n },\r\n\r\n async services() {\r\n const fb = await feedbackConfig();\r\n return fb?.services ?? [];\r\n },\r\n\r\n async mount(options: TicketingMountOptions = {}) {\r\n const fb = await feedbackConfig();\r\n if (!fb) {\r\n throw new Error(\r\n '[clearlaunch] Feedback is not enabled for this project. ' +\r\n 'Turn it on in ClearLaunch \u2192 project \u2192 Feedback.',\r\n );\r\n }\r\n\r\n const mod = resolve<{ mountFeedback: (o: Record<string, unknown>) => TicketingWidget }>(\r\n '@clearlaunch/feedback',\r\n );\r\n if (!mod?.mountFeedback) missing('@clearlaunch/feedback', 'ticketing');\r\n\r\n // A service must be one the project declared, or filtering downstream\r\n // silently accumulates typos that never match anything in the UI.\r\n if (options.service && fb.services?.length && !fb.services.includes(options.service)) {\r\n throw new Error(\r\n `[clearlaunch] service \"${options.service}\" is not declared on this project. ` +\r\n `Declared: ${fb.services.join(', ')}. Add it in ClearLaunch \u2192 project \u2192 Feedback.`,\r\n );\r\n }\r\n\r\n const { service, ...rest } = options;\r\n return mod.mountFeedback({\r\n ...rest,\r\n // Fixed touchpoint wins. Otherwise hand the widget the project's\r\n // declared list so it can offer a picker without the caller having to\r\n // restate what ClearLaunch already knows. Passing both is refused by\r\n // the widget, so they are deliberately exclusive here too.\r\n ...(service\r\n ? { service }\r\n : fb.services?.length ? { services: fb.services } : {}),\r\n token: fb.token,\r\n ...(apiUrl ? { apiUrl } : {}),\r\n });\r\n },\r\n };\r\n}\r\n\r\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n * Guides\r\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\r\n\r\nexport interface GuidesMountOptions {\r\n /** Which published guide. Defaults to the project's first published guide. */\r\n slug?: string;\r\n /** Container for the embedded reader. */\r\n target?: string | HTMLElement;\r\n}\r\n\r\nexport interface Guides {\r\n mount(options?: GuidesMountOptions): Promise<unknown>;\r\n /** Slugs of every published guide on this project. */\r\n slugs(): Promise<string[]>;\r\n /** The slug a bare `mount()` would open, if any. */\r\n defaultSlug(): Promise<string | undefined>;\r\n}\r\n\r\nfunction createGuides(core: ClearCoreClient, apiUrl?: string): Guides {\r\n async function guidesConfig() {\r\n const cfg = await core.config();\r\n return cfg.guides ?? { slugs: [] as string[], default: undefined as string | undefined };\r\n }\r\n\r\n return {\r\n async slugs() {\r\n return (await guidesConfig()).slugs ?? [];\r\n },\r\n\r\n async defaultSlug() {\r\n return (await guidesConfig()).default;\r\n },\r\n\r\n async mount(options: GuidesMountOptions = {}) {\r\n const cfg = await guidesConfig();\r\n const slug = options.slug ?? cfg.default;\r\n if (!slug) {\r\n throw new Error(\r\n '[clearlaunch] This project has no published guide. ' +\r\n 'Publish one in ClearLaunch \u2192 project \u2192 Guides, or pass an explicit `slug`.',\r\n );\r\n }\r\n if (options.slug && cfg.slugs?.length && !cfg.slugs.includes(options.slug)) {\r\n throw new Error(\r\n `[clearlaunch] guide \"${options.slug}\" is not published on this project. ` +\r\n `Published: ${cfg.slugs.join(', ')}.`,\r\n );\r\n }\r\n\r\n const mod = resolve<{ init: (c: Record<string, unknown>) => Promise<unknown> }>(\r\n '@clearlaunch/guide-sdk',\r\n );\r\n if (!mod?.init) missing('@clearlaunch/guide-sdk', 'guides');\r\n\r\n return mod.init({\r\n slug,\r\n ...(options.target ? { target: options.target } : {}),\r\n ...(apiUrl ? { apiUrl } : {}),\r\n });\r\n },\r\n };\r\n}\r\n\r\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n * Client\r\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\r\n\r\nexport interface ClearLaunchClient {\r\n readonly projectKey: string;\r\n /** Raw core client, for direct calls against the public SDK routes. */\r\n readonly core: ClearCoreClient;\r\n /** Resolved project config (name, widgets, theme, guides, feedback). */\r\n config(): Promise<SdkRemoteConfig>;\r\n readonly versions: VersionsWidget;\r\n readonly guides: Guides;\r\n /** Feedback / bug reports. Also available as `.feedback`. */\r\n readonly ticketing: Ticketing;\r\n /** Alias of `.ticketing`, matching the @clearlaunch/feedback package name. */\r\n readonly feedback: Ticketing;\r\n}\r\n\r\n/**\r\n * Create a ClearLaunch client.\r\n *\r\n * Capabilities are lazily constructed on first access and then cached, so an\r\n * app that only ever touches `.versions` never resolves the ticketing or guide\r\n * packages at all.\r\n */\r\nexport function clearSDK(config: ClearCoreConfig): ClearLaunchClient {\r\n const core = createCore(config);\r\n\r\n let versions: VersionsWidget | null = null;\r\n let guides: Guides | null = null;\r\n let ticketing: Ticketing | null = null;\r\n\r\n const client: ClearLaunchClient = {\r\n projectKey: core.projectKey,\r\n core,\r\n config: () => core.config(),\r\n\r\n get versions() {\r\n if (!versions) {\r\n const mod = resolve<{ createVersions: (c: ClearCoreClient) => VersionsWidget }>(\r\n '@clearlaunch/versions',\r\n );\r\n if (!mod?.createVersions) missing('@clearlaunch/versions', 'versions');\r\n versions = mod.createVersions(core);\r\n }\r\n return versions;\r\n },\r\n\r\n get guides() {\r\n if (!guides) guides = createGuides(core, config.apiUrl);\r\n return guides;\r\n },\r\n\r\n get ticketing() {\r\n if (!ticketing) ticketing = createTicketing(core, config.apiUrl);\r\n return ticketing;\r\n },\r\n\r\n get feedback() {\r\n return this.ticketing;\r\n },\r\n };\r\n\r\n return client;\r\n}\r\n\r\n/**\r\n * Back-compat entry for the CDN script tag: `ClearLaunch.init({ projectKey })`.\r\n * Identical to clearSDK().\r\n */\r\nexport const init = clearSDK;\r\n\r\nexport const ClearLaunch = { init, clearSDK, register };\r\nexport default ClearLaunch;\r\n", "/**\r\n * @clearlaunch/core \u2014 the shared foundation every ClearLaunch widget builds on.\r\n *\r\n * One public project key (`pk_\u2026`) identifies the project in the browser. Core\r\n * owns the API base, the fetch client, the remote SDK config (which widgets are\r\n * enabled + theme), and a small style-injection helper. Widget packages\r\n * (@clearlaunch/versions, /guides, /feedback) receive a ClearCoreClient and\r\n * attach themselves to it.\r\n */\r\n\r\nexport interface ClearCoreConfig {\r\n /** The project's public key (pk_\u2026). Safe to ship in the browser. */\r\n projectKey: string;\r\n /** Override the API base. Defaults to the hosted ClearLaunch API. */\r\n apiUrl?: string;\r\n}\r\n\r\nexport interface SdkTheme {\r\n primaryColor?: string;\r\n fontFamily?: string;\r\n borderRadius?: string;\r\n logoUrl?: string;\r\n}\r\n\r\nexport interface SdkRemoteConfig {\r\n projectName: string;\r\n widgets: { versions?: boolean; guides?: boolean; feedback?: boolean };\r\n theme?: SdkTheme;\r\n /**\r\n * Public identifiers the other sub-packages need, resolved from the pk_ key\r\n * so one credential reaches every widget. Both are already public \u2014 the\r\n * feedback token is served by the widget-config route and guide slugs\r\n * appear in /docs/:slug URLs.\r\n *\r\n * Optional because an older API may not return them.\r\n */\r\n guides?: {\r\n /** Published guides only. */\r\n slugs: string[];\r\n /** Which one a bare `.guides` accessor should open. */\r\n default?: string;\r\n };\r\n feedback?:\r\n | { enabled: false }\r\n | {\r\n enabled: true;\r\n token: string;\r\n /** Touchpoints the project has declared (dealership, admin, \u2026). */\r\n services?: string[];\r\n };\r\n}\r\n\r\nexport interface ClearCoreClient {\r\n readonly projectKey: string;\r\n /** Absolute base for this project's public SDK routes:\r\n * `${apiUrl}/api/v1/public/sdk/${projectKey}` */\r\n readonly sdkBase: string;\r\n /** GET a JSON path relative to sdkBase (e.g. 'releases', 'config'). */\r\n get<T = unknown>(path: string): Promise<T>;\r\n /** Cached remote config (widgets enabled + theme). Fetched once. */\r\n config(): Promise<SdkRemoteConfig>;\r\n}\r\n\r\nconst DEFAULT_API_URL = 'https://api.clearlaunch.ai';\r\n\r\n/** Escape untrusted text before inserting into innerHTML. Shared by widgets. */\r\nexport function esc(s: string): string {\r\n const d = document.createElement('div');\r\n d.textContent = s;\r\n return d.innerHTML;\r\n}\r\n\r\n/** Inject a stylesheet once, keyed by id. Shared by widgets. */\r\nexport function injectStyles(id: string, css: string): void {\r\n if (document.getElementById(id)) return;\r\n const style = document.createElement('style');\r\n style.id = id;\r\n style.textContent = css;\r\n document.head.appendChild(style);\r\n}\r\n\r\n/** Resolve a selector-or-element mount target. */\r\nexport function resolveTarget(target: string | HTMLElement): HTMLElement | null {\r\n return typeof target === 'string' ? document.querySelector<HTMLElement>(target) : target;\r\n}\r\n\r\nexport function createCore(config: ClearCoreConfig): ClearCoreClient {\r\n if (!config?.projectKey) throw new Error('ClearLaunch: projectKey is required');\r\n const apiUrl = (config.apiUrl || DEFAULT_API_URL).replace(/\\/$/, '');\r\n const sdkBase = `${apiUrl}/api/v1/public/sdk/${encodeURIComponent(config.projectKey)}`;\r\n\r\n let configPromise: Promise<SdkRemoteConfig> | null = null;\r\n\r\n async function get<T>(path: string): Promise<T> {\r\n const res = await fetch(`${sdkBase}/${path.replace(/^\\//, '')}`);\r\n if (!res.ok) throw new Error(`ClearLaunch: request to ${path} failed (${res.status})`);\r\n return res.json() as Promise<T>;\r\n }\r\n\r\n function configOnce(): Promise<SdkRemoteConfig> {\r\n if (!configPromise) {\r\n configPromise = get<SdkRemoteConfig>('config').catch(() => ({\r\n projectName: '',\r\n widgets: { versions: true },\r\n } as SdkRemoteConfig));\r\n }\r\n return configPromise;\r\n }\r\n\r\n return {\r\n projectKey: config.projectKey,\r\n sdkBase,\r\n get,\r\n config: configOnce,\r\n };\r\n}\r\n"],
5
+ "mappings": "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",
6
+ "names": ["index_exports", "__export", "ClearLaunch", "clearSDK", "index_default", "init", "register", "__toCommonJS", "DEFAULT_API_URL", "createCore", "config", "sdkBase", "DEFAULT_API_URL", "configPromise", "get", "path", "res", "configOnce", "registry", "register", "pkg", "mod", "missing", "capability", "resolve", "registered", "req", "createTicketing", "core", "apiUrl", "feedbackConfig", "cfg", "_a", "fb", "options", "_b", "service", "rest", "createGuides", "guidesConfig", "slug", "clearSDK", "config", "createCore", "versions", "guides", "ticketing", "init", "ClearLaunch", "index_default"]
7
7
  }
@@ -1,39 +1,7 @@
1
- var f="https://api.clearlaunch.com";function l(e){let t=document.createElement("div");return t.textContent=e,t.innerHTML}function c(e,t){if(document.getElementById(e))return;let n=document.createElement("style");n.id=e,n.textContent=t,document.head.appendChild(n)}function d(e){return typeof e=="string"?document.querySelector(e):e}function p(e){if(!(e!=null&&e.projectKey))throw new Error("ClearLaunch: projectKey is required");let n=`${(e.apiUrl||f).replace(/\/$/,"")}/api/v1/public/sdk/${encodeURIComponent(e.projectKey)}`,r=null;async function o(a){let s=await fetch(`${n}/${a.replace(/^\//,"")}`);if(!s.ok)throw new Error(`ClearLaunch: request to ${a} failed (${s.status})`);return s.json()}function m(){return r||(r=o("config").catch(()=>({projectName:"",widgets:{versions:!0}}))),r}return{projectKey:e.projectKey,sdkBase:n,get:o,config:m}}var g=`
2
- .cl-vw { --cl-vw-accent: #6366f1; --cl-vw-radius: 12px;
3
- font-family: var(--cl-vw-font, inherit); color: #1f2430; }
4
- .cl-vw * { box-sizing: border-box; }
5
- .cl-vw__empty { padding: 24px; text-align: center; color: #8891a5; font-size: 14px; }
6
- .cl-vw__release { padding: 16px 0; border-bottom: 1px solid #eceef3; }
7
- .cl-vw__release:last-child { border-bottom: 0; }
8
- .cl-vw__head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 8px; }
9
- .cl-vw__ver {
10
- font-weight: 700; font-size: 15px; color: #fff; background: var(--cl-vw-accent);
11
- padding: 2px 9px; border-radius: 999px; letter-spacing: -0.01em;
12
- }
13
- .cl-vw__date { font-size: 12px; color: #8891a5; }
14
- .cl-vw__group { margin: 10px 0 0; }
15
- .cl-vw__group-label {
16
- font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em;
17
- font-weight: 700; color: #6b7280; margin-bottom: 4px;
18
- }
19
- .cl-vw__group--breaking .cl-vw__group-label { color: #dc2626; }
20
- .cl-vw__list { margin: 0; padding-left: 18px; }
21
- .cl-vw__list li { font-size: 13px; line-height: 1.55; color: #374151; margin: 2px 0; }
22
- @media (prefers-color-scheme: dark) {
23
- .cl-vw { color: #e5e7eb; }
24
- .cl-vw__release { border-bottom-color: #2a2f3a; }
25
- .cl-vw__date, .cl-vw__group-label { color: #9aa3b2; }
26
- .cl-vw__list li { color: #cbd2de; }
27
- }
28
- `;function v(e){if(!e)return"";let t=new Date(e);return isNaN(t.getTime())?"":t.toLocaleDateString(void 0,{year:"numeric",month:"short",day:"numeric"})}function i(e,t,n=""){if(!(t!=null&&t.length))return"";let r=t.map(o=>`<li>${l(o)}</li>`).join("");return`<div class="cl-vw__group ${n}"><div class="cl-vw__group-label">${e}</div><ul class="cl-vw__list">${r}</ul></div>`}function _(e,t){if(!t.length){e.innerHTML='<div class="cl-vw"><div class="cl-vw__empty">No releases yet.</div></div>';return}let n=t.map(r=>`
29
- <div class="cl-vw__release">
30
- <div class="cl-vw__head">
31
- <span class="cl-vw__ver">v${l(r.version)}</span>
32
- <span class="cl-vw__date">${v(r.publishedAt)}</span>
33
- </div>
34
- ${i("Breaking changes",r.notes.breaking,"cl-vw__group--breaking")}
35
- ${i("New features",r.notes.features)}
36
- ${i("Enhancements",r.notes.enhancements)}
37
- ${i("Fixes",r.notes.bugFixes)}
38
- </div>`).join("");e.innerHTML=`<div class="cl-vw">${n}</div>`}function u(e){async function t(){return(await e.get("releases")).releases||[]}return{list:t,async mount(n){let r=d(n);if(!r)throw new Error(`ClearLaunch versions: mount target not found: ${String(n)}`);c("cl-vw-styles",g);try{_(r,await t())}catch{r.innerHTML=`<div class="cl-vw"><div class="cl-vw__empty">Couldn't load release notes.</div></div>`}}}}function w(e){let t=p(e);return{projectKey:t.projectKey,versions:u(t)}}var C={init:w},R=C;export{C as ClearLaunch,R as default,w as init};
1
+ var l=(n=>typeof require!="undefined"?require:typeof Proxy!="undefined"?new Proxy(n,{get:(t,i)=>(typeof require!="undefined"?require:t)[i]}):n)(function(n){if(typeof require!="undefined")return require.apply(this,arguments);throw Error('Dynamic require of "'+n+'" is not supported')});var C="https://api.clearlaunch.ai";function f(n){if(!(n!=null&&n.projectKey))throw new Error("ClearLaunch: projectKey is required");let i=`${(n.apiUrl||C).replace(/\/$/,"")}/api/v1/public/sdk/${encodeURIComponent(n.projectKey)}`,e=null;async function r(o){let c=await fetch(`${i}/${o.replace(/^\//,"")}`);if(!c.ok)throw new Error(`ClearLaunch: request to ${o} failed (${c.status})`);return c.json()}function s(){return e||(e=r("config").catch(()=>({projectName:"",widgets:{versions:!0}}))),e}return{projectKey:n.projectKey,sdkBase:i,get:r,config:s}}var p=new Map;function k(n,t){p.set(n,t)}function u(n,t){throw new Error(`[clearlaunch] The "${t}" capability needs ${n}, which isn't installed.
2
+ Install it: npm install ${n}
3
+ Or, if your bundler can't resolve optional peers, register it yourself:
4
+ import * as mod from '${n}';
5
+ import { register } from '@clearlaunch/sdk';
6
+ register('${n}', mod);`)}function d(n){let t=p.get(n);if(t)return t;try{let i=typeof module!="undefined"&&typeof l=="function"?l:void 0;if(i)return i(n)}catch{}return null}function h(n,t){async function i(){let e=await n.config();return e.feedback&&e.feedback.enabled?e.feedback:null}return{async enabled(){return!!await i()},async services(){var r;let e=await i();return(r=e==null?void 0:e.services)!=null?r:[]},async mount(e={}){var a,g;let r=await i();if(!r)throw new Error("[clearlaunch] Feedback is not enabled for this project. Turn it on in ClearLaunch \u2192 project \u2192 Feedback.");let s=d("@clearlaunch/feedback");if(s!=null&&s.mountFeedback||u("@clearlaunch/feedback","ticketing"),e.service&&((a=r.services)!=null&&a.length)&&!r.services.includes(e.service))throw new Error(`[clearlaunch] service "${e.service}" is not declared on this project. Declared: ${r.services.join(", ")}. Add it in ClearLaunch \u2192 project \u2192 Feedback.`);let{service:o,...c}=e;return s.mountFeedback({...c,...o?{service:o}:(g=r.services)!=null&&g.length?{services:r.services}:{},token:r.token,...t?{apiUrl:t}:{}})}}}function y(n,t){async function i(){var r;return(r=(await n.config()).guides)!=null?r:{slugs:[],default:void 0}}return{async slugs(){var e;return(e=(await i()).slugs)!=null?e:[]},async defaultSlug(){return(await i()).default},async mount(e={}){var c,a;let r=await i(),s=(c=e.slug)!=null?c:r.default;if(!s)throw new Error("[clearlaunch] This project has no published guide. Publish one in ClearLaunch \u2192 project \u2192 Guides, or pass an explicit `slug`.");if(e.slug&&((a=r.slugs)!=null&&a.length)&&!r.slugs.includes(e.slug))throw new Error(`[clearlaunch] guide "${e.slug}" is not published on this project. Published: ${r.slugs.join(", ")}.`);let o=d("@clearlaunch/guide-sdk");return o!=null&&o.init||u("@clearlaunch/guide-sdk","guides"),o.init({slug:s,...e.target?{target:e.target}:{},...t?{apiUrl:t}:{}})}}}function m(n){let t=f(n),i=null,e=null,r=null;return{projectKey:t.projectKey,core:t,config:()=>t.config(),get versions(){if(!i){let o=d("@clearlaunch/versions");o!=null&&o.createVersions||u("@clearlaunch/versions","versions"),i=o.createVersions(t)}return i},get guides(){return e||(e=y(t,n.apiUrl)),e},get ticketing(){return r||(r=h(t,n.apiUrl)),r},get feedback(){return this.ticketing}}}var b=m,T={init:b,clearSDK:m,register:k},j=T;export{T as ClearLaunch,m as clearSDK,j as default,b as init,k as register};
39
7
  //# sourceMappingURL=clearlaunch.esm.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../clearsdk-core/src/index.ts", "../../clearsdk-versions/src/styles.ts", "../../clearsdk-versions/src/index.ts", "../src/index.ts"],
4
- "sourcesContent": ["/**\n * @clearlaunch/core \u2014 the shared foundation every ClearLaunch widget builds on.\n *\n * One public project key (`pk_\u2026`) identifies the project in the browser. Core\n * owns the API base, the fetch client, the remote SDK config (which widgets are\n * enabled + theme), and a small style-injection helper. Widget packages\n * (@clearlaunch/versions, /guides, /feedback) receive a ClearCoreClient and\n * attach themselves to it.\n */\n\nexport interface ClearCoreConfig {\n /** The project's public key (pk_\u2026). Safe to ship in the browser. */\n projectKey: string;\n /** Override the API base. Defaults to the hosted ClearLaunch API. */\n apiUrl?: string;\n}\n\nexport interface SdkTheme {\n primaryColor?: string;\n fontFamily?: string;\n borderRadius?: string;\n logoUrl?: string;\n}\n\nexport interface SdkRemoteConfig {\n projectName: string;\n widgets: { versions?: boolean; guides?: boolean; feedback?: boolean };\n theme?: SdkTheme;\n}\n\nexport interface ClearCoreClient {\n readonly projectKey: string;\n /** Absolute base for this project's public SDK routes:\n * `${apiUrl}/api/v1/public/sdk/${projectKey}` */\n readonly sdkBase: string;\n /** GET a JSON path relative to sdkBase (e.g. 'releases', 'config'). */\n get<T = unknown>(path: string): Promise<T>;\n /** Cached remote config (widgets enabled + theme). Fetched once. */\n config(): Promise<SdkRemoteConfig>;\n}\n\nconst DEFAULT_API_URL = 'https://api.clearlaunch.com';\n\n/** Escape untrusted text before inserting into innerHTML. Shared by widgets. */\nexport function esc(s: string): string {\n const d = document.createElement('div');\n d.textContent = s;\n return d.innerHTML;\n}\n\n/** Inject a stylesheet once, keyed by id. Shared by widgets. */\nexport function injectStyles(id: string, css: string): void {\n if (document.getElementById(id)) return;\n const style = document.createElement('style');\n style.id = id;\n style.textContent = css;\n document.head.appendChild(style);\n}\n\n/** Resolve a selector-or-element mount target. */\nexport function resolveTarget(target: string | HTMLElement): HTMLElement | null {\n return typeof target === 'string' ? document.querySelector<HTMLElement>(target) : target;\n}\n\nexport function createCore(config: ClearCoreConfig): ClearCoreClient {\n if (!config?.projectKey) throw new Error('ClearLaunch: projectKey is required');\n const apiUrl = (config.apiUrl || DEFAULT_API_URL).replace(/\\/$/, '');\n const sdkBase = `${apiUrl}/api/v1/public/sdk/${encodeURIComponent(config.projectKey)}`;\n\n let configPromise: Promise<SdkRemoteConfig> | null = null;\n\n async function get<T>(path: string): Promise<T> {\n const res = await fetch(`${sdkBase}/${path.replace(/^\\//, '')}`);\n if (!res.ok) throw new Error(`ClearLaunch: request to ${path} failed (${res.status})`);\n return res.json() as Promise<T>;\n }\n\n function configOnce(): Promise<SdkRemoteConfig> {\n if (!configPromise) {\n configPromise = get<SdkRemoteConfig>('config').catch(() => ({\n projectName: '',\n widgets: { versions: true },\n } as SdkRemoteConfig));\n }\n return configPromise;\n }\n\n return {\n projectKey: config.projectKey,\n sdkBase,\n get,\n config: configOnce,\n };\n}\n", "/** Self-contained widget CSS, namespaced under .cl-vw so it never leaks into\n * or inherits from the host page. Theme values are injected via CSS vars. */\nexport const VERSIONS_CSS = `\n.cl-vw { --cl-vw-accent: #6366f1; --cl-vw-radius: 12px;\n font-family: var(--cl-vw-font, inherit); color: #1f2430; }\n.cl-vw * { box-sizing: border-box; }\n.cl-vw__empty { padding: 24px; text-align: center; color: #8891a5; font-size: 14px; }\n.cl-vw__release { padding: 16px 0; border-bottom: 1px solid #eceef3; }\n.cl-vw__release:last-child { border-bottom: 0; }\n.cl-vw__head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 8px; }\n.cl-vw__ver {\n font-weight: 700; font-size: 15px; color: #fff; background: var(--cl-vw-accent);\n padding: 2px 9px; border-radius: 999px; letter-spacing: -0.01em;\n}\n.cl-vw__date { font-size: 12px; color: #8891a5; }\n.cl-vw__group { margin: 10px 0 0; }\n.cl-vw__group-label {\n font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em;\n font-weight: 700; color: #6b7280; margin-bottom: 4px;\n}\n.cl-vw__group--breaking .cl-vw__group-label { color: #dc2626; }\n.cl-vw__list { margin: 0; padding-left: 18px; }\n.cl-vw__list li { font-size: 13px; line-height: 1.55; color: #374151; margin: 2px 0; }\n@media (prefers-color-scheme: dark) {\n .cl-vw { color: #e5e7eb; }\n .cl-vw__release { border-bottom-color: #2a2f3a; }\n .cl-vw__date, .cl-vw__group-label { color: #9aa3b2; }\n .cl-vw__list li { color: #cbd2de; }\n}\n`;\n", "import type { ClearCoreClient } from '@clearlaunch/core';\nimport { esc, injectStyles, resolveTarget } from '@clearlaunch/core';\nimport { VERSIONS_CSS } from './styles';\n\nexport interface ReleaseNotesPublic {\n features: string[];\n enhancements: string[];\n bugFixes: string[];\n breaking: string[];\n}\n\nexport interface PublicRelease {\n version: string;\n publishedAt?: string;\n notes: ReleaseNotesPublic;\n html?: string;\n}\n\nexport interface VersionsWidget {\n /** Render the version-history panel into a container (selector or element). */\n mount(target: string | HTMLElement): Promise<void>;\n /** Fetch releases without rendering (for a custom UI). */\n list(): Promise<PublicRelease[]>;\n}\n\nfunction fmtDate(iso?: string): string {\n if (!iso) return '';\n const d = new Date(iso);\n return isNaN(d.getTime()) ? '' : d.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' });\n}\n\nfunction group(label: string, items: string[], modifier = ''): string {\n if (!items?.length) return '';\n const li = items.map(i => `<li>${esc(i)}</li>`).join('');\n return `<div class=\"cl-vw__group ${modifier}\"><div class=\"cl-vw__group-label\">${label}</div><ul class=\"cl-vw__list\">${li}</ul></div>`;\n}\n\nfunction render(el: HTMLElement, releases: PublicRelease[]): void {\n if (!releases.length) {\n el.innerHTML = `<div class=\"cl-vw\"><div class=\"cl-vw__empty\">No releases yet.</div></div>`;\n return;\n }\n const body = releases.map(r => `\n <div class=\"cl-vw__release\">\n <div class=\"cl-vw__head\">\n <span class=\"cl-vw__ver\">v${esc(r.version)}</span>\n <span class=\"cl-vw__date\">${fmtDate(r.publishedAt)}</span>\n </div>\n ${group('Breaking changes', r.notes.breaking, 'cl-vw__group--breaking')}\n ${group('New features', r.notes.features)}\n ${group('Enhancements', r.notes.enhancements)}\n ${group('Fixes', r.notes.bugFixes)}\n </div>`).join('');\n el.innerHTML = `<div class=\"cl-vw\">${body}</div>`;\n}\n\n/** Attach a versions widget to a core client. */\nexport function createVersions(core: ClearCoreClient): VersionsWidget {\n async function list(): Promise<PublicRelease[]> {\n const data = await core.get<{ releases: PublicRelease[] }>('releases');\n return data.releases || [];\n }\n return {\n list,\n async mount(target) {\n const el = resolveTarget(target);\n if (!el) throw new Error(`ClearLaunch versions: mount target not found: ${String(target)}`);\n injectStyles('cl-vw-styles', VERSIONS_CSS);\n try {\n render(el, await list());\n } catch {\n el.innerHTML = `<div class=\"cl-vw\"><div class=\"cl-vw__empty\">Couldn't load release notes.</div></div>`;\n }\n },\n };\n}\n", "/**\n * @clearlaunch/sdk \u2014 the all-in-one bundle for the CDN script tag.\n *\n * This is the batteries-included entry: one <script> gives you\n * window.ClearLaunch.init({ projectKey }) with every widget attached. Under the\n * hood it composes the modular packages (@clearlaunch/core + the widget\n * packages), so apps that prefer smaller bundles can install those directly:\n *\n * import { createCore } from '@clearlaunch/core';\n * import { createVersions } from '@clearlaunch/versions';\n * const core = createCore({ projectKey });\n * const versions = createVersions(core);\n */\nimport { createCore, type ClearCoreConfig } from '@clearlaunch/core';\nimport { createVersions, type VersionsWidget, type PublicRelease } from '@clearlaunch/versions';\n\nexport type { ClearCoreConfig, VersionsWidget, PublicRelease };\n\nexport interface ClearLaunchClient {\n readonly projectKey: string;\n readonly versions: VersionsWidget;\n}\n\nexport function init(config: ClearCoreConfig): ClearLaunchClient {\n const core = createCore(config);\n return {\n projectKey: core.projectKey,\n versions: createVersions(core),\n };\n}\n\nexport const ClearLaunch = { init };\nexport default ClearLaunch;\n"],
5
- "mappings": "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",
6
- "names": ["DEFAULT_API_URL", "esc", "s", "d", "injectStyles", "id", "css", "style", "resolveTarget", "target", "createCore", "config", "sdkBase", "configPromise", "get", "path", "res", "configOnce", "VERSIONS_CSS", "fmtDate", "iso", "d", "group", "label", "items", "modifier", "li", "i", "esc", "render", "el", "releases", "body", "createVersions", "core", "list", "target", "resolveTarget", "injectStyles", "VERSIONS_CSS", "init", "config", "core", "createCore", "createVersions", "ClearLaunch", "index_default"]
3
+ "sources": ["../../clearsdk-core/src/index.ts", "../src/index.ts"],
4
+ "sourcesContent": ["/**\r\n * @clearlaunch/core \u2014 the shared foundation every ClearLaunch widget builds on.\r\n *\r\n * One public project key (`pk_\u2026`) identifies the project in the browser. Core\r\n * owns the API base, the fetch client, the remote SDK config (which widgets are\r\n * enabled + theme), and a small style-injection helper. Widget packages\r\n * (@clearlaunch/versions, /guides, /feedback) receive a ClearCoreClient and\r\n * attach themselves to it.\r\n */\r\n\r\nexport interface ClearCoreConfig {\r\n /** The project's public key (pk_\u2026). Safe to ship in the browser. */\r\n projectKey: string;\r\n /** Override the API base. Defaults to the hosted ClearLaunch API. */\r\n apiUrl?: string;\r\n}\r\n\r\nexport interface SdkTheme {\r\n primaryColor?: string;\r\n fontFamily?: string;\r\n borderRadius?: string;\r\n logoUrl?: string;\r\n}\r\n\r\nexport interface SdkRemoteConfig {\r\n projectName: string;\r\n widgets: { versions?: boolean; guides?: boolean; feedback?: boolean };\r\n theme?: SdkTheme;\r\n /**\r\n * Public identifiers the other sub-packages need, resolved from the pk_ key\r\n * so one credential reaches every widget. Both are already public \u2014 the\r\n * feedback token is served by the widget-config route and guide slugs\r\n * appear in /docs/:slug URLs.\r\n *\r\n * Optional because an older API may not return them.\r\n */\r\n guides?: {\r\n /** Published guides only. */\r\n slugs: string[];\r\n /** Which one a bare `.guides` accessor should open. */\r\n default?: string;\r\n };\r\n feedback?:\r\n | { enabled: false }\r\n | {\r\n enabled: true;\r\n token: string;\r\n /** Touchpoints the project has declared (dealership, admin, \u2026). */\r\n services?: string[];\r\n };\r\n}\r\n\r\nexport interface ClearCoreClient {\r\n readonly projectKey: string;\r\n /** Absolute base for this project's public SDK routes:\r\n * `${apiUrl}/api/v1/public/sdk/${projectKey}` */\r\n readonly sdkBase: string;\r\n /** GET a JSON path relative to sdkBase (e.g. 'releases', 'config'). */\r\n get<T = unknown>(path: string): Promise<T>;\r\n /** Cached remote config (widgets enabled + theme). Fetched once. */\r\n config(): Promise<SdkRemoteConfig>;\r\n}\r\n\r\nconst DEFAULT_API_URL = 'https://api.clearlaunch.ai';\r\n\r\n/** Escape untrusted text before inserting into innerHTML. Shared by widgets. */\r\nexport function esc(s: string): string {\r\n const d = document.createElement('div');\r\n d.textContent = s;\r\n return d.innerHTML;\r\n}\r\n\r\n/** Inject a stylesheet once, keyed by id. Shared by widgets. */\r\nexport function injectStyles(id: string, css: string): void {\r\n if (document.getElementById(id)) return;\r\n const style = document.createElement('style');\r\n style.id = id;\r\n style.textContent = css;\r\n document.head.appendChild(style);\r\n}\r\n\r\n/** Resolve a selector-or-element mount target. */\r\nexport function resolveTarget(target: string | HTMLElement): HTMLElement | null {\r\n return typeof target === 'string' ? document.querySelector<HTMLElement>(target) : target;\r\n}\r\n\r\nexport function createCore(config: ClearCoreConfig): ClearCoreClient {\r\n if (!config?.projectKey) throw new Error('ClearLaunch: projectKey is required');\r\n const apiUrl = (config.apiUrl || DEFAULT_API_URL).replace(/\\/$/, '');\r\n const sdkBase = `${apiUrl}/api/v1/public/sdk/${encodeURIComponent(config.projectKey)}`;\r\n\r\n let configPromise: Promise<SdkRemoteConfig> | null = null;\r\n\r\n async function get<T>(path: string): Promise<T> {\r\n const res = await fetch(`${sdkBase}/${path.replace(/^\\//, '')}`);\r\n if (!res.ok) throw new Error(`ClearLaunch: request to ${path} failed (${res.status})`);\r\n return res.json() as Promise<T>;\r\n }\r\n\r\n function configOnce(): Promise<SdkRemoteConfig> {\r\n if (!configPromise) {\r\n configPromise = get<SdkRemoteConfig>('config').catch(() => ({\r\n projectName: '',\r\n widgets: { versions: true },\r\n } as SdkRemoteConfig));\r\n }\r\n return configPromise;\r\n }\r\n\r\n return {\r\n projectKey: config.projectKey,\r\n sdkBase,\r\n get,\r\n config: configOnce,\r\n };\r\n}\r\n", "/**\r\n * @clearlaunch/sdk \u2014 one project key, every ClearLaunch surface.\r\n *\r\n * import { clearSDK } from '@clearlaunch/sdk';\r\n * const cl = clearSDK({ projectKey: 'pk_\u2026' });\r\n *\r\n * cl.versions.mount('#whats-new'); // release notes\r\n * cl.guides.mount({ target: '#docs' }); // published user guides\r\n * cl.ticketing.mount({ service: 'dealership' }); // feedback / bug reports\r\n *\r\n * ## How composition works\r\n *\r\n * Each capability lives in its own package so a docs site isn't forced to ship\r\n * a ticketing inbox. They are declared as OPTIONAL peer dependencies: install\r\n * only what you use, and the accessor for anything missing throws a message\r\n * naming the exact package to install rather than a bare `undefined`.\r\n *\r\n * Accessors are lazy \u2014 touching `cl.ticketing` is what resolves and mounts it,\r\n * so an unused capability costs nothing at runtime. The bundled CDN build\r\n * inlines all of them (see build.mjs), so the script tag keeps working with no\r\n * install step.\r\n *\r\n * ## One credential\r\n *\r\n * Sub-packages historically needed their own identifiers: a guide slug, a `fb_`\r\n * feedback token. Both are already public \u2014 guide slugs appear in /docs/:slug\r\n * URLs and the feedback token is served by the widget-config route \u2014 so the\r\n * server resolves them from the `pk_` key and returns them in the SDK config\r\n * (ADR feeb30c5). Callers pass one key and never see the others.\r\n */\r\nimport { createCore, type ClearCoreClient, type ClearCoreConfig, type SdkRemoteConfig } from '@clearlaunch/core';\r\nimport type { VersionsWidget, PublicRelease } from '@clearlaunch/versions';\r\nimport type { FeedbackType, FeedbackTheme, TriggerConfig } from '@clearlaunch/feedback';\r\n\r\nexport type {\r\n ClearCoreConfig, SdkRemoteConfig, VersionsWidget, PublicRelease,\r\n FeedbackType, FeedbackTheme, TriggerConfig,\r\n};\r\n\r\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n * Optional peer resolution\r\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\r\n\r\n/**\r\n * Modules the host app supplied by hand.\r\n *\r\n * Bundlers resolve `import` statically, so a truly optional dependency can't be\r\n * `await import`ed without the bundler either erroring or emitting a chunk for\r\n * a package that may not exist. Callers in that situation register the module\r\n * themselves; the CDN build registers all three at startup.\r\n */\r\nconst registry = new Map<string, unknown>();\r\n\r\n/** Supply a capability module explicitly, bypassing package resolution. */\r\nexport function register(pkg: string, mod: unknown): void {\r\n registry.set(pkg, mod);\r\n}\r\n\r\nfunction missing(pkg: string, capability: string): never {\r\n throw new Error(\r\n `[clearlaunch] The \"${capability}\" capability needs ${pkg}, which isn't installed.\\n` +\r\n ` Install it: npm install ${pkg}\\n` +\r\n ` Or, if your bundler can't resolve optional peers, register it yourself:\\n` +\r\n ` import * as mod from '${pkg}';\\n` +\r\n ` import { register } from '@clearlaunch/sdk';\\n` +\r\n ` register('${pkg}', mod);`,\r\n );\r\n}\r\n\r\n/**\r\n * Resolve an optional peer, preferring an explicit registration.\r\n *\r\n * The `require` path covers CJS/Node; the registry covers bundlers. We never\r\n * throw from resolution itself \u2014 the caller decides, so the error names the\r\n * capability the user actually asked for.\r\n */\r\nfunction resolve<T>(pkg: string): T | null {\r\n const registered = registry.get(pkg);\r\n if (registered) return registered as T;\r\n try {\r\n // Hidden from bundlers on purpose: a literal require() of an optional peer\r\n // makes webpack/vite fail the build when it isn't installed.\r\n const req: ((id: string) => unknown) | undefined =\r\n typeof module !== 'undefined' && typeof require === 'function' ? require : undefined;\r\n if (req) return req(pkg) as T;\r\n } catch {\r\n /* not installed, or not a CJS context \u2014 fall through to null */\r\n }\r\n return null;\r\n}\r\n\r\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n * Ticketing\r\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\r\n\r\n/**\r\n * Options for the ticketing widget.\r\n *\r\n * `token` is deliberately absent \u2014 it is resolved from the project key. Every\r\n * other option is passed through to @clearlaunch/feedback.\r\n */\r\nexport interface TicketingMountOptions {\r\n /**\r\n * Touchpoint this widget is embedded on (\"dealership\", \"admin\", \u2026). Stored on\r\n * the submission and the resulting card, so feedback can be filtered by\r\n * surface. Must be one of the services declared on the project.\r\n */\r\n service?: string;\r\n trigger?: TriggerConfig;\r\n theme?: FeedbackTheme;\r\n types?: FeedbackType[];\r\n defaultType?: FeedbackType;\r\n source?: string;\r\n user?: { email?: string; name?: string };\r\n metadata?: Record<string, string>;\r\n text?: Record<string, string>;\r\n onSubmit?: (result: { submissionId: string }) => void;\r\n onError?: (err: Error) => void;\r\n onOpen?: () => void;\r\n onClose?: () => void;\r\n}\r\n\r\nexport interface TicketingWidget {\r\n open(type?: FeedbackType): void;\r\n close(): void;\r\n destroy(): void;\r\n}\r\n\r\nexport interface Ticketing {\r\n /**\r\n * Mount the feedback trigger + dialog. Resolves once the project config has\r\n * supplied the feedback token.\r\n */\r\n mount(options?: TicketingMountOptions): Promise<TicketingWidget>;\r\n /** Touchpoints declared on the project, for building your own picker. */\r\n services(): Promise<string[]>;\r\n /** Whether feedback is switched on for this project. */\r\n enabled(): Promise<boolean>;\r\n}\r\n\r\nfunction createTicketing(core: ClearCoreClient, apiUrl?: string): Ticketing {\r\n async function feedbackConfig() {\r\n const cfg = await core.config();\r\n return cfg.feedback && cfg.feedback.enabled ? cfg.feedback : null;\r\n }\r\n\r\n return {\r\n async enabled() {\r\n return !!(await feedbackConfig());\r\n },\r\n\r\n async services() {\r\n const fb = await feedbackConfig();\r\n return fb?.services ?? [];\r\n },\r\n\r\n async mount(options: TicketingMountOptions = {}) {\r\n const fb = await feedbackConfig();\r\n if (!fb) {\r\n throw new Error(\r\n '[clearlaunch] Feedback is not enabled for this project. ' +\r\n 'Turn it on in ClearLaunch \u2192 project \u2192 Feedback.',\r\n );\r\n }\r\n\r\n const mod = resolve<{ mountFeedback: (o: Record<string, unknown>) => TicketingWidget }>(\r\n '@clearlaunch/feedback',\r\n );\r\n if (!mod?.mountFeedback) missing('@clearlaunch/feedback', 'ticketing');\r\n\r\n // A service must be one the project declared, or filtering downstream\r\n // silently accumulates typos that never match anything in the UI.\r\n if (options.service && fb.services?.length && !fb.services.includes(options.service)) {\r\n throw new Error(\r\n `[clearlaunch] service \"${options.service}\" is not declared on this project. ` +\r\n `Declared: ${fb.services.join(', ')}. Add it in ClearLaunch \u2192 project \u2192 Feedback.`,\r\n );\r\n }\r\n\r\n const { service, ...rest } = options;\r\n return mod.mountFeedback({\r\n ...rest,\r\n // Fixed touchpoint wins. Otherwise hand the widget the project's\r\n // declared list so it can offer a picker without the caller having to\r\n // restate what ClearLaunch already knows. Passing both is refused by\r\n // the widget, so they are deliberately exclusive here too.\r\n ...(service\r\n ? { service }\r\n : fb.services?.length ? { services: fb.services } : {}),\r\n token: fb.token,\r\n ...(apiUrl ? { apiUrl } : {}),\r\n });\r\n },\r\n };\r\n}\r\n\r\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n * Guides\r\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\r\n\r\nexport interface GuidesMountOptions {\r\n /** Which published guide. Defaults to the project's first published guide. */\r\n slug?: string;\r\n /** Container for the embedded reader. */\r\n target?: string | HTMLElement;\r\n}\r\n\r\nexport interface Guides {\r\n mount(options?: GuidesMountOptions): Promise<unknown>;\r\n /** Slugs of every published guide on this project. */\r\n slugs(): Promise<string[]>;\r\n /** The slug a bare `mount()` would open, if any. */\r\n defaultSlug(): Promise<string | undefined>;\r\n}\r\n\r\nfunction createGuides(core: ClearCoreClient, apiUrl?: string): Guides {\r\n async function guidesConfig() {\r\n const cfg = await core.config();\r\n return cfg.guides ?? { slugs: [] as string[], default: undefined as string | undefined };\r\n }\r\n\r\n return {\r\n async slugs() {\r\n return (await guidesConfig()).slugs ?? [];\r\n },\r\n\r\n async defaultSlug() {\r\n return (await guidesConfig()).default;\r\n },\r\n\r\n async mount(options: GuidesMountOptions = {}) {\r\n const cfg = await guidesConfig();\r\n const slug = options.slug ?? cfg.default;\r\n if (!slug) {\r\n throw new Error(\r\n '[clearlaunch] This project has no published guide. ' +\r\n 'Publish one in ClearLaunch \u2192 project \u2192 Guides, or pass an explicit `slug`.',\r\n );\r\n }\r\n if (options.slug && cfg.slugs?.length && !cfg.slugs.includes(options.slug)) {\r\n throw new Error(\r\n `[clearlaunch] guide \"${options.slug}\" is not published on this project. ` +\r\n `Published: ${cfg.slugs.join(', ')}.`,\r\n );\r\n }\r\n\r\n const mod = resolve<{ init: (c: Record<string, unknown>) => Promise<unknown> }>(\r\n '@clearlaunch/guide-sdk',\r\n );\r\n if (!mod?.init) missing('@clearlaunch/guide-sdk', 'guides');\r\n\r\n return mod.init({\r\n slug,\r\n ...(options.target ? { target: options.target } : {}),\r\n ...(apiUrl ? { apiUrl } : {}),\r\n });\r\n },\r\n };\r\n}\r\n\r\n/* \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n * Client\r\n * \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\r\n\r\nexport interface ClearLaunchClient {\r\n readonly projectKey: string;\r\n /** Raw core client, for direct calls against the public SDK routes. */\r\n readonly core: ClearCoreClient;\r\n /** Resolved project config (name, widgets, theme, guides, feedback). */\r\n config(): Promise<SdkRemoteConfig>;\r\n readonly versions: VersionsWidget;\r\n readonly guides: Guides;\r\n /** Feedback / bug reports. Also available as `.feedback`. */\r\n readonly ticketing: Ticketing;\r\n /** Alias of `.ticketing`, matching the @clearlaunch/feedback package name. */\r\n readonly feedback: Ticketing;\r\n}\r\n\r\n/**\r\n * Create a ClearLaunch client.\r\n *\r\n * Capabilities are lazily constructed on first access and then cached, so an\r\n * app that only ever touches `.versions` never resolves the ticketing or guide\r\n * packages at all.\r\n */\r\nexport function clearSDK(config: ClearCoreConfig): ClearLaunchClient {\r\n const core = createCore(config);\r\n\r\n let versions: VersionsWidget | null = null;\r\n let guides: Guides | null = null;\r\n let ticketing: Ticketing | null = null;\r\n\r\n const client: ClearLaunchClient = {\r\n projectKey: core.projectKey,\r\n core,\r\n config: () => core.config(),\r\n\r\n get versions() {\r\n if (!versions) {\r\n const mod = resolve<{ createVersions: (c: ClearCoreClient) => VersionsWidget }>(\r\n '@clearlaunch/versions',\r\n );\r\n if (!mod?.createVersions) missing('@clearlaunch/versions', 'versions');\r\n versions = mod.createVersions(core);\r\n }\r\n return versions;\r\n },\r\n\r\n get guides() {\r\n if (!guides) guides = createGuides(core, config.apiUrl);\r\n return guides;\r\n },\r\n\r\n get ticketing() {\r\n if (!ticketing) ticketing = createTicketing(core, config.apiUrl);\r\n return ticketing;\r\n },\r\n\r\n get feedback() {\r\n return this.ticketing;\r\n },\r\n };\r\n\r\n return client;\r\n}\r\n\r\n/**\r\n * Back-compat entry for the CDN script tag: `ClearLaunch.init({ projectKey })`.\r\n * Identical to clearSDK().\r\n */\r\nexport const init = clearSDK;\r\n\r\nexport const ClearLaunch = { init, clearSDK, register };\r\nexport default ClearLaunch;\r\n"],
5
+ "mappings": "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",
6
+ "names": ["DEFAULT_API_URL", "createCore", "config", "sdkBase", "DEFAULT_API_URL", "configPromise", "get", "path", "res", "configOnce", "registry", "register", "pkg", "mod", "missing", "capability", "resolve", "registered", "req", "__require", "createTicketing", "core", "apiUrl", "feedbackConfig", "cfg", "_a", "fb", "options", "_b", "service", "rest", "createGuides", "guidesConfig", "slug", "clearSDK", "config", "createCore", "versions", "guides", "ticketing", "init", "ClearLaunch", "index_default"]
7
7
  }