cooper-stack 0.1.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/dist/ai.d.ts +60 -0
- package/dist/ai.d.ts.map +1 -0
- package/dist/ai.js +66 -0
- package/dist/ai.js.map +1 -0
- package/dist/api.d.ts +31 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +40 -0
- package/dist/api.js.map +1 -0
- package/dist/auth.d.ts +13 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +16 -0
- package/dist/auth.js.map +1 -0
- package/dist/bridge.d.ts +15 -0
- package/dist/bridge.d.ts.map +1 -0
- package/dist/bridge.js +217 -0
- package/dist/bridge.js.map +1 -0
- package/dist/cache.d.ts +27 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +69 -0
- package/dist/cache.js.map +1 -0
- package/dist/cron.d.ts +22 -0
- package/dist/cron.d.ts.map +1 -0
- package/dist/cron.js +26 -0
- package/dist/cron.js.map +1 -0
- package/dist/db.d.ts +46 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +158 -0
- package/dist/db.js.map +1 -0
- package/dist/error.d.ts +18 -0
- package/dist/error.d.ts.map +1 -0
- package/dist/error.js +30 -0
- package/dist/error.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/islands.d.ts +16 -0
- package/dist/islands.d.ts.map +1 -0
- package/dist/islands.js +23 -0
- package/dist/islands.js.map +1 -0
- package/dist/middleware.d.ts +20 -0
- package/dist/middleware.d.ts.map +1 -0
- package/dist/middleware.js +26 -0
- package/dist/middleware.js.map +1 -0
- package/dist/nats.d.ts +46 -0
- package/dist/nats.d.ts.map +1 -0
- package/dist/nats.js +157 -0
- package/dist/nats.js.map +1 -0
- package/dist/pubsub.d.ts +27 -0
- package/dist/pubsub.d.ts.map +1 -0
- package/dist/pubsub.js +152 -0
- package/dist/pubsub.js.map +1 -0
- package/dist/queue.d.ts +39 -0
- package/dist/queue.d.ts.map +1 -0
- package/dist/queue.js +298 -0
- package/dist/queue.js.map +1 -0
- package/dist/rateLimit.d.ts +29 -0
- package/dist/rateLimit.d.ts.map +1 -0
- package/dist/rateLimit.js +70 -0
- package/dist/rateLimit.js.map +1 -0
- package/dist/registry.d.ts +75 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +41 -0
- package/dist/registry.js.map +1 -0
- package/dist/secrets.d.ts +10 -0
- package/dist/secrets.d.ts.map +1 -0
- package/dist/secrets.js +35 -0
- package/dist/secrets.js.map +1 -0
- package/dist/ssr.d.ts +53 -0
- package/dist/ssr.d.ts.map +1 -0
- package/dist/ssr.js +39 -0
- package/dist/ssr.js.map +1 -0
- package/dist/storage.d.ts +28 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +61 -0
- package/dist/storage.js.map +1 -0
- package/package.json +40 -0
- package/src/ai.ts +99 -0
- package/src/api.ts +56 -0
- package/src/auth.ts +16 -0
- package/src/bridge.ts +267 -0
- package/src/cache.ts +86 -0
- package/src/cron.ts +32 -0
- package/src/db.ts +211 -0
- package/src/error.ts +44 -0
- package/src/index.ts +17 -0
- package/src/islands.ts +28 -0
- package/src/middleware.ts +27 -0
- package/src/nats.ts +186 -0
- package/src/pubsub.ts +208 -0
- package/src/queue.ts +414 -0
- package/src/rateLimit.ts +89 -0
- package/src/registry.ts +98 -0
- package/src/secrets.ts +40 -0
- package/src/ssr.ts +58 -0
- package/src/storage.ts +79 -0
- package/tsconfig.json +17 -0
package/dist/ai.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export interface VectorStoreConfig {
|
|
2
|
+
dimensions: number;
|
|
3
|
+
similarity?: "cosine" | "euclidean" | "dot";
|
|
4
|
+
}
|
|
5
|
+
export interface VectorStoreClient {
|
|
6
|
+
upsert(id: string, vector: number[], metadata?: Record<string, any>): Promise<void>;
|
|
7
|
+
search(vector: number[], opts?: {
|
|
8
|
+
topK?: number;
|
|
9
|
+
filter?: Record<string, any>;
|
|
10
|
+
}): Promise<{
|
|
11
|
+
id: string;
|
|
12
|
+
score: number;
|
|
13
|
+
metadata?: any;
|
|
14
|
+
}[]>;
|
|
15
|
+
delete(id: string): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
export interface LLMGatewayConfig {
|
|
18
|
+
primary: {
|
|
19
|
+
provider: string;
|
|
20
|
+
model: string;
|
|
21
|
+
};
|
|
22
|
+
fallback?: {
|
|
23
|
+
provider: string;
|
|
24
|
+
model: string;
|
|
25
|
+
};
|
|
26
|
+
budget?: {
|
|
27
|
+
dailyLimit: string;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export interface LLMGatewayClient {
|
|
31
|
+
chat(messages: {
|
|
32
|
+
role: string;
|
|
33
|
+
content: string;
|
|
34
|
+
}[]): Promise<string>;
|
|
35
|
+
embed(text: string): Promise<number[]>;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Declare a vector store.
|
|
39
|
+
*
|
|
40
|
+
* ```ts
|
|
41
|
+
* export const embeddings = vectorStore("product-embeddings", {
|
|
42
|
+
* dimensions: 1536,
|
|
43
|
+
* similarity: "cosine",
|
|
44
|
+
* });
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export declare function vectorStore(name: string, config: VectorStoreConfig): VectorStoreClient;
|
|
48
|
+
/**
|
|
49
|
+
* Declare an LLM gateway with cost tracking and fallbacks.
|
|
50
|
+
*
|
|
51
|
+
* ```ts
|
|
52
|
+
* export const llm = llmGateway({
|
|
53
|
+
* primary: { provider: "openai", model: "gpt-4o" },
|
|
54
|
+
* fallback: { provider: "anthropic", model: "claude-sonnet-4-20250514" },
|
|
55
|
+
* budget: { dailyLimit: "$50" },
|
|
56
|
+
* });
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export declare function llmGateway(config: LLMGatewayConfig): LLMGatewayClient;
|
|
60
|
+
//# sourceMappingURL=ai.d.ts.map
|
package/dist/ai.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../src/ai.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,QAAQ,GAAG,WAAW,GAAG,KAAK,CAAC;CAC7C;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpF,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,GAAG,CAAA;KAAE,EAAE,CAAC,CAAC;IAC3I,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,QAAQ,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,MAAM,CAAC,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;CACjC;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACrE,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;CACxC;AAED;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,GAAG,iBAAiB,CAqCtF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,gBAAgB,CAgBrE"}
|
package/dist/ai.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Declare a vector store.
|
|
3
|
+
*
|
|
4
|
+
* ```ts
|
|
5
|
+
* export const embeddings = vectorStore("product-embeddings", {
|
|
6
|
+
* dimensions: 1536,
|
|
7
|
+
* similarity: "cosine",
|
|
8
|
+
* });
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
11
|
+
export function vectorStore(name, config) {
|
|
12
|
+
// Local dev: pgvector extension on embedded Postgres
|
|
13
|
+
// Production: Pinecone, Weaviate, or pgvector on managed Postgres
|
|
14
|
+
const store = new Map();
|
|
15
|
+
const cosineSimilarity = (a, b) => {
|
|
16
|
+
let dot = 0, magA = 0, magB = 0;
|
|
17
|
+
for (let i = 0; i < a.length; i++) {
|
|
18
|
+
dot += a[i] * b[i];
|
|
19
|
+
magA += a[i] * a[i];
|
|
20
|
+
magB += b[i] * b[i];
|
|
21
|
+
}
|
|
22
|
+
return dot / (Math.sqrt(magA) * Math.sqrt(magB));
|
|
23
|
+
};
|
|
24
|
+
return {
|
|
25
|
+
async upsert(id, vector, metadata) {
|
|
26
|
+
store.set(id, { vector, metadata });
|
|
27
|
+
},
|
|
28
|
+
async search(vector, opts) {
|
|
29
|
+
const topK = opts?.topK ?? 10;
|
|
30
|
+
const results = [];
|
|
31
|
+
for (const [id, entry] of store) {
|
|
32
|
+
const score = cosineSimilarity(vector, entry.vector);
|
|
33
|
+
results.push({ id, score, metadata: entry.metadata });
|
|
34
|
+
}
|
|
35
|
+
results.sort((a, b) => b.score - a.score);
|
|
36
|
+
return results.slice(0, topK);
|
|
37
|
+
},
|
|
38
|
+
async delete(id) {
|
|
39
|
+
store.delete(id);
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Declare an LLM gateway with cost tracking and fallbacks.
|
|
45
|
+
*
|
|
46
|
+
* ```ts
|
|
47
|
+
* export const llm = llmGateway({
|
|
48
|
+
* primary: { provider: "openai", model: "gpt-4o" },
|
|
49
|
+
* fallback: { provider: "anthropic", model: "claude-sonnet-4-20250514" },
|
|
50
|
+
* budget: { dailyLimit: "$50" },
|
|
51
|
+
* });
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export function llmGateway(config) {
|
|
55
|
+
return {
|
|
56
|
+
async chat(messages) {
|
|
57
|
+
// Route to the configured provider
|
|
58
|
+
// Track cost, apply rate limits, handle fallback
|
|
59
|
+
throw new Error(`LLM gateway not yet connected. Configure API keys via: cooper secrets set ${config.primary.provider}-api-key --env local`);
|
|
60
|
+
},
|
|
61
|
+
async embed(text) {
|
|
62
|
+
throw new Error(`LLM gateway not yet connected. Configure API keys via: cooper secrets set ${config.primary.provider}-api-key --env local`);
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=ai.js.map
|
package/dist/ai.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai.js","sourceRoot":"","sources":["../src/ai.ts"],"names":[],"mappings":"AAsBA;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,MAAyB;IACjE,qDAAqD;IACrD,kEAAkE;IAClE,MAAM,KAAK,GAAG,IAAI,GAAG,EAAgD,CAAC;IAEtE,MAAM,gBAAgB,GAAG,CAAC,CAAW,EAAE,CAAW,EAAU,EAAE;QAC5D,IAAI,GAAG,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC;QAChC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAClC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YACnB,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YACpB,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACtB,CAAC;QACD,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACnD,CAAC,CAAC;IAEF,OAAO;QACL,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ;YAC/B,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;QACtC,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI;YACvB,MAAM,IAAI,GAAG,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC;YAC9B,MAAM,OAAO,GAAoD,EAAE,CAAC;YAEpE,KAAK,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,KAAK,EAAE,CAAC;gBAChC,MAAM,KAAK,GAAG,gBAAgB,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;gBACrD,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;YACxD,CAAC;YAED,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;YAC1C,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QAChC,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,EAAE;YACb,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACnB,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,UAAU,CAAC,MAAwB;IACjD,OAAO;QACL,KAAK,CAAC,IAAI,CAAC,QAAQ;YACjB,mCAAmC;YACnC,iDAAiD;YACjD,MAAM,IAAI,KAAK,CACb,6EAA6E,MAAM,CAAC,OAAO,CAAC,QAAQ,sBAAsB,CAC3H,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,KAAK,CAAC,IAAI;YACd,MAAM,IAAI,KAAK,CACb,6EAA6E,MAAM,CAAC,OAAO,CAAC,QAAQ,sBAAsB,CAC3H,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/dist/api.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type MiddlewareFn } from "./registry.js";
|
|
2
|
+
import { CooperError } from "./error.js";
|
|
3
|
+
export interface ApiConfig {
|
|
4
|
+
method?: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
5
|
+
path: string;
|
|
6
|
+
auth?: boolean;
|
|
7
|
+
stream?: "sse" | "websocket";
|
|
8
|
+
validate?: any;
|
|
9
|
+
middleware?: MiddlewareFn[];
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Define an API endpoint.
|
|
13
|
+
*
|
|
14
|
+
* ```ts
|
|
15
|
+
* export const getUser = api(
|
|
16
|
+
* { method: "GET", path: "/users/:id", auth: true },
|
|
17
|
+
* async ({ id }, principal) => {
|
|
18
|
+
* const user = await db.queryRow("SELECT * FROM users WHERE id = $1", [id]);
|
|
19
|
+
* if (!user) throw new CooperError("NOT_FOUND", "User not found");
|
|
20
|
+
* return { user };
|
|
21
|
+
* }
|
|
22
|
+
* );
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare function api<TInput = any, TOutput = any>(config: ApiConfig, handler: (input: TInput, principal?: any) => Promise<TOutput>): {
|
|
26
|
+
_cooper_type: "api";
|
|
27
|
+
config: ApiConfig;
|
|
28
|
+
handler: typeof handler;
|
|
29
|
+
};
|
|
30
|
+
export { CooperError };
|
|
31
|
+
//# sourceMappingURL=api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,KAAK,GAAG,WAAW,CAAC;IAC7B,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,UAAU,CAAC,EAAE,YAAY,EAAE,CAAC;CAC7B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE,OAAO,GAAG,GAAG,EAC7C,MAAM,EAAE,SAAS,EACjB,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,GAAG,KAAK,OAAO,CAAC,OAAO,CAAC,GAC5D;IAAE,YAAY,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,OAAO,OAAO,CAAA;CAAE,CAwBrE;AAED,OAAO,EAAE,WAAW,EAAE,CAAC"}
|
package/dist/api.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { registry } from "./registry.js";
|
|
2
|
+
import { CooperError } from "./error.js";
|
|
3
|
+
/**
|
|
4
|
+
* Define an API endpoint.
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* export const getUser = api(
|
|
8
|
+
* { method: "GET", path: "/users/:id", auth: true },
|
|
9
|
+
* async ({ id }, principal) => {
|
|
10
|
+
* const user = await db.queryRow("SELECT * FROM users WHERE id = $1", [id]);
|
|
11
|
+
* if (!user) throw new CooperError("NOT_FOUND", "User not found");
|
|
12
|
+
* return { user };
|
|
13
|
+
* }
|
|
14
|
+
* );
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export function api(config, handler) {
|
|
18
|
+
const method = config.method ?? "GET";
|
|
19
|
+
const key = `${method}:${config.path}`;
|
|
20
|
+
const descriptor = {
|
|
21
|
+
_cooper_type: "api",
|
|
22
|
+
config,
|
|
23
|
+
handler,
|
|
24
|
+
};
|
|
25
|
+
// Register for the bridge to find at runtime
|
|
26
|
+
registry.registerRoute(key, {
|
|
27
|
+
method,
|
|
28
|
+
path: config.path,
|
|
29
|
+
auth: config.auth ?? false,
|
|
30
|
+
stream: config.stream,
|
|
31
|
+
validate: config.validate,
|
|
32
|
+
middleware: config.middleware ?? [],
|
|
33
|
+
handler,
|
|
34
|
+
exportName: "", // filled in by bridge during module scan
|
|
35
|
+
sourceFile: "",
|
|
36
|
+
});
|
|
37
|
+
return descriptor;
|
|
38
|
+
}
|
|
39
|
+
export { CooperError };
|
|
40
|
+
//# sourceMappingURL=api.js.map
|
package/dist/api.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAqB,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAWzC;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,GAAG,CACjB,MAAiB,EACjB,OAA6D;IAE7D,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,KAAK,CAAC;IACtC,MAAM,GAAG,GAAG,GAAG,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;IAEvC,MAAM,UAAU,GAAG;QACjB,YAAY,EAAE,KAAc;QAC5B,MAAM;QACN,OAAO;KACR,CAAC;IAEF,6CAA6C;IAC7C,QAAQ,CAAC,aAAa,CAAC,GAAG,EAAE;QAC1B,MAAM;QACN,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,KAAK;QAC1B,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,EAAE;QACnC,OAAO;QACP,UAAU,EAAE,EAAE,EAAE,yCAAyC;QACzD,UAAU,EAAE,EAAE;KACf,CAAC,CAAC;IAEH,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,OAAO,EAAE,WAAW,EAAE,CAAC"}
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type AuthHandlerFn } from "./registry.js";
|
|
2
|
+
/**
|
|
3
|
+
* Register an auth handler that verifies tokens and returns a principal.
|
|
4
|
+
*
|
|
5
|
+
* ```ts
|
|
6
|
+
* export const auth = authHandler(async (token) => {
|
|
7
|
+
* const payload = await verifyJWT(token);
|
|
8
|
+
* return { userId: payload.sub, role: payload.role };
|
|
9
|
+
* });
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export declare function authHandler(handler: AuthHandlerFn): AuthHandlerFn;
|
|
13
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AAE7D;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,aAAa,iBAGjD"}
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { registry } from "./registry.js";
|
|
2
|
+
/**
|
|
3
|
+
* Register an auth handler that verifies tokens and returns a principal.
|
|
4
|
+
*
|
|
5
|
+
* ```ts
|
|
6
|
+
* export const auth = authHandler(async (token) => {
|
|
7
|
+
* const payload = await verifyJWT(token);
|
|
8
|
+
* return { userId: payload.sub, role: payload.role };
|
|
9
|
+
* });
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export function authHandler(handler) {
|
|
13
|
+
registry.setAuthHandler(handler);
|
|
14
|
+
return handler;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAsB,MAAM,eAAe,CAAC;AAE7D;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW,CAAC,OAAsB;IAChD,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IACjC,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/dist/bridge.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Cooper JS Worker Bridge
|
|
4
|
+
*
|
|
5
|
+
* Spawned by the Rust runtime as a subprocess. Communicates via
|
|
6
|
+
* JSON-RPC over stdin/stdout. Loads user TypeScript modules and
|
|
7
|
+
* executes handler functions on demand.
|
|
8
|
+
*
|
|
9
|
+
* Protocol:
|
|
10
|
+
* → { "id": 1, "method": "call", "params": { "source": "services/users/api.ts", "export": "getUser", "input": {...}, "auth": {...} } }
|
|
11
|
+
* ← { "id": 1, "result": {...} }
|
|
12
|
+
* ← { "id": 1, "error": { "code": "NOT_FOUND", "message": "User not found" } }
|
|
13
|
+
*/
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=bridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;GAWG"}
|
package/dist/bridge.js
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Cooper JS Worker Bridge
|
|
4
|
+
*
|
|
5
|
+
* Spawned by the Rust runtime as a subprocess. Communicates via
|
|
6
|
+
* JSON-RPC over stdin/stdout. Loads user TypeScript modules and
|
|
7
|
+
* executes handler functions on demand.
|
|
8
|
+
*
|
|
9
|
+
* Protocol:
|
|
10
|
+
* → { "id": 1, "method": "call", "params": { "source": "services/users/api.ts", "export": "getUser", "input": {...}, "auth": {...} } }
|
|
11
|
+
* ← { "id": 1, "result": {...} }
|
|
12
|
+
* ← { "id": 1, "error": { "code": "NOT_FOUND", "message": "User not found" } }
|
|
13
|
+
*/
|
|
14
|
+
import { registry } from "./registry.js";
|
|
15
|
+
import { CooperError } from "./error.js";
|
|
16
|
+
import { createInterface } from "node:readline";
|
|
17
|
+
import path from "node:path";
|
|
18
|
+
import { pathToFileURL } from "node:url";
|
|
19
|
+
const projectRoot = process.env.COOPER_PROJECT_ROOT ?? process.cwd();
|
|
20
|
+
// Module cache — avoid re-importing on every request
|
|
21
|
+
const moduleCache = new Map();
|
|
22
|
+
async function loadModule(sourcePath) {
|
|
23
|
+
if (moduleCache.has(sourcePath))
|
|
24
|
+
return moduleCache.get(sourcePath);
|
|
25
|
+
const fullPath = path.resolve(projectRoot, sourcePath);
|
|
26
|
+
const fileUrl = pathToFileURL(fullPath).href;
|
|
27
|
+
try {
|
|
28
|
+
const mod = await import(fileUrl);
|
|
29
|
+
moduleCache.set(sourcePath, mod);
|
|
30
|
+
return mod;
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
throw new Error(`Failed to load module "${sourcePath}": ${err.message}`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
async function handleCall(params) {
|
|
37
|
+
const mod = await loadModule(params.source);
|
|
38
|
+
const exported = mod[params.export];
|
|
39
|
+
if (!exported) {
|
|
40
|
+
throw new CooperError("NOT_FOUND", `Export "${params.export}" not found in ${params.source}`);
|
|
41
|
+
}
|
|
42
|
+
// Get the handler function
|
|
43
|
+
let handler;
|
|
44
|
+
let routeConfig = null;
|
|
45
|
+
if (exported._cooper_type === "api") {
|
|
46
|
+
handler = exported.handler;
|
|
47
|
+
routeConfig = exported.config;
|
|
48
|
+
}
|
|
49
|
+
else if (typeof exported === "function") {
|
|
50
|
+
handler = exported;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
throw new CooperError("INTERNAL", `Export "${params.export}" is not callable`);
|
|
54
|
+
}
|
|
55
|
+
// Validation — run Zod schema if present.
|
|
56
|
+
// Use passthrough() to preserve path params that aren't in the schema.
|
|
57
|
+
let validatedInput = params.input;
|
|
58
|
+
if (routeConfig?.validate) {
|
|
59
|
+
const schema = routeConfig.validate;
|
|
60
|
+
const lenient = typeof schema.passthrough === "function" ? schema.passthrough() : schema;
|
|
61
|
+
const result = lenient.safeParse(params.input);
|
|
62
|
+
if (!result.success) {
|
|
63
|
+
throw new CooperError("VALIDATION_FAILED", result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; "));
|
|
64
|
+
}
|
|
65
|
+
validatedInput = result.data;
|
|
66
|
+
}
|
|
67
|
+
// Auth — verify token and inject principal
|
|
68
|
+
let principal = undefined;
|
|
69
|
+
if (routeConfig?.auth) {
|
|
70
|
+
if (!params.auth?.token) {
|
|
71
|
+
throw new CooperError("UNAUTHORIZED", "Authentication required");
|
|
72
|
+
}
|
|
73
|
+
if (registry.authHandler) {
|
|
74
|
+
principal = await registry.authHandler(params.auth.token);
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
throw new CooperError("INTERNAL", "No auth handler registered");
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Middleware chain
|
|
81
|
+
const middlewares = [
|
|
82
|
+
...registry.globalMiddleware,
|
|
83
|
+
...(routeConfig?.middleware ?? []),
|
|
84
|
+
];
|
|
85
|
+
const req = {
|
|
86
|
+
...validatedInput,
|
|
87
|
+
headers: params.headers ?? {},
|
|
88
|
+
ip: params.headers?.["x-forwarded-for"] ?? "127.0.0.1",
|
|
89
|
+
method: routeConfig?.method ?? "GET",
|
|
90
|
+
path: routeConfig?.path ?? "/",
|
|
91
|
+
};
|
|
92
|
+
// Build the middleware chain
|
|
93
|
+
let idx = 0;
|
|
94
|
+
const runMiddleware = async (currentReq) => {
|
|
95
|
+
if (idx < middlewares.length) {
|
|
96
|
+
const mw = middlewares[idx++];
|
|
97
|
+
return mw(currentReq, runMiddleware);
|
|
98
|
+
}
|
|
99
|
+
// End of chain — call the actual handler
|
|
100
|
+
if (routeConfig?.auth) {
|
|
101
|
+
return handler(validatedInput, principal);
|
|
102
|
+
}
|
|
103
|
+
return handler(validatedInput);
|
|
104
|
+
};
|
|
105
|
+
return runMiddleware(req);
|
|
106
|
+
}
|
|
107
|
+
async function handleCron(params) {
|
|
108
|
+
const mod = await loadModule(params.source);
|
|
109
|
+
const exported = mod[params.export];
|
|
110
|
+
if (!exported) {
|
|
111
|
+
throw new CooperError("NOT_FOUND", `Cron "${params.export}" not found in ${params.source}`);
|
|
112
|
+
}
|
|
113
|
+
if (exported._cooper_type === "cron") {
|
|
114
|
+
// The cron was registered via the SDK, find it in the registry
|
|
115
|
+
const cronEntry = registry.crons.get(exported.name);
|
|
116
|
+
if (cronEntry) {
|
|
117
|
+
await cronEntry.handler();
|
|
118
|
+
return { ok: true };
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
throw new CooperError("INTERNAL", `Cannot execute cron "${params.export}"`);
|
|
122
|
+
}
|
|
123
|
+
async function handlePubSub(params) {
|
|
124
|
+
const topicEntry = registry.topics.get(params.topic);
|
|
125
|
+
if (!topicEntry) {
|
|
126
|
+
throw new CooperError("NOT_FOUND", `Topic "${params.topic}" not registered`);
|
|
127
|
+
}
|
|
128
|
+
const sub = topicEntry.subscribers.get(params.subscriber);
|
|
129
|
+
if (!sub) {
|
|
130
|
+
throw new CooperError("NOT_FOUND", `Subscriber "${params.subscriber}" not found on topic "${params.topic}"`);
|
|
131
|
+
}
|
|
132
|
+
await sub.handler(params.data);
|
|
133
|
+
return { ok: true };
|
|
134
|
+
}
|
|
135
|
+
async function handleRequest(req) {
|
|
136
|
+
try {
|
|
137
|
+
let result;
|
|
138
|
+
switch (req.method) {
|
|
139
|
+
case "call":
|
|
140
|
+
result = await handleCall(req.params);
|
|
141
|
+
break;
|
|
142
|
+
case "cron":
|
|
143
|
+
result = await handleCron(req.params);
|
|
144
|
+
break;
|
|
145
|
+
case "pubsub":
|
|
146
|
+
result = await handlePubSub(req.params);
|
|
147
|
+
break;
|
|
148
|
+
case "ping":
|
|
149
|
+
result = { pong: true, pid: process.pid };
|
|
150
|
+
break;
|
|
151
|
+
case "invalidate":
|
|
152
|
+
// Clear module cache for hot reload
|
|
153
|
+
moduleCache.clear();
|
|
154
|
+
result = { ok: true };
|
|
155
|
+
break;
|
|
156
|
+
default:
|
|
157
|
+
throw new CooperError("INVALID_ARGUMENT", `Unknown method: ${req.method}`);
|
|
158
|
+
}
|
|
159
|
+
return { id: req.id, result };
|
|
160
|
+
}
|
|
161
|
+
catch (err) {
|
|
162
|
+
if (err instanceof CooperError) {
|
|
163
|
+
return {
|
|
164
|
+
id: req.id,
|
|
165
|
+
error: { code: err.code, message: err.message, statusCode: err.statusCode },
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
id: req.id,
|
|
170
|
+
error: { code: "INTERNAL", message: err.message ?? "Unknown error", statusCode: 500 },
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// Main loop — read JSON lines from stdin, write responses to stdout
|
|
175
|
+
const rl = createInterface({ input: process.stdin });
|
|
176
|
+
rl.on("line", async (line) => {
|
|
177
|
+
if (!line.trim())
|
|
178
|
+
return;
|
|
179
|
+
try {
|
|
180
|
+
const req = JSON.parse(line);
|
|
181
|
+
const res = await handleRequest(req);
|
|
182
|
+
process.stdout.write(JSON.stringify(res) + "\n");
|
|
183
|
+
}
|
|
184
|
+
catch (err) {
|
|
185
|
+
process.stdout.write(JSON.stringify({ id: 0, error: { code: "INTERNAL", message: `Bridge parse error: ${err.message}` } }) + "\n");
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
// Preload auth handlers and middleware — these register via side effects
|
|
189
|
+
async function preloadSideEffects() {
|
|
190
|
+
const fs = await import("node:fs");
|
|
191
|
+
const servicesDir = path.join(projectRoot, "services");
|
|
192
|
+
if (!fs.existsSync(servicesDir))
|
|
193
|
+
return;
|
|
194
|
+
const scanDir = (dir) => {
|
|
195
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
196
|
+
const fullPath = path.join(dir, entry.name);
|
|
197
|
+
if (entry.isDirectory()) {
|
|
198
|
+
scanDir(fullPath);
|
|
199
|
+
}
|
|
200
|
+
else if (entry.name.endsWith(".ts") || entry.name.endsWith(".js")) {
|
|
201
|
+
try {
|
|
202
|
+
const content = fs.readFileSync(fullPath, "utf-8");
|
|
203
|
+
if (content.includes("authHandler") || content.includes("middleware(")) {
|
|
204
|
+
const relative = path.relative(projectRoot, fullPath);
|
|
205
|
+
loadModule(relative).catch(() => { });
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
catch { }
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
scanDir(servicesDir);
|
|
213
|
+
}
|
|
214
|
+
await preloadSideEffects();
|
|
215
|
+
// Signal ready
|
|
216
|
+
process.stdout.write(JSON.stringify({ id: 0, result: { ready: true, pid: process.pid } }) + "\n");
|
|
217
|
+
//# sourceMappingURL=bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;AAErE,qDAAqD;AACrD,MAAM,WAAW,GAAG,IAAI,GAAG,EAAe,CAAC;AAE3C,KAAK,UAAU,UAAU,CAAC,UAAkB;IAC1C,IAAI,WAAW,CAAC,GAAG,CAAC,UAAU,CAAC;QAAE,OAAO,WAAW,CAAC,GAAG,CAAC,UAAU,CAAE,CAAC;IAErE,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IACvD,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC;IAE7C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;QAClC,WAAW,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QACjC,OAAO,GAAG,CAAC;IACb,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,0BAA0B,UAAU,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IAC3E,CAAC;AACH,CAAC;AAcD,KAAK,UAAU,UAAU,CAAC,MAMzB;IACC,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAEpC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,WAAW,CAAC,WAAW,EAAE,WAAW,MAAM,CAAC,MAAM,kBAAkB,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAChG,CAAC;IAED,2BAA2B;IAC3B,IAAI,OAAiB,CAAC;IACtB,IAAI,WAAW,GAAQ,IAAI,CAAC;IAE5B,IAAI,QAAQ,CAAC,YAAY,KAAK,KAAK,EAAE,CAAC;QACpC,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;QAC3B,WAAW,GAAG,QAAQ,CAAC,MAAM,CAAC;IAChC,CAAC;SAAM,IAAI,OAAO,QAAQ,KAAK,UAAU,EAAE,CAAC;QAC1C,OAAO,GAAG,QAAQ,CAAC;IACrB,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,WAAW,CAAC,UAAU,EAAE,WAAW,MAAM,CAAC,MAAM,mBAAmB,CAAC,CAAC;IACjF,CAAC;IAED,0CAA0C;IAC1C,uEAAuE;IACvE,IAAI,cAAc,GAAG,MAAM,CAAC,KAAK,CAAC;IAClC,IAAI,WAAW,EAAE,QAAQ,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,WAAW,CAAC,QAAQ,CAAC;QACpC,MAAM,OAAO,GAAG,OAAO,MAAM,CAAC,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;QACzF,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC/C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,IAAI,WAAW,CACnB,mBAAmB,EACnB,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CACpF,CAAC;QACJ,CAAC;QACD,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC;IAC/B,CAAC;IAED,2CAA2C;IAC3C,IAAI,SAAS,GAAQ,SAAS,CAAC;IAC/B,IAAI,WAAW,EAAE,IAAI,EAAE,CAAC;QACtB,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;YACxB,MAAM,IAAI,WAAW,CAAC,cAAc,EAAE,yBAAyB,CAAC,CAAC;QACnE,CAAC;QACD,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC;YACzB,SAAS,GAAG,MAAM,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5D,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,WAAW,CAAC,UAAU,EAAE,4BAA4B,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;IAED,mBAAmB;IACnB,MAAM,WAAW,GAAG;QAClB,GAAG,QAAQ,CAAC,gBAAgB;QAC5B,GAAG,CAAC,WAAW,EAAE,UAAU,IAAI,EAAE,CAAC;KACnC,CAAC;IAEF,MAAM,GAAG,GAAG;QACV,GAAG,cAAc;QACjB,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,EAAE;QAC7B,EAAE,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,iBAAiB,CAAC,IAAI,WAAW;QACtD,MAAM,EAAE,WAAW,EAAE,MAAM,IAAI,KAAK;QACpC,IAAI,EAAE,WAAW,EAAE,IAAI,IAAI,GAAG;KAC/B,CAAC;IAEF,6BAA6B;IAC7B,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,MAAM,aAAa,GAAG,KAAK,EAAE,UAAe,EAAgB,EAAE;QAC5D,IAAI,GAAG,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC;YAC7B,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC;YAC9B,OAAO,EAAE,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;QACvC,CAAC;QACD,yCAAyC;QACzC,IAAI,WAAW,EAAE,IAAI,EAAE,CAAC;YACtB,OAAO,OAAO,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;QAC5C,CAAC;QACD,OAAO,OAAO,CAAC,cAAc,CAAC,CAAC;IACjC,CAAC,CAAC;IAEF,OAAO,aAAa,CAAC,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,MAA0C;IAClE,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAEpC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,WAAW,CAAC,WAAW,EAAE,SAAS,MAAM,CAAC,MAAM,kBAAkB,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9F,CAAC;IAED,IAAI,QAAQ,CAAC,YAAY,KAAK,MAAM,EAAE,CAAC;QACrC,+DAA+D;QAC/D,MAAM,SAAS,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACpD,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,SAAS,CAAC,OAAO,EAAE,CAAC;YAC1B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;QACtB,CAAC;IACH,CAAC;IAED,MAAM,IAAI,WAAW,CAAC,UAAU,EAAE,wBAAwB,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;AAC9E,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,MAI3B;IACC,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACrD,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,WAAW,CAAC,WAAW,EAAE,UAAU,MAAM,CAAC,KAAK,kBAAkB,CAAC,CAAC;IAC/E,CAAC;IAED,MAAM,GAAG,GAAG,UAAU,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC1D,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,WAAW,CAAC,WAAW,EAAE,eAAe,MAAM,CAAC,UAAU,yBAAyB,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC;IAC/G,CAAC;IAED,MAAM,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC/B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;AACtB,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,GAAe;IAC1C,IAAI,CAAC;QACH,IAAI,MAAW,CAAC;QAEhB,QAAQ,GAAG,CAAC,MAAM,EAAE,CAAC;YACnB,KAAK,MAAM;gBACT,MAAM,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBACtC,MAAM;YACR,KAAK,MAAM;gBACT,MAAM,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBACtC,MAAM;YACR,KAAK,QAAQ;gBACX,MAAM,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBACxC,MAAM;YACR,KAAK,MAAM;gBACT,MAAM,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;gBAC1C,MAAM;YACR,KAAK,YAAY;gBACf,oCAAoC;gBACpC,WAAW,CAAC,KAAK,EAAE,CAAC;gBACpB,MAAM,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;gBACtB,MAAM;YACR;gBACE,MAAM,IAAI,WAAW,CAAC,kBAAkB,EAAE,mBAAmB,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QAC/E,CAAC;QAED,OAAO,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC;IAChC,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,IAAI,GAAG,YAAY,WAAW,EAAE,CAAC;YAC/B,OAAO;gBACL,EAAE,EAAE,GAAG,CAAC,EAAE;gBACV,KAAK,EAAE,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE;aAC5E,CAAC;QACJ,CAAC;QACD,OAAO;YACL,EAAE,EAAE,GAAG,CAAC,EAAE;YACV,KAAK,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,IAAI,eAAe,EAAE,UAAU,EAAE,GAAG,EAAE;SACtF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,oEAAoE;AACpE,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;AAErD,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;IAC3B,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;QAAE,OAAO;IAEzB,IAAI,CAAC;QACH,MAAM,GAAG,GAAe,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,GAAG,CAAC,CAAC;QACrC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;IACnD,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,uBAAuB,GAAG,CAAC,OAAO,EAAE,EAAE,EAAE,CAAC,GAAG,IAAI,CAC7G,CAAC;IACJ,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,yEAAyE;AACzE,KAAK,UAAU,kBAAkB;IAC/B,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC;IACnC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IACvD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC;QAAE,OAAO;IAExC,MAAM,OAAO,GAAG,CAAC,GAAW,EAAE,EAAE;QAC9B,KAAK,MAAM,KAAK,IAAI,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;YACjE,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YAC5C,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,OAAO,CAAC,QAAQ,CAAC,CAAC;YACpB,CAAC;iBAAM,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBACpE,IAAI,CAAC;oBACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;oBACnD,IAAI,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;wBACvE,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;wBACtD,UAAU,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;oBACvC,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC,CAAA,CAAC;YACZ,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,CAAC,WAAW,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,kBAAkB,EAAE,CAAC;AAE3B,eAAe;AACf,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC"}
|
package/dist/cache.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface CacheConfig {
|
|
2
|
+
ttl?: string;
|
|
3
|
+
}
|
|
4
|
+
export interface CacheClient<T> {
|
|
5
|
+
get(key: string): Promise<T | null>;
|
|
6
|
+
set(key: string, value: T, opts?: {
|
|
7
|
+
ttl?: string;
|
|
8
|
+
}): Promise<void>;
|
|
9
|
+
getOrSet(key: string, factory: () => Promise<T>, opts?: {
|
|
10
|
+
ttl?: string;
|
|
11
|
+
}): Promise<T>;
|
|
12
|
+
delete(key: string): Promise<void>;
|
|
13
|
+
invalidatePrefix(prefix: string): Promise<void>;
|
|
14
|
+
increment(key: string, opts?: {
|
|
15
|
+
ttl?: string;
|
|
16
|
+
}): Promise<number>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Declare a typed cache.
|
|
20
|
+
*
|
|
21
|
+
* ```ts
|
|
22
|
+
* export const userCache = cache<User>("users", { ttl: "10m" });
|
|
23
|
+
* const user = await userCache.getOrSet(userId, () => db.queryRow(...));
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare function cache<T = any>(name: string, config?: CacheConfig): CacheClient<T>;
|
|
27
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACpC,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACtF,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAClE;AAUD;;;;;;;GAOG;AACH,wBAAgB,KAAK,CAAC,CAAC,GAAG,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,WAAW,CAAC,CAAC,CAAC,CAwDjF"}
|
package/dist/cache.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
function parseTTL(ttl) {
|
|
2
|
+
const match = ttl.match(/^(\d+)(s|m|h|d)$/);
|
|
3
|
+
if (!match)
|
|
4
|
+
return 600;
|
|
5
|
+
const [, num, unit] = match;
|
|
6
|
+
const multipliers = { s: 1, m: 60, h: 3600, d: 86400 };
|
|
7
|
+
return parseInt(num) * (multipliers[unit] ?? 60);
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Declare a typed cache.
|
|
11
|
+
*
|
|
12
|
+
* ```ts
|
|
13
|
+
* export const userCache = cache<User>("users", { ttl: "10m" });
|
|
14
|
+
* const user = await userCache.getOrSet(userId, () => db.queryRow(...));
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export function cache(name, config) {
|
|
18
|
+
const defaultTTL = config?.ttl ?? "10m";
|
|
19
|
+
let redis = null;
|
|
20
|
+
const ensureRedis = async () => {
|
|
21
|
+
if (redis)
|
|
22
|
+
return redis;
|
|
23
|
+
const Redis = (await import("ioredis")).default;
|
|
24
|
+
const url = process.env.COOPER_VALKEY_URL ?? "redis://localhost:6379";
|
|
25
|
+
redis = new Redis(url);
|
|
26
|
+
return redis;
|
|
27
|
+
};
|
|
28
|
+
const prefixed = (key) => `cooper:${name}:${key}`;
|
|
29
|
+
return {
|
|
30
|
+
async get(key) {
|
|
31
|
+
const r = await ensureRedis();
|
|
32
|
+
const val = await r.get(prefixed(key));
|
|
33
|
+
return val ? JSON.parse(val) : null;
|
|
34
|
+
},
|
|
35
|
+
async set(key, value, opts) {
|
|
36
|
+
const r = await ensureRedis();
|
|
37
|
+
const ttlSec = parseTTL(opts?.ttl ?? defaultTTL);
|
|
38
|
+
await r.setex(prefixed(key), ttlSec, JSON.stringify(value));
|
|
39
|
+
},
|
|
40
|
+
async getOrSet(key, factory, opts) {
|
|
41
|
+
const existing = await this.get(key);
|
|
42
|
+
if (existing !== null)
|
|
43
|
+
return existing;
|
|
44
|
+
const value = await factory();
|
|
45
|
+
await this.set(key, value, opts);
|
|
46
|
+
return value;
|
|
47
|
+
},
|
|
48
|
+
async delete(key) {
|
|
49
|
+
const r = await ensureRedis();
|
|
50
|
+
await r.del(prefixed(key));
|
|
51
|
+
},
|
|
52
|
+
async invalidatePrefix(prefix) {
|
|
53
|
+
const r = await ensureRedis();
|
|
54
|
+
const keys = await r.keys(prefixed(prefix) + "*");
|
|
55
|
+
if (keys.length > 0)
|
|
56
|
+
await r.del(...keys);
|
|
57
|
+
},
|
|
58
|
+
async increment(key, opts) {
|
|
59
|
+
const r = await ensureRedis();
|
|
60
|
+
const k = prefixed(key);
|
|
61
|
+
const val = await r.incr(k);
|
|
62
|
+
if (val === 1 && opts?.ttl) {
|
|
63
|
+
await r.expire(k, parseTTL(opts.ttl));
|
|
64
|
+
}
|
|
65
|
+
return val;
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../src/cache.ts"],"names":[],"mappings":"AAaA,SAAS,QAAQ,CAAC,GAAW;IAC3B,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,kBAAkB,CAAC,CAAC;IAC5C,IAAI,CAAC,KAAK;QAAE,OAAO,GAAG,CAAC;IACvB,MAAM,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,KAAK,CAAC;IAC5B,MAAM,WAAW,GAA2B,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC;IAC/E,OAAO,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;AACnD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,KAAK,CAAU,IAAY,EAAE,MAAoB;IAC/D,MAAM,UAAU,GAAG,MAAM,EAAE,GAAG,IAAI,KAAK,CAAC;IACxC,IAAI,KAAK,GAAQ,IAAI,CAAC;IAEtB,MAAM,WAAW,GAAG,KAAK,IAAI,EAAE;QAC7B,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;QACxB,MAAM,KAAK,GAAG,CAAC,MAAM,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;QAChD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,wBAAwB,CAAC;QACtE,KAAK,GAAG,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC;QACvB,OAAO,KAAK,CAAC;IACf,CAAC,CAAC;IAEF,MAAM,QAAQ,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,UAAU,IAAI,IAAI,GAAG,EAAE,CAAC;IAE1D,OAAO;QACL,KAAK,CAAC,GAAG,CAAC,GAAW;YACnB,MAAM,CAAC,GAAG,MAAM,WAAW,EAAE,CAAC;YAC9B,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;YACvC,OAAO,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACtC,CAAC;QAED,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,KAAQ,EAAE,IAAuB;YACtD,MAAM,CAAC,GAAG,MAAM,WAAW,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,GAAG,IAAI,UAAU,CAAC,CAAC;YACjD,MAAM,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QAC9D,CAAC;QAED,KAAK,CAAC,QAAQ,CAAC,GAAW,EAAE,OAAyB,EAAE,IAAuB;YAC5E,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACrC,IAAI,QAAQ,KAAK,IAAI;gBAAE,OAAO,QAAQ,CAAC;YACvC,MAAM,KAAK,GAAG,MAAM,OAAO,EAAE,CAAC;YAC9B,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;YACjC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,GAAW;YACtB,MAAM,CAAC,GAAG,MAAM,WAAW,EAAE,CAAC;YAC9B,MAAM,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;QAC7B,CAAC;QAED,KAAK,CAAC,gBAAgB,CAAC,MAAc;YACnC,MAAM,CAAC,GAAG,MAAM,WAAW,EAAE,CAAC;YAC9B,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC;YAClD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;gBAAE,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;QAC5C,CAAC;QAED,KAAK,CAAC,SAAS,CAAC,GAAW,EAAE,IAAuB;YAClD,MAAM,CAAC,GAAG,MAAM,WAAW,EAAE,CAAC;YAC9B,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;YACxB,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC5B,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,EAAE,GAAG,EAAE,CAAC;gBAC3B,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;YACxC,CAAC;YACD,OAAO,GAAG,CAAC;QACb,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/dist/cron.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface CronConfig {
|
|
2
|
+
schedule: string;
|
|
3
|
+
handler: () => Promise<void>;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Declare a cron job.
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* export const cleanup = cron("cleanup", {
|
|
10
|
+
* schedule: "every 1 hour",
|
|
11
|
+
* handler: async () => {
|
|
12
|
+
* await db.query("DELETE FROM sessions WHERE expires_at < NOW()");
|
|
13
|
+
* },
|
|
14
|
+
* });
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export declare function cron(name: string, config: CronConfig): {
|
|
18
|
+
_cooper_type: "cron";
|
|
19
|
+
name: string;
|
|
20
|
+
schedule: string;
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=cron.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron.d.ts","sourceRoot":"","sources":["../src/cron.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU;;;;EAYpD"}
|