@karmaniverous/entity-manager 5.0.8 → 5.0.10

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 (140) hide show
  1. package/.github/FUNDING.yml +3 -0
  2. package/README.md +1 -2
  3. package/dist/cjs/BaseEntityClient/BaseEntityClient.js +28 -0
  4. package/dist/cjs/BaseQueryBuilder/BaseQueryBuilder.js +62 -0
  5. package/dist/cjs/EntityManager/EntityManager.js +131 -0
  6. package/dist/cjs/EntityManager/ParsedConfig.js +385 -0
  7. package/dist/cjs/EntityManager/addKeys.js +60 -0
  8. package/dist/cjs/EntityManager/createEntityManager.js +46 -0
  9. package/dist/cjs/EntityManager/decodeElement.js +46 -0
  10. package/dist/cjs/EntityManager/decodeGeneratedProperty.js +53 -0
  11. package/dist/cjs/EntityManager/dehydrateIndexItem.js +68 -0
  12. package/dist/cjs/EntityManager/dehydratePageKeyMap.js +93 -0
  13. package/dist/cjs/EntityManager/encodeElement.js +40 -0
  14. package/dist/cjs/EntityManager/encodeGeneratedProperty.js +55 -0
  15. package/dist/cjs/EntityManager/findIndexToken.js +10 -0
  16. package/dist/cjs/EntityManager/getHashKeySpace.js +89 -0
  17. package/dist/cjs/EntityManager/getIndexComponents.js +23 -0
  18. package/dist/cjs/EntityManager/getPrimaryKey.js +76 -0
  19. package/dist/cjs/EntityManager/getShardBump.js +24 -0
  20. package/dist/cjs/EntityManager/query.js +130 -0
  21. package/dist/cjs/EntityManager/rehydrateIndexItem.js +65 -0
  22. package/dist/cjs/EntityManager/rehydratePageKeyMap.js +103 -0
  23. package/dist/cjs/EntityManager/removeKeys.js +51 -0
  24. package/dist/cjs/EntityManager/unwrapIndex.js +59 -0
  25. package/dist/cjs/EntityManager/updateItemHashKey.js +79 -0
  26. package/dist/cjs/EntityManager/updateItemRangeKey.js +65 -0
  27. package/dist/cjs/EntityManager/validateEntityToken.js +17 -0
  28. package/dist/cjs/EntityManager/validateGeneratedProperty.js +23 -0
  29. package/dist/cjs/EntityManager/validateIndexToken.js +16 -0
  30. package/dist/cjs/EntityManager/validateTranscodedProperty.js +16 -0
  31. package/dist/cjs/index.js +15 -0
  32. package/dist/default/lib/EntityManager/EntityManager.js +46 -69
  33. package/dist/default/lib/EntityManager/PrivateEntityManager.js +44 -51
  34. package/dist/index.d.ts +1163 -0
  35. package/dist/mjs/BaseEntityClient/BaseEntityClient.js +26 -0
  36. package/dist/mjs/BaseQueryBuilder/BaseQueryBuilder.js +60 -0
  37. package/dist/mjs/EntityManager/EntityManager.js +129 -0
  38. package/dist/mjs/EntityManager/ParsedConfig.js +383 -0
  39. package/dist/mjs/EntityManager/addKeys.js +58 -0
  40. package/dist/mjs/EntityManager/createEntityManager.js +44 -0
  41. package/dist/mjs/EntityManager/decodeElement.js +44 -0
  42. package/dist/mjs/EntityManager/decodeGeneratedProperty.js +51 -0
  43. package/dist/mjs/EntityManager/dehydrateIndexItem.js +66 -0
  44. package/dist/mjs/EntityManager/dehydratePageKeyMap.js +91 -0
  45. package/dist/mjs/EntityManager/encodeElement.js +38 -0
  46. package/dist/mjs/EntityManager/encodeGeneratedProperty.js +53 -0
  47. package/dist/mjs/EntityManager/findIndexToken.js +8 -0
  48. package/dist/mjs/EntityManager/getHashKeySpace.js +87 -0
  49. package/dist/mjs/EntityManager/getIndexComponents.js +21 -0
  50. package/dist/mjs/EntityManager/getPrimaryKey.js +74 -0
  51. package/dist/mjs/EntityManager/getShardBump.js +22 -0
  52. package/dist/mjs/EntityManager/query.js +128 -0
  53. package/dist/mjs/EntityManager/rehydrateIndexItem.js +63 -0
  54. package/dist/mjs/EntityManager/rehydratePageKeyMap.js +101 -0
  55. package/dist/mjs/EntityManager/removeKeys.js +49 -0
  56. package/dist/mjs/EntityManager/unwrapIndex.js +57 -0
  57. package/dist/mjs/EntityManager/updateItemHashKey.js +77 -0
  58. package/dist/mjs/EntityManager/updateItemRangeKey.js +63 -0
  59. package/dist/mjs/EntityManager/validateEntityToken.js +15 -0
  60. package/dist/mjs/EntityManager/validateGeneratedProperty.js +21 -0
  61. package/dist/mjs/EntityManager/validateIndexToken.js +14 -0
  62. package/dist/mjs/EntityManager/validateTranscodedProperty.js +14 -0
  63. package/dist/mjs/index.js +5 -0
  64. package/docs/.nojekyll +1 -0
  65. package/docs/assets/hierarchy.js +1 -0
  66. package/docs/assets/highlight.css +99 -0
  67. package/docs/assets/icons.js +18 -0
  68. package/docs/assets/icons.svg +1 -0
  69. package/docs/assets/main.js +60 -0
  70. package/docs/assets/navigation.js +1 -0
  71. package/docs/assets/search.js +1 -0
  72. package/docs/assets/style.css +1648 -0
  73. package/docs/classes/index.BaseEntityClient.html +124 -0
  74. package/docs/classes/index.BaseQueryBuilder.html +229 -0
  75. package/docs/classes/index.EntityManager.html +510 -0
  76. package/docs/documents/CHANGELOG.html +1432 -0
  77. package/docs/documents/guides_stan-assistant-guide.html +431 -0
  78. package/docs/functions/index.createEntityManager.html +60 -0
  79. package/docs/hierarchy.html +31 -0
  80. package/docs/index.html +212 -0
  81. package/docs/interfaces/index.BaseConfigMap.html +113 -0
  82. package/docs/interfaces/index.BaseEntityClientOptions.html +82 -0
  83. package/docs/interfaces/index.BaseQueryBuilderOptions.html +92 -0
  84. package/docs/interfaces/index.CapturedConfigMapFrom.html +126 -0
  85. package/docs/interfaces/index.ConfigInput.html +189 -0
  86. package/docs/interfaces/index.ParsedConfig.html +144 -0
  87. package/docs/interfaces/index.ParsedEntityConfig.html +91 -0
  88. package/docs/interfaces/index.ParsedGeneratedPropertiesConfig.html +67 -0
  89. package/docs/interfaces/index.ParsedIndexConfig.html +79 -0
  90. package/docs/interfaces/index.ParsedTranscoder.html +71 -0
  91. package/docs/interfaces/index.QueryOptions.html +180 -0
  92. package/docs/interfaces/index.QueryResult.html +91 -0
  93. package/docs/interfaces/index.ShardBump.html +79 -0
  94. package/docs/interfaces/index.ShardQueryResult.html +93 -0
  95. package/docs/modules/index.html +47 -0
  96. package/docs/modules.html +38 -0
  97. package/docs/sitemap.xml +263 -0
  98. package/docs/types/index.BaseKeyTokens.html +39 -0
  99. package/docs/types/index.Config.html +75 -0
  100. package/docs/types/index.ConfigMap.html +41 -0
  101. package/docs/types/index.ConfigOfClient.html +45 -0
  102. package/docs/types/index.EntitiesFromSchema.html +39 -0
  103. package/docs/types/index.EntityClientItemByToken.html +45 -0
  104. package/docs/types/index.EntityClientRecordByToken.html +43 -0
  105. package/docs/types/index.EntityItem.html +41 -0
  106. package/docs/types/index.EntityItemPartial.html +44 -0
  107. package/docs/types/index.EntityKey.html +40 -0
  108. package/docs/types/index.EntityOfToken.html +39 -0
  109. package/docs/types/index.EntityRecord.html +39 -0
  110. package/docs/types/index.EntityRecordPartial.html +40 -0
  111. package/docs/types/index.EntityToken.html +40 -0
  112. package/docs/types/index.FallbackIndexTokenSet.html +40 -0
  113. package/docs/types/index.HasIndexFor.html +43 -0
  114. package/docs/types/index.HashKeyFrom.html +38 -0
  115. package/docs/types/index.IndexComponentTokens.html +45 -0
  116. package/docs/types/index.IndexHashKeyOf.html +42 -0
  117. package/docs/types/index.IndexRangeKeyOf.html +41 -0
  118. package/docs/types/index.IndexTokensFrom.html +41 -0
  119. package/docs/types/index.IndexTokensOf.html +40 -0
  120. package/docs/types/index.KeysFrom.html +38 -0
  121. package/docs/types/index.PageKey.html +40 -0
  122. package/docs/types/index.PageKeyByIndex.html +46 -0
  123. package/docs/types/index.PresentIndexTokenSet.html +45 -0
  124. package/docs/types/index.Projected.html +39 -0
  125. package/docs/types/index.QueryBuilderQueryOptions.html +45 -0
  126. package/docs/types/index.QueryOptionsByCC.html +49 -0
  127. package/docs/types/index.QueryOptionsByCF.html +47 -0
  128. package/docs/types/index.RangeKeyFrom.html +38 -0
  129. package/docs/types/index.ShardQueryFunction.html +63 -0
  130. package/docs/types/index.ShardQueryMap.html +56 -0
  131. package/docs/types/index.ShardQueryMapByCC.html +49 -0
  132. package/docs/types/index.ShardQueryMapByCF.html +47 -0
  133. package/docs/types/index.ShardedKeysFrom.html +38 -0
  134. package/docs/types/index.StorageItem.html +42 -0
  135. package/docs/types/index.StorageRecord.html +40 -0
  136. package/docs/types/index.TranscodedPropertiesFrom.html +38 -0
  137. package/docs/types/index.UnshardedKeysFrom.html +38 -0
  138. package/docs/types/index.ValidateConfigMap.html +40 -0
  139. package/lib/EntityManager/PrivateEntityManager.js +4 -0
  140. package/package.json +6 -6
