cauthy-auth 0.3.0 → 0.5.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.
@@ -1,4 +1,4 @@
1
- import { J as JsonValue, S as Session, f as SessionStatus, e as SessionOrganization, c as CauthySystem, P as PublicSession, b as CauthyOptions } from './system-BWLddIt2.js';
1
+ import { J as JsonValue, S as Session, f as SessionStatus, e as SessionOrganization, c as CauthySystem, P as PublicSession, b as CauthyOptions } from './system-CL3Q30FT.js';
2
2
  import { JWTVerifyGetKey } from 'jose';
3
3
 
4
4
  /** Something that happened in Cauthy, as a subscriber is told. Moments are UTC. */
@@ -1,4 +1,4 @@
1
- import { J as JsonValue, S as Session, f as SessionStatus, e as SessionOrganization, c as CauthySystem, P as PublicSession, b as CauthyOptions } from './system-BWLddIt2.mjs';
1
+ import { J as JsonValue, S as Session, f as SessionStatus, e as SessionOrganization, c as CauthySystem, P as PublicSession, b as CauthyOptions } from './system-CdvktS7x.mjs';
2
2
  import { JWTVerifyGetKey } from 'jose';
3
3
 
4
4
  /** Something that happened in Cauthy, as a subscriber is told. Moments are UTC. */
package/dist/cli.js CHANGED
@@ -266,10 +266,19 @@ function toWire(theme) {
266
266
  radius: "radius",
267
267
  buttonRadius: "button_radius",
268
268
  fontFamily: "font_family",
269
- logoUrl: "logo_url"
269
+ logoUrl: "logo_url",
270
+ fonts: "fonts",
271
+ layout: "layout",
272
+ panelColors: "panel_colors",
273
+ panelText: "panel_text",
274
+ panelIconUrl: "panel_icon_url",
275
+ texts: "texts"
270
276
  };
271
277
  const wire = {};
272
- for (const [k, v] of Object.entries(theme)) if (v !== void 0 && v !== "") wire[names[k]] = v;
278
+ for (const [k, v] of Object.entries(theme)) {
279
+ if (v === void 0 || v === "" || Array.isArray(v) && v.length === 0) continue;
280
+ wire[names[k]] = v;
281
+ }
273
282
  return wire;
274
283
  }
