@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.
- package/README.md +37 -2
- package/cloudflare/access.ts +134 -0
- package/cloudflare/amqp/client.ts +276 -0
- package/cloudflare/amqp/testing.ts +9 -0
- package/cloudflare/context.ts +66 -0
- package/cloudflare/dispatch/client.ts +30 -0
- package/cloudflare/email/client.ts +77 -0
- package/cloudflare/email/dev.ts +10 -0
- package/cloudflare/email/testing.ts +13 -0
- package/cloudflare/r2/client.ts +154 -0
- package/cloudflare/r2/testing.ts +43 -0
- package/cloudflare/rate-limiter.ts +65 -0
- package/cloudflare/wait-until.ts +12 -0
- package/cloudflare/workers/index.ts +311 -0
- package/cloudflare/workers/testing.ts +94 -0
- package/cloudflare/workers/ticking-do.ts +104 -0
- package/cloudflare/workers-ai/client.ts +30 -0
- package/cloudflare/workers-ai/testing.ts +17 -0
- package/cloudflare/workers-env.ts +12 -0
- package/eslint-config.js +115 -0
- package/monitoring/alerts/client.ts +48 -0
- package/monitoring/alerts/event-config.ts +33 -0
- package/monitoring/alerts/policy.ts +39 -0
- package/monitoring/alerts/registry.ts +44 -0
- package/monitoring/gates/client.ts +90 -0
- package/monitoring/gates/dev.ts +29 -0
- package/monitoring/gates/testing.ts +30 -0
- package/monitoring/logger/client.ts +66 -0
- package/monitoring/prometheus/client.ts +147 -0
- package/monitoring/prometheus/dev.ts +23 -0
- package/monitoring/prometheus/gen/remote_write_pb.ts +105 -0
- package/monitoring/prometheus/metrics.ts +180 -0
- package/monitoring/prometheus/testing.ts +19 -0
- package/monitoring/slack/api.ts +68 -0
- package/monitoring/slack/client.ts +33 -0
- package/monitoring/slack/events.ts +15 -0
- package/package.json +150 -5
- package/server/logger.ts +63 -0
- package/server/rate-limit-client.ts +88 -0
- package/server/rate-limit.ts +24 -0
- package/server/remote-functions.ts +139 -0
- package/server/result.ts +18 -0
- package/server/turnstile.ts +19 -0
- package/storage/clickhouse/client.ts +441 -0
- package/storage/clickhouse/compiler.ts +218 -0
- package/storage/clickhouse/config.ts +13 -0
- package/storage/clickhouse/dev.ts +18 -0
- package/storage/clickhouse/error.ts +61 -0
- package/storage/clickhouse/index.ts +4 -0
- package/storage/clickhouse/native-decoder.ts +192 -0
- package/storage/clickhouse/readers.ts +167 -0
- package/storage/clickhouse/retry.ts +30 -0
- package/storage/clickhouse/schema.ts +163 -0
- package/storage/clickhouse/testing.ts +81 -0
- package/storage/manticore/client.ts +165 -0
- package/storage/manticore/schema.ts +23 -0
- package/storage/postgres/client.ts +44 -0
- package/storage/postgres/testing.ts +275 -0
- package/storage/redis/client.ts +219 -0
- package/storage/redis/protocol.ts +119 -0
- package/storage/redis/schema.ts +17 -0
- package/storage/redis/testing.ts +122 -0
- package/utils/crypto.ts +36 -0
- package/utils/datetime.ts +338 -0
- package/utils/email.ts +173 -0
- package/utils/env.ts +171 -0
- package/utils/errors.ts +67 -0
- package/utils/form.ts +135 -0
- package/utils/http-status.ts +42 -0
- package/utils/money.ts +10 -0
- package/utils/public-host.ts +66 -0
- package/utils/schema.ts +211 -0
- package/utils/strings/format.ts +51 -0
- package/utils/strings/normalize.ts +129 -0
- 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
|
+
};
|