@ductape/mcp 0.2.33 → 0.2.35
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/index.js +163 -20
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -311,6 +311,31 @@ When the target application is a NestJS service or controller, always use @ducta
|
|
|
311
311
|
instead of instantiating @ductape/sdk directly. It provides NestJS DI integration,
|
|
312
312
|
global interceptors, decorators, and type-safe resource handles.
|
|
313
313
|
|
|
314
|
+
PRODUCT RUNTIME SNAPSHOT — REQUIRED FOR SERVER INITIALIZATION:
|
|
315
|
+
Always provide both product and env at module initialization. Nest awaits the SDK's initial
|
|
316
|
+
product runtime snapshot during onModuleInit, before the application accepts traffic. The
|
|
317
|
+
snapshot preloads connected App versions/actions plus database actions/schema metadata, graphs,
|
|
318
|
+
vectors, storage, brokers/topics, sessions, notifications, resilience assets, agents, functions,
|
|
319
|
+
and caches into the execution bootstrap cache. It also hydrates the selected Workbench App
|
|
320
|
+
connection for product+env (variables and token_access credentials). Do not emit api.config()
|
|
321
|
+
or api.oauth() boilerplate when that connection is already configured on the product. Explicit
|
|
322
|
+
api.config() is only a process-local override and has higher precedence. credential_access login
|
|
323
|
+
material remains isolated to the auth action and its encrypted refresh path. External provider/
|
|
324
|
+
database connections remain lazy and pooled.
|
|
325
|
+
|
|
326
|
+
Features, Quotas, Fallbacks, health checks, and direct api.run calls all reuse this same hydrated
|
|
327
|
+
connection through the action processor. Never create a second connection or copy secrets into a
|
|
328
|
+
Feature/Quota/Fallback definition. Reference the existing connected App access_tag and action tag.
|
|
329
|
+
|
|
330
|
+
Runtime synchronization is enabled by default when product + env are present. Do not set
|
|
331
|
+
runtimeSync:false merely to simplify generated code. Configure it only when the user has an
|
|
332
|
+
explicit operational reason:
|
|
333
|
+
runtimeSync: { intervalMs: 30_000, jitter: 0.2, maxBackoffMs: 300_000 }
|
|
334
|
+
|
|
335
|
+
Polling uses runtimeRevision + HTTP ETag/304. databaseRevision is a refresh hint included in the
|
|
336
|
+
umbrella runtimeRevision, so schema and Database Action changes are detected. Failed refreshes
|
|
337
|
+
retain the last-known-good snapshot. Nest stops polling through onModuleDestroy automatically.
|
|
338
|
+
|
|
314
339
|
SETUP — register once in AppModule:
|
|
315
340
|
|
|
316
341
|
╔══════════════════════════════════════════════════════════════════════════╗
|
|
@@ -338,6 +363,7 @@ SETUP — register once in AppModule:
|
|
|
338
363
|
product: 'my-product',
|
|
339
364
|
env: process.env.NODE_ENV === 'production' ? 'prd' : 'snd',
|
|
340
365
|
redisUrl: process.env.DUCTAPE_REDIS_URL, // required — no dispatch() works without this
|
|
366
|
+
runtimeSync: { intervalMs: 30_000, jitter: 0.2 },
|
|
341
367
|
}),
|
|
342
368
|
],
|
|
343
369
|
})
|
|
@@ -352,6 +378,7 @@ SETUP — register once in AppModule:
|
|
|
352
378
|
product: cfg.get('DUCTAPE_PRODUCT'),
|
|
353
379
|
env: cfg.get('DUCTAPE_ENV'),
|
|
354
380
|
redisUrl: cfg.get('DUCTAPE_REDIS_URL'), // required — no dispatch() works without this
|
|
381
|
+
runtimeSync: { intervalMs: 30_000, jitter: 0.2 },
|
|
355
382
|
}),
|
|
356
383
|
})
|
|
357
384
|
|
|
@@ -473,6 +500,7 @@ ALL params are passed as a JSON array in positional order matching the SDK signa
|
|
|
473
500
|
ductape_cli("products apps list --product <id_or_tag> --json") ← compact linked apps only
|
|
474
501
|
ductape_cli("products apps actions list --product <id_or_tag> --app <app_tag> --json")
|
|
475
502
|
ductape_cli("products apps actions get --product <id_or_tag> --app <app_tag> --action <action_tag> --json")
|
|
503
|
+
ductape_cli("products apps configure --product <id_or_tag> --app <app_or_access_tag> --connection-file ductape/apps/<app_tag>/connection.json --json")
|
|
476
504
|
|
|
477
505
|
SDK method signatures (for reference, admin key only):
|
|
478
506
|
product.create [data: { name, description, tag?, envs?: [{slug, name}] }]
|
|
@@ -484,6 +512,7 @@ ALL params are passed as a JSON array in positional order matching the SDK signa
|
|
|
484
512
|
product.apps.add [product_tag, app: { access_tag, envs: [{ app_env_slug, product_env_slug, variables?, auth? }] }]
|
|
485
513
|
product.apps.list [product_tag]
|
|
486
514
|
product.apps.fetch [product_tag, access_tag]
|
|
515
|
+
product.apps.update [product_tag, access_tag, { envs }] ← prefer CLI configure; it preserves omitted auth/variables
|
|
487
516
|
|
|
488
517
|
━━━ MODULE: app ━━━
|
|
489
518
|
app.create [data: { app_name: string, description: string, unique?: boolean }]
|
|
@@ -1186,6 +1215,11 @@ const marketplaceConnectInputSchema = z.object({
|
|
|
1186
1215
|
product_env_slug: z.string().min(1),
|
|
1187
1216
|
})).min(1).describe('Explicit app-to-product environment mappings. Include every product environment that will use the app.'),
|
|
1188
1217
|
});
|
|
1218
|
+
const appConnectionConfigureInputSchema = z.object({
|
|
1219
|
+
product_tag: z.string().min(1).describe('Product containing the existing App connection.'),
|
|
1220
|
+
app_tag: z.string().min(1).describe('Connected App tag or exact product access tag returned by products apps list.'),
|
|
1221
|
+
file: z.string().min(1).describe('Canonical JSON file under ductape/apps/<app-tag>/connection.json containing { envs: [...] }.'),
|
|
1222
|
+
});
|
|
1189
1223
|
const marketplaceInspectInputSchema = z.object({
|
|
1190
1224
|
app_tag: z.string().min(1).describe('Exact public app tag returned by ductape_marketplace_discover.'),
|
|
1191
1225
|
});
|
|
@@ -1312,18 +1346,24 @@ function buildTypeScriptSnippet(payload, operationFamily, method) {
|
|
|
1312
1346
|
const invocationArgs = buildSdkInvocationArgs(payload);
|
|
1313
1347
|
return `import Ductape from "@ductape/sdk";
|
|
1314
1348
|
|
|
1349
|
+
const payload = ${toPrettyJson(payload)};
|
|
1315
1350
|
const ductape = new Ductape({
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1351
|
+
accessKey: process.env.DUCTAPE_ACCESS_KEY!,
|
|
1352
|
+
product: String(payload.product),
|
|
1353
|
+
env: String(payload.env),
|
|
1319
1354
|
redis_url: process.env.DUCTAPE_REDIS_URL,
|
|
1355
|
+
runtime_sync: { interval_ms: 30_000, jitter: 0.2 },
|
|
1320
1356
|
});
|
|
1321
1357
|
|
|
1322
1358
|
async function run() {
|
|
1323
|
-
|
|
1359
|
+
await ductape.ready();
|
|
1324
1360
|
const args = ${toPrettyJson(invocationArgs)};
|
|
1325
|
-
|
|
1326
|
-
|
|
1361
|
+
try {
|
|
1362
|
+
const result = await ductape.${callPath}(args);
|
|
1363
|
+
return { payload, result };
|
|
1364
|
+
} finally {
|
|
1365
|
+
await ductape.close();
|
|
1366
|
+
}
|
|
1327
1367
|
}
|
|
1328
1368
|
|
|
1329
1369
|
run().catch(console.error);
|
|
@@ -1598,7 +1638,7 @@ function shellArgument(value) {
|
|
|
1598
1638
|
}
|
|
1599
1639
|
const docsInputSchema = z.object({
|
|
1600
1640
|
topic: z.string().describe('Feature topic to look up. Supported: ' +
|
|
1601
|
-
'transactions, presave, triggers, aggregations, migrations, indexes, performance, actions, ' +
|
|
1641
|
+
'transactions, presave, triggers, aggregations, migrations, indexes, performance, runtime-sync, actions, ' +
|
|
1602
1642
|
'graphs, storage, cloud, vector, warehouse, secrets, apps, products, sessions, caches, ' +
|
|
1603
1643
|
'notifications, resilience, features, portable-functions, events, logs, migration, cli-authentication, frontend, frontend-analytics, client, react, vue'),
|
|
1604
1644
|
});
|
|
@@ -2509,6 +2549,39 @@ DUCTAPE DATABASE PERFORMANCE GUIDANCE
|
|
|
2509
2549
|
5. Caching
|
|
2510
2550
|
- For read-heavy, rarely-changing data use caches.get before databases.query.
|
|
2511
2551
|
- Invalidate cache keys in an afterWrite trigger (see ductape_docs({ topic: "triggers" })).
|
|
2552
|
+
`.trim(),
|
|
2553
|
+
'runtime-sync': `
|
|
2554
|
+
DUCTAPE PRODUCT RUNTIME SNAPSHOTS
|
|
2555
|
+
|
|
2556
|
+
For every long-lived TypeScript/Node backend, initialize @ductape/sdk with accessKey, product,
|
|
2557
|
+
and env, then await ready() before accepting work:
|
|
2558
|
+
|
|
2559
|
+
const ductape = new Ductape({
|
|
2560
|
+
accessKey: process.env.DUCTAPE_ACCESS_KEY!,
|
|
2561
|
+
product: "payments",
|
|
2562
|
+
env: "prd",
|
|
2563
|
+
runtime_sync: { interval_ms: 30_000, jitter: 0.2, max_backoff_ms: 300_000 },
|
|
2564
|
+
});
|
|
2565
|
+
await ductape.ready();
|
|
2566
|
+
|
|
2567
|
+
This fetches one environment-scoped product snapshot and primes the existing bootstrap cache with
|
|
2568
|
+
connected App versions/actions, databases/actions/table schemas, graphs, vectors, storage,
|
|
2569
|
+
brokers/topics, sessions, notifications, resilience assets, agents, functions, and caches.
|
|
2570
|
+
Connections remain lazy and pooled; snapshot bootstrap does not call external providers.
|
|
2571
|
+
|
|
2572
|
+
Runtime synchronization is automatic when product + env are supplied:
|
|
2573
|
+
- Conditional polling sends If-None-Match with runtimeRevision; unchanged state returns HTTP 304.
|
|
2574
|
+
- runtimeRevision is authoritative. databaseRevision, connectionRevision, secretRevision, and
|
|
2575
|
+
assetRevision are narrower change hints. Any databaseRevision change also changes runtimeRevision.
|
|
2576
|
+
- A changed snapshot is loaded off-path and atomically replaces cache entries. Deleted assets are removed.
|
|
2577
|
+
- Refresh failure retains the last-known-good snapshot and retries with jittered exponential backoff.
|
|
2578
|
+
- Use runtimeSnapshotStatus() for revision/error telemetry and refreshRuntime() for an explicit pull.
|
|
2579
|
+
- Call close() during process shutdown. Do not create one Ductape instance per request.
|
|
2580
|
+
|
|
2581
|
+
For NestJS, use DuctapeModule.forIntegration({ accessKey, product, env, runtimeSync }) instead of
|
|
2582
|
+
new Ductape(). @ductape/nestjs awaits ready() in onModuleInit and closes the poller in
|
|
2583
|
+
onModuleDestroy. Never omit product/env when the service has stable defaults: doing so disables
|
|
2584
|
+
product snapshot bootstrap and returns execution to lazy per-asset bootstrap misses.
|
|
2512
2585
|
`.trim(),
|
|
2513
2586
|
actions: `
|
|
2514
2587
|
DUCTAPE DATABASE ACTIONS
|
|
@@ -3015,20 +3088,49 @@ CONNECT A DISCOVERED APP THROUGH MCP:
|
|
|
3015
3088
|
4. Match each product environment explicitly to one environment exposed by the app.
|
|
3016
3089
|
5. Call ductape_marketplace_connect({ product_tag, app_tag, environments }).
|
|
3017
3090
|
6. Verify with ductape_cli("products apps list --product <product_tag> --json").
|
|
3091
|
+
7. If the App requires variables or auth, create the canonical file at
|
|
3092
|
+
ductape/apps/<app_tag>/connection.json and call ductape_app_connection_configure. A bare
|
|
3093
|
+
connect only establishes access + environment mapping; it does not invent configuration.
|
|
3018
3094
|
Never guess environment mappings or action tags. Connecting mutates product configuration;
|
|
3019
3095
|
obtain user approval when the user has not already requested the connection.
|
|
3020
3096
|
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3097
|
+
Visibility: public marketplace Apps and private Apps owned by the current workspace can be
|
|
3098
|
+
connected. A private App owned by another workspace must be rejected; do not retry around that
|
|
3099
|
+
ownership boundary.
|
|
3100
|
+
|
|
3101
|
+
CONNECTION FILE — REQUIRED SHAPE:
|
|
3102
|
+
File: ductape/apps/<app_tag>/connection.json
|
|
3103
|
+
{
|
|
3104
|
+
"envs": [{
|
|
3105
|
+
"product_env_slug": "prd",
|
|
3106
|
+
"app_env_slug": "production",
|
|
3107
|
+
"variables": [{ "key": "region", "value": "ng" }],
|
|
3108
|
+
"auth": {
|
|
3109
|
+
"auth_tag": "secret-key",
|
|
3110
|
+
"data": {
|
|
3111
|
+
"headers": { "Authorization": "$Secret{PAYSTACK_SECRET_KEY}" },
|
|
3112
|
+
"query": {}, "params": {}, "body": {}
|
|
3113
|
+
}
|
|
3114
|
+
}
|
|
3115
|
+
}]
|
|
3116
|
+
}
|
|
3117
|
+
|
|
3118
|
+
Before writing this file, inspect the exact App version/auth/action schemas. auth.data must have
|
|
3119
|
+
headers/query/params/body objects and must match the selected auth schema. Never guess an auth_tag,
|
|
3120
|
+
variable key, input location, or required field. Store credentials with secrets.create first and
|
|
3121
|
+
write $Secret{KEY}, never plaintext, into the connection file.
|
|
3122
|
+
|
|
3123
|
+
CREATE/REPAIR/ROTATE:
|
|
3124
|
+
ductape_cli("products apps configure --product <product_tag> --app <app_or_access_tag> \
|
|
3125
|
+
--connection-file ductape/apps/<app_tag>/connection.json --json")
|
|
3126
|
+
The command is merge-safe: an omitted auth or variables field preserves the existing saved field.
|
|
3127
|
+
Providing auth or variables explicitly replaces that field for the named product environment.
|
|
3128
|
+
It never returns saved credential values. Include only environments intentionally being changed;
|
|
3129
|
+
other existing mappings are retained. To repair an old connection with no mapping, add its row.
|
|
3130
|
+
|
|
3131
|
+
After configuration, verify the non-secret summary with products apps list, then inspect the exact
|
|
3132
|
+
action contract. Do not test a payment or other side-effecting action merely to verify connection
|
|
3133
|
+
persistence unless the user explicitly requests a safe test and supplies appropriate test input.
|
|
3032
3134
|
|
|
3033
3135
|
ONLY after all five steps can any code call:
|
|
3034
3136
|
ctx.api.run({ app: '<app_tag>', action: '<action_tag>', input: { ... } }) ← in a feature handler
|
|
@@ -3202,8 +3304,11 @@ Product structure (IProduct fields):
|
|
|
3202
3304
|
workflows[] (features), models[], agents[], jobs[]
|
|
3203
3305
|
|
|
3204
3306
|
Bootstrap (single API call returning product context + component config + private key):
|
|
3205
|
-
|
|
3206
|
-
|
|
3307
|
+
Initialize @ductape/sdk with product + env and await ductape.ready(). It fetches the full
|
|
3308
|
+
environment-scoped product runtime snapshot and primes BootstrapCache for connected App actions
|
|
3309
|
+
and product components. A service falls back to its targeted bootstrap endpoint only when the
|
|
3310
|
+
requested asset is absent. Polling uses ETag/304 and atomically refreshes changed state.
|
|
3311
|
+
See ductape_docs({ topic: "runtime-sync" }).
|
|
3207
3312
|
`.trim(),
|
|
3208
3313
|
sessions: `
|
|
3209
3314
|
DUCTAPE SESSIONS
|
|
@@ -4537,8 +4642,12 @@ Import (register an EXISTING cloud resource):
|
|
|
4537
4642
|
// dispatch() requires redis_url in the Ductape initialization options — it throws at runtime without it.
|
|
4538
4643
|
const ductape = new Ductape({
|
|
4539
4644
|
accessKey: process.env.DUCTAPE_ACCESS_KEY,
|
|
4645
|
+
product: "my-product",
|
|
4646
|
+
env: "prd",
|
|
4540
4647
|
redis_url: process.env.DUCTAPE_REDIS_URL, // required for any dispatch(); omit only if never dispatching
|
|
4648
|
+
runtime_sync: { interval_ms: 30_000, jitter: 0.2 },
|
|
4541
4649
|
});
|
|
4650
|
+
await ductape.ready();
|
|
4542
4651
|
await ductape.events.produce({
|
|
4543
4652
|
product: "my-product",
|
|
4544
4653
|
env: "prd",
|
|
@@ -4561,6 +4670,7 @@ Import (register an EXISTING cloud resource):
|
|
|
4561
4670
|
product: 'my-product',
|
|
4562
4671
|
env: process.env.NODE_ENV === 'production' ? 'prd' : 'snd',
|
|
4563
4672
|
redisUrl: process.env.DUCTAPE_REDIS_URL, // required — dispatch() throws without this
|
|
4673
|
+
runtimeSync: { intervalMs: 30_000, jitter: 0.2 },
|
|
4564
4674
|
}),
|
|
4565
4675
|
});
|
|
4566
4676
|
// Environment: DUCTAPE_REDIS_URL=redis://localhost:6379 (local) or rediss://:<pw>@host:6380 (managed)
|
|
@@ -5665,6 +5775,12 @@ const integrateEndpointHandler = async (args) => {
|
|
|
5665
5775
|
'Run: ductape_cli("products apps connect --product <product_tag> --app <app_tag> --env-map ' +
|
|
5666
5776
|
'<app_env>:<product_env> [repeat --env-map per environment] --json"). If the app is a public ' +
|
|
5667
5777
|
'marketplace app, ductape_marketplace_connect does the same thing in one call.',
|
|
5778
|
+
'If the App declares variables or auth, connecting is not the end: call ductape_schema for the ' +
|
|
5779
|
+
'exact app/auth contract, store credential values with secrets.create, write ' +
|
|
5780
|
+
'ductape/apps/<app_tag>/connection.json using $Secret{KEY} references, and call ' +
|
|
5781
|
+
'ductape_app_connection_configure. Never put plaintext secrets in the asset file.',
|
|
5782
|
+
'For an already-connected App, skip connect and use configure. Omitted auth/variables preserve ' +
|
|
5783
|
+
'the current encrypted values, so mapping-only repairs must not force credential rotation.',
|
|
5668
5784
|
],
|
|
5669
5785
|
});
|
|
5670
5786
|
stages.push({
|
|
@@ -5867,6 +5983,11 @@ const DUCTAPE_FIRST_DOCTRINE = 'Follow this checklist before defaulting to plain
|
|
|
5867
5983
|
'(ductape.functions.register/use) — register portable business logic once and reuse it across ' +
|
|
5868
5984
|
'every Feature that needs it. Call ductape_schema before constructing any new resource file, ' +
|
|
5869
5985
|
'so you match the exact required shape rather than guessing.\n\n' +
|
|
5986
|
+
'7. A Workbench App connection is perpetual product+environment runtime configuration. Once its ' +
|
|
5987
|
+
'environment mapping, variables, and auth are saved, generated server code must initialize the ' +
|
|
5988
|
+
'SDK with product+env and await ready(); do not repeat api.config/api.oauth in every codebase. ' +
|
|
5989
|
+
'Direct actions, Features, Quotas, Fallbacks, and health checks reuse that hydrated connection. ' +
|
|
5990
|
+
'Use api.config only when the user explicitly asks for a local override.\n\n' +
|
|
5870
5991
|
'Default assumption for any backend built through this MCP server: orchestration goes through ' +
|
|
5871
5992
|
'Features, provider risk goes through Quotas/Fallback, credentials go through Secrets, shared ' +
|
|
5872
5993
|
'capability goes through reuse, and the ductape/ folder is what ships — not a database table ' +
|
|
@@ -6613,6 +6734,28 @@ async function main() {
|
|
|
6613
6734
|
command: `products apps connect --product ${shellArgument(args.product_tag)} --app ${shellArgument(args.app_tag)}${mappings} --json`,
|
|
6614
6735
|
});
|
|
6615
6736
|
});
|
|
6737
|
+
server.registerTool('ductape_app_connection_configure', {
|
|
6738
|
+
title: 'Configure a Connected Ductape App',
|
|
6739
|
+
description: 'Configure, repair, or rotate an existing product App connection from its canonical JSON asset. ' +
|
|
6740
|
+
'Inspect the App/auth schema first, store secrets separately, use $Secret{KEY} references, and ' +
|
|
6741
|
+
'keep the file under ductape/apps/<app-tag>/connection.json. Omitted auth or variables preserve ' +
|
|
6742
|
+
'the saved encrypted field; the tool never reads credential values back.',
|
|
6743
|
+
inputSchema: appConnectionConfigureInputSchema,
|
|
6744
|
+
}, async (args) => {
|
|
6745
|
+
const normalized = args.file.replace(/\\/g, '/');
|
|
6746
|
+
if (!/(^|\/)ductape\/apps\/[^/]+\/connection\.json$/.test(normalized)) {
|
|
6747
|
+
return {
|
|
6748
|
+
content: [{ type: 'text', text: JSON.stringify({
|
|
6749
|
+
error: 'INVALID_ASSET_PATH',
|
|
6750
|
+
message: 'Connection assets must be permanent JSON files at ductape/apps/<app-tag>/connection.json.',
|
|
6751
|
+
}, null, 2) }],
|
|
6752
|
+
isError: true,
|
|
6753
|
+
};
|
|
6754
|
+
}
|
|
6755
|
+
return cliHandler({
|
|
6756
|
+
command: `products apps configure --product ${shellArgument(args.product_tag)} --app ${shellArgument(args.app_tag)} --connection-file ${shellArgument(args.file)} --json`,
|
|
6757
|
+
});
|
|
6758
|
+
});
|
|
6616
6759
|
server.registerTool('ductape_integrate_endpoint', {
|
|
6617
6760
|
title: 'Integrate a New Endpoint',
|
|
6618
6761
|
description: 'Call this FIRST whenever the user wants to integrate a new API endpoint — before writing any ' +
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ductape/mcp",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.35",
|
|
4
4
|
"description": "MCP server that exposes Ductape SDK operations via the backend proxy",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
],
|
|
16
16
|
"scripts": {
|
|
17
17
|
"build": "tsc",
|
|
18
|
-
"test": "npm run build && node scripts/check-cli-command-security.mjs && node scripts/check-frontend-analytics-guidance.mjs && node scripts/check-events-discovery.mjs && node scripts/check-schema-fallback.mjs && node scripts/check-paystack-action-schema.mjs && node scripts/check-portable-functions.mjs && node scripts/check-feature-control-flow.mjs && node scripts/check-project-link-guidance.mjs && node scripts/check-graph-vector-projection-guidance.mjs && node scripts/check-asset-file-guidance.mjs && node scripts/check-database-action-contract-guidance.mjs",
|
|
18
|
+
"test": "npm run build && node scripts/check-cli-command-security.mjs && node scripts/check-frontend-analytics-guidance.mjs && node scripts/check-events-discovery.mjs && node scripts/check-schema-fallback.mjs && node scripts/check-paystack-action-schema.mjs && node scripts/check-portable-functions.mjs && node scripts/check-feature-control-flow.mjs && node scripts/check-project-link-guidance.mjs && node scripts/check-graph-vector-projection-guidance.mjs && node scripts/check-asset-file-guidance.mjs && node scripts/check-database-action-contract-guidance.mjs && node scripts/check-runtime-sync-guidance.mjs",
|
|
19
19
|
"start": "node dist/index.js",
|
|
20
20
|
"dev": "tsx src/index.ts"
|
|
21
21
|
},
|