275
284
  async function pushTheme(o) {
@@ -1,7 +1,8 @@
1
1
  import { FastifyReply, FastifyPluginAsync } from 'fastify';
2
- import { C as Cauthy } from './cauthy-mNADGlNl.mjs';
3
- import { S as Session } from './system-BWLddIt2.mjs';
2
+ import { C as Cauthy } from './cauthy-Dg-DNIo9.mjs';
3
+ import { S as Session } from './system-CdvktS7x.mjs';
4
4
  import 'jose';
5
+ import './theme.mjs';
5
6
 
6
7
  declare module 'fastify' {
7
8
  interface FastifyRequest {
package/dist/fastify.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import { FastifyReply, FastifyPluginAsync } from 'fastify';
2
- import { C as Cauthy } from './cauthy-C5_lopMQ.js';
3
- import { S as Session } from './system-BWLddIt2.js';
2
+ import { C as Cauthy } from './cauthy--iqtLWNa.js';
3
+ import { S as Session } from './system-CL3Q30FT.js';
4
4
  import 'jose';
5
+ import './theme.js';
5
6
 
6
7
  declare module 'fastify' {
7
8
  interface FastifyRequest {
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
- export { C as Cauthy, a as CauthyEvent, b as CauthyWebhookError, R as Resolved, V as VerifyWebhookOptions, c as createCauthy, v as verifyWebhook } from './cauthy-mNADGlNl.mjs';
2
- export { C as CauthyApiError, a as CauthyConfigError, b as CauthyOptions, c as CauthySystem, J as JsonValue, N as NewMember, O as Organization, d as OrganizationMember, P as PublicSession, S as Session, e as SessionOrganization, f as SessionStatus, g as SessionUser, h as SystemKey, i as SystemOptions, j as createSystem } from './system-BWLddIt2.mjs';
3
- export { CauthyTheme, ImportedTheme, PushThemeOptions, StackmythThemeOptions, pushTheme, themeFromStackmyth } from './theme.mjs';
1
+ export { C as Cauthy, a as CauthyEvent, b as CauthyWebhookError, R as Resolved, V as VerifyWebhookOptions, c as createCauthy, v as verifyWebhook } from './cauthy-Dg-DNIo9.mjs';
2
+ export { C as CauthyApiError, a as CauthyConfigError, b as CauthyOptions, c as CauthySystem, J as JsonValue, N as NewMember, O as Organization, d as OrganizationMember, P as PublicSession, S as Session, e as SessionOrganization, f as SessionStatus, g as SessionUser, h as SystemKey, i as SystemOptions, j as createSystem } from './system-CdvktS7x.mjs';
3
+ export { CauthyTheme, ImportedTheme, PushThemeOptions, StackmythThemeOptions, ThemeFont, ThemeTexts, pushTheme, themeFromStackmyth } from './theme.mjs';
4
4
  export { P as Permitted, a as PolicyPermission, b as PolicyRole, c as PushPolicyOptions, d as can, p as pushPolicy } from './permissions-B-a3eN0h.mjs';
5
5
  import 'jose';
6
6
 
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- export { C as Cauthy, a as CauthyEvent, b as CauthyWebhookError, R as Resolved, V as VerifyWebhookOptions, c as createCauthy, v as verifyWebhook } from './cauthy-C5_lopMQ.js';
2
- export { C as CauthyApiError, a as CauthyConfigError, b as CauthyOptions, c as CauthySystem, J as JsonValue, N as NewMember, O as Organization, d as OrganizationMember, P as PublicSession, S as Session, e as SessionOrganization, f as SessionStatus, g as SessionUser, h as SystemKey, i as SystemOptions, j as createSystem } from './system-BWLddIt2.js';
3
- export { CauthyTheme, ImportedTheme, PushThemeOptions, StackmythThemeOptions, pushTheme, themeFromStackmyth } from './theme.js';
1
+ export { C as Cauthy, a as CauthyEvent, b as CauthyWebhookError, R as Resolved, V as VerifyWebhookOptions, c as createCauthy, v as verifyWebhook } from './cauthy--iqtLWNa.js';
2
+ export { C as CauthyApiError, a as CauthyConfigError, b as CauthyOptions, c as CauthySystem, J as JsonValue, N as NewMember, O as Organization, d as OrganizationMember, P as PublicSession, S as Session, e as SessionOrganization, f as SessionStatus, g as SessionUser, h as SystemKey, i as SystemOptions, j as createSystem } from './system-CL3Q30FT.js';
3
+ export { CauthyTheme, ImportedTheme, PushThemeOptions, StackmythThemeOptions, ThemeFont, ThemeTexts, pushTheme, themeFromStackmyth } from './theme.js';
4
4
  export { P as Permitted, a as PolicyPermission, b as PolicyRole, c as PushPolicyOptions, d as can, p as pushPolicy } from './permissions-B-a3eN0h.js';
5
5
  import 'jose';
6
6
 
package/dist/index.js CHANGED
@@ -93,6 +93,264 @@ async function unseal(sealed, key) {
93
93
  // src/system.ts
94
94
  var import_jose2 = require("jose");
95
95
 
96
+ // src/theme.ts
97
+ var MAX_RADIUS = 40;
98
+ function declarations(css) {
99
+ const text = css.replace(/\/\*[\s\S]*?\*\//g, "");
100
+ const out2 = [];
101
+ const within = [];
102
+ let chunk = "";
103
+ let quote = "";
104
+ let depth = 0;
105
+ const flush = () => {
106
+ const m = /^\s*(--[\w-]+)\s*:\s*([\s\S]+?)\s*$/.exec(chunk);
107
+ if (m) out2.push({ name: m[1], value: m[2].replace(/\s+/g, " ").replace(/\s*!important$/, ""), within: [...within] });
108
+ chunk = "";
109
+ };
110
+ for (const ch of text) {
111
+ if (quote) {
112
+ chunk += ch;
113
+ if (ch === quote) quote = "";
114
+ continue;
115
+ }
116
+ if (ch === '"' || ch === "'") {
117
+ quote = ch;
118
+ chunk += ch;
119
+ } else if (ch === "(") {
120
+ depth++;
121
+ chunk += ch;
122
+ } else if (ch === ")") {
123
+ depth = Math.max(0, depth - 1);
124
+ chunk += ch;
125
+ } else if (ch === "{" && depth === 0) {
126
+ within.push(chunk.trim().replace(/\s+/g, " "));
127
+ chunk = "";
128
+ } else if (ch === "}" && depth === 0) {
129
+ flush();
130
+ within.pop();
131
+ } else if (ch === ";" && depth === 0) {
132
+ flush();
133
+ } else {
134
+ chunk += ch;
135
+ }
136
+ }
137
+ return out2;
138
+ }
139
+ var DARK = /prefers-color-scheme:\s*dark|data-(mode|theme|color-scheme)=["']?dark|\.dark\b/i;
140
+ var LIGHT = /prefers-color-scheme:\s*light|data-(mode|theme|color-scheme)=["']?light|\.light\b/i;
141
+ var NAMED = /data-theme=["']?([\w-]+)/i;
142
+ function applies(d, o) {
143
+ for (const scope of d.within) {
144
+ if (o.mode === "light" && DARK.test(scope)) return false;
145
+ if (o.mode === "dark" && LIGHT.test(scope)) return false;
146
+ const named = NAMED.exec(scope);
147
+ if (named && !/^(dark|light)$/i.test(named[1]) && named[1] !== o.theme) return false;
148
+ if (!scope.startsWith("@") && !/:root|^html\b|^body\b|\[data-|^\*$|:host/.test(scope)) return false;
149
+ }
150
+ return true;
151
+ }
152
+ function resolve(value, vars, seen = 0) {
153
+ if (seen > 16) return null;
154
+ let unresolved = false;
155
+ let out2 = value;
156
+ for (let guard = 0; guard < 32 && /var\(/.test(out2); guard++) {
157
+ out2 = out2.replace(/var\(\s*(--[\w-]+)\s*(?:,\s*([^()]*(?:\([^()]*\)[^()]*)*))?\)/, (_m, name, fallback) => {
158
+ const known = vars.get(name);
159
+ const next = known !== void 0 ? resolve(known, vars, seen + 1) : fallback !== void 0 ? resolve(fallback.trim(), vars, seen + 1) : null;
160
+ if (next === null) unresolved = true;
161
+ return next ?? "";
162
+ });
163
+ if (unresolved) return null;
164
+ }
165
+ return /var\(/.test(out2) ? null : out2.trim();
166
+ }
167
+ var clamp01 = (n) => Math.min(1, Math.max(0, n));
168
+ var hex2 = (n) => Math.round(clamp01(n) * 255).toString(16).padStart(2, "0");
169
+ var gamma = (c) => c <= 31308e-7 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
170
+ function out(r, g, b, a = 1) {
171
+ if (a >= 1) return `#${hex2(r)}${hex2(g)}${hex2(b)}`;
172
+ return `rgba(${Math.round(clamp01(r) * 255)}, ${Math.round(clamp01(g) * 255)}, ${Math.round(clamp01(b) * 255)}, ${Math.round(clamp01(a) * 1e3) / 1e3})`;
173
+ }
174
+ var alpha = (s) => s === void 0 ? 1 : s.endsWith("%") ? parseFloat(s) / 100 : parseFloat(s);
175
+ var KEYWORDS = { white: "#ffffff", black: "#000000" };
176
+ function toColor(value) {
177
+ const v = value.trim().toLowerCase();
178
+ if (KEYWORDS[v]) return KEYWORDS[v];
179
+ if (/^#([0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/.test(v)) return v;
180
+ let m = /^rgba?\(\s*([\d.]+%?)[\s,]+([\d.]+%?)[\s,]+([\d.]+%?)(?:\s*[,/]\s*([\d.]+%?))?\s*\)$/.exec(v);
181
+ if (m) {
182
+ const ch = (s) => s.endsWith("%") ? parseFloat(s) / 100 : parseFloat(s) / 255;
183
+ return out(ch(m[1]), ch(m[2]), ch(m[3]), alpha(m[4]));
184
+ }
185
+ m = /^hsla?\(\s*([\d.]+)(?:deg)?[\s,]+([\d.]+)%[\s,]+([\d.]+)%(?:\s*[,/]\s*([\d.]+%?))?\s*\)$/.exec(v);
186
+ if (m) {
187
+ const h = (parseFloat(m[1]) % 360 + 360) % 360;
188
+ const s = parseFloat(m[2]) / 100;
189
+ const l = parseFloat(m[3]) / 100;
190
+ const f = (n) => {
191
+ const k = (n + h / 30) % 12;
192
+ return l - s * Math.min(l, 1 - l) * Math.max(-1, Math.min(k - 3, 9 - k, 1));
193
+ };
194
+ return out(f(0), f(8), f(4), alpha(m[4]));
195
+ }
196
+ m = /^oklch\(\s*([\d.]+%?)\s+([\d.]+%?)\s+([\d.]+)(?:deg)?(?:\s*\/\s*([\d.]+%?))?\s*\)$/.exec(v);
197
+ if (m) {
198
+ const L = m[1].endsWith("%") ? parseFloat(m[1]) / 100 : parseFloat(m[1]);
199
+ const C = m[2].endsWith("%") ? parseFloat(m[2]) / 100 * 0.4 : parseFloat(m[2]);
200
+ const H = parseFloat(m[3]) * Math.PI / 180;
201
+ const a = C * Math.cos(H);
202
+ const b = C * Math.sin(H);
203
+ const l = Math.pow(L + 0.3963377774 * a + 0.2158037573 * b, 3);
204
+ const mm = Math.pow(L - 0.1055613458 * a - 0.0638541728 * b, 3);
205
+ const s = Math.pow(L - 0.0894841775 * a - 1.291485548 * b, 3);
206
+ return out(
207
+ gamma(4.0767416621 * l - 3.3077115913 * mm + 0.2309699292 * s),
208
+ gamma(-1.2684380046 * l + 2.6097574011 * mm - 0.3413193965 * s),
209
+ gamma(-0.0041960863 * l - 0.7034186147 * mm + 1.707614701 * s),
210
+ alpha(m[4])
211
+ );
212
+ }
213
+ return null;
214
+ }
215
+ function toRadius(value) {
216
+ const m = /^([\d.]+)(px|rem|em)?$/.exec(value.trim());
217
+ if (!m) return null;
218
+ const px = parseFloat(m[1]) * (m[2] === "rem" || m[2] === "em" ? 16 : 1);
219
+ return Number.isFinite(px) ? Math.min(MAX_RADIUS, Math.max(0, Math.round(px))) : null;
220
+ }
221
+ function toFont(value) {
222
+ const v = value.trim();
223
+ return /^[A-Za-z0-9 ,'"_-]{1,200}$/.test(v) && (v.match(/"/g)?.length ?? 0) % 2 === 0 && (v.match(/'/g)?.length ?? 0) % 2 === 0 ? v : null;
224
+ }
225
+ var COLORS = [
226
+ ["background", ["--sm-bg-surface", "--sm-surface"]],
227
+ ["surface", ["--sm-bg-surface-raised", "--sm-surface-raised"]],
228
+ ["text", ["--sm-text-primary", "--sm-surface-text"]],
229
+ ["textMuted", ["--sm-text-secondary"]],
230
+ ["border", ["--sm-border-default", "--sm-surface-border"]],
231
+ ["primary", ["--sm-primary", "--sm-bg-interactive"]],
232
+ ["primaryText", ["--sm-primary-text", "--sm-text-inverse"]],
233
+ ["accent", ["--sm-text-brand", "--sm-border-focus", "--sm-accent"]],
234
+ ["error", ["--sm-error-soft-text", "--sm-error"]],
235
+ ["errorBackground", ["--sm-error-soft"]],
236
+ ["success", ["--sm-success-soft-text", "--sm-success"]],
237
+ ["successBackground", ["--sm-success-soft"]]
238
+ ];
239
+ function themeFromStackmyth(css, options = {}) {
240
+ const o = { mode: options.mode ?? "light", theme: options.theme };
241
+ const vars = /* @__PURE__ */ new Map();
242
+ for (const sheet of Array.isArray(css) ? css : [css]) {
243
+ for (const d of declarations(sheet)) if (applies(d, o)) vars.set(d.name, d.value);
244
+ }
245
+ const theme = {};
246
+ const warnings = [];
247
+ const read = (tokens, to, what) => {
248
+ for (const token of tokens) {
249
+ const raw = vars.get(token);
250
+ if (raw === void 0) continue;
251
+ const value = resolve(raw, vars);
252
+ const got = value === null ? null : to(value);
253
+ if (got !== null) return got;
254
+ warnings.push(`${token}: "${raw}" is not ${what} Cauthy can take`);
255
+ }
256
+ return void 0;
257
+ };
258
+ for (const [field, tokens] of COLORS) {
259
+ const c = read(tokens, toColor, "a colour");
260
+ if (c !== void 0) theme[field] = c;
261
+ }
262
+ const radius = read(["--sm-radius-container", "--sm-radius-md"], toRadius, "a length");
263
+ if (radius !== void 0) theme.radius = radius;
264
+ const button = read(["--sm-radius-interactive", "--sm-radius-sm"], toRadius, "a length");
265
+ if (button !== void 0) theme.buttonRadius = button;
266
+ const font = read(["--sm-font-family"], toFont, "a font list");
267
+ if (font !== void 0) theme.fontFamily = font;
268
+ if (options.logoUrl) theme.logoUrl = options.logoUrl;
269
+ if (vars.size === 0) warnings.push("no custom properties were found: is this the stylesheet that declares the --sm-* tokens?");
270
+ else if (![...vars.keys()].some((k) => k.startsWith("--sm-"))) warnings.push("no --sm-* token was found in these stylesheets");
271
+ return { theme, warnings };
272
+ }
273
+ function toWire(theme) {
274
+ const names = {
275
+ background: "background",
276
+ surface: "surface",
277
+ text: "text",
278
+ textMuted: "text_muted",
279
+ border: "border",
280
+ primary: "primary",
281
+ primaryText: "primary_text",
282
+ accent: "accent",
283
+ error: "error",
284
+ errorBackground: "error_background",
285
+ success: "success",
286
+ successBackground: "success_background",
287
+ radius: "radius",
288
+ buttonRadius: "button_radius",
289
+ fontFamily: "font_family",
290
+ logoUrl: "logo_url",
291
+ fonts: "fonts",
292
+ layout: "layout",
293
+ panelColors: "panel_colors",
294
+ panelText: "panel_text",
295
+ panelIconUrl: "panel_icon_url",
296
+ texts: "texts"
297
+ };
298
+ const wire = {};
299
+ for (const [k, v] of Object.entries(theme)) {
300
+ if (v === void 0 || v === "" || Array.isArray(v) && v.length === 0) continue;
301
+ wire[names[k]] = v;
302
+ }
303
+ return wire;
304
+ }
305
+ function fromWire(wire) {
306
+ const names = {
307
+ background: "background",
308
+ surface: "surface",
309
+ text: "text",
310
+ text_muted: "textMuted",
311
+ border: "border",
312
+ primary: "primary",
313
+ primary_text: "primaryText",
314
+ accent: "accent",
315
+ error: "error",
316
+ error_background: "errorBackground",
317
+ success: "success",
318
+ success_background: "successBackground",
319
+ radius: "radius",
320
+ button_radius: "buttonRadius",
321
+ font_family: "fontFamily",
322
+ logo_url: "logoUrl",
323
+ fonts: "fonts",
324
+ layout: "layout",
325
+ panel_colors: "panelColors",
326
+ panel_text: "panelText",
327
+ panel_icon_url: "panelIconUrl",
328
+ texts: "texts"
329
+ };
330
+ const theme = {};
331
+ for (const [k, v] of Object.entries(wire ?? {})) if (names[k] && v !== void 0 && v !== null && v !== "") theme[names[k]] = v;
332
+ return theme;
333
+ }
334
+ async function pushTheme(o) {
335
+ const env3 = (n) => typeof process !== "undefined" ? process.env?.[n] : void 0;
336
+ const issuer = (o.issuer ?? env3("CAUTHY_ISSUER") ?? "").replace(/\/+$/, "");
337
+ const clientId = o.clientId ?? env3("CAUTHY_CLIENT_ID") ?? "";
338
+ const tenant = o.tenant ?? env3("CAUTHY_TENANT") ?? "";
339
+ const token = o.token ?? env3("CAUTHY_TOKEN") ?? "";
340
+ for (const [name, v] of Object.entries({ CAUTHY_ISSUER: issuer, CAUTHY_CLIENT_ID: clientId, CAUTHY_TENANT: tenant, CAUTHY_TOKEN: token })) {
341
+ if (v === "") throw new Error(`cauthy-auth: ${name} is required to push a theme`);
342
+ }
343
+ const res = await (o.fetch ?? fetch)(`${issuer}/v1/oauth/clients/${encodeURIComponent(clientId)}/theme`, {
344
+ method: "PUT",
345
+ headers: { authorization: `Bearer ${token}`, "x-tenant-key": tenant, "content-type": "application/json" },
346
+ body: JSON.stringify(toWire(o.theme))
347
+ });
348
+ if (!res.ok) {
349
+ const body = await res.json().catch(() => null);
350
+ throw new Error(`cauthy-auth: Cauthy refused the theme (${res.status}): ${body?.errors?.[0]?.message ?? res.statusText}`);
351
+ }
352
+ }
353
+
96
354
  // src/types.ts
97
355
  var CauthyConfigError = class extends Error {
98
356
  constructor(message) {
@@ -253,6 +511,15 @@ function createSystem(given = {}) {
253
511
  const u = await data("POST", "/v1/users", { ...person, client_id: clientId });
254
512
  return { id: u.id, email: u.email };
255
513
  },
514
+ theme: {
515
+ async get(of = clientId) {
516
+ return fromWire(await data("GET", `/v1/oauth/clients/${id(of)}/theme`));
517
+ },
518
+ async set(theme, of = clientId) {
519
+ if (theme === null) await call("DELETE", `/v1/oauth/clients/${id(of)}/theme`);
520
+ else await call("PUT", `/v1/oauth/clients/${id(of)}/theme`, toWire(theme));
521
+ }
522
+ },
256
523
  async publicJwks() {
257
524
  if (!key) return { keys: [] };
258
525
  const { kty, n, e } = asJwk(key) ?? await (0, import_jose2.exportJWK)(await signingKey());
@@ -649,226 +916,6 @@ function createCauthy(given = {}) {
649
916
  };
650
917
  }
651
918
 
652
- // src/theme.ts
653
- var MAX_RADIUS = 40;
654
- function declarations(css) {
655
- const text = css.replace(/\/\*[\s\S]*?\*\//g, "");
656
- const out2 = [];
657
- const within = [];
658
- let chunk = "";
659
- let quote = "";
660
- let depth = 0;
661
- const flush = () => {
662
- const m = /^\s*(--[\w-]+)\s*:\s*([\s\S]+?)\s*$/.exec(chunk);
663
- if (m) out2.push({ name: m[1], value: m[2].replace(/\s+/g, " ").replace(/\s*!important$/, ""), within: [...within] });
664
- chunk = "";
665
- };
666
- for (const ch of text) {
667
- if (quote) {
668
- chunk += ch;
669
- if (ch === quote) quote = "";
670
- continue;
671
- }
672
- if (ch === '"' || ch === "'") {
673
- quote = ch;
674
- chunk += ch;
675
- } else if (ch === "(") {
676
- depth++;
677
- chunk += ch;
678
- } else if (ch === ")") {
679
- depth = Math.max(0, depth - 1);
680
- chunk += ch;
681
- } else if (ch === "{" && depth === 0) {
682
- within.push(chunk.trim().replace(/\s+/g, " "));
683
- chunk = "";
684
- } else if (ch === "}" && depth === 0) {
685
- flush();
686
- within.pop();
687
- } else if (ch === ";" && depth === 0) {
688
- flush();
689
- } else {
690
- chunk += ch;
691
- }
692
- }
693
- return out2;
694
- }
695
- var DARK = /prefers-color-scheme:\s*dark|data-(mode|theme|color-scheme)=["']?dark|\.dark\b/i;
696
- var LIGHT = /prefers-color-scheme:\s*light|data-(mode|theme|color-scheme)=["']?light|\.light\b/i;
697
- var NAMED = /data-theme=["']?([\w-]+)/i;
698
- function applies(d, o) {
699
- for (const scope of d.within) {
700
- if (o.mode === "light" && DARK.test(scope)) return false;
701
- if (o.mode === "dark" && LIGHT.test(scope)) return false;
702
- const named = NAMED.exec(scope);
703
- if (named && !/^(dark|light)$/i.test(named[1]) && named[1] !== o.theme) return false;
704
- if (!scope.startsWith("@") && !/:root|^html\b|^body\b|\[data-|^\*$|:host/.test(scope)) return false;
705
- }
706
- return true;
707
- }
708
- function resolve(value, vars, seen = 0) {
709
- if (seen > 16) return null;
710
- let unresolved = false;
711
- let out2 = value;
712
- for (let guard = 0; guard < 32 && /var\(/.test(out2); guard++) {
713
- out2 = out2.replace(/var\(\s*(--[\w-]+)\s*(?:,\s*([^()]*(?:\([^()]*\)[^()]*)*))?\)/, (_m, name, fallback) => {
714
- const known = vars.get(name);
715
- const next = known !== void 0 ? resolve(known, vars, seen + 1) : fallback !== void 0 ? resolve(fallback.trim(), vars, seen + 1) : null;
716
- if (next === null) unresolved = true;
717
- return next ?? "";
718
- });
719
- if (unresolved) return null;
720
- }
721
- return /var\(/.test(out2) ? null : out2.trim();
722
- }
723
- var clamp01 = (n) => Math.min(1, Math.max(0, n));
724
- var hex2 = (n) => Math.round(clamp01(n) * 255).toString(16).padStart(2, "0");
725
- var gamma = (c) => c <= 31308e-7 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
726
- function out(r, g, b, a = 1) {
727
- if (a >= 1) return `#${hex2(r)}${hex2(g)}${hex2(b)}`;
728
- return `rgba(${Math.round(clamp01(r) * 255)}, ${Math.round(clamp01(g) * 255)}, ${Math.round(clamp01(b) * 255)}, ${Math.round(clamp01(a) * 1e3) / 1e3})`;
729
- }
730
- var alpha = (s) => s === void 0 ? 1 : s.endsWith("%") ? parseFloat(s) / 100 : parseFloat(s);
731
- var KEYWORDS = { white: "#ffffff", black: "#000000" };
732
- function toColor(value) {
733
- const v = value.trim().toLowerCase();
734
- if (KEYWORDS[v]) return KEYWORDS[v];
735
- if (/^#([0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/.test(v)) return v;
736
- let m = /^rgba?\(\s*([\d.]+%?)[\s,]+([\d.]+%?)[\s,]+([\d.]+%?)(?:\s*[,/]\s*([\d.]+%?))?\s*\)$/.exec(v);
737
- if (m) {
738
- const ch = (s) => s.endsWith("%") ? parseFloat(s) / 100 : parseFloat(s) / 255;
739
- return out(ch(m[1]), ch(m[2]), ch(m[3]), alpha(m[4]));
740
- }
741
- m = /^hsla?\(\s*([\d.]+)(?:deg)?[\s,]+([\d.]+)%[\s,]+([\d.]+)%(?:\s*[,/]\s*([\d.]+%?))?\s*\)$/.exec(v);
742
- if (m) {
743
- const h = (parseFloat(m[1]) % 360 + 360) % 360;
744
- const s = parseFloat(m[2]) / 100;
745
- const l = parseFloat(m[3]) / 100;
746
- const f = (n) => {
747
- const k = (n + h / 30) % 12;
748
- return l - s * Math.min(l, 1 - l) * Math.max(-1, Math.min(k - 3, 9 - k, 1));
749
- };
750
- return out(f(0), f(8), f(4), alpha(m[4]));
751
- }
752
- m = /^oklch\(\s*([\d.]+%?)\s+([\d.]+%?)\s+([\d.]+)(?:deg)?(?:\s*\/\s*([\d.]+%?))?\s*\)$/.exec(v);
753
- if (m) {
754
- const L = m[1].endsWith("%") ? parseFloat(m[1]) / 100 : parseFloat(m[1]);
755
- const C = m[2].endsWith("%") ? parseFloat(m[2]) / 100 * 0.4 : parseFloat(m[2]);
756
- const H = parseFloat(m[3]) * Math.PI / 180;
757
- const a = C * Math.cos(H);
758
- const b = C * Math.sin(H);
759
- const l = Math.pow(L + 0.3963377774 * a + 0.2158037573 * b, 3);
760
- const mm = Math.pow(L - 0.1055613458 * a - 0.0638541728 * b, 3);
761
- const s = Math.pow(L - 0.0894841775 * a - 1.291485548 * b, 3);
762
- return out(
763
- gamma(4.0767416621 * l - 3.3077115913 * mm + 0.2309699292 * s),
764
- gamma(-1.2684380046 * l + 2.6097574011 * mm - 0.3413193965 * s),
765
- gamma(-0.0041960863 * l - 0.7034186147 * mm + 1.707614701 * s),
766
- alpha(m[4])
767
- );
768
- }
769
- return null;
770
- }
771
- function toRadius(value) {
772
- const m = /^([\d.]+)(px|rem|em)?$/.exec(value.trim());
773
- if (!m) return null;
774
- const px = parseFloat(m[1]) * (m[2] === "rem" || m[2] === "em" ? 16 : 1);
775
- return Number.isFinite(px) ? Math.min(MAX_RADIUS, Math.max(0, Math.round(px))) : null;
776
- }
777
- function toFont(value) {
778
- const v = value.trim();
779
- return /^[A-Za-z0-9 ,'"_-]{1,200}$/.test(v) && (v.match(/"/g)?.length ?? 0) % 2 === 0 && (v.match(/'/g)?.length ?? 0) % 2 === 0 ? v : null;
780
- }
781
- var COLORS = [
782
- ["background", ["--sm-bg-surface", "--sm-surface"]],
783
- ["surface", ["--sm-bg-surface-raised", "--sm-surface-raised"]],
784
- ["text", ["--sm-text-primary", "--sm-surface-text"]],
785
- ["textMuted", ["--sm-text-secondary"]],
786
- ["border", ["--sm-border-default", "--sm-surface-border"]],
787
- ["primary", ["--sm-primary", "--sm-bg-interactive"]],
788
- ["primaryText", ["--sm-primary-text", "--sm-text-inverse"]],
789
- ["accent", ["--sm-text-brand", "--sm-border-focus", "--sm-accent"]],
790
- ["error", ["--sm-error-soft-text", "--sm-error"]],
791
- ["errorBackground", ["--sm-error-soft"]],
792
- ["success", ["--sm-success-soft-text", "--sm-success"]],
793
- ["successBackground", ["--sm-success-soft"]]
794
- ];
795
- function themeFromStackmyth(css, options = {}) {
796
- const o = { mode: options.mode ?? "light", theme: options.theme };
797
- const vars = /* @__PURE__ */ new Map();
798
- for (const sheet of Array.isArray(css) ? css : [css]) {
799
- for (const d of declarations(sheet)) if (applies(d, o)) vars.set(d.name, d.value);
800
- }
801
- const theme = {};
802
- const warnings = [];
803
- const read = (tokens, to, what) => {
804
- for (const token of tokens) {
805
- const raw = vars.get(token);
806
- if (raw === void 0) continue;
807
- const value = resolve(raw, vars);
808
- const got = value === null ? null : to(value);
809
- if (got !== null) return got;
810
- warnings.push(`${token}: "${raw}" is not ${what} Cauthy can take`);
811
- }
812
- return void 0;
813
- };
814
- for (const [field, tokens] of COLORS) {
815
- const c = read(tokens, toColor, "a colour");
816
- if (c !== void 0) theme[field] = c;
817
- }
818
- const radius = read(["--sm-radius-container", "--sm-radius-md"], toRadius, "a length");
819
- if (radius !== void 0) theme.radius = radius;
820
- const button = read(["--sm-radius-interactive", "--sm-radius-sm"], toRadius, "a length");
821
- if (button !== void 0) theme.buttonRadius = button;
822
- const font = read(["--sm-font-family"], toFont, "a font list");
823
- if (font !== void 0) theme.fontFamily = font;
824
- if (options.logoUrl) theme.logoUrl = options.logoUrl;
825
- if (vars.size === 0) warnings.push("no custom properties were found: is this the stylesheet that declares the --sm-* tokens?");
826
- else if (![...vars.keys()].some((k) => k.startsWith("--sm-"))) warnings.push("no --sm-* token was found in these stylesheets");
827
- return { theme, warnings };
828
- }
829
- function toWire(theme) {
830
- const names = {
831
- background: "background",
832
- surface: "surface",
833
- text: "text",
834
- textMuted: "text_muted",
835
- border: "border",
836
- primary: "primary",
837
- primaryText: "primary_text",
838
- accent: "accent",
839
- error: "error",
840
- errorBackground: "error_background",
841
- success: "success",
842
- successBackground: "success_background",
843
- radius: "radius",
844
- buttonRadius: "button_radius",
845
- fontFamily: "font_family",
846
- logoUrl: "logo_url"
847
- };
848
- const wire = {};
849
- for (const [k, v] of Object.entries(theme)) if (v !== void 0 && v !== "") wire[names[k]] = v;
850
- return wire;
851
- }
852
- async function pushTheme(o) {
853
- const env3 = (n) => typeof process !== "undefined" ? process.env?.[n] : void 0;
854
- const issuer = (o.issuer ?? env3("CAUTHY_ISSUER") ?? "").replace(/\/+$/, "");
855
- const clientId = o.clientId ?? env3("CAUTHY_CLIENT_ID") ?? "";
856
- const tenant = o.tenant ?? env3("CAUTHY_TENANT") ?? "";
857
- const token = o.token ?? env3("CAUTHY_TOKEN") ?? "";
858
- for (const [name, v] of Object.entries({ CAUTHY_ISSUER: issuer, CAUTHY_CLIENT_ID: clientId, CAUTHY_TENANT: tenant, CAUTHY_TOKEN: token })) {
859
- if (v === "") throw new Error(`cauthy-auth: ${name} is required to push a theme`);
860
- }
861
- const res = await (o.fetch ?? fetch)(`${issuer}/v1/oauth/clients/${encodeURIComponent(clientId)}/theme`, {
862
- method: "PUT",
863
- headers: { authorization: `Bearer ${token}`, "x-tenant-key": tenant, "content-type": "application/json" },
864
- body: JSON.stringify(toWire(o.theme))
865
- });
866
- if (!res.ok) {
867
- const body = await res.json().catch(() => null);
868
- throw new Error(`cauthy-auth: Cauthy refused the theme (${res.status}): ${body?.errors?.[0]?.message ?? res.statusText}`);
869
- }
870
- }
871
-
872
919
  // src/permissions.ts
873
920
  function matches(entry, resource, action) {
874
921
  const i = entry.lastIndexOf(":");