@jaypie/dynamodb 0.2.0 → 0.3.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.
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var mcp = require('@jaypie/vocabulary/mcp');
4
- var vocabulary = require('@jaypie/vocabulary');
3
+ var mcp = require('@jaypie/fabric/mcp');
4
+ var fabric = require('@jaypie/fabric');
5
5
  var clientDynamodb = require('@aws-sdk/client-dynamodb');
6
6
  var libDynamodb = require('@aws-sdk/lib-dynamodb');
7
7
  var errors = require('@jaypie/errors');
@@ -77,11 +77,11 @@ function isInitialized() {
77
77
  return docClient !== null && tableName !== null;
78
78
  }
79
79
 
80
- // Re-export shared constants from vocabulary
80
+ // Re-export shared constants from fabric
81
81
  // GSI names (derived from DEFAULT_INDEXES)
82
82
  const INDEX_ALIAS = "indexAlias";
83
83
  const INDEX_CLASS = "indexClass";
84
- const INDEX_OU = "indexOu";
84
+ const INDEX_SCOPE = "indexScope";
85
85
  const INDEX_TYPE = "indexType";
86
86
  const INDEX_XID = "indexXid";
87
87
 
@@ -89,53 +89,53 @@ const INDEX_XID = "indexXid";
89
89
  // Key Builders
90
90
  // =============================================================================
91
91
  /**
92
- * Build the indexOu key for hierarchical queries
93
- * @param ou - The organizational unit (APEX or "{parent.model}#{parent.id}")
92
+ * Build the indexScope key for hierarchical queries
93
+ * @param scope - The scope (APEX or "{parent.model}#{parent.id}")
94
94
  * @param model - The entity model name
95
- * @returns Composite key: "{ou}#{model}"
95
+ * @returns Composite key: "{scope}#{model}"
96
96
  */
