@zeyolabs/kit 0.0.0-stage → 2026.11.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/README.md +37 -2
  2. package/cloudflare/access.ts +134 -0
  3. package/cloudflare/amqp/client.ts +276 -0
  4. package/cloudflare/amqp/testing.ts +9 -0
  5. package/cloudflare/context.ts +66 -0
  6. package/cloudflare/dispatch/client.ts +30 -0
  7. package/cloudflare/email/client.ts +77 -0
  8. package/cloudflare/email/dev.ts +10 -0
  9. package/cloudflare/email/testing.ts +13 -0
  10. package/cloudflare/r2/client.ts +154 -0
  11. package/cloudflare/r2/testing.ts +43 -0
  12. package/cloudflare/rate-limiter.ts +65 -0
  13. package/cloudflare/wait-until.ts +12 -0
  14. package/cloudflare/workers/index.ts +311 -0
  15. package/cloudflare/workers/testing.ts +94 -0
  16. package/cloudflare/workers/ticking-do.ts +104 -0
  17. package/cloudflare/workers-ai/client.ts +30 -0
  18. package/cloudflare/workers-ai/testing.ts +17 -0
  19. package/cloudflare/workers-env.ts +12 -0
  20. package/eslint-config.js +115 -0
  21. package/monitoring/alerts/client.ts +48 -0
  22. package/monitoring/alerts/event-config.ts +33 -0
  23. package/monitoring/alerts/policy.ts +39 -0
  24. package/monitoring/alerts/registry.ts +44 -0
  25. package/monitoring/gates/client.ts +90 -0
  26. package/monitoring/gates/dev.ts +29 -0
  27. package/monitoring/gates/testing.ts +30 -0
  28. package/monitoring/logger/client.ts +66 -0
  29. package/monitoring/prometheus/client.ts +147 -0
  30. package/monitoring/prometheus/dev.ts +23 -0
  31. package/monitoring/prometheus/gen/remote_write_pb.ts +105 -0
  32. package/monitoring/prometheus/metrics.ts +180 -0
  33. package/monitoring/prometheus/testing.ts +19 -0
  34. package/monitoring/slack/api.ts +68 -0
  35. package/monitoring/slack/client.ts +33 -0
  36. package/monitoring/slack/events.ts +15 -0
  37. package/package.json +150 -5
  38. package/server/logger.ts +63 -0
  39. package/server/rate-limit-client.ts +88 -0
  40. package/server/rate-limit.ts +24 -0
  41. package/server/remote-functions.ts +139 -0
  42. package/server/result.ts +18 -0
  43. package/server/turnstile.ts +19 -0
  44. package/storage/clickhouse/client.ts +441 -0
  45. package/storage/clickhouse/compiler.ts +218 -0
  46. package/storage/clickhouse/config.ts +13 -0
  47. package/storage/clickhouse/dev.ts +18 -0
  48. package/storage/clickhouse/error.ts +61 -0
  49. package/storage/clickhouse/index.ts +4 -0
  50. package/storage/clickhouse/native-decoder.ts +192 -0
  51. package/storage/clickhouse/readers.ts +167 -0
  52. package/storage/clickhouse/retry.ts +30 -0
  53. package/storage/clickhouse/schema.ts +163 -0
  54. package/storage/clickhouse/testing.ts +81 -0
  55. package/storage/manticore/client.ts +165 -0
  56. package/storage/manticore/schema.ts +23 -0
  57. package/storage/postgres/client.ts +44 -0
  58. package/storage/postgres/testing.ts +275 -0
  59. package/storage/redis/client.ts +219 -0
  60. package/storage/redis/protocol.ts +119 -0
  61. package/storage/redis/schema.ts +17 -0
  62. package/storage/redis/testing.ts +122 -0
  63. package/utils/crypto.ts +36 -0
  64. package/utils/datetime.ts +338 -0
  65. package/utils/email.ts +173 -0
  66. package/utils/env.ts +171 -0
  67. package/utils/errors.ts +67 -0
  68. package/utils/form.ts +135 -0
  69. package/utils/http-status.ts +42 -0
  70. package/utils/money.ts +10 -0
  71. package/utils/public-host.ts +66 -0
  72. package/utils/schema.ts +211 -0
  73. package/utils/strings/format.ts +51 -0
  74. package/utils/strings/normalize.ts +129 -0
  75. package/utils/transport.ts +25 -0
