directus-deploy-cli 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.
Files changed (46) hide show
  1. package/README.md +62 -0
  2. package/dist/cli.js +132 -0
  3. package/dist/cli.js.map +1 -0
  4. package/dist/diff.js +31 -0
  5. package/dist/diff.js.map +1 -0
  6. package/dist/http.js +114 -0
  7. package/dist/http.js.map +1 -0
  8. package/dist/identity.js +124 -0
  9. package/dist/identity.js.map +1 -0
  10. package/dist/manifest.js +84 -0
  11. package/dist/manifest.js.map +1 -0
  12. package/dist/mcp-server.js +197 -0
  13. package/dist/mcp-server.js.map +1 -0
  14. package/dist/reconcilers/collections.js +82 -0
  15. package/dist/reconcilers/collections.js.map +1 -0
  16. package/dist/reconcilers/fields.js +92 -0
  17. package/dist/reconcilers/fields.js.map +1 -0
  18. package/dist/reconcilers/flows.js +122 -0
  19. package/dist/reconcilers/flows.js.map +1 -0
  20. package/dist/reconcilers/migrations.js +182 -0
  21. package/dist/reconcilers/migrations.js.map +1 -0
  22. package/dist/reconcilers/operations.js +164 -0
  23. package/dist/reconcilers/operations.js.map +1 -0
  24. package/dist/reconcilers/permissions.js +87 -0
  25. package/dist/reconcilers/permissions.js.map +1 -0
  26. package/dist/reconcilers/policies.js +105 -0
  27. package/dist/reconcilers/policies.js.map +1 -0
  28. package/dist/reconcilers/register.js +183 -0
  29. package/dist/reconcilers/register.js.map +1 -0
  30. package/dist/reconcilers/relations.js +56 -0
  31. package/dist/reconcilers/relations.js.map +1 -0
  32. package/dist/reconcilers/roles.js +71 -0
  33. package/dist/reconcilers/roles.js.map +1 -0
  34. package/dist/reconcilers/seeds.js +162 -0
  35. package/dist/reconcilers/seeds.js.map +1 -0
  36. package/dist/report.js +16 -0
  37. package/dist/report.js.map +1 -0
  38. package/dist/runner.js +160 -0
  39. package/dist/runner.js.map +1 -0
  40. package/dist/sanitize.js +31 -0
  41. package/dist/sanitize.js.map +1 -0
  42. package/dist/sql.js +102 -0
  43. package/dist/sql.js.map +1 -0
  44. package/dist/types.js +2 -0
  45. package/dist/types.js.map +1 -0
  46. package/package.json +45 -0
