@onreza/runtime 0.2.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,153 @@
1
+ # @onreza/runtime
2
+
3
+ Runtime SDK for ONREZA platform APIs with TypeScript support.
4
+
5
+ ## Установка
6
+
7
+ ```bash
8
+ bun add @onreza/runtime
9
+ ```
10
+
11
+ ## Модули
12
+
13
+ ### `@onreza/runtime/kv`
14
+
15
+ KV store (namespace-isolated):
16
+
17
+ ```typescript
18
+ import { kv, isKVAvailable } from '@onreza/runtime/kv';
19
+
20
+ // Check availability (optional)
21
+ if (isKVAvailable()) {
22
+ // Set with TTL
23
+ await kv.set('session:123', { userId: '456' }, { ttl: 3600 });
24
+
25
+ // Get as JSON
26
+ const user = await kv.get('user:123', { type: 'json' });
27
+
28
+ // Check existence
29
+ const exists = await kv.has('user:123');
30
+
31
+ // Delete
32
+ await kv.delete('session:123');
33
+
34
+ // List keys with prefix
35
+ const { keys, cursor } = await kv.list({ prefix: 'user:', limit: 50 });
36
+ }
37
+ ```
38
+
39
+ ### `@onreza/runtime/db`
40
+
41
+ D1-compatible database:
42
+
43
+ ```typescript
44
+ import { db, isDBAvailable } from '@onreza/runtime/db';
45
+
46
+ if (isDBAvailable()) {
47
+ // Prepare and execute query
48
+ const stmt = db.prepare('SELECT * FROM users WHERE id = ?');
49
+ const { results } = await stmt.bind(1).all();
50
+
51
+ // Get first row
52
+ const user = await db.prepare('SELECT * FROM users WHERE id = ?').bind(1).first();
53
+
54
+ // Insert
55
+ await db.prepare('INSERT INTO users (name) VALUES (?)').bind('Alice').run();
56
+
57
+ // Batch operations
58
+ const stmt1 = db.prepare('UPDATE users SET name = ? WHERE id = ?').bind('Bob', 1);
59
+ const stmt2 = db.prepare('UPDATE users SET name = ? WHERE id = ?').bind('Charlie', 2);
60
+ await db.batch([stmt1, stmt2]);
61
+ }
62
+ ```
63
+
64
+ ### `@onreza/runtime/context`
65
+
66
+ Request context and geolocation:
67
+
68
+ ```typescript
69
+ import { getContext, isContextAvailable, getClientIp, getGeo, getRequestId } from '@onreza/runtime/context';
70
+
71
+ if (isContextAvailable()) {
72
+ // Get full context
73
+ const ctx = getContext();
74
+ console.log(ctx.geo?.city); // 'Moscow'
75
+ console.log(ctx.geo?.country); // 'RU'
76
+ console.log(ctx.clientIp); // '1.2.3.4'
77
+ console.log(ctx.requestId); // UUID v7
78
+
79
+ // Or use shortcuts
80
+ const ip = getClientIp();
81
+ const geo = getGeo();
82
+ const requestId = getRequestId();
83
+ }
84
+ ```
85
+
86
+ ### `@onreza/runtime/env`
87
+
88
+ Environment variables:
89
+
90
+ ```typescript
91
+ import { env, isEnvAvailable, getEnv } from '@onreza/runtime/env';
92
+
93
+ if (isEnvAvailable()) {
94
+ // Get required variable (throws if missing)
95
+ const apiKey = env.get('API_KEY');
96
+
97
+ // Get with default
98
+ const timeout = getEnv('TIMEOUT', '5000');
99
+
100
+ // Check existence
101
+ if (env.has('DEBUG')) {
102
+ console.log('Debug mode enabled');
103
+ }
104
+
105
+ // Iterate all variables
106
+ for (const [key, value] of env.entries()) {
107
+ console.log(`${key}=${value}`);
108
+ }
109
+ }
110
+ ```
111
+
112
+ ### `@onreza/runtime/image`
113
+
114
+ Image optimization URL builder:
115
+
116
+ ```typescript
117
+ import { imageUrl, generateSrcset, DEFAULT_SIZES } from '@onreza/runtime/image';
118
+
119
+ // Basic usage
120
+ const url = imageUrl('/images/hero.jpg', { width: 1080 });
121
+ // → '/_onreza/image?url=%2Fimages%2Fhero.jpg&w=1080&q=75'
122
+
123
+ // With all options
124
+ const optimized = imageUrl('/images/photo.jpg', {
125
+ width: 640,
126
+ height: 480,
127
+ quality: 80,
128
+ format: 'webp',
129
+ fit: 'cover',
130
+ blur: 10,
131
+ dpr: 2
132
+ });
133
+
134
+ // Generate srcset for responsive images
135
+ const srcset = generateSrcset('/images/photo.jpg', [640, 1080, 1920], { quality: 80 });
136
+ // → '/_onreza/image?url=...&w=640&q=80 640w, /_onreza/image?url=...&w=1080&q=80 1080w, ...'
137
+ ```
138
+
139
+ ### `@onreza/runtime/types`
140
+
141
+ All types combined:
142
+
143
+ ```typescript
144
+ /// <reference types="@onreza/runtime/types" />
145
+
146
+ // Or import specific types
147
+ import type { KVStore, D1Database, OnrezaContext } from '@onreza/runtime/types';
148
+ ```
149
+
150
+ ## Требования
151
+
152
+ - TypeScript 5.0+
153
+ - ONREZA runtime environment (edge runtime)
@@ -0,0 +1,45 @@
1
+ /**
2
+ * ONREZA Request Context SDK
3
+ *
4
+ * Utilities for accessing request context and geolocation
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * import { getContext, isContextAvailable } from '@onreza/runtime/context';
9
+ *
10
+ * if (isContextAvailable()) {
11
+ * const ctx = getContext();
12
+ * console.log(ctx.geo?.city);
13
+ * console.log(ctx.requestId);
14
+ * }
15
+ * ```
16
+ */
17
+ import type { OnrezaContext, OnrezaGeo } from "../types.d.ts";
18
+ /**
19
+ * Check if request context is available
20
+ *
21
+ * @returns true if ONREZA.context is available
22
+ */
23
+ export declare function isContextAvailable(): boolean;
24
+ /**
25
+ * Get the ONREZA request context
26
+ * @throws Error if not running in ONREZA runtime
27
+ */
28
+ export declare function getContext(): OnrezaContext;
29
+ /**
30
+ * Get client IP from context
31
+ * @returns Client IP or null if not available
32
+ */
33
+ export declare function getClientIp(): string | null;
34
+ /**
35
+ * Get GeoIP data from context
36
+ * @returns Geo data or null if not available
37
+ */
38
+ export declare function getGeo(): OnrezaGeo | null;
39
+ /**
40
+ * Get request ID from context
41
+ * @returns Request ID or null if not available
42
+ */
43
+ export declare function getRequestId(): string | null;
44
+ export type { OnrezaContext, OnrezaGeo } from "../types.d.ts";
45
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAS9D;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAE5C;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,aAAa,CAM1C;AAED;;;GAGG;AACH,wBAAgB,WAAW,IAAI,MAAM,GAAG,IAAI,CAG3C;AAED;;;GAGG;AACH,wBAAgB,MAAM,IAAI,SAAS,GAAG,IAAI,CAGzC;AAED;;;GAGG;AACH,wBAAgB,YAAY,IAAI,MAAM,GAAG,IAAI,CAG5C;AAGD,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * ONREZA Request Context SDK
3
+ *
4
+ * Utilities for accessing request context and geolocation
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * import { getContext, isContextAvailable } from '@onreza/runtime/context';
9
+ *
10
+ * if (isContextAvailable()) {
11
+ * const ctx = getContext();
12
+ * console.log(ctx.geo?.city);
13
+ * console.log(ctx.requestId);
14
+ * }
15
+ * ```
16
+ */
17
+ /**
18
+ * Check if running in ONREZA runtime environment
19
+ */
20
+ function isOnrezaRuntime() {
21
+ return typeof globalThis.ONREZA !== "undefined";
22
+ }
23
+ /**
24
+ * Check if request context is available
25
+ *
26
+ * @returns true if ONREZA.context is available
27
+ */
28
+ export function isContextAvailable() {
29
+ return isOnrezaRuntime() && !!globalThis.ONREZA?.context;
30
+ }
31
+ /**
32
+ * Get the ONREZA request context
33
+ * @throws Error if not running in ONREZA runtime
34
+ */
35
+ export function getContext() {
36
+ const onreza = globalThis.ONREZA;
37
+ if (!onreza?.context) {
38
+ throw new Error("ONREZA context is not available. " + "Make sure you are running in ONREZA runtime.");
39
+ }
40
+ return onreza.context;
41
+ }
42
+ /**
43
+ * Get client IP from context
44
+ * @returns Client IP or null if not available
45
+ */
46
+ export function getClientIp() {
47
+ if (!isContextAvailable())
48
+ return null;
49
+ return getContext().clientIp;
50
+ }
51
+ /**
52
+ * Get GeoIP data from context
53
+ * @returns Geo data or null if not available
54
+ */
55
+ export function getGeo() {
56
+ if (!isContextAvailable())
57
+ return null;
58
+ return getContext().geo;
59
+ }
60
+ /**
61
+ * Get request ID from context
62
+ * @returns Request ID or null if not available
63
+ */
64
+ export function getRequestId() {
65
+ if (!isContextAvailable())
66
+ return null;
67
+ return getContext().requestId;
68
+ }
69
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH;;GAEG;AACH,SAAS,eAAe;IACtB,OAAO,OAAQ,UAAmC,CAAC,MAAM,KAAK,WAAW,CAAC;AAC5E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB;IAChC,OAAO,eAAe,EAAE,IAAI,CAAC,CAAE,UAAiD,CAAC,MAAM,EAAE,OAAO,CAAC;AACnG,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU;IACxB,MAAM,MAAM,GAAI,UAAuD,CAAC,MAAM,CAAC;IAC/E,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,mCAAmC,GAAG,8CAA8C,CAAC,CAAC;IACxG,CAAC;IACD,OAAO,MAAM,CAAC,OAAO,CAAC;AACxB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW;IACzB,IAAI,CAAC,kBAAkB,EAAE;QAAE,OAAO,IAAI,CAAC;IACvC,OAAO,UAAU,EAAE,CAAC,QAAQ,CAAC;AAC/B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,MAAM;IACpB,IAAI,CAAC,kBAAkB,EAAE;QAAE,OAAO,IAAI,CAAC;IACvC,OAAO,UAAU,EAAE,CAAC,GAAG,CAAC;AAC1B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY;IAC1B,IAAI,CAAC,kBAAkB,EAAE;QAAE,OAAO,IAAI,CAAC;IACvC,OAAO,UAAU,EAAE,CAAC,SAAS,CAAC;AAChC,CAAC"}
package/dist/db.d.ts ADDED
@@ -0,0 +1,39 @@
1
+ /**
2
+ * ONREZA D1 Database SDK
3
+ *
4
+ * Types and wrappers for ONREZA.db platform API
5
+ * Compatible with Cloudflare D1
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { db, isDBAvailable } from '@onreza/runtime/db';
10
+ *
11
+ * if (isDBAvailable()) {
12
+ * // Prepare and execute query
13
+ * const stmt = db.prepare('SELECT * FROM users WHERE id = ?');
14
+ * const { results } = await stmt.bind(1).all();
15
+ *
16
+ * // Get first row
17
+ * const user = await db.prepare('SELECT * FROM users WHERE id = ?').bind(1).first();
18
+ *
19
+ * // Insert
20
+ * await db.prepare('INSERT INTO users (name) VALUES (?)').bind('Alice').run();
21
+ * }
22
+ * ```
23
+ */
24
+ import type { D1Database } from "../types.d.ts";
25
+ /**
26
+ * D1 Database operations
27
+ *
28
+ * Note: In ONREZA runtime, this uses the platform-injected ONREZA.db.
29
+ * Outside runtime, operations throw an error.
30
+ */
31
+ export declare const db: Pick<D1Database, "batch" | "exec" | "prepare">;
32
+ /**
33
+ * Check if D1 database is available in the current environment
34
+ *
35
+ * @returns true if ONREZA.db is available
36
+ */
37
+ export declare function isDBAvailable(): boolean;
38
+ export type { D1Database, D1PreparedStatement, D1Result } from "../types.d.ts";
39
+ //# sourceMappingURL=db.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAiC,MAAM,eAAe,CAAC;AAwB/E;;;;;GAKG;AACH,eAAO,MAAM,EAAE,EAyBV,IAAI,CAAC,UAAU,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC,CAAC;AAEpD;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAGD,YAAY,EAAE,UAAU,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC"}
package/dist/db.js ADDED
@@ -0,0 +1,81 @@
1
+ /**
2
+ * ONREZA D1 Database SDK
3
+ *
4
+ * Types and wrappers for ONREZA.db platform API
5
+ * Compatible with Cloudflare D1
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { db, isDBAvailable } from '@onreza/runtime/db';
10
+ *
11
+ * if (isDBAvailable()) {
12
+ * // Prepare and execute query
13
+ * const stmt = db.prepare('SELECT * FROM users WHERE id = ?');
14
+ * const { results } = await stmt.bind(1).all();
15
+ *
16
+ * // Get first row
17
+ * const user = await db.prepare('SELECT * FROM users WHERE id = ?').bind(1).first();
18
+ *
19
+ * // Insert
20
+ * await db.prepare('INSERT INTO users (name) VALUES (?)').bind('Alice').run();
21
+ * }
22
+ * ```
23
+ */
24
+ /**
25
+ * Check if running in ONREZA runtime environment
26
+ */
27
+ function isOnrezaRuntime() {
28
+ return typeof globalThis.ONREZA !== "undefined";
29
+ }
30
+ /**
31
+ * Get the ONREZA D1 database instance
32
+ * @throws Error if not running in ONREZA runtime
33
+ */
34
+ function getDatabase() {
35
+ const onreza = globalThis.ONREZA;
36
+ if (!onreza?.db) {
37
+ throw new Error("ONREZA D1 database is not available. " +
38
+ 'Make sure you are running in ONREZA runtime and have "bindings.db: true" in your manifest.');
39
+ }
40
+ return onreza.db;
41
+ }
42
+ /**
43
+ * D1 Database operations
44
+ *
45
+ * Note: In ONREZA runtime, this uses the platform-injected ONREZA.db.
46
+ * Outside runtime, operations throw an error.
47
+ */
48
+ export const db = {
49
+ /**
50
+ * Batch execute statements atomically
51
+ */
52
+ // biome-ignore lint/suspicious/useAwait: Wrapper for D1Database API
53
+ async batch(statements) {
54
+ const database = getDatabase();
55
+ return database.batch(statements);
56
+ },
57
+ /**
58
+ * Execute multiple statements (DDL)
59
+ */
60
+ // biome-ignore lint/suspicious/useAwait: Wrapper for D1Database API
61
+ async exec(query) {
62
+ const database = getDatabase();
63
+ return database.exec(query);
64
+ },
65
+ /**
66
+ * Prepare a SQL statement
67
+ */
68
+ prepare(query) {
69
+ const database = getDatabase();
70
+ return database.prepare(query);
71
+ },
72
+ };
73
+ /**
74
+ * Check if D1 database is available in the current environment
75
+ *
76
+ * @returns true if ONREZA.db is available
77
+ */
78
+ export function isDBAvailable() {
79
+ return isOnrezaRuntime() && !!globalThis.ONREZA?.db;
80
+ }
81
+ //# sourceMappingURL=db.js.map
package/dist/db.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH;;GAEG;AACH,SAAS,eAAe;IACtB,OAAO,OAAQ,UAAmC,CAAC,MAAM,KAAK,WAAW,CAAC;AAC5E,CAAC;AAED;;;GAGG;AACH,SAAS,WAAW;IAClB,MAAM,MAAM,GAAI,UAA+C,CAAC,MAAM,CAAC;IACvE,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CACb,uCAAuC;YACrC,4FAA4F,CAC/F,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC,EAAE,CAAC;AACnB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,EAAE,GAAG;IAChB;;OAEG;IACH,oEAAoE;IACpE,KAAK,CAAC,KAAK,CAAc,UAAiC;QACxD,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;QAC/B,OAAO,QAAQ,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACpC,CAAC;IACD;;OAEG;IACH,oEAAoE;IACpE,KAAK,CAAC,IAAI,CAAC,KAAa;QACtB,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;QAC/B,OAAO,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,KAAa;QACnB,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;QAC/B,OAAO,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;CACgD,CAAC;AAEpD;;;;GAIG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO,eAAe,EAAE,IAAI,CAAC,CAAE,UAA4C,CAAC,MAAM,EAAE,EAAE,CAAC;AACzF,CAAC"}
package/dist/env.d.ts ADDED
@@ -0,0 +1,58 @@
1
+ /**
2
+ * ONREZA Environment SDK
3
+ *
4
+ * Utilities for accessing environment variables
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * import { env, isEnvAvailable, getEnv } from '@onreza/runtime/env';
9
+ *
10
+ * if (isEnvAvailable()) {
11
+ * // Get required variable (throws if missing)
12
+ * const apiKey = env.get('API_KEY');
13
+ *
14
+ * // Get with default
15
+ * const timeout = getEnv('TIMEOUT', '5000');
16
+ *
17
+ * // Check existence
18
+ * if (env.has('DEBUG')) {
19
+ * console.log('Debug mode enabled');
20
+ * }
21
+ * }
22
+ * ```
23
+ */
24
+ /**
25
+ * Environment variable operations
26
+ */
27
+ export declare const env: {
28
+ /**
29
+ * Iterate over all environment variables
30
+ */
31
+ entries(): IterableIterator<[string, string]>;
32
+ /**
33
+ * Get environment variable
34
+ * @param key - Variable name
35
+ * @returns Value or undefined if not set
36
+ */
37
+ get(key: string): string | undefined;
38
+ /**
39
+ * Check if environment variable exists
40
+ * @param key - Variable name
41
+ * @returns true if exists
42
+ */
43
+ has(key: string): boolean;
44
+ };
45
+ /**
46
+ * Check if env store is available
47
+ * @returns true if ONREZA.env is available
48
+ */
49
+ export declare function isEnvAvailable(): boolean;
50
+ /**
51
+ * Get environment variable with default value
52
+ * @param key - Variable name
53
+ * @param defaultValue - Default if not set
54
+ * @returns Value or default
55
+ */
56
+ export declare function getEnv(key: string, defaultValue: string): string;
57
+ export type { EnvStore } from "../types.d.ts";
58
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAuBH;;GAEG;AACH,eAAO,MAAM,GAAG;IACd;;OAEG;eACQ,gBAAgB,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAG7C;;;;OAIG;aACM,MAAM,GAAG,MAAM,GAAG,SAAS;IAIpC;;;;OAIG;aACM,MAAM,GAAG,OAAO;CAG1B,CAAC;AAEF;;;GAGG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAExC;AAED;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAGhE;AAGD,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC"}
package/dist/env.js ADDED
@@ -0,0 +1,86 @@
1
+ /**
2
+ * ONREZA Environment SDK
3
+ *
4
+ * Utilities for accessing environment variables
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * import { env, isEnvAvailable, getEnv } from '@onreza/runtime/env';
9
+ *
10
+ * if (isEnvAvailable()) {
11
+ * // Get required variable (throws if missing)
12
+ * const apiKey = env.get('API_KEY');
13
+ *
14
+ * // Get with default
15
+ * const timeout = getEnv('TIMEOUT', '5000');
16
+ *
17
+ * // Check existence
18
+ * if (env.has('DEBUG')) {
19
+ * console.log('Debug mode enabled');
20
+ * }
21
+ * }
22
+ * ```
23
+ */
24
+ /**
25
+ * Check if running in ONREZA runtime environment
26
+ */
27
+ function isOnrezaRuntime() {
28
+ return typeof globalThis.ONREZA !== "undefined";
29
+ }
30
+ /**
31
+ * Get the ONREZA env store instance
32
+ * @throws Error if not running in ONREZA runtime
33
+ */
34
+ function getEnvStore() {
35
+ const onreza = globalThis.ONREZA;
36
+ if (!onreza?.env) {
37
+ throw new Error("ONREZA env is not available. Make sure you are running in ONREZA runtime.");
38
+ }
39
+ return onreza.env;
40
+ }
41
+ /**
42
+ * Environment variable operations
43
+ */
44
+ export const env = {
45
+ /**
46
+ * Iterate over all environment variables
47
+ */
48
+ entries() {
49
+ return getEnvStore().entries();
50
+ },
51
+ /**
52
+ * Get environment variable
53
+ * @param key - Variable name
54
+ * @returns Value or undefined if not set
55
+ */
56
+ get(key) {
57
+ return getEnvStore().get(key);
58
+ },
59
+ /**
60
+ * Check if environment variable exists
61
+ * @param key - Variable name
62
+ * @returns true if exists
63
+ */
64
+ has(key) {
65
+ return getEnvStore().has(key);
66
+ },
67
+ };
68
+ /**
69
+ * Check if env store is available
70
+ * @returns true if ONREZA.env is available
71
+ */
72
+ export function isEnvAvailable() {
73
+ return isOnrezaRuntime() && !!globalThis.ONREZA?.env;
74
+ }
75
+ /**
76
+ * Get environment variable with default value
77
+ * @param key - Variable name
78
+ * @param defaultValue - Default if not set
79
+ * @returns Value or default
80
+ */
81
+ export function getEnv(key, defaultValue) {
82
+ if (!isEnvAvailable())
83
+ return defaultValue;
84
+ return env.get(key) ?? defaultValue;
85
+ }
86
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH;;GAEG;AACH,SAAS,eAAe;IACtB,OAAO,OAAQ,UAAmC,CAAC,MAAM,KAAK,WAAW,CAAC;AAC5E,CAAC;AAED;;;GAGG;AACH,SAAS,WAAW;IAClB,MAAM,MAAM,GAAI,UAA8C,CAAC,MAAM,CAAC;IACtE,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC,CAAC;IAC/F,CAAC;IACD,OAAO,MAAM,CAAC,GAAG,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG;IACjB;;OAEG;IACH,OAAO;QACL,OAAO,WAAW,EAAE,CAAC,OAAO,EAAE,CAAC;IACjC,CAAC;IACD;;;;OAIG;IACH,GAAG,CAAC,GAAW;QACb,OAAO,WAAW,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IAED;;;;OAIG;IACH,GAAG,CAAC,GAAW;QACb,OAAO,WAAW,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;CACF,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO,eAAe,EAAE,IAAI,CAAC,CAAE,UAA6C,CAAC,MAAM,EAAE,GAAG,CAAC;AAC3F,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,MAAM,CAAC,GAAW,EAAE,YAAoB;IACtD,IAAI,CAAC,cAAc,EAAE;QAAE,OAAO,YAAY,CAAC;IAC3C,OAAO,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC;AACtC,CAAC"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * ONREZA Image Optimization SDK
3
+ *
4
+ * URL builder for platform image optimization service
5
+ * Endpoint: /_onreza/image
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { imageUrl, generateSrcset, DEFAULT_SIZES } from '@onreza/runtime/image';
10
+ *
11
+ * // Basic usage
12
+ * const url = imageUrl('/images/hero.jpg', { width: 1080 });
13
+ * // → '/_onreza/image?url=%2Fimages%2Fhero.jpg&w=1080&q=75'
14
+ *
15
+ * // With quality and format
16
+ * const optimized = imageUrl('/images/photo.jpg', {
17
+ * width: 640,
18
+ * quality: 80,
19
+ * format: 'webp'
20
+ * });
21
+ *
22
+ * // Generate srcset for responsive images
23
+ * const srcset = generateSrcset('/images/photo.jpg', [640, 1080, 1920]);
24
+ * // → '/_onreza/image?url=...&w=640 640w, /_onreza/image?url=...&w=1080 1080w, ...'
25
+ * ```
26
+ */
27
+ /** Default platform image sizes */
28
+ export declare const DEFAULT_SIZES: readonly [640, 750, 828, 1080, 1200, 1920, 2048, 3840];
29
+ /** Supported image formats */
30
+ export type ImageFormat = "webp" | "avif";
31
+ /** Resize fit modes */
32
+ export type ImageFit = "cover" | "contain" | "fill";
33
+ /**
34
+ * Image transformation options
35
+ */
36
+ export interface ImageTransformOptions {
37
+ /** Target width in pixels (must be from allowed sizes) */
38
+ width?: number;
39
+ /** Target height in pixels (optional, maintains aspect ratio by default) */
40
+ height?: number;
41
+ /** Quality 1-100 (default: 75) */
42
+ quality?: number;
43
+ /** Output format (default: auto from Accept header) */
44
+ format?: ImageFormat;
45
+ /** Resize fit mode (default: 'cover') */
46
+ fit?: ImageFit;
47
+ /** Gaussian blur sigma 0-250 (default: 0) */
48
+ blur?: number;
49
+ /** Device Pixel Ratio 1-5 (default: 1) - multiplies width/height */
50
+ dpr?: number;
51
+ }
52
+ /**
53
+ * Build ONREZA image optimization URL
54
+ *
55
+ * @param src - Relative image path (e.g., "/images/photo.jpg")
56
+ * @param options - Transformation options
57
+ * @returns Optimized image URL
58
+ * @throws Error if src is absolute URL or contains path traversal
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * imageUrl('/images/hero.jpg', { width: 1080 })
63
+ * // → '/_onreza/image?url=%2Fimages%2Fhero.jpg&w=1080&q=75'
64
+ *
65
+ * imageUrl('/images/photo.jpg', { width: 640, quality: 80, format: 'webp', blur: 10 })
66
+ * // → '/_onreza/image?url=%2Fimages%2Fphoto.jpg&w=640&q=80&f=webp&blur=10'
67
+ * ```
68
+ */
69
+ export declare function imageUrl(src: string, options?: ImageTransformOptions): string;
70
+ /**
71
+ * Validate and normalize image options
72
+ *
73
+ * @param options - Raw options
74
+ * @returns Normalized options with valid values
75
+ */
76
+ export declare function validateImageOptions(options: ImageTransformOptions): Required<Pick<ImageTransformOptions, "quality" | "blur" | "dpr" | "fit">> & Pick<ImageTransformOptions, "width" | "height" | "format">;
77
+ /**
78
+ * Generate responsive srcset attribute
79
+ *
80
+ * @param src - Relative image path
81
+ * @param widths - Array of desired widths (will be normalized to allowed sizes)
82
+ * @param options - Base options (applied to all sizes)
83
+ * @returns srcset string for img srcset attribute
84
+ *
85
+ * @example
86
+ * ```typescript
87
+ * generateSrcset('/images/photo.jpg', [640, 1080, 1920], { quality: 80 })
88
+ * // → '/_onreza/image?url=...&w=640&q=80 640w, /_onreza/image?url=...&w=1080&q=80 1080w, ...'
89
+ * ```
90
+ */
91
+ export declare function generateSrcset(src: string, widths: number[], options?: Omit<ImageTransformOptions, "width">): string;
92
+ //# sourceMappingURL=image.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../src/image.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,mCAAmC;AACnC,eAAO,MAAM,aAAa,wDAAyD,CAAC;AAEpF,8BAA8B;AAC9B,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,CAAC;AAE1C,uBAAuB;AACvB,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,yCAAyC;IACzC,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf,6CAA6C;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAgCD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,qBAA0B,GAAG,MAAM,CAyCjF;AASD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,qBAAqB,GAC7B,QAAQ,CAAC,IAAI,CAAC,qBAAqB,EAAE,SAAS,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,CAAC,CAAC,GAC1E,IAAI,CAAC,qBAAqB,EAAE,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC,CAU3D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EAAE,EAChB,OAAO,GAAE,IAAI,CAAC,qBAAqB,EAAE,OAAO,CAAM,GACjD,MAAM,CAQR"}
package/dist/image.js ADDED
@@ -0,0 +1,150 @@
1
+ /**
2
+ * ONREZA Image Optimization SDK
3
+ *
4
+ * URL builder for platform image optimization service
5
+ * Endpoint: /_onreza/image
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { imageUrl, generateSrcset, DEFAULT_SIZES } from '@onreza/runtime/image';
10
+ *
11
+ * // Basic usage
12
+ * const url = imageUrl('/images/hero.jpg', { width: 1080 });
13
+ * // → '/_onreza/image?url=%2Fimages%2Fhero.jpg&w=1080&q=75'
14
+ *
15
+ * // With quality and format
16
+ * const optimized = imageUrl('/images/photo.jpg', {
17
+ * width: 640,
18
+ * quality: 80,
19
+ * format: 'webp'
20
+ * });
21
+ *
22
+ * // Generate srcset for responsive images
23
+ * const srcset = generateSrcset('/images/photo.jpg', [640, 1080, 1920]);
24
+ * // → '/_onreza/image?url=...&w=640 640w, /_onreza/image?url=...&w=1080 1080w, ...'
25
+ * ```
26
+ */
27
+ /** Default platform image sizes */
28
+ export const DEFAULT_SIZES = [640, 750, 828, 1080, 1200, 1920, 2048, 3840];
29
+ /**
30
+ * Validate image source path
31
+ * @throws Error if path is invalid
32
+ */
33
+ function validateSrc(src) {
34
+ // Reject absolute URLs
35
+ if (src.startsWith("http://") || src.startsWith("https://") || src.startsWith("//")) {
36
+ throw new Error(`Image source must be a relative path, got: ${src}`);
37
+ }
38
+ // Path traversal protection
39
+ const normalized = src.replace(/\\/g, "/");
40
+ if (normalized.includes("..") ||
41
+ normalized.includes("%2e") ||
42
+ normalized.includes("%2E") ||
43
+ normalized.includes("%252e") ||
44
+ normalized.includes("%252E")) {
45
+ throw new Error(`Path traversal detected in image source: ${src}`);
46
+ }
47
+ }
48
+ /**
49
+ * Clamp value to range
50
+ */
51
+ function clamp(value, min, max) {
52
+ return Math.min(Math.max(value, min), max);
53
+ }
54
+ /**
55
+ * Build ONREZA image optimization URL
56
+ *
57
+ * @param src - Relative image path (e.g., "/images/photo.jpg")
58
+ * @param options - Transformation options
59
+ * @returns Optimized image URL
60
+ * @throws Error if src is absolute URL or contains path traversal
61
+ *
62
+ * @example
63
+ * ```typescript
64
+ * imageUrl('/images/hero.jpg', { width: 1080 })
65
+ * // → '/_onreza/image?url=%2Fimages%2Fhero.jpg&w=1080&q=75'
66
+ *
67
+ * imageUrl('/images/photo.jpg', { width: 640, quality: 80, format: 'webp', blur: 10 })
68
+ * // → '/_onreza/image?url=%2Fimages%2Fphoto.jpg&w=640&q=80&f=webp&blur=10'
69
+ * ```
70
+ */
71
+ export function imageUrl(src, options = {}) {
72
+ validateSrc(src);
73
+ const params = new URLSearchParams();
74
+ params.set("url", src);
75
+ // Width (required)
76
+ if (options.width !== undefined) {
77
+ params.set("w", String(options.width));
78
+ }
79
+ // Height (optional)
80
+ if (options.height !== undefined) {
81
+ params.set("h", String(options.height));
82
+ }
83
+ // Quality (default: 75)
84
+ const quality = options.quality !== undefined ? clamp(options.quality, 1, 100) : 75;
85
+ params.set("q", String(quality));
86
+ // Format (optional)
87
+ if (options.format) {
88
+ params.set("f", options.format);
89
+ }
90
+ // Fit mode (optional, default: cover)
91
+ if (options.fit && options.fit !== "cover") {
92
+ params.set("fit", options.fit);
93
+ }
94
+ // Blur (optional, 0-250)
95
+ if (options.blur !== undefined && options.blur > 0) {
96
+ params.set("blur", String(clamp(options.blur, 0, 250)));
97
+ }
98
+ // DPR (optional, 1-5)
99
+ if (options.dpr !== undefined && options.dpr !== 1) {
100
+ params.set("dpr", String(clamp(options.dpr, 1, 5)));
101
+ }
102
+ return `/_onreza/image?${params.toString()}`;
103
+ }
104
+ /**
105
+ * Find nearest allowed width from DEFAULT_SIZES
106
+ */
107
+ function findNearestWidth(width) {
108
+ return DEFAULT_SIZES.reduce((prev, curr) => (Math.abs(curr - width) < Math.abs(prev - width) ? curr : prev));
109
+ }
110
+ /**
111
+ * Validate and normalize image options
112
+ *
113
+ * @param options - Raw options
114
+ * @returns Normalized options with valid values
115
+ */
116
+ export function validateImageOptions(options) {
117
+ return {
118
+ blur: clamp(options.blur ?? 0, 0, 250),
119
+ dpr: clamp(options.dpr ?? 1, 1, 5),
120
+ fit: options.fit ?? "cover",
121
+ format: options.format,
122
+ height: options.height,
123
+ quality: clamp(options.quality ?? 75, 1, 100),
124
+ width: options.width !== undefined ? findNearestWidth(options.width) : undefined,
125
+ };
126
+ }
127
+ /**
128
+ * Generate responsive srcset attribute
129
+ *
130
+ * @param src - Relative image path
131
+ * @param widths - Array of desired widths (will be normalized to allowed sizes)
132
+ * @param options - Base options (applied to all sizes)
133
+ * @returns srcset string for img srcset attribute
134
+ *
135
+ * @example
136
+ * ```typescript
137
+ * generateSrcset('/images/photo.jpg', [640, 1080, 1920], { quality: 80 })
138
+ * // → '/_onreza/image?url=...&w=640&q=80 640w, /_onreza/image?url=...&w=1080&q=80 1080w, ...'
139
+ * ```
140
+ */
141
+ export function generateSrcset(src, widths, options = {}) {
142
+ return widths
143
+ .map((width) => {
144
+ const nearest = findNearestWidth(width);
145
+ const url = imageUrl(src, { ...options, width: nearest });
146
+ return `${url} ${nearest}w`;
147
+ })
148
+ .join(", ");
149
+ }
150
+ //# sourceMappingURL=image.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image.js","sourceRoot":"","sources":["../src/image.ts"],"names":[],"mappings":"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"}
package/dist/kv.d.ts ADDED
@@ -0,0 +1,35 @@
1
+ /**
2
+ * ONREZA KV Store SDK
3
+ *
4
+ * Types and wrappers for ONREZA.kv platform API
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * import { kv, isKVAvailable } from '@onreza/runtime/kv';
9
+ *
10
+ * // Check availability (optional)
11
+ * if (isKVAvailable()) {
12
+ * // Set with TTL
13
+ * await kv.set('session:123', { userId: '456' }, { ttl: 3600 });
14
+ *
15
+ * // Get as JSON
16
+ * const user = await kv.get('user:123', { type: 'json' });
17
+ * }
18
+ * ```
19
+ */
20
+ import type { KVStore } from "../types.d.ts";
21
+ /**
22
+ * KV store operations
23
+ *
24
+ * Note: In ONREZA runtime, this uses the platform-injected ONREZA.kv.
25
+ * Outside runtime, operations throw an error.
26
+ */
27
+ export declare const kv: KVStore;
28
+ /**
29
+ * Check if KV store is available in the current environment
30
+ *
31
+ * @returns true if ONREZA.kv is available
32
+ */
33
+ export declare function isKVAvailable(): boolean;
34
+ export type { KVGetOptions, KVListOptions, KVListResult, KVSetOptions, KVStore } from "../types.d.ts";
35
+ //# sourceMappingURL=kv.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kv.d.ts","sourceRoot":"","sources":["../src/kv.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAA2D,OAAO,EAAE,MAAM,eAAe,CAAC;AAwBtG;;;;;GAKG;AACH,eAAO,MAAM,EAAE,EA8FV,OAAO,CAAC;AAEb;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAGD,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC"}
package/dist/kv.js ADDED
@@ -0,0 +1,144 @@
1
+ /**
2
+ * ONREZA KV Store SDK
3
+ *
4
+ * Types and wrappers for ONREZA.kv platform API
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * import { kv, isKVAvailable } from '@onreza/runtime/kv';
9
+ *
10
+ * // Check availability (optional)
11
+ * if (isKVAvailable()) {
12
+ * // Set with TTL
13
+ * await kv.set('session:123', { userId: '456' }, { ttl: 3600 });
14
+ *
15
+ * // Get as JSON
16
+ * const user = await kv.get('user:123', { type: 'json' });
17
+ * }
18
+ * ```
19
+ */
20
+ /**
21
+ * Check if running in ONREZA runtime environment
22
+ */
23
+ function isOnrezaRuntime() {
24
+ return typeof globalThis.ONREZA !== "undefined";
25
+ }
26
+ /**
27
+ * Get the ONREZA KV store instance
28
+ * @throws Error if not running in ONREZA runtime
29
+ */
30
+ function getKVStore() {
31
+ const onreza = globalThis.ONREZA;
32
+ if (!onreza?.kv) {
33
+ throw new Error("ONREZA KV store is not available. " +
34
+ 'Make sure you are running in ONREZA runtime and have "bindings.kv: true" in your manifest.');
35
+ }
36
+ return onreza.kv;
37
+ }
38
+ /**
39
+ * KV store operations
40
+ *
41
+ * Note: In ONREZA runtime, this uses the platform-injected ONREZA.kv.
42
+ * Outside runtime, operations throw an error.
43
+ */
44
+ export const kv = {
45
+ /**
46
+ * Delete a key from the KV store
47
+ *
48
+ * @param key - The key to delete
49
+ * @returns true if key existed and was deleted, false otherwise
50
+ */
51
+ // biome-ignore lint/suspicious/useAwait: Wrapper for KVStore API
52
+ async delete(key) {
53
+ const store = getKVStore();
54
+ return store.delete(key);
55
+ },
56
+ /**
57
+ * Get a value from the KV store
58
+ *
59
+ * @param key - The key to retrieve
60
+ * @param options - Get options (type: 'text' | 'json' | 'arrayBuffer')
61
+ * @returns The value or null if not found
62
+ *
63
+ * @example
64
+ * ```typescript
65
+ * // Get as string (default)
66
+ * const value = await kv.get('my-key');
67
+ *
68
+ * // Get as JSON
69
+ * const data = await kv.get('user:123', { type: 'json' });
70
+ * ```
71
+ */
72
+ // biome-ignore lint/suspicious/useAwait: Wrapper for KVStore API
73
+ async get(key, options) {
74
+ const store = getKVStore();
75
+ return store.get(key, options);
76
+ },
77
+ /**
78
+ * Check if a key exists in the KV store
79
+ *
80
+ * @param key - The key to check
81
+ * @returns true if key exists, false otherwise
82
+ */
83
+ // biome-ignore lint/suspicious/useAwait: Wrapper for KVStore API
84
+ async has(key) {
85
+ const store = getKVStore();
86
+ return store.has(key);
87
+ },
88
+ /**
89
+ * List keys in the KV store with optional filtering
90
+ *
91
+ * @param options - List options (prefix, limit, cursor)
92
+ * @returns Object with keys array and optional cursor for pagination
93
+ *
94
+ * @example
95
+ * ```typescript
96
+ * // List first 50 keys with prefix
97
+ * const { keys, cursor } = await kv.list({ prefix: 'user:', limit: 50 });
98
+ *
99
+ * // Get next page
100
+ * if (cursor) {
101
+ * const next = await kv.list({ prefix: 'user:', limit: 50, cursor });
102
+ * }
103
+ * ```
104
+ */
105
+ // biome-ignore lint/suspicious/useAwait: Wrapper for KVStore API
106
+ async list(options) {
107
+ const store = getKVStore();
108
+ return store.list(options);
109
+ },
110
+ /**
111
+ * Set a value in the KV store
112
+ *
113
+ * @param key - The key to set
114
+ * @param value - The value to store (string, object, or ArrayBuffer)
115
+ * @param options - Set options (ttl in seconds)
116
+ * @returns Promise that resolves when set is complete
117
+ *
118
+ * @example
119
+ * ```typescript
120
+ * // Set string
121
+ * await kv.set('name', 'John');
122
+ *
123
+ * // Set object (auto-JSON.stringify)
124
+ * await kv.set('user', { name: 'John', age: 30 });
125
+ *
126
+ * // Set with TTL (1 hour)
127
+ * await kv.set('session', { id: 'abc' }, { ttl: 3600 });
128
+ * ```
129
+ */
130
+ // biome-ignore lint/suspicious/useAwait: Wrapper for KVStore API
131
+ async set(key, value, options) {
132
+ const store = getKVStore();
133
+ return store.set(key, value, options);
134
+ },
135
+ };
136
+ /**
137
+ * Check if KV store is available in the current environment
138
+ *
139
+ * @returns true if ONREZA.kv is available
140
+ */
141
+ export function isKVAvailable() {
142
+ return isOnrezaRuntime() && !!globalThis.ONREZA?.kv;
143
+ }
144
+ //# sourceMappingURL=kv.js.map
package/dist/kv.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kv.js","sourceRoot":"","sources":["../src/kv.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH;;GAEG;AACH,SAAS,eAAe;IACtB,OAAO,OAAQ,UAAmC,CAAC,MAAM,KAAK,WAAW,CAAC;AAC5E,CAAC;AAED;;;GAGG;AACH,SAAS,UAAU;IACjB,MAAM,MAAM,GAAI,UAA4C,CAAC,MAAM,CAAC;IACpE,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CACb,oCAAoC;YAClC,4FAA4F,CAC/F,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC,EAAE,CAAC;AACnB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,EAAE,GAAG;IAChB;;;;;OAKG;IACH,iEAAiE;IACjE,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IACD;;;;;;;;;;;;;;;OAeG;IACH,iEAAiE;IACjE,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,OAAsB;QAC3C,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC;QAC3B,OAAQ,KAAK,CAAC,GAAiE,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAChG,CAAC;IAED;;;;;OAKG;IACH,iEAAiE;IACjE,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;IAED;;;;;;;;;;;;;;;;OAgBG;IACH,iEAAiE;IACjE,KAAK,CAAC,IAAI,CAAC,OAAuB;QAChC,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAED;;;;;;;;;;;;;;;;;;;OAmBG;IACH,iEAAiE;IACjE,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,KAAoC,EAAE,OAAsB;QACjF,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC;CACS,CAAC;AAEb;;;;GAIG;AACH,MAAM,UAAU,aAAa;IAC3B,OAAO,eAAe,EAAE,IAAI,CAAC,CAAE,UAA4C,CAAC,MAAM,EAAE,EAAE,CAAC;AACzF,CAAC"}
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@onreza/runtime",
3
+ "version": "0.2.0",
4
+ "description": "ONREZA runtime SDK - types and utilities for platform APIs",
5
+ "license": "MIT",
6
+ "author": "ONREZA OSS <opensource@onreza.ru>",
7
+ "type": "module",
8
+ "exports": {
9
+ "./kv": {
10
+ "types": "./dist/kv.d.ts",
11
+ "import": "./dist/kv.js"
12
+ },
13
+ "./db": {
14
+ "types": "./dist/db.d.ts",
15
+ "import": "./dist/db.js"
16
+ },
17
+ "./context": {
18
+ "types": "./dist/context.d.ts",
19
+ "import": "./dist/context.js"
20
+ },
21
+ "./image": {
22
+ "types": "./dist/image.d.ts",
23
+ "import": "./dist/image.js"
24
+ },
25
+ "./env": {
26
+ "types": "./dist/env.d.ts",
27
+ "import": "./dist/env.js"
28
+ },
29
+ "./types": {
30
+ "types": "./types.d.ts"
31
+ }
32
+ },
33
+ "files": ["dist", "types.d.ts"],
34
+ "keywords": ["onreza", "runtime", "edge", "kv", "d1", "image-optimization"],
35
+ "scripts": {
36
+ "build": "bun run build.ts",
37
+ "test": "bun test",
38
+ "typecheck": "tsc --noEmit"
39
+ },
40
+ "devDependencies": {
41
+ "@types/bun": "latest"
42
+ }
43
+ }
package/types.d.ts ADDED
@@ -0,0 +1,222 @@
1
+ /**
2
+ * ONREZA Runtime Global Types
3
+ *
4
+ * These types define the platform-injected global ONREZA object
5
+ * available in edge runtime (nrz-isolate).
6
+ *
7
+ * Usage in your code:
8
+ * ```typescript
9
+ * /// <reference types="@onreza/runtime/types" />
10
+ *
11
+ * // Or import specific modules:
12
+ * import { kv } from '@onreza/runtime/kv';
13
+ * import { db } from '@onreza/runtime/db';
14
+ * ```
15
+ */
16
+
17
+ declare global {
18
+ /**
19
+ * ONREZA platform runtime API
20
+ * Injected by nrz-isolate at runtime
21
+ */
22
+ const ONREZA: OnrezaRuntime;
23
+ }
24
+
25
+ /**
26
+ * GeoIP data from edge server
27
+ */
28
+ export interface OnrezaGeo {
29
+ /** ISO 3166-1 alpha-2 country code */
30
+ country: string | null;
31
+ /** City name */
32
+ city: string | null;
33
+ /** Continent code */
34
+ continent: string | null;
35
+ /** Edge region (e.g., "ru-central-1") */
36
+ region: string | null;
37
+ }
38
+
39
+ /**
40
+ * Platform context - readonly metadata about the current request
41
+ */
42
+ export interface OnrezaContext {
43
+ /** Client IP address (forwarded from edge) */
44
+ readonly clientIp: string | null;
45
+ /** GeoIP data */
46
+ readonly geo: OnrezaGeo;
47
+ /** Current deployment ID */
48
+ readonly deploymentId: string | null;
49
+ /** Project ID */
50
+ readonly projectId: string | null;
51
+ /** Git commit SHA (short) */
52
+ readonly commitSha: string | null;
53
+ /** Unique request ID (UUID v7, generated per request) */
54
+ readonly requestId: string | null;
55
+ }
56
+
57
+ /**
58
+ * KV store operations result
59
+ */
60
+ export interface KVListResult {
61
+ /** Keys in the result */
62
+ keys: string[];
63
+ /** Cursor for pagination (undefined if no more results) */
64
+ cursor?: string;
65
+ }
66
+
67
+ /**
68
+ * KV store options for set operations
69
+ */
70
+ export interface KVSetOptions {
71
+ /** TTL in seconds (0 = no expiry) */
72
+ ttl?: number;
73
+ }
74
+
75
+ /**
76
+ * KV store get options
77
+ */
78
+ export interface KVGetOptions {
79
+ /** Expected return type */
80
+ type?: "text" | "json" | "arrayBuffer";
81
+ }
82
+
83
+ /**
84
+ * KV store list options
85
+ */
86
+ export interface KVListOptions {
87
+ /** Key prefix to filter */
88
+ prefix?: string;
89
+ /** Maximum number of keys to return (max 1000) */
90
+ limit?: number;
91
+ /** Cursor for pagination */
92
+ cursor?: string;
93
+ }
94
+
95
+ /**
96
+ * D1 database result metadata
97
+ */
98
+ export interface D1Meta {
99
+ /** Execution time in seconds */
100
+ duration: number;
101
+ /** Rows changed (0 for SELECT) */
102
+ changes: number;
103
+ /** Last inserted rowid (0 for SELECT) */
104
+ last_row_id: number;
105
+ /** True if changes > 0 */
106
+ changed_db: boolean;
107
+ /** DB + WAL size in bytes */
108
+ size_after: number;
109
+ /** Result row count */
110
+ rows_read: number;
111
+ /** Same as changes (capped at 0) */
112
+ rows_written: number;
113
+ /** Always "nrz-isolate" */
114
+ served_by: string;
115
+ /** Always "local" (single-region) */
116
+ served_by_region: string;
117
+ /** Always true (no replicas) */
118
+ served_by_primary: boolean;
119
+ /** Timing details */
120
+ timings: {
121
+ /** SQL execution time in milliseconds */
122
+ sql_duration_ms: number;
123
+ };
124
+ /** Always 1 (no retries) */
125
+ total_attempts: number;
126
+ }
127
+
128
+ /**
129
+ * D1 query result
130
+ */
131
+ export interface D1Result<T = unknown> {
132
+ /** Query results */
133
+ results: T[];
134
+ /** Whether query succeeded */
135
+ success: boolean;
136
+ /** Result metadata */
137
+ meta: D1Meta;
138
+ }
139
+
140
+ /**
141
+ * D1 prepared statement
142
+ */
143
+ export interface D1PreparedStatement {
144
+ /** Bind parameters and return statement */
145
+ bind(...values: unknown[]): D1PreparedStatement;
146
+ /** Execute and return all rows */
147
+ all<T = unknown>(): Promise<D1Result<T>>;
148
+ /** Execute and return first row or null */
149
+ first<T = unknown>(colName?: string): Promise<T | null>;
150
+ /** Execute write operation */
151
+ run(): Promise<D1Result>;
152
+ /** Return raw array of arrays */
153
+ raw<T = unknown[]>(): Promise<T[]>;
154
+ raw<T = unknown[]>(options: { columnNames: true }): Promise<{ columns: string[]; results: T[] }>;
155
+ }
156
+
157
+ /**
158
+ * D1 database API
159
+ * Compatible with Cloudflare D1
160
+ */
161
+ export interface D1Database {
162
+ /** Prepare a statement */
163
+ prepare(query: string): D1PreparedStatement;
164
+ /** Execute multiple statements (DDL) */
165
+ exec(query: string): Promise<{ count: number; duration: number }>;
166
+ /** Batch execute statements atomically */
167
+ batch<T = unknown>(statements: D1PreparedStatement[]): Promise<D1Result<T>[]>;
168
+ /** Dump database (not implemented - throws Error) */
169
+ dump(): Promise<ArrayBuffer>;
170
+ /** With session (not implemented - throws Error) */
171
+ withSession<T>(callback: (db: D1Database) => T | Promise<T>): Promise<T>;
172
+ }
173
+
174
+ /**
175
+ * KV store API
176
+ * Namespace-isolated by project_id
177
+ */
178
+ export interface KVStore {
179
+ /** Get value by key */
180
+ get(key: string, options?: { type: "text" }): Promise<string | null>;
181
+ get<T = unknown>(key: string, options: { type: "json" }): Promise<T | null>;
182
+ get(key: string, options: { type: "arrayBuffer" }): Promise<ArrayBuffer | null>;
183
+ get(key: string): Promise<string | null>;
184
+
185
+ /** Set value */
186
+ set(key: string, value: string | object | ArrayBuffer, options?: KVSetOptions): Promise<void>;
187
+
188
+ /** Delete key */
189
+ delete(key: string): Promise<boolean>;
190
+
191
+ /** Check if key exists */
192
+ has(key: string): Promise<boolean>;
193
+
194
+ /** List keys with optional prefix */
195
+ list(options?: KVListOptions): Promise<KVListResult>;
196
+ }
197
+
198
+ /**
199
+ * Environment variable access
200
+ */
201
+ export interface EnvStore {
202
+ /** Get environment variable */
203
+ get(key: string): string | undefined;
204
+ /** Check if environment variable exists */
205
+ has(key: string): boolean;
206
+ /** Iterate over all environment variables */
207
+ entries(): IterableIterator<[string, string]>;
208
+ }
209
+
210
+ /**
211
+ * Main ONREZA runtime interface
212
+ */
213
+ export interface OnrezaRuntime {
214
+ /** KV store (requires bindings.kv: true in manifest) */
215
+ readonly kv: KVStore;
216
+ /** D1 database (requires bindings.db: true in manifest) */
217
+ readonly db: D1Database;
218
+ /** Platform context (request metadata) */
219
+ readonly context: OnrezaContext;
220
+ /** Environment variables */
221
+ readonly env: EnvStore;
222
+ }