@@ -0,0 +1,129 @@
1
+ import { parse } from 'tldts';
2
+
3
+ const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
4
+
5
+ export function isEmail(value: string): boolean {
6
+ return EMAIL_RE.test(value);
7
+ }
8
+
9
+ /** Cleans a raw value down to its minimal storage form — a plain object of functions (a
10
+ * Library, same pattern as `Crypto`/`Schema`), not a service: pure string transforms, no I/O. */
11
+ export const Normalize = {
12
+ email(value: string): string {
13
+ return value.trim().toLowerCase();
14
+ },
15
+
16
+ /**
17
+ * The registrable (root) domain for a URL or bare hostname via the Public Suffix List, or `''`
18
+ * when none can be parsed. e.g. `https://www.skma.co.uk/x` → `skma.co.uk`.
19
+ */
20
+ domain(raw: string): string {
21
+ const value = raw.trim().toLowerCase();
22
+ if (!value) return '';
23
+ const url = /^[a-z][a-z0-9+.-]*:\/\//.test(value) ? value : `https://${value}`;
24
+ return parse(url).domain ?? '';
25
+ },
26
+
27
+ /**
28
+ * A URL cleaned to its minimal storage form: no protocol (`https` is always assumed at
29
+ * display/export — see `fullUrl` in `lists/columns.ts`), `www` dropped, any other subdomain
30
+ * kept, no trailing slash-only path. `''` when nothing parseable.
31
+ * e.g. `https://www.domain.com/` → `domain.com`; `http://blog.domain.com` → `blog.domain.com`;
32
+ * `domain.com/pricing` → `domain.com/pricing`.
33
+ */
34
+ url(raw: string): string {
35
+ const value = raw.trim();
36
+ if (!value) return '';
37
+ const withProtocol = /^[a-z][a-z0-9+.-]*:\/\//i.test(value) ? value : `https://${value}`;
38
+ let url: URL;
39
+ try {
40
+ url = new URL(withProtocol);
41
+ } catch {
42
+ return '';
43
+ }
44
+ const parsed = parse(url.hostname.toLowerCase());
45
+ if (!parsed.domain) return '';
46
+ const subdomain = parsed.subdomain && parsed.subdomain !== 'www' ? `${parsed.subdomain}.` : '';
47
+ const path = url.pathname === '/' ? '' : url.pathname.replace(/\/+$/, '');
48
+ return `${subdomain}${parsed.domain}${path}${url.search}${url.hash}`;
49
+ },
50
+
51
+ /**
52
+ * An X/Twitter profile reduced to its bare handle: no `@`, no host, no protocol — storage is
53
+ * always the minimal form, `xFullUrl` (`lists/columns.ts`) rebuilds the clickable profile URL at
54
+ * display/export time. Accepts a full URL (`x.com` or the legacy `twitter.com` host), a bare
55
+ * `@handle`, or an already-bare handle. `''` when nothing usable is left.
56
+ * e.g. `https://x.com/elonmusk` → `elonmusk`; `twitter.com/elonmusk` → `elonmusk`;
57
+ * `@elonmusk` → `elonmusk`.
58
+ */
59
+ xHandle(raw: string): string {
60
+ const trimmed = raw.trim().replace(/^\/+|\/+$/g, '');
61
+ if (!trimmed) return '';
62
+ if (!/(?:^|[./])(x|twitter)\.com/i.test(trimmed)) return trimmed.replace(/^@/, ''); // already bare
63
+ const withProtocol = /^https?:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`;
64
+ try {
65
+ return new URL(withProtocol).pathname.replace(/^\/+|\/+$/g, '');
66
+ } catch {
67
+ return trimmed.replace(/^@/, '');
68
+ }
69
+ },
70
+ };
71
+
72
+ /** Deterministic slug: lowercase, non-alphanumeric runs collapsed to a single `-`, no leading or
73
+ * trailing dash. e.g. "Q3 Growth — Final!" → "q3-growth-final". */
74
+ export function slugify(value: string): string {
75
+ return value
76
+ .trim()
77
+ .toLowerCase()
78
+ .replace(/[^a-z0-9]+/g, '-')
79
+ .replace(/^-+|-+$/g, '');
80
+ }
81
+
82
+ /** Title-cases each word ("SHELDON" / "mark" → "Sheldon" / "Mark") — for a person's name, not
83
+ * free text (would mangle brand names/acronyms). */
84
+ export function titleCase(str: string): string {
85
+ return str.replace(
86
+ /\w\S*/g,
87
+ (txt) => txt.charAt(0).toUpperCase() + txt.substring(1).toLowerCase()
88
+ );
89
+ }
90
+
91
+ /** e.g. "John Doe" → "JD". Falls back to "?" for a blank/whitespace-only name. */
92
+ export function initials(name: string, max = 2): string {
93
+ return (
94
+ name
95
+ .split(' ')
96
+ .filter(Boolean)
97
+ .slice(0, max)
98
+ .map((w) => w[0]?.toUpperCase())
99
+ .join('') || '?'
100
+ );
101
+ }
102
+
103
+ /** Subsequence match — every character of `needle` appears in `haystack`, in order. */
104
+ export function fuzzySearch(needle: string, haystack: string): boolean {
105
+ const hlen = haystack.length;
106
+ const nlen = needle.length;
107
+
108
+ if (nlen > hlen) {
109
+ return false;
110
+ }
111
+ if (nlen === hlen) {
112
+ return needle.toLowerCase() === haystack.toLowerCase();
113
+ }
114
+
115
+ const lowerNeedle = needle.toLowerCase();
116
+ const lowerHaystack = haystack.toLowerCase();
117
+
118
+ outer: for (let i = 0, j = 0; i < nlen; i++) {
119
+ const nch = lowerNeedle.charCodeAt(i);
120
+ while (j < hlen) {
121
+ if (lowerHaystack.charCodeAt(j++) === nch) {
122
+ continue outer;
123
+ }
124
+ }
125
+ return false;
126
+ }
127
+
128
+ return true;
129
+ }
@@ -0,0 +1,25 @@
1
+ import type { Transport } from '@sveltejs/kit/hooks';
2
+
3
+ import { CalendarDate, fromDate, Time, ZonedDateTime } from '@internationalized/date';
4
+
5
+ // Shared SvelteKit universal-hooks transport: encode/decode the `@internationalized/date` types
6
+ // so they survive serialization across the load / remote-function boundary. Re-exported from each
7
+ // app's `hooks.ts`.
8
+ export const transport: Transport = {
9
+ CalendarDate: {
10
+ decode: ([year, month, day]: [number, number, number]) => new CalendarDate(year, month, day),
11
+ encode: (d) => d instanceof CalendarDate && [d.year, d.month, d.day],
12
+ },
13
+ Time: {
14
+ decode: ([hour, minute, second, millisecond]: [number, number, number, number]) =>
15
+ new Time(hour, minute, second, millisecond),
16
+ encode: (t) => t instanceof Time && [t.hour, t.minute, t.second, t.millisecond],
17
+ },
18
+ ZonedDateTime: {
19
+ decode: ([absoluteString, timezone]: [string, string]) => {
20
+ const nativeDate = new Date(absoluteString);
21
+ return fromDate(nativeDate, timezone);
22
+ },
23
+ encode: (value) => value instanceof ZonedDateTime && [value.toAbsoluteString(), value.timeZone],
24
+ },
25
+ };