@@ -0,0 +1,60 @@
1
+ <!DOCTYPE html><html class="default" lang="en" data-base="../"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>createEntityManager | @karmaniverous/entity-manager</title><meta name="description" content="Documentation for @karmaniverous/entity-manager"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script><script async src="../assets/hierarchy.js" id="tsd-hierarchy-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar">
2
+ <div class="tsd-toolbar-contents container"><a href="https://github.com/karmaniverous/entity-manager" class="title">@karmaniverous/entity-manager</a>
3
+ <div id="tsd-toolbar-links"></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/>
4
+ <ul role="listbox" id="tsd-search-results"></ul>
5
+ <div id="tsd-search-status" aria-live="polite" aria-atomic="true">
6
+ <div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></header>
7
+ <div class="container container-main">
8
+ <div class="col-content">
9
+ <div class="tsd-page-title">
10
+ <ul class="tsd-breadcrumb" aria-label="Breadcrumb">
11
+ <li><a href="../modules/index.html">index</a></li>
12
+ <li><a href="" aria-current="page">createEntityManager</a></li></ul>
13
+ <h1>Function createEntityManager</h1></div>
14
+ <section class="tsd-panel">
15
+ <ul class="tsd-signatures">
16
+ <li class="">
17
+ <div class="tsd-signature tsd-anchor-link" id="createentitymanager"><span class="tsd-kind-call-signature">createEntityManager</span><span class="tsd-signature-symbol">&lt;</span><br/>    <span class="tsd-signature-keyword">const</span> <a class="tsd-signature-type tsd-kind-type-parameter" href="#createentitymanagercc">CC</a> <span class="tsd-signature-keyword">extends</span> <a href="../interfaces/index.ConfigInput.html" class="tsd-signature-type tsd-kind-interface">ConfigInput</a><span class="tsd-signature-symbol">,</span><br/>    <a class="tsd-signature-type tsd-kind-type-parameter" href="#createentitymanagerem">EM</a> <span class="tsd-signature-keyword">extends</span> <a href="https://docs.karmanivero.us/entity-tools/types/entity-tools.EntityMap.html" class="tsd-signature-type external" target="_blank">EntityMap</a> <span class="tsd-signature-symbol">=</span> <a href="../types/index.EntitiesFromSchema.html" class="tsd-signature-type tsd-kind-type-alias">EntitiesFromSchema</a><span class="tsd-signature-symbol">&lt;</span><a class="tsd-signature-type tsd-kind-type-parameter" href="#createentitymanagercc">CC</a><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol">,</span><br/><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol">(</span><br/>    <span class="tsd-kind-parameter">config</span><span class="tsd-signature-symbol">:</span> <a class="tsd-signature-type tsd-kind-type-parameter" href="#createentitymanagercc">CC</a><span class="tsd-signature-symbol">,</span><br/>    <span class="tsd-kind-parameter">logger</span><span class="tsd-signature-symbol">?:</span> <a href="https://www.typescriptlang.org/docs/handbook/utility-types.html#picktype-keys" class="tsd-signature-type external" target="_blank">Pick</a><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">Console</span><span class="tsd-signature-symbol">,</span> <span class="tsd-signature-type">&quot;debug&quot;</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">&quot;error&quot;</span><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol">,</span><br/><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <a href="../classes/index.EntityManager.html" class="tsd-signature-type tsd-kind-class">EntityManager</a><span class="tsd-signature-symbol">&lt;</span><a href="../interfaces/index.CapturedConfigMapFrom.html" class="tsd-signature-type tsd-kind-interface">CapturedConfigMapFrom</a><span class="tsd-signature-symbol">&lt;</span><a class="tsd-signature-type tsd-kind-type-parameter" href="#createentitymanagercc">CC</a><span class="tsd-signature-symbol">,</span> <a class="tsd-signature-type tsd-kind-type-parameter" href="#createentitymanagerem">EM</a><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol">,</span> <a class="tsd-signature-type tsd-kind-type-parameter" href="#createentitymanagercc">CC</a><span class="tsd-signature-symbol">&gt;</span><a href="#createentitymanager" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="../assets/icons.svg#icon-anchor"></use></svg></a></div>
18
+ <div class="tsd-description">
19
+ <div class="tsd-comment tsd-typography"><p>Values-first factory that captures literal tokens and index names directly
20
+ from the provided config value. Runtime config parsing/validation is
21
+ unchanged (performed in the EntityManager constructor).</p>
22
+ </div>
23
+ <section class="tsd-panel">
24
+ <h4>Type Parameters</h4>
25
+ <ul class="tsd-type-parameter-list">
26
+ <li><span id="createentitymanagercc"><span class="tsd-signature-keyword">const</span> <span class="tsd-kind-type-parameter">CC</span> <span class="tsd-signature-keyword">extends</span> <a href="../interfaces/index.ConfigInput.html" class="tsd-signature-type tsd-kind-interface">ConfigInput</a></span>
27
+ <div class="tsd-comment tsd-typography"><p>Captured config input (values-first). Prefer <code>as const</code> and
28
+ <code>satisfies</code> at call sites to preserve literal keys.</p>
29
+ </div></li>
30
+ <li><span id="createentitymanagerem"><span class="tsd-kind-type-parameter">EM</span> <span class="tsd-signature-keyword">extends</span> <a href="https://docs.karmanivero.us/entity-tools/types/entity-tools.EntityMap.html" class="tsd-signature-type external" target="_blank">EntityMap</a> = <a href="../types/index.EntitiesFromSchema.html" class="tsd-signature-type tsd-kind-type-alias">EntitiesFromSchema</a><span class="tsd-signature-symbol">&lt;</span><a class="tsd-signature-type tsd-kind-type-parameter" href="#createentitymanagercc">CC</a><span class="tsd-signature-symbol">&gt;</span></span>
31
+ <div class="tsd-comment tsd-typography"><p>EntityMap for the manager. Defaults to a minimal derived map
32
+ from <code>CC.entitiesSchema</code> when present; otherwise falls back to EntityMap.</p>
33
+ </div></li></ul></section>
34
+ <div class="tsd-parameters">
35
+ <h4 class="tsd-parameters-title">Parameters</h4>
36
+ <ul class="tsd-parameter-list">
37
+ <li><span><span class="tsd-kind-parameter">config</span>: <a class="tsd-signature-type tsd-kind-type-parameter" href="#createentitymanagercc">CC</a></span></li>
38
+ <li><span><span class="tsd-kind-parameter">logger</span>: <a href="https://www.typescriptlang.org/docs/handbook/utility-types.html#picktype-keys" class="tsd-signature-type external" target="_blank">Pick</a><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">Console</span><span class="tsd-signature-symbol">,</span> <span class="tsd-signature-type">&quot;debug&quot;</span> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">&quot;error&quot;</span><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol"> = console</span></span></li></ul></div>
39
+ <h4 class="tsd-returns-title">Returns <a href="../classes/index.EntityManager.html" class="tsd-signature-type tsd-kind-class">EntityManager</a><span class="tsd-signature-symbol">&lt;</span><a href="../interfaces/index.CapturedConfigMapFrom.html" class="tsd-signature-type tsd-kind-interface">CapturedConfigMapFrom</a><span class="tsd-signature-symbol">&lt;</span><a class="tsd-signature-type tsd-kind-type-parameter" href="#createentitymanagercc">CC</a><span class="tsd-signature-symbol">,</span> <a class="tsd-signature-type tsd-kind-type-parameter" href="#createentitymanagerem">EM</a><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol">,</span> <a class="tsd-signature-type tsd-kind-type-parameter" href="#createentitymanagercc">CC</a><span class="tsd-signature-symbol">&gt;</span></h4><p>An <a href="../classes/index.EntityManager.html" class="tsd-kind-class"><code>EntityManager</code></a> instance whose type
40
+ captures CF from the single values-first config literal (<a href="../interfaces/index.ConfigInput.html" class="tsd-kind-interface"><code>ConfigInput</code></a>)
41
+ as the second generic parameter (phantom; type-only).</p>
42
+ <aside class="tsd-sources">
43
+ <ul>
44
+ <li>Defined in <a href="https://github.com/karmaniverous/entity-manager/blob/d2ff954ea0261727cdbac42b98076fc3e0181656/src/EntityManager/createEntityManager.ts#L226">EntityManager/createEntityManager.ts:226</a></li></ul></aside></div></li></ul></section></div>
45
+ <div class="col-sidebar">
46
+ <div class="page-menu">
47
+ <div class="tsd-navigation settings">
48
+ <details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg>
49
+ <h3>Settings</h3></summary>
50
+ <div class="tsd-accordion-details">
51
+ <div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span>
52
+ <ul id="tsd-filter-options">
53
+ <li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li></ul></div>
54
+ <div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div>
55
+ <div class="site-menu">
56
+ <nav class="tsd-navigation"><a href="../modules.html">@karmaniverous/entity-manager</a>
57
+ <ul class="tsd-small-nested-navigation" id="tsd-nav-container">
58
+ <li>Loading...</li></ul></nav></div></div></div><footer>
59
+ <p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer>
60
+ <div class="overlay"></div></body></html>
@@ -0,0 +1,31 @@
1
+ <!DOCTYPE html><html class="default" lang="en" data-base="./"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>@karmaniverous/entity-manager</title><meta name="description" content="Documentation for @karmaniverous/entity-manager"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="assets/style.css"/><link rel="stylesheet" href="assets/highlight.css"/><script defer src="assets/main.js"></script><script async src="assets/icons.js" id="tsd-icons-script"></script><script async src="assets/search.js" id="tsd-search-script"></script><script async src="assets/navigation.js" id="tsd-nav-script"></script><script async src="assets/hierarchy.js" id="tsd-hierarchy-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar">
2
+ <div class="tsd-toolbar-contents container"><a href="https://github.com/karmaniverous/entity-manager" class="title">@karmaniverous/entity-manager</a>
3
+ <div id="tsd-toolbar-links"></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/>
4
+ <ul role="listbox" id="tsd-search-results"></ul>
5
+ <div id="tsd-search-status" aria-live="polite" aria-atomic="true">
6
+ <div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-menu"></use></svg></a></div></header>
7
+ <div class="container container-main">
8
+ <div class="col-content">
9
+ <div class="tsd-page-title">
10
+ <h1>@karmaniverous/entity-manager</h1></div>
11
+ <h2>Hierarchy Summary</h2>
12
+ <ul class="tsd-full-hierarchy">
13
+ <li data-refl="71" id="index.BaseConfigMap"><a href="interfaces/index.BaseConfigMap.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Interface"><use href="assets/icons.svg#icon-256"></use></svg>BaseConfigMap</a>
14
+ <ul>
15
+ <li data-refl="167" id="index.CapturedConfigMapFrom"><a href="interfaces/index.CapturedConfigMapFrom.html"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Interface"><use href="assets/icons.svg#icon-256"></use></svg>CapturedConfigMapFrom</a></li></ul></li></ul></div>
16
+ <div class="col-sidebar">
17
+ <div class="page-menu">
18
+ <div class="tsd-navigation settings">
19
+ <details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-chevronDown"></use></svg>
20
+ <h3>Settings</h3></summary>
21
+ <div class="tsd-accordion-details">
22
+ <div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span>
23
+ <ul id="tsd-filter-options">
24
+ <li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li></ul></div>
25
+ <div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div>
26
+ <div class="site-menu">
27
+ <nav class="tsd-navigation"><a href="modules.html">@karmaniverous/entity-manager</a>
28
+ <ul class="tsd-small-nested-navigation" id="tsd-nav-container">
29
+ <li>Loading...</li></ul></nav></div></div></div><footer>
30
+ <p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer>
31
+ <div class="overlay"></div></body></html>
@@ -0,0 +1,212 @@
1
+ <!DOCTYPE html><html class="default" lang="en" data-base="./"><head><meta charset="utf-8"/><link rel="canonical" href="https://docs.karmanivero.us/entity-manager/"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>@karmaniverous/entity-manager</title><meta name="description" content="Documentation for @karmaniverous/entity-manager"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="assets/style.css"/><link rel="stylesheet" href="assets/highlight.css"/><script defer src="assets/main.js"></script><script async src="assets/icons.js" id="tsd-icons-script"></script><script async src="assets/search.js" id="tsd-search-script"></script><script async src="assets/navigation.js" id="tsd-nav-script"></script><script async src="assets/hierarchy.js" id="tsd-hierarchy-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar">
2
+ <div class="tsd-toolbar-contents container"><a href="https://github.com/karmaniverous/entity-manager" class="title">@karmaniverous/entity-manager</a>
3
+ <div id="tsd-toolbar-links"></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/>
4
+ <ul role="listbox" id="tsd-search-results"></ul>
5
+ <div id="tsd-search-status" aria-live="polite" aria-atomic="true">
6
+ <div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-menu"></use></svg></a></div></header>
7
+ <div class="container container-main">
8
+ <div class="col-content">
9
+ <div class="tsd-page-title">
10
+ <h1>@karmaniverous/entity-manager</h1></div>
11
+ <div class="tsd-panel tsd-typography"><h1 id="entity-manager" class="tsd-anchor-link">entity-manager<a href="#entity-manager" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h1>
12
+ <p><a href="https://www.npmjs.com/package/@karmaniverous/entity-manager" target="_blank" class="external"><img src="https://img.shields.io/npm/v/@karmaniverous/entity-manager.svg" alt="npm version"></a> <img src="https://img.shields.io/node/v/@karmaniverous/entity-manager" alt="Node Current"> <a href="https://github.com/karmaniverous/entity-manager/tree/main/LICENSE.md" target="_blank" class="external"><img src="https://img.shields.io/badge/license-BSD--3--Clause-blue.svg" alt="license"></a></p>
13
+ <p>Entity Manager implements rational indexing &amp; cross‑shard querying at scale in your NoSQL database so you can focus on application logic. It is provider‑agnostic (great fit for DynamoDB) and TypeScript‑first with strong types and runtime validation.</p>
14
+ <p>Key links:</p>
15
+ <ul>
16
+ <li>Docs: <a href="https://docs.karmanivero.us/entity-manager">https://docs.karmanivero.us/entity-manager</a></li>
17
+ <li>Discussions: <a href="https://github.com/karmaniverous/entity-manager/discussions" target="_blank" class="external">https://github.com/karmaniverous/entity-manager/discussions</a></li>
18
+ </ul>
19
+ <h2 id="why-this-library" class="tsd-anchor-link">Why this library?<a href="#why-this-library" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2>
20
+ <p>Modern NoSQL puts the burden of indexing, sharding, and pagination on the application. Entity Manager gives you:</p>
21
+ <ul>
22
+ <li>Values‑first configuration with runtime validation (Zod) and best‑in‑class inference.</li>
23
+ <li>Token‑aware and index‑aware types end‑to‑end (entities, keys, page keys, queries).</li>
24
+ <li>Deterministic sharding with a time‑based scale‑up schedule.</li>
25
+ <li>Cross‑shard, multi‑index query orchestration with dedupe and sorting.</li>
26
+ <li>Dehydration/rehydration of page keys to pass a single compact token between calls.</li>
27
+ </ul>
28
+ <h2 id="install" class="tsd-anchor-link">Install<a href="#install" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2>
29
+ <pre><code class="bash"><span class="hl-0">npm</span><span class="hl-1"> </span><span class="hl-2">install</span><span class="hl-1"> </span><span class="hl-2">@karmaniverous/entity-manager</span><br/><span class="hl-3"># optional (tests/demo helpers)</span><br/><span class="hl-0">npm</span><span class="hl-1"> </span><span class="hl-2">install</span><span class="hl-1"> </span><span class="hl-4">--save-dev</span><span class="hl-1"> </span><span class="hl-2">@karmaniverous/mock-db</span>
30
+ </code><button type="button">Copy</button></pre>
31
+
32
+ <h2 id="dx-highlights" class="tsd-anchor-link">DX highlights<a href="#dx-highlights" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2>
33
+ <ul>
34
+ <li>Values‑first + schema‑first config:
35
+ <ul>
36
+ <li>Use a config literal (prefer <code>as const</code> and <code>satisfies</code>) to preserve literal tokens.</li>
37
+ <li>Optionally provide Zod schemas (<code>entitiesSchema</code>) to infer entity shapes without generics.</li>
38
+ </ul>
39
+ </li>
40
+ <li>Projection‑aware typing (type‑only K):
41
+ <ul>
42
+ <li>Pass attributes as a const tuple (K) through your query types to narrow result items to Pick&lt;…&gt; of those properties.</li>
43
+ <li>No runtime change; adapters execute projections. Adapters should auto‑include <code>uniqueProperty</code> and any explicit sort keys when callers omit them to preserve dedupe/sort invariants.</li>
44
+ </ul>
45
+ </li>
46
+ <li>Index‑aware typing (values‑first config literal “CF” and captured config “CC” helpers):
47
+ <ul>
48
+ <li>CF (values‑first config literal): drive index token unions and page‑key narrowing directly from a values‑first config literal (<code>QueryOptionsByCF</code>, <code>ShardQueryMapByCF</code>).</li>
49
+ <li>CC (Captured Config): derive index tokens from a captured config type while reusing CF for narrowing (<code>QueryOptionsByCC</code>, <code>ShardQueryMapByCC</code>).</li>
50
+ </ul>
51
+ </li>
52
+ <li>Token‑aware helpers:
53
+ <ul>
54
+ <li><code>addKeys</code>, <code>getPrimaryKey</code>, <code>removeKeys</code> narrow types by entity token (no casts).</li>
55
+ </ul>
56
+ </li>
57
+ <li>Index‑aware page keys (optional CF channel):
58
+ <ul>
59
+ <li>Provide a values‑first config literal (CF) with <code>indexes</code> and get typed page keys per index.</li>
60
+ <li>Use <code>QueryOptionsByCF</code> and <code>ShardQueryMapByCF</code> to derive index token unions directly from CF.</li>
61
+ </ul>
62
+ </li>
63
+ <li>CC-based DX sugar (values-first captured config):
64
+ <ul>
65
+ <li>Use <code>QueryOptionsByCC</code> and <code>ShardQueryMapByCC</code> to derive index token unions from a captured config type (via <code>IndexTokensFrom</code>), while still benefiting from page-key narrowing.</li>
66
+ </ul>
67
+ </li>
68
+ </ul>
69
+ <h2 id="quick-start-valuesfirst-schemafirst" class="tsd-anchor-link">Quick start (values‑first + schema‑first)<a href="#quick-start-valuesfirst-schemafirst" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2>
70
+ <pre><code class="ts"><span class="hl-5">import</span><span class="hl-1"> { </span><span class="hl-6">z</span><span class="hl-1"> } </span><span class="hl-5">from</span><span class="hl-1"> </span><span class="hl-2">&#39;zod&#39;</span><span class="hl-1">;</span><br/><span class="hl-5">import</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-6">createEntityManager</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">defaultTranscodes</span><span class="hl-1">,</span><br/><span class="hl-1">} </span><span class="hl-5">from</span><span class="hl-1"> </span><span class="hl-2">&#39;@karmaniverous/entity-manager&#39;</span><span class="hl-1">;</span><br/><br/><span class="hl-3">// 1) Schema-first entity shapes (non-generated fields only)</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">userSchema</span><span class="hl-1"> = </span><span class="hl-6">z</span><span class="hl-1">.</span><span class="hl-0">object</span><span class="hl-1">({</span><br/><span class="hl-1"> </span><span class="hl-6">userId:</span><span class="hl-1"> </span><span class="hl-6">z</span><span class="hl-1">.</span><span class="hl-0">string</span><span class="hl-1">(), </span><span class="hl-3">// unique property</span><br/><span class="hl-1"> </span><span class="hl-6">created:</span><span class="hl-1"> </span><span class="hl-6">z</span><span class="hl-1">.</span><span class="hl-0">number</span><span class="hl-1">(), </span><span class="hl-3">// timestamp property</span><br/><span class="hl-1"> </span><span class="hl-6">updated:</span><span class="hl-1"> </span><span class="hl-6">z</span><span class="hl-1">.</span><span class="hl-0">number</span><span class="hl-1">().</span><span class="hl-0">optional</span><span class="hl-1">(),</span><br/><span class="hl-1"> </span><span class="hl-6">firstNameCanonical:</span><span class="hl-1"> </span><span class="hl-6">z</span><span class="hl-1">.</span><span class="hl-0">string</span><span class="hl-1">(),</span><br/><span class="hl-1"> </span><span class="hl-6">lastNameCanonical:</span><span class="hl-1"> </span><span class="hl-6">z</span><span class="hl-1">.</span><span class="hl-0">string</span><span class="hl-1">(),</span><br/><span class="hl-1">});</span><br/><br/><span class="hl-3">// 2) Values-first config literal (prefer `as const`)</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">config</span><span class="hl-1"> = {</span><br/><span class="hl-1"> </span><span class="hl-6">hashKey:</span><span class="hl-1"> </span><span class="hl-2">&#39;hashKey2&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">rangeKey:</span><span class="hl-1"> </span><span class="hl-2">&#39;rangeKey&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">generatedProperties:</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-6">sharded:</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-6">userPK:</span><span class="hl-1"> [</span><span class="hl-2">&#39;userId&#39;</span><span class="hl-1">] </span><span class="hl-5">as</span><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> </span><span class="hl-6">unsharded:</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-6">firstNameRK:</span><span class="hl-1"> [</span><span class="hl-2">&#39;firstNameCanonical&#39;</span><span class="hl-1">, </span><span class="hl-2">&#39;lastNameCanonical&#39;</span><span class="hl-1">] </span><span class="hl-5">as</span><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">lastNameRK:</span><span class="hl-1"> [</span><span class="hl-2">&#39;lastNameCanonical&#39;</span><span class="hl-1">, </span><span class="hl-2">&#39;firstNameCanonical&#39;</span><span class="hl-1">] </span><span class="hl-5">as</span><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> </span><span class="hl-6">propertyTranscodes:</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-6">userId:</span><span class="hl-1"> </span><span class="hl-2">&#39;string&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">created:</span><span class="hl-1"> </span><span class="hl-2">&#39;timestamp&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">updated:</span><span class="hl-1"> </span><span class="hl-2">&#39;timestamp&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">firstNameCanonical:</span><span class="hl-1"> </span><span class="hl-2">&#39;string&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">lastNameCanonical:</span><span class="hl-1"> </span><span class="hl-2">&#39;string&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> </span><span class="hl-6">indexes:</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-6">created:</span><span class="hl-1"> { </span><span class="hl-6">hashKey:</span><span class="hl-1"> </span><span class="hl-2">&#39;hashKey2&#39;</span><span class="hl-1">, </span><span class="hl-6">rangeKey:</span><span class="hl-1"> </span><span class="hl-2">&#39;created&#39;</span><span class="hl-1"> },</span><br/><span class="hl-1"> </span><span class="hl-6">userCreated:</span><span class="hl-1"> { </span><span class="hl-6">hashKey:</span><span class="hl-1"> </span><span class="hl-2">&#39;userPK&#39;</span><span class="hl-1">, </span><span class="hl-6">rangeKey:</span><span class="hl-1"> </span><span class="hl-2">&#39;created&#39;</span><span class="hl-1"> },</span><br/><span class="hl-1"> </span><span class="hl-6">firstName:</span><span class="hl-1"> { </span><span class="hl-6">hashKey:</span><span class="hl-1"> </span><span class="hl-2">&#39;hashKey2&#39;</span><span class="hl-1">, </span><span class="hl-6">rangeKey:</span><span class="hl-1"> </span><span class="hl-2">&#39;firstNameRK&#39;</span><span class="hl-1"> },</span><br/><span class="hl-1"> </span><span class="hl-6">lastName:</span><span class="hl-1"> { </span><span class="hl-6">hashKey:</span><span class="hl-1"> </span><span class="hl-2">&#39;hashKey2&#39;</span><span class="hl-1">, </span><span class="hl-6">rangeKey:</span><span class="hl-1"> </span><span class="hl-2">&#39;lastNameRK&#39;</span><span class="hl-1"> },</span><br/><span class="hl-1"> } </span><span class="hl-5">as</span><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">entities:</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-6">user:</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-6">uniqueProperty:</span><span class="hl-1"> </span><span class="hl-2">&#39;userId&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">timestampProperty:</span><span class="hl-1"> </span><span class="hl-2">&#39;created&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">shardBumps:</span><span class="hl-1"> [{ </span><span class="hl-6">timestamp:</span><span class="hl-1"> </span><span class="hl-6">Date</span><span class="hl-1">.</span><span class="hl-0">now</span><span class="hl-1">(), </span><span class="hl-6">charBits:</span><span class="hl-1"> </span><span class="hl-8">2</span><span class="hl-1">, </span><span class="hl-6">chars:</span><span class="hl-1"> </span><span class="hl-8">1</span><span class="hl-1"> }],</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> },</span><br/><span class="hl-1"> </span><span class="hl-6">entitiesSchema:</span><span class="hl-1"> { </span><span class="hl-6">user:</span><span class="hl-1"> </span><span class="hl-6">userSchema</span><span class="hl-1"> },</span><br/><span class="hl-1"> </span><span class="hl-6">transcodes:</span><span class="hl-1"> </span><span class="hl-6">defaultTranscodes</span><span class="hl-1">,</span><br/><span class="hl-1">} </span><span class="hl-5">as</span><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1">;</span><br/><br/><span class="hl-3">// 3) Create the manager — types captured from values, shapes from schemas</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">manager</span><span class="hl-1"> = </span><span class="hl-0">createEntityManager</span><span class="hl-1">(</span><span class="hl-6">config</span><span class="hl-1">);</span>
71
+ </code><button type="button">Copy</button></pre>
72
+
73
+ <h3 id="tokenaware-helpers" class="tsd-anchor-link">Token‑aware helpers<a href="#tokenaware-helpers" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
74
+ <pre><code class="ts"><span class="hl-3">// Input item (no generated keys yet)</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">user</span><span class="hl-1"> = {</span><br/><span class="hl-1"> </span><span class="hl-6">userId:</span><span class="hl-1"> </span><span class="hl-2">&#39;u1&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">created:</span><span class="hl-1"> </span><span class="hl-6">Date</span><span class="hl-1">.</span><span class="hl-0">now</span><span class="hl-1">(),</span><br/><span class="hl-1"> </span><span class="hl-6">firstNameCanonical:</span><span class="hl-1"> </span><span class="hl-2">&#39;lee&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">lastNameCanonical:</span><span class="hl-1"> </span><span class="hl-2">&#39;zhang&#39;</span><span class="hl-1">,</span><br/><span class="hl-1">};</span><br/><br/><span class="hl-3">// Add generated keys (hashKey/rangeKey + index tokens)</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">record</span><span class="hl-1"> = </span><span class="hl-6">manager</span><span class="hl-1">.</span><span class="hl-0">addKeys</span><span class="hl-1">(</span><span class="hl-2">&#39;user&#39;</span><span class="hl-1">, </span><span class="hl-6">user</span><span class="hl-1">);</span><br/><br/><span class="hl-3">// Compute one or more primary keys</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">keys</span><span class="hl-1"> = </span><span class="hl-6">manager</span><span class="hl-1">.</span><span class="hl-0">getPrimaryKey</span><span class="hl-1">(</span><span class="hl-2">&#39;user&#39;</span><span class="hl-1">, { </span><span class="hl-6">userId:</span><span class="hl-1"> </span><span class="hl-2">&#39;u1&#39;</span><span class="hl-1"> });</span><br/><br/><span class="hl-3">// Strip generated keys after read</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">item</span><span class="hl-1"> = </span><span class="hl-6">manager</span><span class="hl-1">.</span><span class="hl-0">removeKeys</span><span class="hl-1">(</span><span class="hl-2">&#39;user&#39;</span><span class="hl-1">, </span><span class="hl-6">record</span><span class="hl-1">);</span>
75
+ </code><button type="button">Copy</button></pre>
76
+
77
+ <p>Types narrow automatically from the entity token (<code>'user'</code>). No casts required.</p>
78
+ <h2 id="indexaware-querying-valuesfirst-config-literal-cf-channel" class="tsd-anchor-link">Index‑aware querying (values‑first config literal, “CF” channel)<a href="#indexaware-querying-valuesfirst-config-literal-cf-channel" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2>
79
+ <p>When you author a values‑first config literal with <code>indexes</code> (prefer <code>as const</code>), Entity Manager can:</p>
80
+ <ul>
81
+ <li>Constrain <code>shardQueryMap</code> keys to the index key union.</li>
82
+ <li>Narrow page‑key shapes per index (only its component tokens).</li>
83
+ <li>Derive ITS (index token subset) automatically from CF via <code>QueryOptionsByCF</code> and <code>ShardQueryMapByCF</code>.</li>
84
+ </ul>
85
+ <pre><code class="ts"><span class="hl-5">import</span><span class="hl-1"> </span><span class="hl-5">type</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-6">ShardQueryFunction</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">ShardQueryMapByCF</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">QueryOptionsByCF</span><span class="hl-1">,</span><br/><span class="hl-1">} </span><span class="hl-5">from</span><span class="hl-1"> </span><span class="hl-2">&#39;@karmaniverous/entity-manager&#39;</span><span class="hl-1">;</span><br/><br/><span class="hl-3">// CF: capture index tokens from a values-first literal</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">cf</span><span class="hl-1"> = {</span><br/><span class="hl-1"> </span><span class="hl-6">indexes:</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-6">firstName:</span><span class="hl-1"> { </span><span class="hl-6">hashKey:</span><span class="hl-1"> </span><span class="hl-2">&#39;hashKey2&#39;</span><span class="hl-1">, </span><span class="hl-6">rangeKey:</span><span class="hl-1"> </span><span class="hl-2">&#39;firstNameRK&#39;</span><span class="hl-1"> },</span><br/><span class="hl-1"> </span><span class="hl-6">lastName:</span><span class="hl-1"> { </span><span class="hl-6">hashKey:</span><span class="hl-1"> </span><span class="hl-2">&#39;hashKey2&#39;</span><span class="hl-1">, </span><span class="hl-6">rangeKey:</span><span class="hl-1"> </span><span class="hl-2">&#39;lastNameRK&#39;</span><span class="hl-1"> },</span><br/><span class="hl-1"> },</span><br/><span class="hl-1">} </span><span class="hl-5">as</span><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1">;</span><br/><span class="hl-4">type</span><span class="hl-1"> </span><span class="hl-9">CF</span><span class="hl-1"> = </span><span class="hl-4">typeof</span><span class="hl-1"> </span><span class="hl-6">cf</span><span class="hl-1">;</span><br/><br/><span class="hl-3">// SQFs are typed; pageKey is narrowed to index components per IT</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">firstNameSQF</span><span class="hl-1">: </span><span class="hl-9">ShardQueryFunction</span><span class="hl-1">&lt;</span><br/><span class="hl-1"> </span><span class="hl-9">MyConfigMap</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">&#39;user&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">&#39;firstName&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-9">CF</span><br/><span class="hl-1">&gt; = </span><span class="hl-4">async</span><span class="hl-1"> (</span><span class="hl-6">hashKey</span><span class="hl-1">, </span><span class="hl-6">pageKey</span><span class="hl-1">, </span><span class="hl-6">pageSize</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> ({ </span><span class="hl-6">count:</span><span class="hl-1"> </span><span class="hl-8">0</span><span class="hl-1">, </span><span class="hl-6">items:</span><span class="hl-1"> [], </span><span class="hl-6">pageKey</span><span class="hl-1"> });</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">lastNameSQF</span><span class="hl-1">: </span><span class="hl-9">ShardQueryFunction</span><span class="hl-1">&lt;</span><br/><span class="hl-1"> </span><span class="hl-9">MyConfigMap</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">&#39;user&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">&#39;lastName&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-9">CF</span><br/><span class="hl-1">&gt; = </span><span class="hl-4">async</span><span class="hl-1"> (</span><span class="hl-6">hashKey</span><span class="hl-1">, </span><span class="hl-6">pageKey</span><span class="hl-1">, </span><span class="hl-6">pageSize</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> ({ </span><span class="hl-6">count:</span><span class="hl-1"> </span><span class="hl-8">0</span><span class="hl-1">, </span><span class="hl-6">items:</span><span class="hl-1"> [], </span><span class="hl-6">pageKey</span><span class="hl-1"> });</span><br/><br/><span class="hl-3">// CF-aware shardQueryMap — only &#39;firstName&#39; | &#39;lastName&#39; allowed</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">shardQueryMap</span><span class="hl-1">: </span><span class="hl-9">ShardQueryMapByCF</span><span class="hl-1">&lt;</span><span class="hl-9">MyConfigMap</span><span class="hl-1">, </span><span class="hl-2">&#39;user&#39;</span><span class="hl-1">, </span><span class="hl-9">CF</span><span class="hl-1">&gt; = {</span><br/><span class="hl-1"> </span><span class="hl-6">firstName:</span><span class="hl-1"> </span><span class="hl-6">firstNameSQF</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">lastName:</span><span class="hl-1"> </span><span class="hl-6">lastNameSQF</span><span class="hl-1">,</span><br/><span class="hl-1">};</span><br/><br/><span class="hl-3">// Derive ITS from CF for options</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">options</span><span class="hl-1">: </span><span class="hl-9">QueryOptionsByCF</span><span class="hl-1">&lt;</span><span class="hl-9">MyConfigMap</span><span class="hl-1">, </span><span class="hl-2">&#39;user&#39;</span><span class="hl-1">, </span><span class="hl-9">CF</span><span class="hl-1">&gt; = {</span><br/><span class="hl-1"> </span><span class="hl-6">entityToken:</span><span class="hl-1"> </span><span class="hl-2">&#39;user&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">item:</span><span class="hl-1"> {},</span><br/><span class="hl-1"> </span><span class="hl-6">shardQueryMap</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">limit:</span><span class="hl-1"> </span><span class="hl-8">50</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">pageSize:</span><span class="hl-1"> </span><span class="hl-8">10</span><span class="hl-1">,</span><br/><span class="hl-1">};</span><br/><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">result</span><span class="hl-1"> = </span><span class="hl-5">await</span><span class="hl-1"> </span><span class="hl-6">manager</span><span class="hl-1">.</span><span class="hl-0">query</span><span class="hl-1">(</span><span class="hl-6">options</span><span class="hl-1">);</span><br/><span class="hl-3">// result.pageKeyMap is a compact string — pass it to the next call’s options.pageKeyMap</span>
86
+ </code><button type="button">Copy</button></pre>
87
+
88
+ <h3 id="captured-config-cc-aliases" class="tsd-anchor-link">Captured Config (“CC”) aliases<a href="#captured-config-cc-aliases" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h3>
89
+ <p>You can also derive ITS (index token subset) directly from a values‑first captured config type (CC) using <code>QueryOptionsByCC</code> and <code>ShardQueryMapByCC</code>. This mirrors the CF helpers but drives ITS from the CC type (via <code>IndexTokensFrom</code>) and passes the same CC through the CF channel for page‑key narrowing.</p>
90
+ <pre><code class="ts"><span class="hl-5">import</span><span class="hl-1"> </span><span class="hl-5">type</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-6">ShardQueryFunction</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">ShardQueryMapByCC</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">QueryOptionsByCC</span><span class="hl-1">,</span><br/><span class="hl-1">} </span><span class="hl-5">from</span><span class="hl-1"> </span><span class="hl-2">&#39;@karmaniverous/entity-manager&#39;</span><span class="hl-1">;</span><br/><br/><span class="hl-3">// A values-first config literal capturing index tokens (the same shape used for CF)</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">cc</span><span class="hl-1"> = {</span><br/><span class="hl-1"> </span><span class="hl-6">indexes:</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-6">firstName:</span><span class="hl-1"> { </span><span class="hl-6">hashKey:</span><span class="hl-1"> </span><span class="hl-2">&#39;hashKey2&#39;</span><span class="hl-1">, </span><span class="hl-6">rangeKey:</span><span class="hl-1"> </span><span class="hl-2">&#39;firstNameRK&#39;</span><span class="hl-1"> },</span><br/><span class="hl-1"> </span><span class="hl-6">lastName:</span><span class="hl-1"> { </span><span class="hl-6">hashKey:</span><span class="hl-1"> </span><span class="hl-2">&#39;hashKey2&#39;</span><span class="hl-1">, </span><span class="hl-6">rangeKey:</span><span class="hl-1"> </span><span class="hl-2">&#39;lastNameRK&#39;</span><span class="hl-1"> },</span><br/><span class="hl-1"> },</span><br/><span class="hl-1">} </span><span class="hl-5">as</span><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1">;</span><br/><span class="hl-4">type</span><span class="hl-1"> </span><span class="hl-9">CC</span><span class="hl-1"> = </span><span class="hl-4">typeof</span><span class="hl-1"> </span><span class="hl-6">cc</span><span class="hl-1">;</span><br/><br/><span class="hl-3">// Reuse typed SQFs (pageKey narrowed per index)</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">firstNameSQF</span><span class="hl-1">: </span><span class="hl-9">ShardQueryFunction</span><span class="hl-1">&lt;</span><br/><span class="hl-1"> </span><span class="hl-9">MyConfigMap</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">&#39;user&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">&#39;firstName&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-9">CC</span><br/><span class="hl-1">&gt; = </span><span class="hl-4">async</span><span class="hl-1"> (</span><span class="hl-6">hashKey</span><span class="hl-1">, </span><span class="hl-6">pageKey</span><span class="hl-1">, </span><span class="hl-6">pageSize</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> ({ </span><span class="hl-6">count:</span><span class="hl-1"> </span><span class="hl-8">0</span><span class="hl-1">, </span><span class="hl-6">items:</span><span class="hl-1"> [], </span><span class="hl-6">pageKey</span><span class="hl-1"> });</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">lastNameSQF</span><span class="hl-1">: </span><span class="hl-9">ShardQueryFunction</span><span class="hl-1">&lt;</span><br/><span class="hl-1"> </span><span class="hl-9">MyConfigMap</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">&#39;user&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-2">&#39;lastName&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-9">CC</span><br/><span class="hl-1">&gt; = </span><span class="hl-4">async</span><span class="hl-1"> (</span><span class="hl-6">hashKey</span><span class="hl-1">, </span><span class="hl-6">pageKey</span><span class="hl-1">, </span><span class="hl-6">pageSize</span><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> ({ </span><span class="hl-6">count:</span><span class="hl-1"> </span><span class="hl-8">0</span><span class="hl-1">, </span><span class="hl-6">items:</span><span class="hl-1"> [], </span><span class="hl-6">pageKey</span><span class="hl-1"> });</span><br/><br/><span class="hl-3">// CC-aware shardQueryMap — only &#39;firstName&#39; | &#39;lastName&#39; allowed</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">shardQueryMapCC</span><span class="hl-1">: </span><span class="hl-9">ShardQueryMapByCC</span><span class="hl-1">&lt;</span><span class="hl-9">MyConfigMap</span><span class="hl-1">, </span><span class="hl-2">&#39;user&#39;</span><span class="hl-1">, </span><span class="hl-9">CC</span><span class="hl-1">&gt; = {</span><br/><span class="hl-1"> </span><span class="hl-6">firstName:</span><span class="hl-1"> </span><span class="hl-6">firstNameSQF</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">lastName:</span><span class="hl-1"> </span><span class="hl-6">lastNameSQF</span><span class="hl-1">,</span><br/><span class="hl-1">};</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">optionsCC</span><span class="hl-1">: </span><span class="hl-9">QueryOptionsByCC</span><span class="hl-1">&lt;</span><span class="hl-9">MyConfigMap</span><span class="hl-1">, </span><span class="hl-2">&#39;user&#39;</span><span class="hl-1">, </span><span class="hl-9">CC</span><span class="hl-1">&gt; = {</span><br/><span class="hl-1"> </span><span class="hl-6">entityToken:</span><span class="hl-1"> </span><span class="hl-2">&#39;user&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">item:</span><span class="hl-1"> {},</span><br/><span class="hl-1"> </span><span class="hl-6">shardQueryMap:</span><span class="hl-1"> </span><span class="hl-6">shardQueryMapCC</span><span class="hl-1">,</span><br/><span class="hl-1">};</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">resultCC</span><span class="hl-1"> = </span><span class="hl-5">await</span><span class="hl-1"> </span><span class="hl-6">manager</span><span class="hl-1">.</span><span class="hl-0">query</span><span class="hl-1">(</span><span class="hl-6">optionsCC</span><span class="hl-1">);</span>
91
+ </code><button type="button">Copy</button></pre>
92
+
93
+ <p>Notes:</p>
94
+ <ul>
95
+ <li>Entity Manager enumerates hash‑key space for the time window, rehydrates page keys (when present), executes shard queries in parallel (throttled), dedupes by unique property, sorts, and dehydrates a new pageKeyMap.</li>
96
+ <li>For provider integration, the SQF lambda encapsulates the platform‑specific query for one index + shard page. See tests and entity‑client‑dynamodb for examples.</li>
97
+ </ul>
98
+ <h2 id="projectionaware-typing-k" class="tsd-anchor-link">Projection‑aware typing (K)<a href="#projectionaware-typing-k" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2>
99
+ <p>Entity Manager supports a type‑only projection channel K that narrows result item shapes when a provider adapter projects a subset of attributes at runtime. Pass your attributes as a const tuple and thread K through <code>ShardQueryFunction/Map</code>, <code>QueryOptions</code>, and <code>QueryResult</code>.</p>
100
+ <pre><code class="ts"><span class="hl-5">import</span><span class="hl-1"> </span><span class="hl-5">type</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-6">ConfigMap</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">EntityItemByToken</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">QueryOptions</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">QueryResult</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">ShardQueryFunction</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">ShardQueryMap</span><span class="hl-1">,</span><br/><span class="hl-1">} </span><span class="hl-5">from</span><span class="hl-1"> </span><span class="hl-2">&#39;@karmaniverous/entity-manager&#39;</span><span class="hl-1">;</span><br/><br/><span class="hl-3">// Minimal entities (example)</span><br/><span class="hl-4">interface</span><span class="hl-1"> </span><span class="hl-9">Email</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-6">created</span><span class="hl-1">: </span><span class="hl-9">number</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-6">email</span><span class="hl-1">: </span><span class="hl-9">string</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-6">userId</span><span class="hl-1">: </span><span class="hl-9">string</span><span class="hl-1">;</span><br/><span class="hl-1">}</span><br/><span class="hl-4">interface</span><span class="hl-1"> </span><span class="hl-9">User</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-6">beneficiaryId</span><span class="hl-1">: </span><span class="hl-9">string</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-6">created</span><span class="hl-1">: </span><span class="hl-9">number</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-6">firstNameCanonical</span><span class="hl-1">: </span><span class="hl-9">string</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-6">lastNameCanonical</span><span class="hl-1">: </span><span class="hl-9">string</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-6">phone</span><span class="hl-1">?: </span><span class="hl-9">string</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-6">updated</span><span class="hl-1">: </span><span class="hl-9">number</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-6">userId</span><span class="hl-1">: </span><span class="hl-9">string</span><span class="hl-1">;</span><br/><span class="hl-1">}</span><br/><br/><span class="hl-4">type</span><span class="hl-1"> </span><span class="hl-9">MyConfigMap</span><span class="hl-1"> = </span><span class="hl-9">ConfigMap</span><span class="hl-1">&lt;{</span><br/><span class="hl-1"> </span><span class="hl-6">EntityMap</span><span class="hl-1">: { </span><span class="hl-6">email</span><span class="hl-1">: </span><span class="hl-9">Email</span><span class="hl-1">; </span><span class="hl-6">user</span><span class="hl-1">: </span><span class="hl-9">User</span><span class="hl-1"> };</span><br/><span class="hl-1"> </span><span class="hl-6">HashKey</span><span class="hl-1">: </span><span class="hl-2">&#39;hashKey2&#39;</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-6">RangeKey</span><span class="hl-1">: </span><span class="hl-2">&#39;rangeKey&#39;</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-6">ShardedKeys</span><span class="hl-1">: </span><span class="hl-2">&#39;beneficiaryPK&#39;</span><span class="hl-1"> | </span><span class="hl-2">&#39;userPK&#39;</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-6">UnshardedKeys</span><span class="hl-1">: </span><span class="hl-2">&#39;firstNameRK&#39;</span><span class="hl-1"> | </span><span class="hl-2">&#39;lastNameRK&#39;</span><span class="hl-1"> | </span><span class="hl-2">&#39;phoneRK&#39;</span><span class="hl-1">;</span><br/><span class="hl-1"> </span><span class="hl-6">TranscodedProperties</span><span class="hl-1">:</span><br/><span class="hl-1"> | </span><span class="hl-2">&#39;beneficiaryId&#39;</span><br/><span class="hl-1"> | </span><span class="hl-2">&#39;created&#39;</span><br/><span class="hl-1"> | </span><span class="hl-2">&#39;email&#39;</span><br/><span class="hl-1"> | </span><span class="hl-2">&#39;firstNameCanonical&#39;</span><br/><span class="hl-1"> | </span><span class="hl-2">&#39;lastNameCanonical&#39;</span><br/><span class="hl-1"> | </span><span class="hl-2">&#39;phone&#39;</span><br/><span class="hl-1"> | </span><span class="hl-2">&#39;updated&#39;</span><br/><span class="hl-1"> | </span><span class="hl-2">&#39;userId&#39;</span><span class="hl-1">;</span><br/><span class="hl-1">}&gt;;</span><br/><br/><span class="hl-3">// CF capturing a single index</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">cf</span><span class="hl-1"> = {</span><br/><span class="hl-1"> </span><span class="hl-6">indexes:</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-6">firstName:</span><span class="hl-1"> { </span><span class="hl-6">hashKey:</span><span class="hl-1"> </span><span class="hl-2">&#39;hashKey2&#39;</span><span class="hl-1">, </span><span class="hl-6">rangeKey:</span><span class="hl-1"> </span><span class="hl-2">&#39;firstNameRK&#39;</span><span class="hl-1"> },</span><br/><span class="hl-1"> },</span><br/><span class="hl-1">} </span><span class="hl-5">as</span><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1">;</span><br/><span class="hl-4">type</span><span class="hl-1"> </span><span class="hl-9">CF</span><span class="hl-1"> = </span><span class="hl-4">typeof</span><span class="hl-1"> </span><span class="hl-6">cf</span><span class="hl-1">;</span><br/><br/><span class="hl-3">// Projection attributes as const tuple — narrows K.</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">attrs</span><span class="hl-1"> = [</span><span class="hl-2">&#39;userId&#39;</span><span class="hl-1">, </span><span class="hl-2">&#39;created&#39;</span><span class="hl-1">] </span><span class="hl-5">as</span><span class="hl-1"> </span><span class="hl-4">const</span><span class="hl-1">;</span><br/><span class="hl-4">type</span><span class="hl-1"> </span><span class="hl-9">K</span><span class="hl-1"> = </span><span class="hl-4">typeof</span><span class="hl-1"> </span><span class="hl-6">attrs</span><span class="hl-1">;</span><br/><br/><span class="hl-3">// A typed SQF: pageKey narrows via CF; items narrow via K (type-only).</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-0">sqf</span><span class="hl-1">: </span><span class="hl-9">ShardQueryFunction</span><span class="hl-1">&lt;</span><span class="hl-9">MyConfigMap</span><span class="hl-1">, </span><span class="hl-2">&#39;user&#39;</span><span class="hl-1">, </span><span class="hl-2">&#39;firstName&#39;</span><span class="hl-1">, </span><span class="hl-9">CF</span><span class="hl-1">, </span><span class="hl-9">K</span><span class="hl-1">&gt; = </span><span class="hl-4">async</span><span class="hl-1"> (</span><br/><span class="hl-1"> </span><span class="hl-6">_hashKey</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">_pageKey</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">_pageSize</span><span class="hl-1">,</span><br/><span class="hl-1">) </span><span class="hl-4">=&gt;</span><span class="hl-1"> ({</span><br/><span class="hl-1"> </span><span class="hl-6">count:</span><span class="hl-1"> </span><span class="hl-8">0</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">items:</span><span class="hl-1"> [], </span><span class="hl-3">// never[] is assignable to the projected array</span><br/><span class="hl-1"> </span><span class="hl-6">pageKey:</span><span class="hl-1"> </span><span class="hl-6">_pageKey</span><span class="hl-1">,</span><br/><span class="hl-1">});</span><br/><br/><span class="hl-3">// ShardQueryMap carrying CF and K.</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">map</span><span class="hl-1">: </span><span class="hl-9">ShardQueryMap</span><span class="hl-1">&lt;</span><span class="hl-9">MyConfigMap</span><span class="hl-1">, </span><span class="hl-2">&#39;user&#39;</span><span class="hl-1">, </span><span class="hl-2">&#39;firstName&#39;</span><span class="hl-1">, </span><span class="hl-9">CF</span><span class="hl-1">, </span><span class="hl-9">K</span><span class="hl-1">&gt; = {</span><br/><span class="hl-1"> </span><span class="hl-6">firstName:</span><span class="hl-1"> </span><span class="hl-6">sqf</span><span class="hl-1">,</span><br/><span class="hl-1">};</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">options</span><span class="hl-1">: </span><span class="hl-9">QueryOptions</span><span class="hl-1">&lt;</span><span class="hl-9">MyConfigMap</span><span class="hl-1">, </span><span class="hl-2">&#39;user&#39;</span><span class="hl-1">, </span><span class="hl-2">&#39;firstName&#39;</span><span class="hl-1">, </span><span class="hl-9">CF</span><span class="hl-1">, </span><span class="hl-9">K</span><span class="hl-1">&gt; = {</span><br/><span class="hl-1"> </span><span class="hl-6">entityToken:</span><span class="hl-1"> </span><span class="hl-2">&#39;user&#39;</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">item:</span><span class="hl-1"> {},</span><br/><span class="hl-1"> </span><span class="hl-6">shardQueryMap:</span><span class="hl-1"> </span><span class="hl-6">map</span><span class="hl-1">,</span><br/><span class="hl-1">};</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">result</span><span class="hl-1">: </span><span class="hl-9">QueryResult</span><span class="hl-1">&lt;</span><span class="hl-9">MyConfigMap</span><span class="hl-1">, </span><span class="hl-2">&#39;user&#39;</span><span class="hl-1">, </span><span class="hl-2">&#39;firstName&#39;</span><span class="hl-1">, </span><span class="hl-9">K</span><span class="hl-1">&gt; =</span><br/><span class="hl-1"> </span><span class="hl-5">await</span><span class="hl-1"> </span><span class="hl-6">manager</span><span class="hl-1">.</span><span class="hl-0">query</span><span class="hl-1">(</span><span class="hl-6">options</span><span class="hl-1">);</span><br/><span class="hl-3">// result.items: Pick&lt;EntityItemByToken&lt;MyConfigMap, &#39;user&#39;&gt;, &#39;userId&#39; | &#39;created&#39;&gt;[]</span>
101
+ </code><button type="button">Copy</button></pre>
102
+
103
+ <p>Notes:</p>
104
+ <ul>
105
+ <li>K is a type‑only channel; it does not change runtime behavior. Providers (e.g., DynamoDB adapters) execute projections.</li>
106
+ <li>Dedupe/sort invariants: Entity Manager dedupes by <code>uniqueProperty</code> and applies <code>QueryOptions.sortOrder</code>. If your adapter projects attributes, ensure it auto‑includes <code>uniqueProperty</code> and any explicit sort keys when callers omit them from K.</li>
107
+ </ul>
108
+ <h2 id="page-keys-in-a-nutshell" class="tsd-anchor-link">Page keys in a nutshell<a href="#page-keys-in-a-nutshell" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2>
109
+ <ul>
110
+ <li><code>rehydratePageKeyMap</code> decodes a dehydrated array (compressed string) into a two‑layer map of <code>{ indexToken: { hashKeyValue: pageKey | undefined } }</code>.</li>
111
+ <li><code>dehydratePageKeyMap</code> performs the inverse and emits a compact array (compressed in <code>query()</code>).</li>
112
+ <li>You rarely call these directly — <code>query()</code> composes them for you — but the API is exposed for advanced flows.</li>
113
+ </ul>
114
+ <h2 id="esm-cjs" class="tsd-anchor-link">ESM / CJS<a href="#esm-cjs" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2>
115
+ <pre><code class="ts"><span class="hl-3">// ESM</span><br/><span class="hl-5">import</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-6">createEntityManager</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-6">defaultTranscodes</span><span class="hl-1">,</span><br/><span class="hl-1">} </span><span class="hl-5">from</span><span class="hl-1"> </span><span class="hl-2">&#39;@karmaniverous/entity-manager&#39;</span><span class="hl-1">;</span><br/><br/><span class="hl-3">// CJS</span><br/><span class="hl-4">const</span><span class="hl-1"> {</span><br/><span class="hl-1"> </span><span class="hl-7">createEntityManager</span><span class="hl-1">,</span><br/><span class="hl-1"> </span><span class="hl-7">defaultTranscodes</span><span class="hl-1">,</span><br/><span class="hl-1">} = </span><span class="hl-0">require</span><span class="hl-1">(</span><span class="hl-2">&#39;@karmaniverous/entity-manager&#39;</span><span class="hl-1">);</span>
116
+ </code><button type="button">Copy</button></pre>
117
+
118
+ <h2 id="logging" class="tsd-anchor-link">Logging<a href="#logging" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2>
119
+ <p>Entity Manager logs debug and error details via the injected logger (defaults to <code>console</code>).</p>
120
+ <pre><code class="ts"><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">logger</span><span class="hl-1"> = { </span><span class="hl-0">debug</span><span class="hl-6">:</span><span class="hl-1"> () </span><span class="hl-4">=&gt;</span><span class="hl-1"> </span><span class="hl-4">undefined</span><span class="hl-1">, </span><span class="hl-6">error:</span><span class="hl-1"> </span><span class="hl-6">console</span><span class="hl-1">.</span><span class="hl-6">error</span><span class="hl-1"> };</span><br/><span class="hl-4">const</span><span class="hl-1"> </span><span class="hl-7">manager</span><span class="hl-1"> = </span><span class="hl-0">createEntityManager</span><span class="hl-1">(</span><span class="hl-6">config</span><span class="hl-1">, </span><span class="hl-6">logger</span><span class="hl-1">);</span>
121
+ </code><button type="button">Copy</button></pre>
122
+
123
+ <h2 id="types-youll-reach-for" class="tsd-anchor-link">Types you’ll reach for<a href="#types-youll-reach-for" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2>
124
+ <ul>
125
+ <li>Values/schema capture
126
+ <ul>
127
+ <li><code>createEntityManager(config, logger?)</code></li>
128
+ <li><code>ConfigInput</code> (values‑first), <code>CapturedConfigMapFrom</code>, <code>EntitiesFromSchema</code></li>
129
+ </ul>
130
+ </li>
131
+ <li>Token aware
132
+ <ul>
133
+ <li><code>EntityToken&lt;CC&gt;</code></li>
134
+ <li><code>EntityItem&lt;CC, ET&gt;</code> — strict domain (full), includes optional key/token properties</li>
135
+ <li><code>EntityItemPartial&lt;CC, ET, K&gt;</code> — projected/seed domain; required keys when K provided, permissive partial when K omitted</li>
136
+ <li><code>EntityRecord&lt;CC, ET&gt;</code> — DB record (required keys) + partial domain fields</li>
137
+ <li><code>EntityRecordPartial&lt;CC, ET, K&gt;</code> — projected DB record</li>
138
+ </ul>
139
+ </li>
140
+ <li>Index aware (values‑first config literal, “CF” channel)
141
+ <ul>
142
+ <li><code>PageKeyByIndex&lt;CC, ET, IT, CF&gt;</code></li>
143
+ <li><code>ShardQueryFunction&lt;CC, ET, IT, CF&gt;</code>, <code>ShardQueryMap&lt;CC, ET, ITS, CF&gt;</code></li>
144
+ <li><code>QueryOptions&lt;CC, ET, ITS, CF&gt;</code>, <code>QueryResult&lt;CC, ET, ITS&gt;</code></li>
145
+ <li>DX sugar: <code>IndexTokensOf&lt;CF&gt;</code>, <code>QueryOptionsByCF</code>, <code>ShardQueryMapByCF</code>, <code>IndexTokensFrom&lt;CC&gt;</code>, <code>QueryOptionsByCC</code>, <code>ShardQueryMapByCC</code></li>
146
+ </ul>
147
+ </li>
148
+ <li>Projection helpers
149
+ <ul>
150
+ <li><code>KeysFrom&lt;K&gt;</code></li>
151
+ <li><code>Projected&lt;T, K&gt;</code></li>
152
+ <li><code>ProjectedItemByToken&lt;CC, ET, K&gt;</code></li>
153
+ </ul>
154
+ </li>
155
+ <li>Advanced (storage shapes; exported for reference and TypeDoc)
156
+ <ul>
157
+ <li><code>StorageItem&lt;CC&gt;</code>, <code>StorageRecord&lt;CC&gt;</code></li>
158
+ </ul>
159
+ </li>
160
+ </ul>
161
+ <p>See the full API: <a href="https://docs.karmanivero.us/entity-manager">https://docs.karmanivero.us/entity-manager</a></p>
162
+ <h2 id="scripts-repo" class="tsd-anchor-link">Scripts (repo)<a href="#scripts-repo" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2>
163
+ <ul>
164
+ <li>build: rollup outputs ESM/CJS + .d.ts</li>
165
+ <li>test: vitest with coverage</li>
166
+ <li>lint: ESLint (type‑aware) + Prettier</li>
167
+ <li>docs: TypeDoc</li>
168
+ <li>typecheck: tsc + tsd (type‑level tests)</li>
169
+ </ul>
170
+ <h2 id="license" class="tsd-anchor-link">License<a href="#license" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2>
171
+ <p>BSD‑3‑Clause (see package.json).</p>
172
+ <hr>
173
+ <p>Built for you with ❤️ on Bali! Find more great tools &amp; templates on <a href="https://github.com/karmaniverous" target="_blank" class="external">my GitHub Profile</a>.</p>
174
+ </div></div>
175
+ <div class="col-sidebar">
176
+ <div class="page-menu">
177
+ <div class="tsd-navigation settings">
178
+ <details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-chevronDown"></use></svg>
179
+ <h3>Settings</h3></summary>
180
+ <div class="tsd-accordion-details">
181
+ <div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span>
182
+ <ul id="tsd-filter-options">
183
+ <li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li></ul></div>
184
+ <div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div>
185
+ <details open class="tsd-accordion tsd-page-navigation"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-chevronDown"></use></svg>
186
+ <h3>On This Page</h3></summary>
187
+ <div class="tsd-accordion-details"><a href="#entity-manager"><span>entity-<wbr/>manager</span></a>
188
+ <ul>
189
+ <li><a href="#why-this-library"><span>Why this library?</span></a></li>
190
+ <li><a href="#install"><span>Install</span></a></li>
191
+ <li><a href="#dx-highlights"><span>DX highlights</span></a></li>
192
+ <li><a href="#quick-start-valuesfirst-schemafirst"><span>Quick start (values‑first + schema‑first)</span></a></li>
193
+ <li>
194
+ <ul>
195
+ <li><a href="#tokenaware-helpers"><span>Token‑aware helpers</span></a></li></ul></li>
196
+ <li><a href="#indexaware-querying-valuesfirst-config-literal-cf-channel"><span>Index‑aware querying (values‑first config literal, “<wbr/>CF” channel)</span></a></li>
197
+ <li>
198
+ <ul>
199
+ <li><a href="#captured-config-cc-aliases"><span>Captured <wbr/>Config (“<wbr/>CC”) aliases</span></a></li></ul></li>
200
+ <li><a href="#projectionaware-typing-k"><span>Projection‑aware typing (<wbr/>K)</span></a></li>
201
+ <li><a href="#page-keys-in-a-nutshell"><span>Page keys in a nutshell</span></a></li>
202
+ <li><a href="#esm-cjs"><span>ESM / <wbr/>CJS</span></a></li>
203
+ <li><a href="#logging"><span>Logging</span></a></li>
204
+ <li><a href="#types-youll-reach-for"><span>Types you’ll reach for</span></a></li>
205
+ <li><a href="#scripts-repo"><span>Scripts (repo)</span></a></li>
206
+ <li><a href="#license"><span>License</span></a></li></ul></div></details></div>
207
+ <div class="site-menu">
208
+ <nav class="tsd-navigation"><a href="modules.html">@karmaniverous/entity-manager</a>
209
+ <ul class="tsd-small-nested-navigation" id="tsd-nav-container">
210
+ <li>Loading...</li></ul></nav></div></div></div><footer>
211
+ <p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer>
212
+ <div class="overlay"></div></body></html>