package/dist/runner.js ADDED
@@ -0,0 +1,160 @@
1
+ import { loadSnapshot } from "./manifest.js";
2
+ import { reconcileCollections } from "./reconcilers/collections.js";
3
+ import { reconcileFields } from "./reconcilers/fields.js";
4
+ import { reconcileRelations } from "./reconcilers/relations.js";
5
+ import { reconcileRoles } from "./reconcilers/roles.js";
6
+ import { reconcilePolicies } from "./reconcilers/policies.js";
7
+ import { reconcilePermissions } from "./reconcilers/permissions.js";
8
+ import { reconcileFlowsPass1, reconcileFlowsPass2 } from "./reconcilers/flows.js";
9
+ import { reconcileOperationsPass1, reconcileOperationsPass2, } from "./reconcilers/operations.js";
10
+ import { reconcileMigrations } from "./reconcilers/migrations.js";
11
+ import { reconcileRegister } from "./reconcilers/register.js";
12
+ import { reconcileSeeds } from "./reconcilers/seeds.js";
13
+ import { buildIdentity } from "./identity.js";
14
+ export function summarize(results, target) {
15
+ const counts = {
16
+ created: 0,
17
+ updated: 0,
18
+ unchanged: 0,
19
+ skipped: 0,
20
+ failed: 0,
21
+ };
22
+ for (const r of results)
23
+ counts[r.action] += 1;
24
+ return { target, results, counts };
25
+ }
26
+ export async function run(input) {
27
+ const snapshot = await loadSnapshot(input.paths);
28
+ const results = [];
29
+ // Migrations first — they may introduce raw-SQL tables and columns that
30
+ // subsequent reconcilers reference. Idempotent (tracked per-file in
31
+ // lola_deploy_migrations on the target).
32
+ if (input.entities.has("migrations") && input.migrationsDir) {
33
+ results.push(...(await reconcileMigrations({
34
+ migrationsDir: input.migrationsDir,
35
+ client: input.client,
36
+ opts: input.opts,
37
+ })));
38
+ // Register manifests for raw-SQL adopted tables. Runs alongside migrations
39
+ // because the two are conceptually paired: a migration creates the raw
40
+ // table, its manifest teaches Directus about the columns. Piggy-backs on
41
+ // the `migrations` entity kind so callers don't need to opt in twice.
42
+ results.push(...(await reconcileRegister({
43
+ registerDir: input.paths.registerDir,
44
+ client: input.client,
45
+ opts: input.opts,
46
+ })));
47
+ }
48
+ // Order matters:
49
+ // collections → fields → relations (schema, string keys)
50
+ // roles → policies → permissions (auto-id, cross-refs by name)
51
+ if (input.entities.has("collections")) {
52
+ results.push(...(await reconcileCollections({
53
+ collections: snapshot.collections,
54
+ registerManifests: snapshot.registerManifests,
55
+ client: input.client,
56
+ opts: input.opts,
57
+ })));
58
+ }
59
+ if (input.entities.has("fields")) {
60
+ results.push(...(await reconcileFields({
61
+ fieldsByCollection: snapshot.fieldsByCollection,
62
+ registerManifests: snapshot.registerManifests,
63
+ client: input.client,
64
+ opts: input.opts,
65
+ })));
66
+ }
67
+ if (input.entities.has("relations")) {
68
+ results.push(...(await reconcileRelations({
69
+ relationsByCollection: snapshot.relationsByCollection,
70
+ client: input.client,
71
+ opts: input.opts,
72
+ })));
73
+ }
74
+ // Auto-id entities need an identity index built once per phase.
75
+ const needsIdentity = input.entities.has("policies") ||
76
+ input.entities.has("permissions") ||
77
+ input.entities.has("roles") ||
78
+ input.entities.has("flows") ||
79
+ input.entities.has("operations");
80
+ if (needsIdentity) {
81
+ if (input.entities.has("roles")) {
82
+ results.push(...(await reconcileRoles({
83
+ roles: snapshot.roles,
84
+ client: input.client,
85
+ opts: input.opts,
86
+ })));
87
+ }
88
+ const identity1 = await buildIdentity(input.client, snapshot.policies, snapshot.roles, snapshot.flows, snapshot.operations);
89
+ if (input.entities.has("policies")) {
90
+ results.push(...(await reconcilePolicies({
91
+ policies: snapshot.policies,
92
+ identity: identity1,
93
+ client: input.client,
94
+ opts: input.opts,
95
+ })));
96
+ }
97
+ if (input.entities.has("permissions")) {
98
+ // Re-fetch identity so policies just created are resolvable.
99
+ const identity2 = await buildIdentity(input.client, snapshot.policies, snapshot.roles, snapshot.flows, snapshot.operations);
100
+ results.push(...(await reconcilePermissions({
101
+ permissions: snapshot.permissions,
102
+ identity: identity2,
103
+ client: input.client,
104
+ opts: input.opts,
105
+ })));
106
+ }
107
+ // Flows + operations: two-pass to break the mutual FK cycle.
108
+ if (input.entities.has("flows") || input.entities.has("operations")) {
109
+ const identityF = await buildIdentity(input.client, snapshot.policies, snapshot.roles, snapshot.flows, snapshot.operations);
110
+ if (input.entities.has("flows")) {
111
+ results.push(...(await reconcileFlowsPass1({
112
+ flows: snapshot.flows,
113
+ identity: identityF,
114
+ client: input.client,
115
+ opts: input.opts,
116
+ })));
117
+ }
118
+ if (input.entities.has("operations")) {
119
+ // Refresh identity so newly-created flow ids become resolvable.
120
+ const identityO = await buildIdentity(input.client, snapshot.policies, snapshot.roles, snapshot.flows, snapshot.operations);
121
+ results.push(...(await reconcileOperationsPass1({
122
+ operations: snapshot.operations,
123
+ identity: identityO,
124
+ client: input.client,
125
+ opts: input.opts,
126
+ })));
127
+ // Second pass on operations: resolve/reject refs.
128
+ const identityO2 = await buildIdentity(input.client, snapshot.policies, snapshot.roles, snapshot.flows, snapshot.operations);
129
+ results.push(...(await reconcileOperationsPass2({
130
+ operations: snapshot.operations,
131
+ identity: identityO2,
132
+ client: input.client,
133
+ opts: input.opts,
134
+ })));
135
+ }
136
+ if (input.entities.has("flows")) {
137
+ // Final pass on flows: link each flow's entry `operation` to its
138
+ // freshly-reconciled server op id.
139
+ const identityFinal = await buildIdentity(input.client, snapshot.policies, snapshot.roles, snapshot.flows, snapshot.operations);
140
+ results.push(...(await reconcileFlowsPass2({
141
+ flows: snapshot.flows,
142
+ identity: identityFinal,
143
+ client: input.client,
144
+ opts: input.opts,
145
+ })));
146
+ }
147
+ }
148
+ }
149
+ // Seed data — data-tables (messaging_templates, notification_types, …). Runs
150
+ // last so any referenced collections/policies/flows exist first.
151
+ if (input.entities.has("seeds") && input.seedDir) {
152
+ results.push(...(await reconcileSeeds({
153
+ seedDir: input.seedDir,
154
+ client: input.client,
155
+ opts: input.opts,
156
+ })));
157
+ }
158
+ return summarize(results, input.target);
159
+ }
160
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ // Strip server-managed keys from a payload before POST/PATCH.
2
+ // Directus in practice ignores unknown top-level keys on writes, but sending
3
+ // Tractr's `_syncId` or stale timestamps is confusing at best and could break
4
+ // on a future Directus release. Also recursively cleans nested `meta` which
5
+ // carries its own auto-id in some entity kinds.
6
+ const SERVER_ONLY_KEYS = new Set([
7
+ "_syncId",
8
+ "id",
9
+ "date_created",
10
+ "user_created",
11
+ "date_updated",
12
+ "user_updated",
13
+ ]);
14
+ function stripKeys(obj) {
15
+ const out = {};
16
+ for (const [k, v] of Object.entries(obj)) {
17
+ if (SERVER_ONLY_KEYS.has(k))
18
+ continue;
19
+ out[k] = v;
20
+ }
21
+ return out;
22
+ }
23
+ export function sanitizeForWrite(payload) {
24
+ const cleaned = stripKeys(payload);
25
+ const meta = cleaned["meta"];
26
+ if (meta && typeof meta === "object" && !Array.isArray(meta)) {
27
+ cleaned["meta"] = stripKeys(meta);
28
+ }
29
+ return cleaned;
30
+ }
31
+ //# sourceMappingURL=sanitize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sanitize.js","sourceRoot":"","sources":["../src/sanitize.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,6EAA6E;AAC7E,8EAA8E;AAC9E,4EAA4E;AAC5E,gDAAgD;AAEhD,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC;IAC/B,SAAS;IACT,IAAI;IACJ,cAAc;IACd,cAAc;IACd,cAAc;IACd,cAAc;CACf,CAAC,CAAC;AAEH,SAAS,SAAS,CAAC,GAA4B;IAC7C,MAAM,GAAG,GAA4B,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACzC,IAAI,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC;YAAE,SAAS;QACtC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACb,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,OAAgC;IAC/D,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7B,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7D,OAAO,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC,IAA+B,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
package/dist/sql.js ADDED
@@ -0,0 +1,102 @@
1
+ // Split a SQL blob into individual statements. Respects:
2
+ // -- line comments (up to newline)
3
+ // /* block comments */
4
+ // 'single-quoted' strings (with '' escape)
5
+ // $$ or $tag$ dollar-quoted blocks (Postgres)
6
+ //
7
+ // Naive splitters (e.g. `raw-query/execute`'s server-side one that we've been
8
+ // dodging all day) don't understand comments and blow up on any semicolon in
9
+ // a comment. We do it correctly here.
10
+ export function splitSql(input) {
11
+ const out = [];
12
+ let buf = "";
13
+ let i = 0;
14
+ const n = input.length;
15
+ const push = () => {
16
+ const trimmed = buf.trim();
17
+ if (trimmed)
18
+ out.push(trimmed);
19
+ buf = "";
20
+ };
21
+ while (i < n) {
22
+ const c = input[i];
23
+ const c2 = input[i + 1] ?? "";
24
+ // Line comment: --... until newline
25
+ if (c === "-" && c2 === "-") {
26
+ buf += c + c2;
27
+ i += 2;
28
+ while (i < n && input[i] !== "\n") {
29
+ buf += input[i];
30
+ i += 1;
31
+ }
32
+ continue;
33
+ }
34
+ // Block comment: /* ... */ (non-nested, per SQL spec's most common usage)
35
+ if (c === "/" && c2 === "*") {
36
+ buf += c + c2;
37
+ i += 2;
38
+ while (i < n && !(input[i] === "*" && input[i + 1] === "/")) {
39
+ buf += input[i];
40
+ i += 1;
41
+ }
42
+ if (i < n) {
43
+ buf += "*/";
44
+ i += 2;
45
+ }
46
+ continue;
47
+ }
48
+ // Single-quoted string: '...' with '' escape
49
+ if (c === "'") {
50
+ buf += c;
51
+ i += 1;
52
+ while (i < n) {
53
+ const ch = input[i];
54
+ buf += ch;
55
+ i += 1;
56
+ if (ch === "'") {
57
+ if (input[i] === "'") {
58
+ buf += "'";
59
+ i += 1;
60
+ continue;
61
+ }
62
+ break;
63
+ }
64
+ }
65
+ continue;
66
+ }
67
+ // Dollar-quoted block: $tag$ ... $tag$ (tag can be empty)
68
+ if (c === "$") {
69
+ const tagEnd = input.indexOf("$", i + 1);
70
+ // Consider it a dollar quote only if what's between the two $ is an
71
+ // identifier-like tag (letters/digits/_) or empty AND the closing tag
72
+ // appears later.
73
+ if (tagEnd !== -1) {
74
+ const tag = input.slice(i + 1, tagEnd);
75
+ if (/^[A-Za-z0-9_]*$/.test(tag)) {
76
+ const closer = `$${tag}$`;
77
+ const closeAt = input.indexOf(closer, tagEnd + 1);
78
+ if (closeAt !== -1) {
79
+ buf += input.slice(i, closeAt + closer.length);
80
+ i = closeAt + closer.length;
81
+ continue;
82
+ }
83
+ }
84
+ }
85
+ buf += c;
86
+ i += 1;
87
+ continue;
88
+ }
89
+ // Statement terminator
90
+ if (c === ";") {
91
+ buf += ";";
92
+ i += 1;
93
+ push();
94
+ continue;
95
+ }
96
+ buf += c;
97
+ i += 1;
98
+ }
99
+ push();
100
+ return out;
101
+ }
102
+ //# sourceMappingURL=sql.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sql.js","sourceRoot":"","sources":["../src/sql.ts"],"names":[],"mappings":"AAAA,yDAAyD;AACzD,qCAAqC;AACrC,yBAAyB;AACzB,6CAA6C;AAC7C,gDAAgD;AAChD,EAAE;AACF,8EAA8E;AAC9E,6EAA6E;AAC7E,sCAAsC;AAEtC,MAAM,UAAU,QAAQ,CAAC,KAAa;IACpC,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;IAEvB,MAAM,IAAI,GAAG,GAAG,EAAE;QAChB,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;QAC3B,IAAI,OAAO;YAAE,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/B,GAAG,GAAG,EAAE,CAAC;IACX,CAAC,CAAC;IAEF,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACb,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;QACpB,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QAE9B,oCAAoC;QACpC,IAAI,CAAC,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YAC5B,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACd,CAAC,IAAI,CAAC,CAAC;YACP,OAAO,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;gBAClC,GAAG,IAAI,KAAK,CAAC,CAAC,CAAE,CAAC;gBACjB,CAAC,IAAI,CAAC,CAAC;YACT,CAAC;YACD,SAAS;QACX,CAAC;QAED,0EAA0E;QAC1E,IAAI,CAAC,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;YAC5B,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACd,CAAC,IAAI,CAAC,CAAC;YACP,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC;gBAC5D,GAAG,IAAI,KAAK,CAAC,CAAC,CAAE,CAAC;gBACjB,CAAC,IAAI,CAAC,CAAC;YACT,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBACV,GAAG,IAAI,IAAI,CAAC;gBACZ,CAAC,IAAI,CAAC,CAAC;YACT,CAAC;YACD,SAAS;QACX,CAAC;QAED,6CAA6C;QAC7C,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;YACd,GAAG,IAAI,CAAC,CAAC;YACT,CAAC,IAAI,CAAC,CAAC;YACP,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;gBACb,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;gBACrB,GAAG,IAAI,EAAE,CAAC;gBACV,CAAC,IAAI,CAAC,CAAC;gBACP,IAAI,EAAE,KAAK,GAAG,EAAE,CAAC;oBACf,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;wBACrB,GAAG,IAAI,GAAG,CAAC;wBACX,CAAC,IAAI,CAAC,CAAC;wBACP,SAAS;oBACX,CAAC;oBACD,MAAM;gBACR,CAAC;YACH,CAAC;YACD,SAAS;QACX,CAAC;QAED,0DAA0D;QAC1D,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;YACd,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;YACzC,oEAAoE;YACpE,sEAAsE;YACtE,iBAAiB;YACjB,IAAI,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;gBAClB,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC;gBACvC,IAAI,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;oBAChC,MAAM,MAAM,GAAG,IAAI,GAAG,GAAG,CAAC;oBAC1B,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC;oBAClD,IAAI,OAAO,KAAK,CAAC,CAAC,EAAE,CAAC;wBACnB,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;wBAC/C,CAAC,GAAG,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC;wBAC5B,SAAS;oBACX,CAAC;gBACH,CAAC;YACH,CAAC;YACD,GAAG,IAAI,CAAC,CAAC;YACT,CAAC,IAAI,CAAC,CAAC;YACP,SAAS;QACX,CAAC;QAED,uBAAuB;QACvB,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;YACd,GAAG,IAAI,GAAG,CAAC;YACX,CAAC,IAAI,CAAC,CAAC;YACP,IAAI,EAAE,CAAC;YACP,SAAS;QACX,CAAC;QAED,GAAG,IAAI,CAAC,CAAC;QACT,CAAC,IAAI,CAAC,CAAC;IACT,CAAC;IACD,IAAI,EAAE,CAAC;IACP,OAAO,GAAG,CAAC;AACb,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "directus-deploy-cli",
3
+ "version": "0.1.0",
4
+ "description": "Per-entity, non-atomic Directus deployment tool. Reconciles collections/fields/relations/roles/policies/permissions/flows/operations/migrations/seeds from git to any environment.",
5
+ "type": "module",
6
+ "bin": {
7
+ "directus-deploy": "dist/cli.js",
8
+ "directus-deploy-mcp": "dist/mcp-server.js"
9
+ },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/lola-market-team/directus-deploy-cli.git"
13
+ },
14
+ "license": "MIT",
15
+ "keywords": ["directus", "deploy", "reconcile", "sync", "cli"],
16
+ "publishConfig": {
17
+ "access": "public"
18
+ },
19
+ "scripts": {
20
+ "build": "tsc",
21
+ "dev": "tsx src/cli.ts",
22
+ "test": "vitest run",
23
+ "test:live": "vitest run --config vitest.live.config.ts",
24
+ "test:watch": "vitest",
25
+ "typecheck": "tsc --noEmit",
26
+ "prepublishOnly": "npm run build"
27
+ },
28
+ "engines": {
29
+ "node": ">=20"
30
+ },
31
+ "dependencies": {
32
+ "@modelcontextprotocol/sdk": "^1.29.0",
33
+ "commander": "^12.1.0"
34
+ },
35
+ "devDependencies": {
36
+ "@types/node": "^20.14.0",
37
+ "tsx": "^4.19.0",
38
+ "typescript": "^5.6.0",
39
+ "vitest": "^2.1.0"
40
+ },
41
+ "files": [
42
+ "dist",
43
+ "README.md"
44
+ ]
45
+ }