97
- function buildIndexOu(ou, model) {
98
- return `${ou}${vocabulary.SEPARATOR}${model}`;
97
+ function buildIndexScope(scope, model) {
98
+ return `${scope}${fabric.SEPARATOR}${model}`;
99
99
  }
100
100
  /**
101
101
  * Build the indexAlias key for human-friendly lookups
102
- * @param ou - The organizational unit
102
+ * @param scope - The scope
103
103
  * @param model - The entity model name
104
104
  * @param alias - The human-friendly alias
105
- * @returns Composite key: "{ou}#{model}#{alias}"
105
+ * @returns Composite key: "{scope}#{model}#{alias}"
106
106
  */
107
- function buildIndexAlias(ou, model, alias) {
108
- return `${ou}${vocabulary.SEPARATOR}${model}${vocabulary.SEPARATOR}${alias}`;
107
+ function buildIndexAlias(scope, model, alias) {
108
+ return `${scope}${fabric.SEPARATOR}${model}${fabric.SEPARATOR}${alias}`;
109
109
  }
110
110
  /**
111
111
  * Build the indexClass key for category filtering
112
- * @param ou - The organizational unit
112
+ * @param scope - The scope
113
113
  * @param model - The entity model name
114
114
  * @param recordClass - The category classification
115
- * @returns Composite key: "{ou}#{model}#{class}"
115
+ * @returns Composite key: "{scope}#{model}#{class}"
116
116
  */
117
- function buildIndexClass(ou, model, recordClass) {
118
- return `${ou}${vocabulary.SEPARATOR}${model}${vocabulary.SEPARATOR}${recordClass}`;
117
+ function buildIndexClass(scope, model, recordClass) {
118
+ return `${scope}${fabric.SEPARATOR}${model}${fabric.SEPARATOR}${recordClass}`;
119
119
  }
120
120
  /**
121
121
  * Build the indexType key for type filtering
122
- * @param ou - The organizational unit
122
+ * @param scope - The scope
123
123
  * @param model - The entity model name
124
124
  * @param type - The type classification
125
- * @returns Composite key: "{ou}#{model}#{type}"
125
+ * @returns Composite key: "{scope}#{model}#{type}"
126
126
  */
127
- function buildIndexType(ou, model, type) {
128
- return `${ou}${vocabulary.SEPARATOR}${model}${vocabulary.SEPARATOR}${type}`;
127
+ function buildIndexType(scope, model, type) {
128
+ return `${scope}${fabric.SEPARATOR}${model}${fabric.SEPARATOR}${type}`;
129
129
  }
130
130
  /**
131
131
  * Build the indexXid key for external ID lookups
132
- * @param ou - The organizational unit
132
+ * @param scope - The scope
133
133
  * @param model - The entity model name
134
134
  * @param xid - The external ID
135
- * @returns Composite key: "{ou}#{model}#{xid}"
135
+ * @returns Composite key: "{scope}#{model}#{xid}"
136
136
  */
137
- function buildIndexXid(ou, model, xid) {
138
- return `${ou}${vocabulary.SEPARATOR}${model}${vocabulary.SEPARATOR}${xid}`;
137
+ function buildIndexXid(scope, model, xid) {
138
+ return `${scope}${fabric.SEPARATOR}${model}${fabric.SEPARATOR}${xid}`;
139
139
  }
140
140
  /**
141
141
  * Auto-populate GSI index keys on an entity
@@ -143,7 +143,7 @@ function buildIndexXid(ou, model, xid) {
143
143
  * Uses the model's registered indexes (from vocabulary registry) or
144
144
  * DEFAULT_INDEXES if no custom indexes are registered.
145
145
  *
146
- * - indexOu is always populated from ou + model
146
+ * - indexScope is always populated from scope + model
147
147
  * - indexAlias is populated only when alias is present
148
148
  * - indexClass is populated only when class is present
149
149
  * - indexType is populated only when type is present
@@ -154,9 +154,9 @@ function buildIndexXid(ou, model, xid) {
154
154
  * @returns The entity with populated index keys
155
155
  */
156
156
  function indexEntity(entity, suffix = "") {
157
- const indexes = vocabulary.getModelIndexes(entity.model);
158
- // Cast through unknown to bridge the type gap between StorableEntity and IndexableEntity
159
- return vocabulary.populateIndexKeys(entity, indexes, suffix);
157
+ const indexes = fabric.getModelIndexes(entity.model);
158
+ // Cast through unknown to bridge the type gap between StorableEntity and IndexableModel
159
+ return fabric.populateIndexKeys(entity, indexes, suffix);
160
160
  }
161
161
 
162
162
  /**
@@ -166,20 +166,20 @@ function calculateEntitySuffix(entity) {
166
166
  const hasArchived = Boolean(entity.archivedAt);
167
167
  const hasDeleted = Boolean(entity.deletedAt);
168
168
  if (hasArchived && hasDeleted) {
169
- return vocabulary.ARCHIVED_SUFFIX + vocabulary.DELETED_SUFFIX;
169
+ return fabric.ARCHIVED_SUFFIX + fabric.DELETED_SUFFIX;
170
170
  }
171
171
  if (hasArchived) {
172
- return vocabulary.ARCHIVED_SUFFIX;
172
+ return fabric.ARCHIVED_SUFFIX;
173
173
  }
174
174
  if (hasDeleted) {
175
- return vocabulary.DELETED_SUFFIX;
175
+ return fabric.DELETED_SUFFIX;
176
176
  }
177
177
  return "";
178
178
  }
179
179
  /**
180
180
  * Get a single entity by primary key
181
181
  */
182
- const getEntity = vocabulary.serviceHandler({
182
+ const getEntity = fabric.fabricService({
183
183
  alias: "getEntity",
184
184
  description: "Get a single entity by primary key",
185
185
  input: {
@@ -201,7 +201,7 @@ const getEntity = vocabulary.serviceHandler({
201
201
  * Put (create or replace) an entity
202
202
  * Auto-populates GSI index keys via indexEntity
203
203
  *
204
- * Note: This is a regular async function (not serviceHandler) because it accepts
204
+ * Note: This is a regular async function (not fabricService) because it accepts
205
205
  * complex StorableEntity objects that can't be coerced by vocabulary's type system.
206
206
  */
207
207
  async function putEntity({ entity, }) {
@@ -220,7 +220,7 @@ async function putEntity({ entity, }) {
220
220
  * Update an existing entity
221
221
  * Auto-populates GSI index keys and sets updatedAt
222
222
  *
223
- * Note: This is a regular async function (not serviceHandler) because it accepts
223
+ * Note: This is a regular async function (not fabricService) because it accepts
224
224
  * complex StorableEntity objects that can't be coerced by vocabulary's type system.
225
225
  */
226
226
  async function updateEntity({ entity, }) {
@@ -242,7 +242,7 @@ async function updateEntity({ entity, }) {
242
242
  * Soft delete an entity by setting deletedAt timestamp
243
243
  * Re-indexes with appropriate suffix based on archived/deleted state
244
244
  */
245
- const deleteEntity = vocabulary.serviceHandler({
245
+ const deleteEntity = fabric.fabricService({
246
246
  alias: "deleteEntity",
247
247
  description: "Soft delete an entity (sets deletedAt timestamp)",
248
248
  input: {
@@ -279,7 +279,7 @@ const deleteEntity = vocabulary.serviceHandler({
279
279
  * Archive an entity by setting archivedAt timestamp
280
280
  * Re-indexes with appropriate suffix based on archived/deleted state
281
281
  */
282
- const archiveEntity = vocabulary.serviceHandler({
282
+ const archiveEntity = fabric.fabricService({
283
283
  alias: "archiveEntity",
284
284
  description: "Archive an entity (sets archivedAt timestamp)",
285
285
  input: {
@@ -316,7 +316,7 @@ const archiveEntity = vocabulary.serviceHandler({
316
316
  * Hard delete an entity (permanently removes from table)
317
317
  * Use with caution - prefer deleteEntity for soft delete
318
318
  */
319
- const destroyEntity = vocabulary.serviceHandler({
319
+ const destroyEntity = fabric.fabricService({
320
320
  alias: "destroyEntity",
321
321
  description: "Hard delete an entity (permanently removes from table)",
322
322
  input: {
@@ -341,13 +341,13 @@ const destroyEntity = vocabulary.serviceHandler({
341
341
  */
342
342
  function calculateSuffix({ archived, deleted, }) {
343
343
  if (archived && deleted) {
344
- return vocabulary.ARCHIVED_SUFFIX + vocabulary.DELETED_SUFFIX;
344
+ return fabric.ARCHIVED_SUFFIX + fabric.DELETED_SUFFIX;
345
345
  }
346
346
  if (archived) {
347
- return vocabulary.ARCHIVED_SUFFIX;
347
+ return fabric.ARCHIVED_SUFFIX;
348
348
  }
349
349
  if (deleted) {
350
- return vocabulary.DELETED_SUFFIX;
350
+ return fabric.DELETED_SUFFIX;
351
351
  }
352
352
  return "";
353
353
  }
@@ -379,16 +379,16 @@ async function executeQuery(indexName, keyValue, options = {}) {
379
379
  };
380
380
  }
381
381
  /**
382
- * Query entities by organizational unit (parent hierarchy)
383
- * Uses indexOu GSI
382
+ * Query entities by scope (parent hierarchy)
383
+ * Uses indexScope GSI
384
384
  *
385
- * Note: This is a regular async function (not serviceHandler) because it accepts
385
+ * Note: This is a regular async function (not fabricService) because it accepts
386
386
  * complex startKey objects that can't be coerced by vocabulary's type system.
387
387
  */
388
- async function queryByOu({ archived = false, ascending = false, deleted = false, limit, model, ou, startKey, }) {
388
+ async function queryByScope({ archived = false, ascending = false, deleted = false, limit, model, scope, startKey, }) {
389
389
  const suffix = calculateSuffix({ archived, deleted });
390
- const keyValue = buildIndexOu(ou, model) + suffix;
391
- return executeQuery(INDEX_OU, keyValue, {
390
+ const keyValue = buildIndexScope(scope, model) + suffix;
391
+ return executeQuery(INDEX_SCOPE, keyValue, {
392
392
  ascending,
393
393
  limit,
394
394
  startKey,
@@ -398,7 +398,7 @@ async function queryByOu({ archived = false, ascending = false, deleted = false,
398
398
  * Query a single entity by human-friendly alias
399
399
  * Uses indexAlias GSI
400
400
  */
401
- const queryByAlias = vocabulary.serviceHandler({
401
+ const queryByAlias = fabric.fabricService({
402
402
  alias: "queryByAlias",
403
403
  description: "Query a single entity by human-friendly alias",
404
404
  input: {
@@ -416,16 +416,19 @@ const queryByAlias = vocabulary.serviceHandler({
416
416
  description: "Query deleted entities instead of active ones",
417
417
  },
418
418
  model: { type: String, description: "Entity model name" },
419
- ou: { type: String, description: "Organizational unit (@ for root)" },
419
+ scope: { type: String, description: "Scope (@ for root)" },
420
420
  },
421
- service: async ({ alias, archived, deleted, model, ou, }) => {
421
+ service: async ({ alias, archived, deleted, model, scope, }) => {
422
422
  const aliasStr = alias;
423
423
  const archivedBool = archived;
424
424
  const deletedBool = deleted;
425
425
  const modelStr = model;
426
- const ouStr = ou;
427
- const suffix = calculateSuffix({ archived: archivedBool, deleted: deletedBool });
428
- const keyValue = buildIndexAlias(ouStr, modelStr, aliasStr) + suffix;
426
+ const scopeStr = scope;
427
+ const suffix = calculateSuffix({
428
+ archived: archivedBool,
429
+ deleted: deletedBool,
430
+ });
431
+ const keyValue = buildIndexAlias(scopeStr, modelStr, aliasStr) + suffix;
429
432
  const result = await executeQuery(INDEX_ALIAS, keyValue, {
430
433
  limit: 1,
431
434
  });
@@ -436,12 +439,12 @@ const queryByAlias = vocabulary.serviceHandler({
436
439
  * Query entities by category classification
437
440
  * Uses indexClass GSI
438
441
  *
439
- * Note: This is a regular async function (not serviceHandler) because it accepts
442
+ * Note: This is a regular async function (not fabricService) because it accepts
440
443
  * complex startKey objects that can't be coerced by vocabulary's type system.
441
444
  */
442
- async function queryByClass({ archived = false, ascending = false, deleted = false, limit, model, ou, recordClass, startKey, }) {
445
+ async function queryByClass({ archived = false, ascending = false, deleted = false, limit, model, scope, recordClass, startKey, }) {
443
446
  const suffix = calculateSuffix({ archived, deleted });
444
- const keyValue = buildIndexClass(ou, model, recordClass) + suffix;
447
+ const keyValue = buildIndexClass(scope, model, recordClass) + suffix;
445
448
  return executeQuery(INDEX_CLASS, keyValue, {
446
449
  ascending,
447
450
  limit,
@@ -452,12 +455,12 @@ async function queryByClass({ archived = false, ascending = false, deleted = fal
452
455
  * Query entities by type classification
453
456
  * Uses indexType GSI
454
457
  *
455
- * Note: This is a regular async function (not serviceHandler) because it accepts
458
+ * Note: This is a regular async function (not fabricService) because it accepts
456
459
  * complex startKey objects that can't be coerced by vocabulary's type system.
457
460
  */
458
- async function queryByType({ archived = false, ascending = false, deleted = false, limit, model, ou, startKey, type, }) {
461
+ async function queryByType({ archived = false, ascending = false, deleted = false, limit, model, scope, startKey, type, }) {
459
462
  const suffix = calculateSuffix({ archived, deleted });
460
- const keyValue = buildIndexType(ou, model, type) + suffix;
463
+ const keyValue = buildIndexType(scope, model, type) + suffix;
461
464
  return executeQuery(INDEX_TYPE, keyValue, {
462
465
  ascending,
463
466
  limit,
@@ -468,7 +471,7 @@ async function queryByType({ archived = false, ascending = false, deleted = fals
468
471
  * Query a single entity by external ID
469
472
  * Uses indexXid GSI
470
473
  */
471
- const queryByXid = vocabulary.serviceHandler({
474
+ const queryByXid = fabric.fabricService({
472
475
  alias: "queryByXid",
473
476
  description: "Query a single entity by external ID",
474
477
  input: {
@@ -485,17 +488,20 @@ const queryByXid = vocabulary.serviceHandler({
485
488
  description: "Query deleted entities instead of active ones",
486
489
  },
487
490
  model: { type: String, description: "Entity model name" },
488
- ou: { type: String, description: "Organizational unit (@ for root)" },
491
+ scope: { type: String, description: "Scope (@ for root)" },
489
492
  xid: { type: String, description: "External ID" },
490
493
  },
491
- service: async ({ archived, deleted, model, ou, xid, }) => {
494
+ service: async ({ archived, deleted, model, scope, xid, }) => {
492
495
  const archivedBool = archived;
493
496
  const deletedBool = deleted;
494
497
  const modelStr = model;
495
- const ouStr = ou;
498
+ const scopeStr = scope;
496
499
  const xidStr = xid;
497
- const suffix = calculateSuffix({ archived: archivedBool, deleted: deletedBool });
498
- const keyValue = buildIndexXid(ouStr, modelStr, xidStr) + suffix;
500
+ const suffix = calculateSuffix({
501
+ archived: archivedBool,
502
+ deleted: deletedBool,
503
+ });
504
+ const keyValue = buildIndexXid(scopeStr, modelStr, xidStr) + suffix;
499
505
  const result = await executeQuery(INDEX_XID, keyValue, {
500
506
  limit: 1,
501
507
  });
@@ -524,12 +530,12 @@ function generateIndexName(pk) {
524
530
  function collectAllIndexes() {
525
531
  const indexMap = new Map();
526
532
  // Add DEFAULT_INDEXES first
527
- for (const index of vocabulary.DEFAULT_INDEXES) {
533
+ for (const index of fabric.DEFAULT_INDEXES) {
528
534
  const name = index.name ?? generateIndexName(index.pk);
529
535
  indexMap.set(name, { ...index, name });
530
536
  }
531
537
  // Add registered model indexes (will not overwrite if name already exists)
532
- for (const index of vocabulary.getAllRegisteredIndexes()) {
538
+ for (const index of fabric.getAllRegisteredIndexes()) {
533
539
  const name = index.name ?? generateIndexName(index.pk);
534
540
  if (!indexMap.has(name)) {
535
541
  indexMap.set(name, { ...index, name });
@@ -616,7 +622,7 @@ function createTableParams(tableName, billingMode) {
616
622
  /**
617
623
  * Create DynamoDB table with Jaypie GSI schema
618
624
  */
619
- const createTableHandler = vocabulary.serviceHandler({
625
+ const createTableHandler = fabric.fabricService({
620
626
  alias: "dynamodb_create_table",
621
627
  description: "Create DynamoDB table with Jaypie GSI schema",
622
628
  input: {
@@ -680,7 +686,7 @@ const DEFAULT_TABLE_NAME = "jaypie-local";
680
686
  /**
681
687
  * Generate docker-compose.yml for local DynamoDB development
682
688
  */
683
- const dockerComposeHandler = vocabulary.serviceHandler({
689
+ const dockerComposeHandler = fabric.fabricService({
684
690
  alias: "dynamodb_generate_docker_compose",
685
691
  description: "Generate docker-compose.yml for local DynamoDB development",
686
692
  input: {
@@ -778,7 +784,7 @@ function ensureInitialized() {
778
784
  /**
779
785
  * Check DynamoDB connection status and configuration
780
786
  */
781
- const statusHandler = vocabulary.serviceHandler({
787
+ const statusHandler = fabric.fabricService({
782
788
  alias: "dynamodb_status",
783
789
  description: "Check DynamoDB connection status and configuration",
784
790
  service: async () => {
@@ -809,12 +815,12 @@ function wrapWithInit(handler) {
809
815
  return wrapped;
810
816
  }
811
817
  // MCP-specific serviceHandler wrappers for functions with complex inputs
812
- // Note: These wrap the regular async functions to make them work with registerMcpTool
818
+ // Note: These wrap the regular async functions to make them work with fabricMcp
813
819
  /**
814
820
  * MCP wrapper for putEntity
815
821
  * Accepts entity JSON directly from LLM
816
822
  */
817
- const mcpPutEntity = vocabulary.serviceHandler({
823
+ const mcpPutEntity = fabric.fabricService({
818
824
  alias: "dynamodb_put",
819
825
  description: "Create or replace an entity in DynamoDB (auto-indexes GSI keys)",
820
826
  input: {
@@ -822,10 +828,18 @@ const mcpPutEntity = vocabulary.serviceHandler({
822
828
  id: { type: String, description: "Entity ID (sort key)" },
823
829
  model: { type: String, description: "Entity model name (partition key)" },
824
830
  name: { type: String, description: "Entity name" },
825
- ou: { type: String, description: "Organizational unit (@ for root)" },
831
+ scope: { type: String, description: "Scope (@ for root)" },
826
832
  // Optional fields
827
- alias: { type: String, required: false, description: "Human-friendly alias" },
828
- class: { type: String, required: false, description: "Category classification" },
833
+ alias: {
834
+ type: String,
835
+ required: false,
836
+ description: "Human-friendly alias",
837
+ },
838
+ class: {
839
+ type: String,
840
+ required: false,
841
+ description: "Category classification",
842
+ },
829
843
  type: { type: String, required: false, description: "Type classification" },
830
844
  xid: { type: String, required: false, description: "External ID" },
831
845
  },
@@ -838,7 +852,7 @@ const mcpPutEntity = vocabulary.serviceHandler({
838
852
  id: input.id,
839
853
  model: input.model,
840
854
  name: input.name,
841
- ou: input.ou,
855
+ scope: input.scope,
842
856
  sequence: Date.now(),
843
857
  type: input.type,
844
858
  updatedAt: now,
@@ -851,7 +865,7 @@ const mcpPutEntity = vocabulary.serviceHandler({
851
865
  * MCP wrapper for updateEntity
852
866
  * Accepts entity JSON directly from LLM
853
867
  */
854
- const mcpUpdateEntity = vocabulary.serviceHandler({
868
+ const mcpUpdateEntity = fabric.fabricService({
855
869
  alias: "dynamodb_update",
856
870
  description: "Update an entity in DynamoDB (sets updatedAt, re-indexes GSI keys)",
857
871
  input: {
@@ -860,9 +874,17 @@ const mcpUpdateEntity = vocabulary.serviceHandler({
860
874
  model: { type: String, description: "Entity model name (partition key)" },
861
875
  // Fields that can be updated
862
876
  name: { type: String, required: false, description: "Entity name" },
863
- ou: { type: String, required: false, description: "Organizational unit" },
864
- alias: { type: String, required: false, description: "Human-friendly alias" },
865
- class: { type: String, required: false, description: "Category classification" },
877
+ scope: { type: String, required: false, description: "Scope" },
878
+ alias: {
879
+ type: String,
880
+ required: false,
881
+ description: "Human-friendly alias",
882
+ },
883
+ class: {
884
+ type: String,
885
+ required: false,
886
+ description: "Category classification",
887
+ },
866
888
  type: { type: String, required: false, description: "Type classification" },
867
889
  xid: { type: String, required: false, description: "External ID" },
868
890
  },
@@ -881,7 +903,7 @@ const mcpUpdateEntity = vocabulary.serviceHandler({
881
903
  ...(input.alias !== undefined && { alias: input.alias }),
882
904
  ...(input.class !== undefined && { class: input.class }),
883
905
  ...(input.name !== undefined && { name: input.name }),
884
- ...(input.ou !== undefined && { ou: input.ou }),
906
+ ...(input.scope !== undefined && { scope: input.scope }),
885
907
  ...(input.type !== undefined && { type: input.type }),
886
908
  ...(input.xid !== undefined && { xid: input.xid }),
887
909
  };
@@ -889,15 +911,15 @@ const mcpUpdateEntity = vocabulary.serviceHandler({
889
911
  },
890
912
  });
891
913
  /**
892
- * MCP wrapper for queryByOu
914
+ * MCP wrapper for queryByScope
893
915
  * Note: Pagination via startKey is not exposed to MCP; use limit instead
894
916
  */
895
- const mcpQueryByOu = vocabulary.serviceHandler({
896
- alias: "dynamodb_query_ou",
897
- description: "Query entities by organizational unit (parent hierarchy)",
917
+ const mcpQueryByScope = fabric.fabricService({
918
+ alias: "dynamodb_query_scope",
919
+ description: "Query entities by scope (parent hierarchy)",
898
920
  input: {
899
921
  model: { type: String, description: "Entity model name" },
900
- ou: { type: String, description: "Organizational unit (@ for root)" },
922
+ scope: { type: String, description: "Scope (@ for root)" },
901
923
  archived: {
902
924
  type: Boolean,
903
925
  default: false,
@@ -923,13 +945,13 @@ const mcpQueryByOu = vocabulary.serviceHandler({
923
945
  },
924
946
  },
925
947
  service: async (input) => {
926
- return queryByOu({
948
+ return queryByScope({
927
949
  archived: input.archived,
928
950
  ascending: input.ascending,
929
951
  deleted: input.deleted,
930
952
  limit: input.limit,
931
953
  model: input.model,
932
- ou: input.ou,
954
+ scope: input.scope,
933
955
  });
934
956
  },
935
957
  });
@@ -937,12 +959,12 @@ const mcpQueryByOu = vocabulary.serviceHandler({
937
959
  * MCP wrapper for queryByClass
938
960
  * Note: Pagination via startKey is not exposed to MCP; use limit instead
939
961
  */
940
- const mcpQueryByClass = vocabulary.serviceHandler({
962
+ const mcpQueryByClass = fabric.fabricService({
941
963
  alias: "dynamodb_query_class",
942
964
  description: "Query entities by category classification",
943
965
  input: {
944
966
  model: { type: String, description: "Entity model name" },
945
- ou: { type: String, description: "Organizational unit (@ for root)" },
967
+ scope: { type: String, description: "Scope (@ for root)" },
946
968
  recordClass: { type: String, description: "Category classification" },
947
969
  archived: {
948
970
  type: Boolean,
@@ -975,7 +997,7 @@ const mcpQueryByClass = vocabulary.serviceHandler({
975
997
  deleted: input.deleted,
976
998
  limit: input.limit,
977
999
  model: input.model,
978
- ou: input.ou,
1000
+ scope: input.scope,
979
1001
  recordClass: input.recordClass,
980
1002
  });
981
1003
  },
@@ -984,12 +1006,12 @@ const mcpQueryByClass = vocabulary.serviceHandler({
984
1006
  * MCP wrapper for queryByType
985
1007
  * Note: Pagination via startKey is not exposed to MCP; use limit instead
986
1008
  */
987
- const mcpQueryByType = vocabulary.serviceHandler({
1009
+ const mcpQueryByType = fabric.fabricService({
988
1010
  alias: "dynamodb_query_type",
989
1011
  description: "Query entities by type classification",
990
1012
  input: {
991
1013
  model: { type: String, description: "Entity model name" },
992
- ou: { type: String, description: "Organizational unit (@ for root)" },
1014
+ scope: { type: String, description: "Scope (@ for root)" },
993
1015
  type: { type: String, description: "Type classification" },
994
1016
  archived: {
995
1017
  type: Boolean,
@@ -1022,7 +1044,7 @@ const mcpQueryByType = vocabulary.serviceHandler({
1022
1044
  deleted: input.deleted,
1023
1045
  limit: input.limit,
1024
1046
  model: input.model,
1025
- ou: input.ou,
1047
+ scope: input.scope,
1026
1048
  type: input.type,
1027
1049
  });
1028
1050
  },
@@ -1034,80 +1056,80 @@ function registerDynamoDbTools(config) {
1034
1056
  const { includeAdmin = true, server } = config;
1035
1057
  const tools = [];
1036
1058
  // Entity operations
1037
- mcp.registerMcpTool({
1038
- handler: wrapWithInit(getEntity),
1059
+ mcp.fabricMcp({
1060
+ service: wrapWithInit(getEntity),
1039
1061
  name: "dynamodb_get",
1040
1062
  server,
1041
1063
  });
1042
1064
  tools.push("dynamodb_get");
1043
- mcp.registerMcpTool({
1044
- handler: wrapWithInit(mcpPutEntity),
1065
+ mcp.fabricMcp({
1066
+ service: wrapWithInit(mcpPutEntity),
1045
1067
  name: "dynamodb_put",
1046
1068
  server,
1047
1069
  });
1048
1070
  tools.push("dynamodb_put");
1049
- mcp.registerMcpTool({
1050
- handler: wrapWithInit(mcpUpdateEntity),
1071
+ mcp.fabricMcp({
1072
+ service: wrapWithInit(mcpUpdateEntity),
1051
1073
  name: "dynamodb_update",
1052
1074
  server,
1053
1075
  });
1054
1076
  tools.push("dynamodb_update");
1055
- mcp.registerMcpTool({
1056
- handler: wrapWithInit(deleteEntity),
1077
+ mcp.fabricMcp({
1078
+ service: wrapWithInit(deleteEntity),
1057
1079
  name: "dynamodb_delete",
1058
1080
  server,
1059
1081
  });
1060
1082
  tools.push("dynamodb_delete");
1061
- mcp.registerMcpTool({
1062
- handler: wrapWithInit(archiveEntity),
1083
+ mcp.fabricMcp({
1084
+ service: wrapWithInit(archiveEntity),
1063
1085
  name: "dynamodb_archive",
1064
1086
  server,
1065
1087
  });
1066
1088
  tools.push("dynamodb_archive");
1067
- mcp.registerMcpTool({
1068
- handler: wrapWithInit(destroyEntity),
1089
+ mcp.fabricMcp({
1090
+ service: wrapWithInit(destroyEntity),
1069
1091
  name: "dynamodb_destroy",
1070
1092
  server,
1071
1093
  });
1072
1094
  tools.push("dynamodb_destroy");
1073
1095
  // Query operations
1074
- mcp.registerMcpTool({
1075
- handler: wrapWithInit(mcpQueryByOu),
1076
- name: "dynamodb_query_ou",
1096
+ mcp.fabricMcp({
1097
+ service: wrapWithInit(mcpQueryByScope),
1098
+ name: "dynamodb_query_scope",
1077
1099
  server,
1078
1100
  });
1079
- tools.push("dynamodb_query_ou");
1080
- mcp.registerMcpTool({
1081
- handler: wrapWithInit(queryByAlias),
1101
+ tools.push("dynamodb_query_scope");
1102
+ mcp.fabricMcp({
1103
+ service: wrapWithInit(queryByAlias),
1082
1104
  name: "dynamodb_query_alias",
1083
1105
  server,
1084
1106
  });
1085
1107
  tools.push("dynamodb_query_alias");
1086
- mcp.registerMcpTool({
1087
- handler: wrapWithInit(mcpQueryByClass),
1108
+ mcp.fabricMcp({
1109
+ service: wrapWithInit(mcpQueryByClass),
1088
1110
  name: "dynamodb_query_class",
1089
1111
  server,
1090
1112
  });
1091
1113
  tools.push("dynamodb_query_class");
1092
- mcp.registerMcpTool({
1093
- handler: wrapWithInit(mcpQueryByType),
1114
+ mcp.fabricMcp({
1115
+ service: wrapWithInit(mcpQueryByType),
1094
1116
  name: "dynamodb_query_type",
1095
1117
  server,
1096
1118
  });
1097
1119
  tools.push("dynamodb_query_type");
1098
- mcp.registerMcpTool({
1099
- handler: wrapWithInit(queryByXid),
1120
+ mcp.fabricMcp({
1121
+ service: wrapWithInit(queryByXid),
1100
1122
  name: "dynamodb_query_xid",
1101
1123
  server,
1102
1124
  });
1103
1125
  tools.push("dynamodb_query_xid");
1104
1126
  // Admin tools (MCP-only)
1105
1127
  if (includeAdmin) {
1106
- mcp.registerMcpTool({ handler: statusHandler, server });
1128
+ mcp.fabricMcp({ service: statusHandler, server });
1107
1129
  tools.push("dynamodb_status");
1108
- mcp.registerMcpTool({ handler: createTableHandler, server });
1130
+ mcp.fabricMcp({ service: createTableHandler, server });
1109
1131
  tools.push("dynamodb_create_table");
1110
- mcp.registerMcpTool({ handler: dockerComposeHandler, server });
1132
+ mcp.fabricMcp({ service: dockerComposeHandler, server });
1111
1133
  tools.push("dynamodb_generate_docker_compose");
1112
1134
  }
1113
1135
  return { tools };