@meetploy/cli 1.12.2 → 1.13.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/dashboard-dist/assets/main-Bj2g1WCI.js +324 -0
- package/dist/dashboard-dist/assets/{main-BnI0iIIW.css → main-q4PKg1PN.css} +1 -1
- package/dist/dashboard-dist/index.html +2 -2
- package/dist/dev.js +79 -0
- package/dist/index.js +197 -22
- package/package.json +1 -1
- package/dist/dashboard-dist/assets/main-DnrX4BgS.js +0 -319
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'module';
|
|
3
3
|
import { mkdir, writeFile, readFile, chmod, access } from 'fs/promises';
|
|
4
|
-
import { join, dirname, relative } from 'path';
|
|
4
|
+
import { join, dirname, relative, basename } from 'path';
|
|
5
5
|
import { existsSync, readFileSync, writeFileSync, unlinkSync, readFile as readFile$1, mkdirSync } from 'fs';
|
|
6
6
|
import { promisify } from 'util';
|
|
7
7
|
import { parse } from 'yaml';
|
|
@@ -196,6 +196,7 @@ function validatePloyConfig(config, configFile = "ploy.yaml", options = {}) {
|
|
|
196
196
|
validatedConfig.main = validateRelativePath(config.main, "main", configFile);
|
|
197
197
|
validateBindings(config.db, "db", configFile);
|
|
198
198
|
validateBindings(config.queue, "queue", configFile);
|
|
199
|
+
validateBindings(config.cache, "cache", configFile);
|
|
199
200
|
validateBindings(config.workflow, "workflow", configFile);
|
|
200
201
|
if (config.ai !== void 0 && typeof config.ai !== "boolean") {
|
|
201
202
|
throw new Error(`'ai' in ${configFile} must be a boolean`);
|
|
@@ -275,7 +276,7 @@ function readAndValidatePloyConfigSync(projectDir, configPath, validationOptions
|
|
|
275
276
|
return validatePloyConfig(config, configFile, validationOptions);
|
|
276
277
|
}
|
|
277
278
|
function hasBindings(config) {
|
|
278
|
-
return !!(config.db || config.queue || config.workflow || config.ai || config.auth);
|
|
279
|
+
return !!(config.db || config.queue || config.cache || config.workflow || config.ai || config.auth);
|
|
279
280
|
}
|
|
280
281
|
function getWorkerEntryPoint(projectDir, config) {
|
|
281
282
|
if (config.main) {
|
|
@@ -331,6 +332,66 @@ var init_cli = __esm({
|
|
|
331
332
|
}
|
|
332
333
|
});
|
|
333
334
|
|
|
335
|
+
// ../emulator/dist/runtime/cache-runtime.js
|
|
336
|
+
var CACHE_RUNTIME_CODE;
|
|
337
|
+
var init_cache_runtime = __esm({
|
|
338
|
+
"../emulator/dist/runtime/cache-runtime.js"() {
|
|
339
|
+
CACHE_RUNTIME_CODE = `
|
|
340
|
+
interface CacheBinding {
|
|
341
|
+
get: (key: string) => Promise<string | null>;
|
|
342
|
+
set: (key: string, value: string, opts: { ttl: number }) => Promise<void>;
|
|
343
|
+
delete: (key: string) => Promise<void>;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
export function initializeCache(cacheName: string, serviceUrl: string): CacheBinding {
|
|
347
|
+
return {
|
|
348
|
+
async get(key: string): Promise<string | null> {
|
|
349
|
+
const response = await fetch(serviceUrl + "/cache/get", {
|
|
350
|
+
method: "POST",
|
|
351
|
+
headers: { "Content-Type": "application/json" },
|
|
352
|
+
body: JSON.stringify({ cacheName, key }),
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
if (!response.ok) {
|
|
356
|
+
const errorText = await response.text();
|
|
357
|
+
throw new Error("Cache get failed: " + errorText);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
const result = await response.json();
|
|
361
|
+
return result.value ?? null;
|
|
362
|
+
},
|
|
363
|
+
|
|
364
|
+
async set(key: string, value: string, opts: { ttl: number }): Promise<void> {
|
|
365
|
+
const response = await fetch(serviceUrl + "/cache/set", {
|
|
366
|
+
method: "POST",
|
|
367
|
+
headers: { "Content-Type": "application/json" },
|
|
368
|
+
body: JSON.stringify({ cacheName, key, value, ttl: opts.ttl }),
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
if (!response.ok) {
|
|
372
|
+
const errorText = await response.text();
|
|
373
|
+
throw new Error("Cache set failed: " + errorText);
|
|
374
|
+
}
|
|
375
|
+
},
|
|
376
|
+
|
|
377
|
+
async delete(key: string): Promise<void> {
|
|
378
|
+
const response = await fetch(serviceUrl + "/cache/delete", {
|
|
379
|
+
method: "POST",
|
|
380
|
+
headers: { "Content-Type": "application/json" },
|
|
381
|
+
body: JSON.stringify({ cacheName, key }),
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
if (!response.ok) {
|
|
385
|
+
const errorText = await response.text();
|
|
386
|
+
throw new Error("Cache delete failed: " + errorText);
|
|
387
|
+
}
|
|
388
|
+
},
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
`;
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
|
|
334
395
|
// ../shared/dist/d1-runtime.js
|
|
335
396
|
var DB_RUNTIME_CODE, DB_RUNTIME_CODE_PRODUCTION;
|
|
336
397
|
var init_d1_runtime = __esm({
|
|
@@ -942,6 +1003,12 @@ function generateWrapperCode(config, mockServiceUrl) {
|
|
|
942
1003
|
bindings.push(` ${bindingName}: initializeQueue("${queueName}", "${mockServiceUrl}"),`);
|
|
943
1004
|
}
|
|
944
1005
|
}
|
|
1006
|
+
if (config.cache) {
|
|
1007
|
+
imports.push('import { initializeCache } from "__ploy_cache_runtime__";');
|
|
1008
|
+
for (const [bindingName, cacheName] of Object.entries(config.cache)) {
|
|
1009
|
+
bindings.push(` ${bindingName}: initializeCache("${cacheName}", "${mockServiceUrl}"),`);
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
945
1012
|
if (config.workflow) {
|
|
946
1013
|
imports.push('import { initializeWorkflow, createStepContext, executeWorkflow } from "__ploy_workflow_runtime__";');
|
|
947
1014
|
for (const [bindingName, workflowName] of Object.entries(config.workflow)) {
|
|
@@ -1045,6 +1112,10 @@ function createRuntimePlugin(_config) {
|
|
|
1045
1112
|
path: "__ploy_queue_runtime__",
|
|
1046
1113
|
namespace: "ploy-runtime"
|
|
1047
1114
|
}));
|
|
1115
|
+
build2.onResolve({ filter: /^__ploy_cache_runtime__$/ }, () => ({
|
|
1116
|
+
path: "__ploy_cache_runtime__",
|
|
1117
|
+
namespace: "ploy-runtime"
|
|
1118
|
+
}));
|
|
1048
1119
|
build2.onResolve({ filter: /^__ploy_workflow_runtime__$/ }, () => ({
|
|
1049
1120
|
path: "__ploy_workflow_runtime__",
|
|
1050
1121
|
namespace: "ploy-runtime"
|
|
@@ -1057,6 +1128,10 @@ function createRuntimePlugin(_config) {
|
|
|
1057
1128
|
contents: QUEUE_RUNTIME_CODE,
|
|
1058
1129
|
loader: "ts"
|
|
1059
1130
|
}));
|
|
1131
|
+
build2.onLoad({ filter: /^__ploy_cache_runtime__$/, namespace: "ploy-runtime" }, () => ({
|
|
1132
|
+
contents: CACHE_RUNTIME_CODE,
|
|
1133
|
+
loader: "ts"
|
|
1134
|
+
}));
|
|
1060
1135
|
build2.onLoad({ filter: /^__ploy_workflow_runtime__$/, namespace: "ploy-runtime" }, () => ({
|
|
1061
1136
|
contents: WORKFLOW_RUNTIME_CODE,
|
|
1062
1137
|
loader: "ts"
|
|
@@ -1097,6 +1172,7 @@ async function bundleWorker(options) {
|
|
|
1097
1172
|
var NODE_BUILTINS;
|
|
1098
1173
|
var init_bundler = __esm({
|
|
1099
1174
|
"../emulator/dist/bundler/bundler.js"() {
|
|
1175
|
+
init_cache_runtime();
|
|
1100
1176
|
init_db_runtime();
|
|
1101
1177
|
init_queue_runtime();
|
|
1102
1178
|
init_workflow_runtime();
|
|
@@ -1156,9 +1232,6 @@ function log(message) {
|
|
|
1156
1232
|
function success(message) {
|
|
1157
1233
|
console.log(`${COLORS.dim}[${timestamp()}]${COLORS.reset} ${COLORS.green}[ploy]${COLORS.reset} ${message}`);
|
|
1158
1234
|
}
|
|
1159
|
-
function warn(message) {
|
|
1160
|
-
console.log(`${COLORS.dim}[${timestamp()}]${COLORS.reset} ${COLORS.yellow}[ploy]${COLORS.reset} ${message}`);
|
|
1161
|
-
}
|
|
1162
1235
|
function error(message) {
|
|
1163
1236
|
console.error(`${COLORS.dim}[${timestamp()}]${COLORS.reset} ${COLORS.red}[ploy]${COLORS.reset} ${message}`);
|
|
1164
1237
|
}
|
|
@@ -1181,6 +1254,22 @@ var init_logger = __esm({
|
|
|
1181
1254
|
};
|
|
1182
1255
|
}
|
|
1183
1256
|
});
|
|
1257
|
+
function isIgnored(filePath) {
|
|
1258
|
+
const name = basename(filePath);
|
|
1259
|
+
if (name.startsWith(".")) {
|
|
1260
|
+
return true;
|
|
1261
|
+
}
|
|
1262
|
+
if (IGNORED_DIRS.has(name)) {
|
|
1263
|
+
return true;
|
|
1264
|
+
}
|
|
1265
|
+
if (IGNORED_FILES.has(name)) {
|
|
1266
|
+
return true;
|
|
1267
|
+
}
|
|
1268
|
+
if (name.endsWith(".log")) {
|
|
1269
|
+
return true;
|
|
1270
|
+
}
|
|
1271
|
+
return false;
|
|
1272
|
+
}
|
|
1184
1273
|
function createFileWatcher(srcDir, onRebuild) {
|
|
1185
1274
|
let watcher = null;
|
|
1186
1275
|
let debounceTimer = null;
|
|
@@ -1213,25 +1302,11 @@ function createFileWatcher(srcDir, onRebuild) {
|
|
|
1213
1302
|
watcher = watch(srcDir, {
|
|
1214
1303
|
persistent: true,
|
|
1215
1304
|
ignoreInitial: true,
|
|
1216
|
-
ignored:
|
|
1217
|
-
"**/node_modules/**",
|
|
1218
|
-
"**/dist/**",
|
|
1219
|
-
"**/.*",
|
|
1220
|
-
"**/.*/**",
|
|
1221
|
-
"**/coverage/**",
|
|
1222
|
-
"**/build/**",
|
|
1223
|
-
"**/*.log",
|
|
1224
|
-
"**/pnpm-lock.yaml",
|
|
1225
|
-
"**/package-lock.json",
|
|
1226
|
-
"**/yarn.lock"
|
|
1227
|
-
]
|
|
1305
|
+
ignored: isIgnored
|
|
1228
1306
|
});
|
|
1229
1307
|
watcher.on("error", (err) => {
|
|
1230
1308
|
const error2 = err;
|
|
1231
|
-
if (error2.code
|
|
1232
|
-
warn("Warning: Too many open files. Some file changes may not be detected.");
|
|
1233
|
-
warn("Consider increasing your system's file descriptor limit (ulimit -n).");
|
|
1234
|
-
} else {
|
|
1309
|
+
if (error2.code !== "EMFILE") {
|
|
1235
1310
|
error(`File watcher error: ${error2.message || String(err)}`);
|
|
1236
1311
|
}
|
|
1237
1312
|
});
|
|
@@ -1263,9 +1338,16 @@ function createFileWatcher(srcDir, onRebuild) {
|
|
|
1263
1338
|
}
|
|
1264
1339
|
};
|
|
1265
1340
|
}
|
|
1341
|
+
var IGNORED_DIRS, IGNORED_FILES;
|
|
1266
1342
|
var init_watcher = __esm({
|
|
1267
1343
|
"../emulator/dist/bundler/watcher.js"() {
|
|
1268
1344
|
init_logger();
|
|
1345
|
+
IGNORED_DIRS = /* @__PURE__ */ new Set(["node_modules", "dist", "coverage", "build"]);
|
|
1346
|
+
IGNORED_FILES = /* @__PURE__ */ new Set([
|
|
1347
|
+
"pnpm-lock.yaml",
|
|
1348
|
+
"package-lock.json",
|
|
1349
|
+
"yarn.lock"
|
|
1350
|
+
]);
|
|
1269
1351
|
}
|
|
1270
1352
|
});
|
|
1271
1353
|
|
|
@@ -1587,6 +1669,40 @@ var init_auth_service = __esm({
|
|
|
1587
1669
|
SESSION_TOKEN_EXPIRY = 7 * 24 * 60 * 60;
|
|
1588
1670
|
}
|
|
1589
1671
|
});
|
|
1672
|
+
|
|
1673
|
+
// ../emulator/dist/services/cache-service.js
|
|
1674
|
+
function createCacheHandlers(db) {
|
|
1675
|
+
const getHandler = async (c) => {
|
|
1676
|
+
const body = await c.req.json();
|
|
1677
|
+
const { cacheName, key } = body;
|
|
1678
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
1679
|
+
const row = db.prepare(`SELECT value FROM cache_entries WHERE cache_name = ? AND key = ? AND expires_at > ?`).get(cacheName, key, now);
|
|
1680
|
+
return c.json({ value: row?.value ?? null });
|
|
1681
|
+
};
|
|
1682
|
+
const setHandler = async (c) => {
|
|
1683
|
+
const body = await c.req.json();
|
|
1684
|
+
const { cacheName, key, value, ttl } = body;
|
|
1685
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
1686
|
+
const expiresAt = now + ttl;
|
|
1687
|
+
db.prepare(`INSERT OR REPLACE INTO cache_entries (cache_name, key, value, expires_at) VALUES (?, ?, ?, ?)`).run(cacheName, key, value, expiresAt);
|
|
1688
|
+
return c.json({ success: true });
|
|
1689
|
+
};
|
|
1690
|
+
const deleteHandler = async (c) => {
|
|
1691
|
+
const body = await c.req.json();
|
|
1692
|
+
const { cacheName, key } = body;
|
|
1693
|
+
db.prepare(`DELETE FROM cache_entries WHERE cache_name = ? AND key = ?`).run(cacheName, key);
|
|
1694
|
+
return c.json({ success: true });
|
|
1695
|
+
};
|
|
1696
|
+
return {
|
|
1697
|
+
getHandler,
|
|
1698
|
+
setHandler,
|
|
1699
|
+
deleteHandler
|
|
1700
|
+
};
|
|
1701
|
+
}
|
|
1702
|
+
var init_cache_service = __esm({
|
|
1703
|
+
"../emulator/dist/services/cache-service.js"() {
|
|
1704
|
+
}
|
|
1705
|
+
});
|
|
1590
1706
|
function findDashboardDistPath() {
|
|
1591
1707
|
const possiblePaths = [
|
|
1592
1708
|
join(__dirname, "dashboard-dist"),
|
|
@@ -1614,6 +1730,7 @@ function createDashboardRoutes(app, dbManager2, config) {
|
|
|
1614
1730
|
return c.json({
|
|
1615
1731
|
db: config.db,
|
|
1616
1732
|
queue: config.queue,
|
|
1733
|
+
cache: config.cache,
|
|
1617
1734
|
workflow: config.workflow,
|
|
1618
1735
|
auth: config.auth
|
|
1619
1736
|
});
|
|
@@ -1954,6 +2071,39 @@ function createDashboardRoutes(app, dbManager2, config) {
|
|
|
1954
2071
|
return c.json({ error: err instanceof Error ? err.message : String(err) }, 500);
|
|
1955
2072
|
}
|
|
1956
2073
|
});
|
|
2074
|
+
app.get("/api/cache/:binding/entries", (c) => {
|
|
2075
|
+
const binding = c.req.param("binding");
|
|
2076
|
+
const cacheName = config.cache?.[binding];
|
|
2077
|
+
const limit = parseInt(c.req.query("limit") || "20", 10);
|
|
2078
|
+
const offset = parseInt(c.req.query("offset") || "0", 10);
|
|
2079
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
2080
|
+
if (!cacheName) {
|
|
2081
|
+
return c.json({ error: "Cache binding not found" }, 404);
|
|
2082
|
+
}
|
|
2083
|
+
try {
|
|
2084
|
+
const db = dbManager2.emulatorDb;
|
|
2085
|
+
const total = db.prepare(`SELECT COUNT(*) as count FROM cache_entries
|
|
2086
|
+
WHERE cache_name = ? AND expires_at > ?`).get(cacheName, now).count;
|
|
2087
|
+
const entries = db.prepare(`SELECT key, value, expires_at
|
|
2088
|
+
FROM cache_entries
|
|
2089
|
+
WHERE cache_name = ? AND expires_at > ?
|
|
2090
|
+
ORDER BY key ASC
|
|
2091
|
+
LIMIT ? OFFSET ?`).all(cacheName, now, limit, offset);
|
|
2092
|
+
return c.json({
|
|
2093
|
+
entries: entries.map((e) => ({
|
|
2094
|
+
key: e.key,
|
|
2095
|
+
value: e.value,
|
|
2096
|
+
ttlSeconds: Math.max(0, e.expires_at - now),
|
|
2097
|
+
expiresAt: new Date(e.expires_at * 1e3).toISOString()
|
|
2098
|
+
})),
|
|
2099
|
+
total,
|
|
2100
|
+
limit,
|
|
2101
|
+
offset
|
|
2102
|
+
});
|
|
2103
|
+
} catch (err) {
|
|
2104
|
+
return c.json({ error: err instanceof Error ? err.message : String(err) }, 500);
|
|
2105
|
+
}
|
|
2106
|
+
});
|
|
1957
2107
|
app.get("/api/workflow/:binding/executions", (c) => {
|
|
1958
2108
|
const binding = c.req.param("binding");
|
|
1959
2109
|
const workflowConfig = config.workflow?.[binding];
|
|
@@ -2583,6 +2733,12 @@ async function startMockServer(dbManager2, config, options = {}) {
|
|
|
2583
2733
|
app.post("/workflow/complete", workflowHandlers.completeHandler);
|
|
2584
2734
|
app.post("/workflow/fail", workflowHandlers.failHandler);
|
|
2585
2735
|
}
|
|
2736
|
+
if (config.cache) {
|
|
2737
|
+
const cacheHandlers = createCacheHandlers(dbManager2.emulatorDb);
|
|
2738
|
+
app.post("/cache/get", cacheHandlers.getHandler);
|
|
2739
|
+
app.post("/cache/set", cacheHandlers.setHandler);
|
|
2740
|
+
app.post("/cache/delete", cacheHandlers.deleteHandler);
|
|
2741
|
+
}
|
|
2586
2742
|
if (config.auth) {
|
|
2587
2743
|
const authHandlers = createAuthHandlers(dbManager2.emulatorDb);
|
|
2588
2744
|
app.post("/auth/signup", authHandlers.signupHandler);
|
|
@@ -2613,6 +2769,7 @@ var DEFAULT_MOCK_SERVER_PORT;
|
|
|
2613
2769
|
var init_mock_server = __esm({
|
|
2614
2770
|
"../emulator/dist/services/mock-server.js"() {
|
|
2615
2771
|
init_auth_service();
|
|
2772
|
+
init_cache_service();
|
|
2616
2773
|
init_dashboard_routes();
|
|
2617
2774
|
init_db_service();
|
|
2618
2775
|
init_queue_service();
|
|
@@ -2772,6 +2929,15 @@ CREATE TABLE IF NOT EXISTS auth_settings (
|
|
|
2772
2929
|
|
|
2773
2930
|
-- Insert default settings if not exists
|
|
2774
2931
|
INSERT OR IGNORE INTO auth_settings (id) VALUES (1);
|
|
2932
|
+
|
|
2933
|
+
-- Cache entries table
|
|
2934
|
+
CREATE TABLE IF NOT EXISTS cache_entries (
|
|
2935
|
+
cache_name TEXT NOT NULL,
|
|
2936
|
+
key TEXT NOT NULL,
|
|
2937
|
+
value TEXT NOT NULL,
|
|
2938
|
+
expires_at INTEGER NOT NULL,
|
|
2939
|
+
PRIMARY KEY (cache_name, key)
|
|
2940
|
+
);
|
|
2775
2941
|
`;
|
|
2776
2942
|
}
|
|
2777
2943
|
});
|
|
@@ -2872,6 +3038,9 @@ var init_emulator = __esm({
|
|
|
2872
3038
|
if (this.config.queue) {
|
|
2873
3039
|
log(` Queue bindings: ${Object.keys(this.config.queue).join(", ")}`);
|
|
2874
3040
|
}
|
|
3041
|
+
if (this.config.cache) {
|
|
3042
|
+
log(` Cache bindings: ${Object.keys(this.config.cache).join(", ")}`);
|
|
3043
|
+
}
|
|
2875
3044
|
if (this.config.workflow) {
|
|
2876
3045
|
log(` Workflow bindings: ${Object.keys(this.config.workflow).join(", ")}`);
|
|
2877
3046
|
}
|
|
@@ -4856,6 +5025,12 @@ function generateEnvType(config) {
|
|
|
4856
5025
|
properties.push(` ${bindingName}: QueueBinding;`);
|
|
4857
5026
|
}
|
|
4858
5027
|
}
|
|
5028
|
+
if (config.cache) {
|
|
5029
|
+
imports.push("CacheBinding");
|
|
5030
|
+
for (const bindingName of Object.keys(config.cache)) {
|
|
5031
|
+
properties.push(` ${bindingName}: CacheBinding;`);
|
|
5032
|
+
}
|
|
5033
|
+
}
|
|
4859
5034
|
if (config.workflow) {
|
|
4860
5035
|
imports.push("WorkflowBinding");
|
|
4861
5036
|
for (const bindingName of Object.keys(config.workflow)) {
|
|
@@ -4903,7 +5078,7 @@ async function typesCommand(options = {}) {
|
|
|
4903
5078
|
console.error("Error: ploy.yaml not found in current directory");
|
|
4904
5079
|
process.exit(1);
|
|
4905
5080
|
}
|
|
4906
|
-
const hasBindings2 = config.ai || config.db || config.queue || config.workflow;
|
|
5081
|
+
const hasBindings2 = config.ai || config.db || config.queue || config.cache || config.workflow;
|
|
4907
5082
|
if (!hasBindings2) {
|
|
4908
5083
|
console.log("No bindings found in ploy.yaml. Generating empty Env.");
|
|
4909
5084
|
}
|