@harperfast/harper 5.3.0-beta.4 → 5.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.
- package/bin/backup.ts +6 -1
- package/components/Application.ts +486 -115
- package/components/DESIGN.md +109 -21
- package/components/deploymentProvenance.ts +28 -0
- package/components/operations.js +14 -7
- package/components/packageComponent.ts +5 -1
- package/config-root.schema.json +1 -1
- package/dataLayer/DESIGN.md +35 -7
- package/dataLayer/blobBackup.ts +71 -30
- package/dataLayer/harperBridge/ResourceBridge.ts +16 -2
- package/dataLayer/rocksdbBackup.ts +88 -34
- package/dataLayer/schemaDescribe.ts +45 -1
- package/dist/bin/backup.js +1 -1
- package/dist/bin/backup.js.map +1 -1
- package/dist/components/Application.d.ts +11 -21
- package/dist/components/Application.js +436 -105
- package/dist/components/Application.js.map +1 -1
- package/dist/components/deploymentProvenance.d.ts +4 -0
- package/dist/components/deploymentProvenance.js +32 -0
- package/dist/components/deploymentProvenance.js.map +1 -0
- package/dist/components/operations.js +14 -7
- package/dist/components/operations.js.map +1 -1
- package/dist/components/packageComponent.js +6 -1
- package/dist/components/packageComponent.js.map +1 -1
- package/dist/dataLayer/blobBackup.d.ts +30 -3
- package/dist/dataLayer/blobBackup.js +73 -36
- package/dist/dataLayer/blobBackup.js.map +1 -1
- package/dist/dataLayer/harperBridge/ResourceBridge.d.ts +1 -0
- package/dist/dataLayer/harperBridge/ResourceBridge.js +15 -3
- package/dist/dataLayer/harperBridge/ResourceBridge.js.map +1 -1
- package/dist/dataLayer/rocksdbBackup.d.ts +4 -1
- package/dist/dataLayer/rocksdbBackup.js +74 -36
- package/dist/dataLayer/rocksdbBackup.js.map +1 -1
- package/dist/dataLayer/schemaDescribe.js +45 -1
- package/dist/dataLayer/schemaDescribe.js.map +1 -1
- package/dist/resources/DatabaseTransaction.d.ts +1 -0
- package/dist/resources/DatabaseTransaction.js +33 -8
- package/dist/resources/DatabaseTransaction.js.map +1 -1
- package/dist/resources/ResourceInterface.d.ts +7 -3
- package/dist/resources/ResourceInterface.js +2 -0
- package/dist/resources/ResourceInterface.js.map +1 -1
- package/dist/resources/Table.d.ts +151 -445
- package/dist/resources/Table.js +209 -8
- package/dist/resources/Table.js.map +1 -1
- package/dist/resources/analytics/write.d.ts +11 -0
- package/dist/resources/analytics/write.js +3 -0
- package/dist/resources/analytics/write.js.map +1 -1
- package/dist/resources/blob.d.ts +30 -0
- package/dist/resources/blob.js +189 -1
- package/dist/resources/blob.js.map +1 -1
- package/dist/resources/databases.d.ts +1 -0
- package/dist/resources/databases.js +80 -15
- package/dist/resources/databases.js.map +1 -1
- package/dist/resources/derivedIndexRuntime.d.ts +13 -0
- package/dist/resources/derivedIndexRuntime.js +57 -5
- package/dist/resources/derivedIndexRuntime.js.map +1 -1
- package/dist/resources/derivedIndexes.d.ts +1 -0
- package/dist/resources/derivedIndexes.js +116 -15
- package/dist/resources/derivedIndexes.js.map +1 -1
- package/dist/resources/fullTextSchema.d.ts +5 -3
- package/dist/resources/fullTextSchema.js +48 -5
- package/dist/resources/fullTextSchema.js.map +1 -1
- package/dist/resources/fullTextSchemaLifecycle.d.ts +2 -0
- package/dist/resources/fullTextSchemaLifecycle.js +33 -0
- package/dist/resources/fullTextSchemaLifecycle.js.map +1 -1
- package/dist/resources/graphql.js +30 -12
- package/dist/resources/graphql.js.map +1 -1
- package/dist/resources/indexes/HierarchicalNavigableSmallWorld.d.ts +21 -1
- package/dist/resources/indexes/HierarchicalNavigableSmallWorld.js +114 -5
- package/dist/resources/indexes/HierarchicalNavigableSmallWorld.js.map +1 -1
- package/dist/resources/indexes/fullTextDerivedIndex.d.ts +11 -2
- package/dist/resources/indexes/fullTextDerivedIndex.js +187 -24
- package/dist/resources/indexes/fullTextDerivedIndex.js.map +1 -1
- package/dist/resources/indexes/fullTextNativeBinding.d.ts +99 -1
- package/dist/resources/indexes/fullTextNativeBinding.js +35 -1
- package/dist/resources/indexes/fullTextNativeBinding.js.map +1 -1
- package/dist/resources/indexes/fullTextQueryIndex.d.ts +58 -0
- package/dist/resources/indexes/fullTextQueryIndex.js +943 -0
- package/dist/resources/indexes/fullTextQueryIndex.js.map +1 -0
- package/dist/resources/indexes/fullTextQueryProtocol.d.ts +6 -0
- package/dist/resources/indexes/fullTextQueryProtocol.js +32 -0
- package/dist/resources/indexes/fullTextQueryProtocol.js.map +1 -0
- package/dist/resources/indexes/nativeFullTextDerivedIndexLifecycle.d.ts +4 -1
- package/dist/resources/indexes/nativeFullTextDerivedIndexLifecycle.js +30 -7
- package/dist/resources/indexes/nativeFullTextDerivedIndexLifecycle.js.map +1 -1
- package/dist/resources/search.d.ts +41 -0
- package/dist/resources/search.js +468 -26
- package/dist/resources/search.js.map +1 -1
- package/dist/resources/transactionBroadcast.js +101 -50
- package/dist/resources/transactionBroadcast.js.map +1 -1
- package/dist/resources/typeParity.d.ts +9 -0
- package/dist/resources/typeParity.js +3 -0
- package/dist/resources/typeParity.js.map +1 -0
- package/dist/server/REST.js.map +1 -1
- package/dist/server/itc/serverHandlers.js +48 -8
- package/dist/server/itc/serverHandlers.js.map +1 -1
- package/dist/server/serverHelpers/contentTypes.d.ts +7 -0
- package/dist/server/serverHelpers/contentTypes.js +36 -23
- package/dist/server/serverHelpers/contentTypes.js.map +1 -1
- package/dist/server/serverHelpers/uwsServer.js +28 -5
- package/dist/server/serverHelpers/uwsServer.js.map +1 -1
- package/dist/server/threads/itc.js +19 -0
- package/dist/server/threads/itc.js.map +1 -1
- package/dist/server/threads/manageThreads.d.ts +3 -0
- package/dist/server/threads/manageThreads.js +90 -23
- package/dist/server/threads/manageThreads.js.map +1 -1
- package/dist/utility/operation_authorization.js +25 -7
- package/dist/utility/operation_authorization.js.map +1 -1
- package/dist/utility/signalling.js +3 -0
- package/dist/utility/signalling.js.map +1 -1
- package/dist/validation/searchValidator.js +22 -2
- package/dist/validation/searchValidator.js.map +1 -1
- package/npm-shrinkwrap.json +22 -22
- package/package.json +2 -4
- package/resources/DESIGN.md +19 -2
- package/resources/DatabaseTransaction.ts +40 -10
- package/resources/FULL_TEXT.md +97 -0
- package/resources/ResourceInterface.ts +8 -2
- package/resources/Table.ts +767 -17
- package/resources/analytics/write.ts +3 -3
- package/resources/blob.ts +183 -1
- package/resources/databases.ts +126 -14
- package/resources/derivedIndexRuntime.ts +79 -6
- package/resources/derivedIndexes.ts +142 -18
- package/resources/fullTextSchema.ts +55 -9
- package/resources/fullTextSchemaLifecycle.ts +45 -0
- package/resources/graphql.ts +33 -12
- package/resources/indexes/DESIGN.md +167 -15
- package/resources/indexes/HierarchicalNavigableSmallWorld.ts +125 -5
- package/resources/indexes/fullTextDerivedIndex.ts +216 -32
- package/resources/indexes/fullTextNativeBinding.ts +133 -3
- package/resources/indexes/fullTextQueryIndex.ts +1120 -0
- package/resources/indexes/fullTextQueryProtocol.ts +35 -0
- package/resources/indexes/nativeFullTextDerivedIndexLifecycle.ts +28 -8
- package/resources/search.ts +513 -26
- package/resources/transactionBroadcast.ts +86 -47
- package/resources/typeParity.ts +20 -0
- package/schema.graphql +18 -5
- package/server/DESIGN.md +18 -0
- package/server/REST.ts +1 -1
- package/server/itc/serverHandlers.js +61 -8
- package/server/serverHelpers/contentTypes.ts +31 -26
- package/server/serverHelpers/uwsServer.ts +35 -7
- package/server/threads/itc.js +21 -0
- package/server/threads/manageThreads.js +95 -21
- package/studio/web/assets/{Chat-Bq60AO-g.js → Chat-CNEKMllJ.js} +13 -13
- package/studio/web/assets/FloatingChat-CEnWhHeR.js +23 -0
- package/studio/web/assets/SearchDialog-CwhJdEdY.js +1 -0
- package/studio/web/assets/{abnfDiagram-O67JEVCF-DpPZWMOf.js → abnfDiagram-O67JEVCF-raXE027J.js} +1 -1
- package/studio/web/assets/alertDialog-BbWD9Xxa.js +1 -0
- package/studio/web/assets/apiToken-DC5vsaaO.js +1 -0
- package/studio/web/assets/applications-DQZxDy0x.js +296 -0
- package/studio/web/assets/architecture-7GRP2DOG-DDmz3hpI.js +1 -0
- package/studio/web/assets/{architectureDiagram-NJMV4G6O-OmgLraID.js → architectureDiagram-NJMV4G6O-C8_Eet7w.js} +1 -1
- package/studio/web/assets/arrow-up-D2g_57vT.js +1 -0
- package/studio/web/assets/authStore-CJCaADw9.js +3 -0
- package/studio/web/assets/{blockDiagram-BEXU5L5S-Cv7CD3Ai.js → blockDiagram-BEXU5L5S-DR6S5-1D.js} +1 -1
- package/studio/web/assets/{button-MFP9n8Ck.js → button-DWwfgGWI.js} +2 -2
- package/studio/web/assets/{c4Diagram-YGBWAQC7-Ds1vKYnN.js → c4Diagram-YGBWAQC7-BAfZ1G01.js} +1 -1
- package/studio/web/assets/channel-D0AkPjJ8.js +1 -0
- package/studio/web/assets/{chevron-up-CFe8x5Bp.js → chevron-up-CFxbMGv2.js} +1 -1
- package/studio/web/assets/{chunk-3FUC2YCW-DpnBPH8B.js → chunk-3FUC2YCW-DuRp-j19.js} +1 -1
- package/studio/web/assets/{chunk-5DYCD2WN-LLLCQSzg.js → chunk-5DYCD2WN-BceBfIHT.js} +1 -1
- package/studio/web/assets/{chunk-742MDFTN-BL8J_pIO.js → chunk-742MDFTN-CIkt8ijt.js} +1 -1
- package/studio/web/assets/{chunk-7INBJB4K-C-hJHiiK.js → chunk-7INBJB4K-BpeAXyOi.js} +1 -1
- package/studio/web/assets/{chunk-7M6MHVWA-C6ZqkFbA.js → chunk-7M6MHVWA-h6WlaTzO.js} +1 -1
- package/studio/web/assets/{chunk-7PRAP22T-CUXM8BG6.js → chunk-7PRAP22T-KyqX6x3f.js} +1 -1
- package/studio/web/assets/{chunk-GTNCS2PH-DJ2BFvS1.js → chunk-GTNCS2PH-DGHLXyow.js} +1 -1
- package/studio/web/assets/{chunk-GWA4HPMP-C42bSqLL.js → chunk-GWA4HPMP-DsejB6gA.js} +1 -1
- package/studio/web/assets/{chunk-MBY4JIJT-C-5jz6Lo.js → chunk-MBY4JIJT-BwSGweQP.js} +1 -1
- package/studio/web/assets/{chunk-NETBCI7D-D-bzlN4r.js → chunk-NETBCI7D-C8UnOw_f.js} +1 -1
- package/studio/web/assets/{chunk-O7XYJQB3-ep14zA23.js → chunk-O7XYJQB3-CBS3nZYV.js} +1 -1
- package/studio/web/assets/{chunk-UA2S7LBM-BMRWRHED.js → chunk-UA2S7LBM-BHpEdH8D.js} +1 -1
- package/studio/web/assets/{chunk-WEXAMYUT-DdLYVdX1.js → chunk-WEXAMYUT-BAIhTwyh.js} +1 -1
- package/studio/web/assets/{chunk-Z7XXMR3K-BmKEDjcP.js → chunk-Z7XXMR3K-DSHbImdf.js} +1 -1
- package/studio/web/assets/{chunk-ZIGJFQKS-DLZgdNxA.js → chunk-ZIGJFQKS-Cs8fUn7y.js} +1 -1
- package/studio/web/assets/{classDiagram-v2-NBCMYWYE-DOI5vgKT.js → classDiagram-v2-NBCMYWYE-DmDPkt2u.js} +1 -1
- package/studio/web/assets/cn-6T8VranJ.js +1 -0
- package/studio/web/assets/{codicon-Brq4_Ui5.ttf → codicon-DF1abBS2.ttf} +0 -0
- package/studio/web/assets/{createLucideIcon-bziYxJli.js → createLucideIcon-fO5dL7D5.js} +1 -1
- package/studio/web/assets/{css.worker-l1psR_wG.js → css.worker-DoT-OOzx.js} +36 -36
- package/studio/web/assets/{cssMode-DJyc9mHj.js → cssMode-Dz2DxF4e.js} +1 -1
- package/studio/web/assets/{cynefin-OW5HDTMX-BSW-DB7S.js → cynefin-OW5HDTMX-DIvbXLSj.js} +1 -1
- package/studio/web/assets/{cynefinDiagram-VND7K2PF-CbAHEwxt.js → cynefinDiagram-VND7K2PF-BdtaXiCE.js} +1 -1
- package/studio/web/assets/{dagre-6A5THRUB-Csxewgs4.js → dagre-6A5THRUB-C7RUWHyz.js} +1 -1
- package/studio/web/assets/{diagram-22UHCM2B-a0rt8tY4.js → diagram-22UHCM2B-DJCvcaWP.js} +1 -1
- package/studio/web/assets/{diagram-3UASUU5V-lEj2SVNh.js → diagram-3UASUU5V-Du6VKWln.js} +1 -1
- package/studio/web/assets/{diagram-ATOU4E4O-HcrAeB-q.js → diagram-ATOU4E4O-dxRfeG4B.js} +1 -1
- package/studio/web/assets/{diagram-CDSNMT55-CYxiuyEx.js → diagram-CDSNMT55-l5Ga0u-W.js} +1 -1
- package/studio/web/assets/{diagram-MLGK6HIB-ChbCJTgJ.js → diagram-MLGK6HIB-CNQY47LA.js} +1 -1
- package/studio/web/assets/{diagram-MPIPVDR6-DaX9Y-N3.js → diagram-MPIPVDR6-7prveD1B.js} +1 -1
- package/studio/web/assets/{dist-Cz2Y6-6G.js → dist-BrRuMUzt.js} +1 -1
- package/studio/web/assets/{download-CtostjYn.js → download-Cn6tPG4L.js} +1 -1
- package/studio/web/assets/{ebnfDiagram-ZINNZB2B-CwAsENB1.js → ebnfDiagram-ZINNZB2B-5OnkTpfi.js} +1 -1
- package/studio/web/assets/{editor-DDIsQfj6.js → editor-B3mjd3tz.js} +1 -1
- package/studio/web/assets/editor.worker-Yd1NR0QT.js +33 -0
- package/studio/web/assets/{elk-276RUBZZ-Hexg9E4D.js → elk-276RUBZZ-DxDQPjQT.js} +1 -1
- package/studio/web/assets/{erDiagram-OPXOYQCR-CeC-wwO1.js → erDiagram-OPXOYQCR-CQlCX84D.js} +1 -1
- package/studio/web/assets/eventmodeling-NTZA5JFV-DONQf5aG.js +1 -0
- package/studio/web/assets/flowDiagram-KWPJA3E3-BoZ8_QR1.js +1 -0
- package/studio/web/assets/{ganttDiagram-FUAMR5RP-C2_Hhl1-.js → ganttDiagram-FUAMR5RP-bloX3Voy.js} +1 -1
- package/studio/web/assets/{getAnalytics-CjthMQqF.js → getAnalytics-C0FHjtdQ.js} +1 -1
- package/studio/web/assets/{gitGraph-4MIJSDKK-xIk5Vuew.js → gitGraph-4MIJSDKK-BrXWmJt2.js} +1 -1
- package/studio/web/assets/{gitGraphDiagram-X574FWY7-CMxJ34up.js → gitGraphDiagram-X574FWY7-C2KnnZeY.js} +1 -1
- package/studio/web/assets/{html-g1BJHxLy.js → html-BsRGM7tp.js} +1 -1
- package/studio/web/assets/{html.worker-DdwM4IrA.js → html.worker-B1dwY0Ay.js} +27 -27
- package/studio/web/assets/{htmlMode-Vh5IglCQ.js → htmlMode-tUKJaA3o.js} +1 -1
- package/studio/web/assets/index-72cEH474.css +1 -0
- package/studio/web/assets/index-BuqFjN5K.js +828 -0
- package/studio/web/assets/index.lazy-CcpfQFY_.js +2 -0
- package/studio/web/assets/{info-A6RAGUB7-o49TEbj-.js → info-A6RAGUB7-BhzBHe4U.js} +1 -1
- package/studio/web/assets/{infoDiagram-VRGFBTTK-Cjhh7yzZ.js → infoDiagram-VRGFBTTK-B0J1132p.js} +1 -1
- package/studio/web/assets/{ishikawaDiagram-OU5B5YK6-C63aXRmh.js → ishikawaDiagram-OU5B5YK6-BNk0tuQx.js} +1 -1
- package/studio/web/assets/{javascript-5VIolqf7.js → javascript-BZ_uRGHl.js} +1 -1
- package/studio/web/assets/{journeyDiagram-ZHPQQLJL-D_o0P5Mu.js → journeyDiagram-ZHPQQLJL-Be79RMQM.js} +1 -1
- package/studio/web/assets/json.worker-BQqXGI3X.js +65 -0
- package/studio/web/assets/{jsonMode-DG4zQraI.js → jsonMode-DgB-aFMj.js} +1 -1
- package/studio/web/assets/{kanban-definition-PNTS6WVX-CTI9SSxY.js → kanban-definition-PNTS6WVX-4uuoQP9W.js} +1 -1
- package/studio/web/assets/{languageServices-t5FBpX-i.js → languageServices-BleuBw17.js} +1 -1
- package/studio/web/assets/localStorageKeys-etzFY_xV.js +1 -0
- package/studio/web/assets/{lspLanguageFeatures-DgVnNPh-.js → lspLanguageFeatures-ByVYLSsQ.js} +1 -1
- package/studio/web/assets/{mermaid-parser.core-C2lcH_jP.js → mermaid-parser.core-V1UYMeXV.js} +3 -3
- package/studio/web/assets/{mermaid.core-BG5bjfIG.js → mermaid.core-1PX6R49U.js} +4 -4
- package/studio/web/assets/{mindmap-definition-NLK3R4M7-BK7ho6JD.js → mindmap-definition-NLK3R4M7-C70Ctm0J.js} +1 -1
- package/studio/web/assets/notifications-D1Nf-Edn.js +1 -0
- package/studio/web/assets/notifications-TuzN0IMi.js +1 -0
- package/studio/web/assets/{packet-AYTQ26CC-BHPy6KBV.js → packet-AYTQ26CC-DWbXHx5g.js} +1 -1
- package/studio/web/assets/{pegDiagram-GJSIUBJH-DzjwG3jO.js → pegDiagram-GJSIUBJH-d6z1cc7W.js} +1 -1
- package/studio/web/assets/{pie-WAS4IAKB-D0cP-DTU.js → pie-WAS4IAKB-DjoTm3yr.js} +1 -1
- package/studio/web/assets/{pieDiagram-5QR66LMP-C_hOP9Lv.js → pieDiagram-5QR66LMP-Dz3RHpDA.js} +1 -1
- package/studio/web/assets/profile-D7C7Lupz.js +1 -0
- package/studio/web/assets/{quadrantDiagram-O4NWA36T-CZW8PbV1.js → quadrantDiagram-O4NWA36T-CIF5Qkou.js} +1 -1
- package/studio/web/assets/{radar-RG4KPBEZ-C8fk0U81.js → radar-RG4KPBEZ-CVBgjCOj.js} +1 -1
- package/studio/web/assets/{railroad-74A4TZTK-B60FWm17.js → railroad-74A4TZTK-BdhXw10Q.js} +1 -1
- package/studio/web/assets/railroad-abnf-HS5TGJTU-BcoQPN39.js +1 -0
- package/studio/web/assets/railroad-ebnf-LZEXJU2U-B1Lke2JN.js +1 -0
- package/studio/web/assets/railroad-peg-WCYAUIDC-D-oJFkiV.js +1 -0
- package/studio/web/assets/{railroadDiagram-XR7U4H2S-DyyNmgbU.js → railroadDiagram-XR7U4H2S-y3Jv2U6N.js} +1 -1
- package/studio/web/assets/regions-nGQCm-v8.js +1 -0
- package/studio/web/assets/register-C3x9Ze6P.js +909 -0
- package/studio/web/assets/register-DjpsE8to.css +1 -0
- package/studio/web/assets/{requirementDiagram-PLB6GJNP-C4H-mLKu.js → requirementDiagram-PLB6GJNP-ChINZEmu.js} +1 -1
- package/studio/web/assets/restartGate-nHAFLDh-.js +1 -0
- package/studio/web/assets/{sankeyDiagram-IPEJSGJF-DHDyga4c.js → sankeyDiagram-IPEJSGJF-D9AyLce2.js} +1 -1
- package/studio/web/assets/{sequenceDiagram-PO4LG4MO-CdNcHXRI.js → sequenceDiagram-PO4LG4MO-hfk4aIEm.js} +1 -1
- package/studio/web/assets/{setComponentFile-z4-qJCbA.js → setComponentFile-DpjrRqeG.js} +1 -1
- package/studio/web/assets/{setup-CS50uJ4x.js → setup-CGiKLZ9e.js} +2 -2
- package/studio/web/assets/{stateDiagram-v2-GCMORJYK-CpKuXq15.js → stateDiagram-v2-GCMORJYK-Bs8RIb9K.js} +1 -1
- package/studio/web/assets/status-CGJwrNPH.js +61 -0
- package/studio/web/assets/{swimlanes-2SLR337P-NRHa2D8I.js → swimlanes-2SLR337P-B52xrf6t.js} +1 -1
- package/studio/web/assets/swimlanesDiagram-TC7HE7FX-DfN7BAP5.js +8 -0
- package/studio/web/assets/tabs-BCTQzoQK.js +1 -0
- package/studio/web/assets/{timeline-definition-EJHVYXUP-D39Y-xpq.js → timeline-definition-EJHVYXUP-DJSITpQX.js} +1 -1
- package/studio/web/assets/toggleHighContrast-C-Ne6P7T.js +51 -0
- package/studio/web/assets/toggleHighContrast-n7clI0si.css +1 -0
- package/studio/web/assets/{treeView-Q6P3EWNA-CRWR9OqD.js → treeView-Q6P3EWNA-C-epdxRo.js} +1 -1
- package/studio/web/assets/{treemap-WGGIJYW6-ZfXyJgLO.js → treemap-WGGIJYW6-DOVyp_zw.js} +1 -1
- package/studio/web/assets/{ts.worker-DDMUrpqh.js → ts.worker-Clm12uY6.js} +131 -131
- package/studio/web/assets/{tsMode-D83Gg3cq.js → tsMode-CSreYTys.js} +1 -1
- package/studio/web/assets/{typescript-Dfp-GrNq.js → typescript-MnxBk89W.js} +1 -1
- package/studio/web/assets/{useEntityRestURL-BKetlINf.js → useEntityRestURL-TNrh77-s.js} +1 -1
- package/studio/web/assets/{usecaseDiagram-POWQR4AR-jf-zIDZ_.js → usecaseDiagram-POWQR4AR-B6252cbq.js} +1 -1
- package/studio/web/assets/{vendor-core-BdkdbUek.js → vendor-core-6LhfJlRC.js} +1 -1
- package/studio/web/assets/vendor-datadog-ozKf-pts.js +6 -0
- package/studio/web/assets/{vendor-react-izWchTRL.js → vendor-react-BOliS0BL.js} +1 -1
- package/studio/web/assets/vendor-tanstack-Bntfka-M.js +2 -0
- package/studio/web/assets/vendor-ui-9EYYDgoN.js +41 -0
- package/studio/web/assets/{vennDiagram-UO4OBE2U-BKYAZUh_.js → vennDiagram-UO4OBE2U-DZTsDA4k.js} +1 -1
- package/studio/web/assets/{wardley-WFR3VGLG-BO7f36ci.js → wardley-WFR3VGLG-Cfqoe6z4.js} +1 -1
- package/studio/web/assets/{wardleyDiagram-VNRHLVJA-Djb0JDQc.js → wardleyDiagram-VNRHLVJA-qu_f7Tvl.js} +1 -1
- package/studio/web/assets/{workers-CCvmDLH3.js → workers-BfZlUNVI.js} +3 -3
- package/studio/web/assets/{xml-06pZp00U.js → xml-BHd6qGH7.js} +1 -1
- package/studio/web/assets/{xychartDiagram-PMCCYNJV-BQh9ubvb.js → xychartDiagram-PMCCYNJV-UrOKRsmR.js} +1 -1
- package/studio/web/assets/{yaml-iSnWMVlV.js → yaml-C53R8OQq.js} +1 -1
- package/studio/web/assets/{yaml.worker-DAK2o_H1.js → yaml.worker-D9JekGdp.js} +183 -183
- package/studio/web/index.html +15 -15
- package/utility/operation_authorization.ts +27 -7
- package/utility/signalling.ts +3 -0
- package/validation/searchValidator.ts +22 -13
- package/studio/web/assets/FloatingChat-D4560T0p.js +0 -23
- package/studio/web/assets/alertDialog-UrbiMgQt.js +0 -1
- package/studio/web/assets/apiToken-BEvbFPMc.js +0 -1
- package/studio/web/assets/applications-CSUVTH4E.js +0 -296
- package/studio/web/assets/architecture-7GRP2DOG-11l4Ny1l.js +0 -1
- package/studio/web/assets/authStore-5jSS5pTW.js +0 -3
- package/studio/web/assets/channel-BDtouPd6.js +0 -1
- package/studio/web/assets/dialog-DTepachC.js +0 -1
- package/studio/web/assets/editor.worker-CkkvdXvO.js +0 -33
- package/studio/web/assets/eventmodeling-NTZA5JFV-CFb03e0o.js +0 -1
- package/studio/web/assets/flowDiagram-KWPJA3E3-Cidi00_Y.js +0 -1
- package/studio/web/assets/index-CPoDzQTe.css +0 -1
- package/studio/web/assets/index-DGRAzvO4.js +0 -824
- package/studio/web/assets/index.lazy-vgSic7et.js +0 -2
- package/studio/web/assets/json.worker-CSi2hF-a.js +0 -65
- package/studio/web/assets/notifications-BeWcX04m.js +0 -1
- package/studio/web/assets/notifications-DUGWrWoO.js +0 -1
- package/studio/web/assets/profile-BvUEDBzW.js +0 -1
- package/studio/web/assets/railroad-abnf-HS5TGJTU-CLMVZvH0.js +0 -1
- package/studio/web/assets/railroad-ebnf-LZEXJU2U--tlwFoVB.js +0 -1
- package/studio/web/assets/railroad-peg-WCYAUIDC-Dpuslblm.js +0 -1
- package/studio/web/assets/regions-CB-_2m7M.js +0 -1
- package/studio/web/assets/register-1w1Zr3b2.js +0 -848
- package/studio/web/assets/register-jjEx9u7D.css +0 -1
- package/studio/web/assets/setLocalStorage-D_kflv4U.js +0 -1
- package/studio/web/assets/status-CI0wOdOE.js +0 -61
- package/studio/web/assets/swimlanesDiagram-TC7HE7FX-BBk4t4hO.js +0 -8
- package/studio/web/assets/tabs-CnQ_zenf.js +0 -1
- package/studio/web/assets/toggleHighContrast--ixms01u.css +0 -1
- package/studio/web/assets/toggleHighContrast-BsAE4jPe.js +0 -49
- package/studio/web/assets/useLocalStorage-BYoZF60G.js +0 -1
- package/studio/web/assets/vendor-datadog-fCQhBHGk.js +0 -6
- package/studio/web/assets/vendor-tanstack-CQ1aRjVa.js +0 -2
- package/studio/web/assets/vendor-ui-aE1tHcW7.js +0 -41
- package/studio/web/assets/x-vYntCxm4.js +0 -1
|
@@ -44,7 +44,22 @@ const hdbUtils = __importStar(require("../utility/common_utils.js"));
|
|
|
44
44
|
const common_validators_ts_1 = require("./common_validators.js");
|
|
45
45
|
const hdbError_ts_1 = require("../utility/errors/hdbError.js");
|
|
46
46
|
const databases_ts_1 = require("../resources/databases.js");
|
|
47
|
+
const fullTextQueryProtocol_ts_1 = require("../resources/indexes/fullTextQueryProtocol.js");
|
|
47
48
|
const { HTTP_STATUS_CODES } = hdbError_ts_1.hdbErrors;
|
|
49
|
+
const FULL_TEXT_COMPARATOR_SET = new Set(fullTextQueryProtocol_ts_1.FULL_TEXT_COMPARATORS);
|
|
50
|
+
const SEARCH_BY_CONDITIONS_COMPARATORS = [
|
|
51
|
+
'equals',
|
|
52
|
+
'contains',
|
|
53
|
+
'starts_with',
|
|
54
|
+
'ends_with',
|
|
55
|
+
'greater_than',
|
|
56
|
+
'greater_than_equal',
|
|
57
|
+
'less_than',
|
|
58
|
+
'less_than_equal',
|
|
59
|
+
'between',
|
|
60
|
+
'not_equal',
|
|
61
|
+
...fullTextQueryProtocol_ts_1.FULL_TEXT_COMPARATORS,
|
|
62
|
+
];
|
|
48
63
|
const searchByValueSchema = joi_1.default.object({
|
|
49
64
|
database: common_validators_ts_1.hdbDatabase,
|
|
50
65
|
schema: common_validators_ts_1.hdbDatabase,
|
|
@@ -73,8 +88,12 @@ const searchByConditionsSchema = joi_1.default.object({
|
|
|
73
88
|
.items(joi_1.default.alternatives(joi_1.default.object({ operator: joi_1.default.string().valid('and', 'or').default('and').lowercase(), conditions: joi_1.default.array() }), joi_1.default.object({
|
|
74
89
|
attribute: joi_1.default.alternatives(common_validators_ts_1.hdbSchemaTable, joi_1.default.array().min(1)),
|
|
75
90
|
comparator: joi_1.default.string()
|
|
76
|
-
.valid(
|
|
91
|
+
.valid(...SEARCH_BY_CONDITIONS_COMPARATORS)
|
|
77
92
|
.optional(),
|
|
93
|
+
fields: joi_1.default.array().min(1).items(common_validators_ts_1.hdbSchemaTable).optional(),
|
|
94
|
+
includeHighlights: joi_1.default.bool().optional(),
|
|
95
|
+
maxIndexLagMilliseconds: joi_1.default.number().min(0).optional(),
|
|
96
|
+
waitForIndexMilliseconds: joi_1.default.number().min(0).max(30_000).optional(),
|
|
78
97
|
value: joi_1.default.when('comparator', {
|
|
79
98
|
switch: [
|
|
80
99
|
{ is: 'equals', then: joi_1.default.any() },
|
|
@@ -150,7 +169,8 @@ function default_1(searchObject, type) {
|
|
|
150
169
|
for (const condition of searchObject.conditions) {
|
|
151
170
|
if (condition.conditions)
|
|
152
171
|
addConditions(condition);
|
|
153
|
-
|
|
172
|
+
// Table.search resolves full-text names together with source-field authorization.
|
|
173
|
+
else if (!FULL_TEXT_COMPARATOR_SET.has(condition.comparator))
|
|
154
174
|
checkAttributes.push(condition.attribute);
|
|
155
175
|
}
|
|
156
176
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"searchValidator.js","sourceRoot":"","sources":["../../validation/searchValidator.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"searchValidator.js","sourceRoot":"","sources":["../../validation/searchValidator.ts"],"names":[],"mappings":"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"}
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "harper",
|
|
3
|
-
"version": "5.3.0
|
|
3
|
+
"version": "5.3.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "harper",
|
|
9
|
-
"version": "5.3.0
|
|
9
|
+
"version": "5.3.0",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@endo/static-module-record": "^1.1.2",
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
"node": "^22.18.0 || >=24.0.0"
|
|
101
101
|
},
|
|
102
102
|
"optionalDependencies": {
|
|
103
|
-
"@harperfast/fulltext": "0.
|
|
103
|
+
"@harperfast/fulltext": "0.3.0",
|
|
104
104
|
"@harperfast/hnsw": "0.4.0",
|
|
105
105
|
"bufferutil": "4.1.0",
|
|
106
106
|
"segfault-handler": "1.3.0",
|
|
@@ -696,25 +696,25 @@
|
|
|
696
696
|
"license": "Apache-2.0"
|
|
697
697
|
},
|
|
698
698
|
"node_modules/@harperfast/fulltext": {
|
|
699
|
-
"version": "0.
|
|
700
|
-
"resolved": "https://registry.npmjs.org/@harperfast/fulltext/-/fulltext-0.
|
|
701
|
-
"integrity": "sha512-
|
|
699
|
+
"version": "0.3.0",
|
|
700
|
+
"resolved": "https://registry.npmjs.org/@harperfast/fulltext/-/fulltext-0.3.0.tgz",
|
|
701
|
+
"integrity": "sha512-co/h26nQ3JTpUx63MzhIxoKU0q1Ygkn5/JDmH8oNnVwhHuvEPP6qAoRemf08wficV0qOWM7LN/CPOvkE+OOajw==",
|
|
702
702
|
"license": "Apache-2.0",
|
|
703
703
|
"optional": true,
|
|
704
704
|
"engines": {
|
|
705
705
|
"node": "^22.18.0 || >=24.0.0"
|
|
706
706
|
},
|
|
707
707
|
"optionalDependencies": {
|
|
708
|
-
"@harperfast/fulltext-darwin-arm64": "0.
|
|
709
|
-
"@harperfast/fulltext-linux-arm64-gnu": "0.
|
|
710
|
-
"@harperfast/fulltext-linux-x64-gnu": "0.
|
|
711
|
-
"@harperfast/fulltext-win32-x64-msvc": "0.
|
|
708
|
+
"@harperfast/fulltext-darwin-arm64": "0.3.0",
|
|
709
|
+
"@harperfast/fulltext-linux-arm64-gnu": "0.3.0",
|
|
710
|
+
"@harperfast/fulltext-linux-x64-gnu": "0.3.0",
|
|
711
|
+
"@harperfast/fulltext-win32-x64-msvc": "0.3.0"
|
|
712
712
|
}
|
|
713
713
|
},
|
|
714
714
|
"node_modules/@harperfast/fulltext-darwin-arm64": {
|
|
715
|
-
"version": "0.
|
|
716
|
-
"resolved": "https://registry.npmjs.org/@harperfast/fulltext-darwin-arm64/-/fulltext-darwin-arm64-0.
|
|
717
|
-
"integrity": "sha512-
|
|
715
|
+
"version": "0.3.0",
|
|
716
|
+
"resolved": "https://registry.npmjs.org/@harperfast/fulltext-darwin-arm64/-/fulltext-darwin-arm64-0.3.0.tgz",
|
|
717
|
+
"integrity": "sha512-B/m088dRD87veV9BsFdFm5texc4R0VR2Gq7UKxySPX6eaBH1L1xFH3M1cx1c+xgVWfdSxoLMDl+gX8Xs8ANVcA==",
|
|
718
718
|
"cpu": [
|
|
719
719
|
"arm64"
|
|
720
720
|
],
|
|
@@ -728,9 +728,9 @@
|
|
|
728
728
|
}
|
|
729
729
|
},
|
|
730
730
|
"node_modules/@harperfast/fulltext-linux-arm64-gnu": {
|
|
731
|
-
"version": "0.
|
|
732
|
-
"resolved": "https://registry.npmjs.org/@harperfast/fulltext-linux-arm64-gnu/-/fulltext-linux-arm64-gnu-0.
|
|
733
|
-
"integrity": "sha512-
|
|
731
|
+
"version": "0.3.0",
|
|
732
|
+
"resolved": "https://registry.npmjs.org/@harperfast/fulltext-linux-arm64-gnu/-/fulltext-linux-arm64-gnu-0.3.0.tgz",
|
|
733
|
+
"integrity": "sha512-Lt35OD+FA/TOXlWnoNKCv6hhZtvWOg37TjDfRuHyRMVCy8hrrTwR63pfkl/UPya5YN6RaDZGEw8XWYwk1KqFCA==",
|
|
734
734
|
"cpu": [
|
|
735
735
|
"arm64"
|
|
736
736
|
],
|
|
@@ -747,9 +747,9 @@
|
|
|
747
747
|
}
|
|
748
748
|
},
|
|
749
749
|
"node_modules/@harperfast/fulltext-linux-x64-gnu": {
|
|
750
|
-
"version": "0.
|
|
751
|
-
"resolved": "https://registry.npmjs.org/@harperfast/fulltext-linux-x64-gnu/-/fulltext-linux-x64-gnu-0.
|
|
752
|
-
"integrity": "sha512
|
|
750
|
+
"version": "0.3.0",
|
|
751
|
+
"resolved": "https://registry.npmjs.org/@harperfast/fulltext-linux-x64-gnu/-/fulltext-linux-x64-gnu-0.3.0.tgz",
|
|
752
|
+
"integrity": "sha512-+jw4/wwfDMwRJeAnxwG8gGkDKLU8a9vYudGWJCwSMLpCSDymPikn7bhN0q/9i1qYEouQwbx6eqWiM2/k30gAeA==",
|
|
753
753
|
"cpu": [
|
|
754
754
|
"x64"
|
|
755
755
|
],
|
|
@@ -766,9 +766,9 @@
|
|
|
766
766
|
}
|
|
767
767
|
},
|
|
768
768
|
"node_modules/@harperfast/fulltext-win32-x64-msvc": {
|
|
769
|
-
"version": "0.
|
|
770
|
-
"resolved": "https://registry.npmjs.org/@harperfast/fulltext-win32-x64-msvc/-/fulltext-win32-x64-msvc-0.
|
|
771
|
-
"integrity": "sha512-
|
|
769
|
+
"version": "0.3.0",
|
|
770
|
+
"resolved": "https://registry.npmjs.org/@harperfast/fulltext-win32-x64-msvc/-/fulltext-win32-x64-msvc-0.3.0.tgz",
|
|
771
|
+
"integrity": "sha512-eUgin3y67xJ0RwKho7QeNAQFtNi9UnJ4t6SVUZqpZfVxzXmh5di2npYVV9S4Sku+R53pSvm8szcqd42cT2PBaw==",
|
|
772
772
|
"cpu": [
|
|
773
773
|
"x64"
|
|
774
774
|
],
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@harperfast/harper",
|
|
3
3
|
"description": "Harper is an open-source Node.js performance platform that unifies database, cache, application, and messaging layers into one in-memory process.",
|
|
4
|
-
"version": "5.3.0
|
|
4
|
+
"version": "5.3.0",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://harper.fast",
|
|
7
7
|
"bugs": {
|
|
@@ -151,7 +151,6 @@
|
|
|
151
151
|
"@types/sinon": "^22.0.0",
|
|
152
152
|
"@types/tar-fs": "^2.0.4",
|
|
153
153
|
"@types/tar-stream": "^3.1.4",
|
|
154
|
-
"@typescript-eslint/parser": "^8.48.1",
|
|
155
154
|
"axios": "1.20.0",
|
|
156
155
|
"chai": "^6.2.0",
|
|
157
156
|
"chai-as-promised": "^8.0.2",
|
|
@@ -175,7 +174,6 @@
|
|
|
175
174
|
"supertest": "^7.1.4",
|
|
176
175
|
"tsx": "^4.20.6",
|
|
177
176
|
"typescript": "^5.8.2",
|
|
178
|
-
"typescript-eslint": "^8.45.0",
|
|
179
177
|
"undici": "^7.24.4",
|
|
180
178
|
"uWebSockets.js": "https://github.com/uNetworking/uWebSockets.js/archive/624987739d4da0acb628aaf2a10fc43e7ce27c5c.tar.gz",
|
|
181
179
|
"why-is-node-still-running": "^1.0.0"
|
|
@@ -271,7 +269,7 @@
|
|
|
271
269
|
}
|
|
272
270
|
},
|
|
273
271
|
"optionalDependencies": {
|
|
274
|
-
"@harperfast/fulltext": "0.
|
|
272
|
+
"@harperfast/fulltext": "0.3.0",
|
|
275
273
|
"@harperfast/hnsw": "0.4.0",
|
|
276
274
|
"bufferutil": "4.1.0",
|
|
277
275
|
"segfault-handler": "1.3.0",
|
package/resources/DESIGN.md
CHANGED
|
@@ -34,6 +34,19 @@ The Resource layer is Harper's universal abstraction: all queryable/mutable thin
|
|
|
34
34
|
|
|
35
35
|
---
|
|
36
36
|
|
|
37
|
+
## Full-text declarations and reader snapshots
|
|
38
|
+
|
|
39
|
+
User-facing syntax: [Full-text search](FULL_TEXT.md).
|
|
40
|
+
|
|
41
|
+
- Compile `name: FullText @fullText(...)` into `fullTextIndexes` and the internal durable `fullTextFields` name set. Programmatic declarations default that name set to every index name. Keep write/projection guards independent of query-reader readiness; the name set does not distinguish earlier declarations from new ones. Never add the declaration to `attributes` or record `properties`: it has no stored, computed, or selectable value. Source fields own permissions.
|
|
42
|
+
- Accept only field placement with its name supplied by the field. Reject a `name` argument, table-level declarations, and index names that collide with current stored attributes. Earlier beta declarations and indexes have no supported upgrade path.
|
|
43
|
+
- Hold one reader lease for the entire search, including every native result page and highlight trace. Reload only an idle reader. Publication during an active query opens a replacement for subsequent queries and retires the old reader after its lease drains. Offset paging across different native snapshots can duplicate or skip hits; deduplication cannot recover skipped hits.
|
|
44
|
+
- Native fulltext owns commits and reader snapshots. Harper owns audit coverage, worker epochs, readiness, and publication notifications. A stable native snapshot does not imply a global record snapshot during concurrent writes; source versions are checked when hydrating hits.
|
|
45
|
+
|
|
46
|
+
Sources: [schema parser](graphql.ts), [declaration compiler and generation identity](fullTextSchema.ts), [table read/write guards](Table.ts), [reader leases and paging](indexes/fullTextQueryIndex.ts), [publication-between-pages regression](../unitTests/resources/fullTextQueryIndex.test.js).
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
37
50
|
## `Resource.ts` — base class
|
|
38
51
|
|
|
39
52
|
Static methods are protocol entry points (each wrapped in `transactional()`); instance methods are the per-resource behavior hooks subclasses override.
|
|
@@ -100,7 +113,7 @@ One giant `makeTable()` factory that returns a `TableResource extends Resource`
|
|
|
100
113
|
| How does a URL path map to a Resource? | `Resources.ts → getMatch` (exact/prefix fast path) then `matchParamRoute` (parameterised routes); see "Path routing" below |
|
|
101
114
|
| What do chained conditions (`a=ge=X&=le=Y`) mean over array values? | SAME-ELEMENT scoping: `prepareConditions` (`Table.ts → search`) collapses the chain into one range comparator (`gele`/`gtlt`/…) before execution, so the indexed path (per-element index entries, one range scan) and the unindexed path (`search.ts → attributeComparator`, per-element `some` over the collapsed predicate) agree. Repeating the attribute as two independent conditions is independently existential (different elements may satisfy different legs). Only a single `and`-chained leg is supported — `\|=` and a second `&=` are rejected. An indexed scan whose range spans more than one indexed value collapses to one result per record before paging (`search.ts → distinctRecords`, #2434), so `limit`/`offset` count records rather than index entries; element equality stays uncollapsed because `[indexedValue, primaryKey]` is already unique. Pinned by `unitTests/resources/query-array-scoping.test.js`; known gaps: chained-leg values are never type-coerced (#2433), an undeclared (untyped) indexed attribute holding an array still repeats per entry, error paths (#2435). |
|
|
102
115
|
| How does HNSW keep the graph connected on delete? | `indexes/HierarchicalNavigableSmallWorld.ts → index()` delete path: zero-degree orphans reindexed via `needsReindexing`; severed multi-node islands detected and reconnected by `repairSeveredNeighbors` (#1712) |
|
|
103
|
-
| How is a filter applied _during_ a vector search? | Predicate-aware traversal (#1241): `search.ts → executeConditions` composes companion AND conditions with request `vectorFilter` / `rowFilter` predicates into one `(primaryKey) => boolean` (`composeRecordFilter`) and passes it to `HierarchicalNavigableSmallWorld.search(cond, ctx, { filter })`. The filter gates result admission at layer 0 only (routing ignores it, ACORN-style); a visit budget (`filterExpansion`) bounds the under-filled/selective case. Very selective _condition_ filters are instead diverted to the exact brute-force path by the query planner's `estimateCountAsSort` ordering.
|
|
116
|
+
| How is a filter applied _during_ a vector search? | Predicate-aware traversal (#1241): `search.ts → executeConditions` composes companion AND conditions with request `vectorFilter` / `rowFilter` predicates into one `(primaryKey) => boolean` (`composeRecordFilter`) and passes it to `HierarchicalNavigableSmallWorld.search(cond, ctx, { filter })`. The filter gates result admission at layer 0 only (routing ignores it, ACORN-style); a visit budget (`filterExpansion`) bounds the under-filled/selective case. Companion conditions an index range answers exactly (equality, `gt`/`ge`, `between`, nested AND/OR over those, when the record predicate rejects every value the index cannot supply: a missing value, and a `0` that may have been written as `-0`) are additionally planned into a key-only scan (`planCandidateKeys`, #2688) and passed as `{ candidateKeys }`; the index admits from that key set instead of loading a record per visited node, and drops the predicate entirely when the set covers every pushed-down condition and no `rowFilter`/`vectorFilter` is in play. Very selective _condition_ filters are instead diverted to the exact brute-force path by the query planner's `estimateCountAsSort` ordering. |
|
|
104
117
|
| How does post-ordering resolve vector distances safely? | Each comparator owns its `Sort`, passes it directly to the custom-index resolver, and caches distances by that immutable per-query sort object. |
|
|
105
118
|
| How is application row filtering applied? | Authorization admission happens in the resource operation before query work. The legacy `allow*` hook, when armed by the protocol, is evaluated once with its historical receiver semantics; overriding it never changes its scope. An operation override may add indexed conditions and/or attach the JavaScript-only synchronous `target.rowFilter(record, context)`. `Table.search` composes it with query filters and rechecks the final materialized cache/source record. `SubscriptionRequest.rowFilter` covers full-row events; `eventFilter(event, context)` explicitly handles tombstones/messages/raw events. Prefer indexed conditions because an opaque predicate may inspect every admitted candidate and `limit` applies after filtering. |
|
|
106
119
|
|
|
@@ -365,8 +378,10 @@ Tests: `../unitTests/resources/defineResource.test.js`, `../unitTests/resources/
|
|
|
365
378
|
- **The override makes the access-control decision.** No `allow*` predicate runs for it. An override that is not meant to be public must check authorization itself.
|
|
366
379
|
- **FK-side relationship accessors (`relationship.from`) are a synchronous contract** (v4 parity). The resolvers built in `Table.updatedAttributes` must read through `getSync`/`getEntry` (which block on a RocksDB block-cache miss, like v4's LMDB page faults) — never `get()`, whose `async: true` path returns a Promise on a cache miss and would leak an intermittent value-or-Promise to `record.<relation>` in user code. Pinned by the "relationship property access is synchronous" test in `../unitTests/resources/query.test.js`, which stubs `store.get` to throw.
|
|
367
380
|
- **Known gap, not covered by that test:** the `.to` side (one-to-many/many-to-many, resolved via `relatedTable.search(...).asArray`) is synchronous for a local read, but `asArray` can still hand back a Promise when the search lands on a **caching** table whose row needs source revalidation — `transformEntryForSelect` returns `loadingFromSource.then(transform)` for an expired/invalidated entry. Same bug class this PR closes on the FK side; not yet fixed here.
|
|
381
|
+
- **A combined `@relationship(from, to)` joins `related[to] == local[from]`, never the local primary key**, and only on an array-typed attribute (a scalar one is logged and gets no resolver). Four paths read `from` independently and must stay in step: the array resolver in `Table.updatedAttributes`, the index-driven join in `searchByIndex` (`joinTo` then `joinFrom`), the join-filtered select in `Table.transformEntryForSelect` (`resolver.from`), and a join filter's switch to an id set in `filterByType`. Pinned by the "@relationship with both from and to" block in `../unitTests/resources/query.test.js`, which uses a related record keyed by the local primary key as a decoy. Two more readers (`drivesRebuildingIndex`, the join estimate's `fromIndex` weighting in `estimateCondition`) affect only condition ordering, not join results, so they are not pinned by that block.
|
|
368
382
|
- When adding a new early-return path inside a commit handler in `_writeUpdate`, follow the blob-cleanup protocol in "Blob orphan cleanup" below.
|
|
369
383
|
- If you add a new top-level section to `Table.ts`, drop a `// #section: <name>` marker at its start and add a row to the section map above.
|
|
384
|
+
- **The table class's published type is the explicit `TableResourceClass` / `TableResourceInstance` pair in `Table.ts`, not the inferred class.** Both are deliberately unexported: the declaration file still carries them, but the user-facing name stays `Table`. TypeScript 6.0+ cannot write a declaration for the class `makeTable()` returns (TS4094 on its `#private` members, so no `Table.d.ts`), and 5.9 leaked those members as `"__#private@…"` keys. A new public member, static or changed signature on the class must be mirrored in the interfaces: the `_TableResourceMatchesItsDeclaredTypes` guard after the class fails `tsc` naming the member, comparing exact types (`resources/typeParity.ts`) because assignability lets `any`, dropped overloads and bivariant parameters through. `#private` state and closure variables need no entry. `unitTests/types/tableClass.type-test.ts` pins the consumer side (subclass overrides, typed statics, no private keys).
|
|
370
385
|
- Tests for this layer live in `../unitTests/resources/`.
|
|
371
386
|
|
|
372
387
|
---
|
|
@@ -466,6 +481,7 @@ Opt-in deflate compression for file-backed blobs (harper#2443) has three load-be
|
|
|
466
481
|
- **Write-bearing request transactions are aborted and poisoned** (issue #1407). The monitor calls `abortDueToTimeout()`, which sets `timedOut`, forces `open = CLOSED` (so `doneReadTxn` takes the discard path instead of re-entering `commit()` via the `LINGERING` branch — which would now throw), then `abort()`s. `addWrite`/`commit` both guard on `timedOut` and throw `transactionOpenTooLongError` (503), so the in-flight request rolls back cleanly rather than the monitor silently force-committing a partial write set (atomicity violation + orphaned secondary-index entries that only a full rebuild repairs). The old behavior `commit()`d and reused the still-open transaction.
|
|
467
482
|
- **`hasPendingWrites()` walks the `next` chain.** Writes to a second database live on `transaction.next` (see `txnForContext`), so a transaction that reads database A (head, tracked via its read snapshot, empty `writes`) and writes database B (`next`) is still write-bearing. Without the walk the head looks read-only and the monitor's force-commit path would cascade-commit B. `abortDueToTimeout()` poisons + aborts the whole chain.
|
|
468
483
|
- **Read-only, `sourceApply`, and `isReplay` transactions keep the prior force-commit behavior.** Read-only long transactions (large scans/exports) have no atomicity/index risk and must not have their ongoing reads poisoned. Canonical-source applies (replication peer / external caching source) and crash-recovery replay have no resubscribe/resume path: aborting a write would drop it while the resume cursor advances past it — a permanent divergence (harper-pro#348). `sourceApply` is propagated down the `next` chain in `txnForContext`, so gating on the head suffices. (Replay is additionally synchronous, so the async monitor can't fire mid-replay anyway.)
|
|
484
|
+
- **The owner's commit waits for the monitor's force-commit.** That commit claims every staged write, marks the transaction `CLOSED`, and detaches its handle, so the owner's later `commit()` finds nothing to do. The monitor therefore stores the promise it got back as `monitorCommit`: `commit()` chains on it and the monitor clears it on success. A failure is kept until the owner's final (`doneWriting`) commit rejects with it and releases the context, since the monitor itself only logs it. That release is deliberately not `abort()`: a multi-store commit can fail after its head store landed, and `abort()`'s blob cleanup would unlink files the head's audit entries still reference. A landed store always finishes its own bookkeeping (writes cleared, record locks released) before a chained store's failure surfaces, including a synchronous throw from `next.commit()`.
|
|
469
485
|
|
|
470
486
|
- **A transaction parked in its commit phase is spared, not poisoned** (issue #2062). `commit()` sets `committing` around its pre-commit await (the `before`/`beforeIntermediate` completions — in practice a blob's durable file write) and the monitor logs instead of aborting while it is set. The limit polices an _application_ holding a transaction open with an unfinished write set; once `commit()` is entered the write set is sealed and the caller is awaiting the commit, so the time is core's own I/O, and a multi-tens-of-MB deploy payload legitimately outruns the limit. Poisoning there was actively destructive: `abort()` cleared the write set and unlinked the write's pre-saved blobs, and the resumed commit then found nothing to write and resolved as **success** — the caller was told its write landed, and was left holding a blob whose file was gone but whose `fileId` was still set, so its next `put` silently minted a reference to a destroyed file (the deploy-payload case: `Blob file not found` on the peer, unrecoverably). The grace is bounded — `COMMIT_PHASE_GRACE` over-limit ticks, ~10 min at the 30s default, since sparing re-arms `timeout` — because the transaction still pins a read snapshot; a source that stalls rather than finishing falls through to the normal abort. `sourceApply`/`isReplay` are spared without a bound: they may be neither aborted (harper-pro#348) nor force-committed mid-write (that would durably commit a replica record whose blob file is still being written), and their blob sources are bounded by the receive-side idle watchdog instead.
|
|
471
487
|
- **Resuming from that await re-checks that the transaction is still alive.** `timedOut` (monitor poison, including via the `next` chain) throws `transactionOpenTooLongError`; a write set cleared with the handle released — a plain `abort()` in the same window — throws `Transaction was aborted while its commit was waiting on pre-commit work`. Without both, either path resolves as a phantom commit. `LMDBTransaction.commit` carries the same pair around its own `before` phase.
|
|
@@ -692,12 +708,13 @@ The additive-only rule above repairs the _consumer_ of a partial peer snapshot;
|
|
|
692
708
|
|
|
693
709
|
## Audit-store `'committed'` notification batching (`transactionBroadcast.ts`)
|
|
694
710
|
|
|
695
|
-
The cross-thread subscription path (default `crossThreads`) drives every `Table.subscribe()` consumer. When the database's audit store emits `'committed'`, we walk the audit log via a reusable iterator and dispatch matching records to subscribers.
|
|
711
|
+
The cross-thread subscription path (default `crossThreads`) drives every `Table.subscribe()` consumer. When the database's audit store emits `'committed'`, we walk the audit log via a reusable iterator and dispatch matching records to subscribers. These properties of this path are easy to break and worth knowing about before changing it:
|
|
696
712
|
|
|
697
713
|
- **`databaseSubscriptions.activeCount`** is the count of live `Subscription` instances on a database. It is incremented at the end of `addSubscription` (after the Subscription is created, so the `scope: 'full-database'` early-return path correctly skips counting) and decremented in `Subscription.end()`. `notifyFromTransactionData` short-circuits when this is zero — the reusable rocksdb iterator stays put and resumes from its position the next time a subscriber arrives. Without this short-circuit, an idle database with no subscribers still pays the audit-log iteration cost on every commit during replication backlog catch-up.
|
|
698
714
|
- **`notifyScheduled` + `setImmediate`** in the `'committed'` listener defers the iteration off the commit microtask. Multiple `'committed'` events that land in the same event-loop turn collapse into one notify pass. `notifyScheduled` stays set for the entire drain — including across yield-and-resume turns — so a re-entry from a new `'committed'` event cannot spawn a second concurrent notify on the same iterator.
|
|
699
715
|
- **Batched yielding** in `notifyFromTransactionData` (`NOTIFY_BATCH_SIZE`) is gated by `allowYield`. The `'committed'` path passes `allowYield = true`; the `listenToCommits` (same-thread `aftercommit`) path does not, because that path holds an inter-thread `'thread-local-writes'` lock that must not span event-loop turns. `subscribersWithTxns` is carried across yields via `subscriptions.pendingTxnSubscribers` so the `end_txn` signal fires exactly once when the iterator truly drains. When `activeCount` drops to zero mid-yield, the next continuation drops the carry-over to avoid invoking ended subscribers' listeners.
|
|
700
716
|
- **The ancestor key walk must strictly shrink.** `notifyFromTransactionData` notifies a changed key and then each `/`-delimited ancestor (`a/b/c` → `a/b/` → `a/` → the `null` root). It stops when the computed parent equals the current key, because a key rooted at `/` otherwise yields `/` as its own parent forever, and this loop is synchronous inside the notify pass with the batch yield outside it, so a single non-terminating walk seizes every worker holding a subscription on the table (harper#2687). Any change to the parent computation must keep a `/`, `/foo`, or `//x` key terminating in `unitTests/resources/transactionBroadcastKeyWalk.test.js`.
|
|
717
|
+
- **Ending a subscription never reshapes a subscriber array a delivery loop is walking.** Listeners run synchronously inside the fan-out and can end their own or any other subscription there: a throwing `rowFilter`/`eventFilter` closes one through `failSubscription`, and a `'data'` listener can call `end()`. Splicing in place shifted the next subscriber past the loop, which then silently missed that record (harper#2771). `Subscription.end()` therefore marks the subscription ended at once — it nulls `subscriptions`, the liveness signal `Table.subscribe` also reads, and decrements `activeCount` — but when its key's array is being walked it only sets the array's `hasEnded`. Each array counts the loops walking it in `traversals`, and the loop that brings the count back to zero compacts the ended entries out, detaching an emptied key and table as `end()` would. Outside a walk, `end()` removes the subscription immediately. Each loop walks only the array's length at its start, so a subscription added to a key during that key's delivery starts with the next record. The `reload` walk visits at most as many keys as the table had when it started (a key added during the walk can take the place of one that left). Without both bounds, a listener that ends and re-subscribes extends the loop forever. The per-key, `reload` and `end_txn` loops all skip a subscription whose `subscriptions` is null. A new loop over these arrays needs the same count, bound and check (`unitTests/resources/transactionBroadcastEndDuringDelivery.test.js`).
|
|
701
718
|
|
|
702
719
|
## Audit-entry removal loops must track every `removeAuditEntry()`/`removeEntry()` promise
|
|
703
720
|
|
|
@@ -737,6 +737,9 @@ export class DatabaseTransaction implements Transaction {
|
|
|
737
737
|
// open-transaction limit. Once poisoned, any further addWrite/commit throws transactionOpenTooLongError
|
|
738
738
|
// so the request rolls back cleanly instead of silently committing a partial write set (issue #1407).
|
|
739
739
|
declare timedOut?: boolean;
|
|
740
|
+
// The monitor's force-commit, which the owner's commit joins (resources/DESIGN.md). Kept after a failure
|
|
741
|
+
// until a final commit reports it: the monitor only logs it.
|
|
742
|
+
declare monitorCommit?: Promise<CommitResolution>;
|
|
740
743
|
// Set once the retained read handle's write intents have been released (see commit()'s
|
|
741
744
|
// outstanding-iterators branch), so a retry round cannot re-fire the release.
|
|
742
745
|
declare writesAbandoned?: boolean;
|
|
@@ -1420,6 +1423,19 @@ export class DatabaseTransaction implements Transaction {
|
|
|
1420
1423
|
*/
|
|
1421
1424
|
commit(options: CommitOptions = {}): MaybePromise<CommitResolution> {
|
|
1422
1425
|
if (this.timedOut) throw transactionOpenTooLongError();
|
|
1426
|
+
if (this.monitorCommit && !options.transaction) {
|
|
1427
|
+
return this.monitorCommit.then(
|
|
1428
|
+
() => this.commit(options),
|
|
1429
|
+
(error) => {
|
|
1430
|
+
// The failed commit ran its terminal cleanup, but as a non-final commit it kept the context.
|
|
1431
|
+
if (options.doneWriting) {
|
|
1432
|
+
this.monitorCommit = undefined;
|
|
1433
|
+
this.releaseContext(true);
|
|
1434
|
+
}
|
|
1435
|
+
throw error;
|
|
1436
|
+
}
|
|
1437
|
+
);
|
|
1438
|
+
}
|
|
1423
1439
|
// reused across retries — the native layer resets it in place (fresh snapshot) on IsBusy/TryAgain —
|
|
1424
1440
|
// but reassigned to a fresh replay transaction when outstanding read iterators retain this.transaction
|
|
1425
1441
|
let transaction = options.transaction ?? this.transaction;
|
|
@@ -1669,9 +1685,15 @@ export class DatabaseTransaction implements Transaction {
|
|
|
1669
1685
|
if (this.next) {
|
|
1670
1686
|
// never forward options.transaction (a retry/replay round's HEAD-store handle) to
|
|
1671
1687
|
// the next store — it must commit its own writes through its own transaction
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1688
|
+
let nextCommit: MaybePromise<CommitResolution>;
|
|
1689
|
+
try {
|
|
1690
|
+
nextCommit = this.next.commit(options.transaction ? { ...options, transaction: undefined } : options);
|
|
1691
|
+
} catch (error) {
|
|
1692
|
+
// This store has landed; its bookkeeping below must run before the failure surfaces.
|
|
1693
|
+
nextCommit = Promise.reject(error);
|
|
1694
|
+
nextCommit.catch(() => {}); // still rejects Promise.all, even if bookkeeping throws first
|
|
1695
|
+
}
|
|
1696
|
+
completions.push(nextCommit);
|
|
1675
1697
|
}
|
|
1676
1698
|
if (options?.flush) {
|
|
1677
1699
|
completions.push(this.writes[0].store.flushed);
|
|
@@ -2483,15 +2505,23 @@ function startMonitoringTxns() {
|
|
|
2483
2505
|
// Read-only long transaction (no atomicity/index risk — e.g. a large scan or export), or a
|
|
2484
2506
|
// canonical-source apply/replay that must never drop a write: preserve the prior behavior of
|
|
2485
2507
|
// committing to close out the snapshot without poisoning the transaction.
|
|
2508
|
+
let result: MaybePromise<CommitResolution>;
|
|
2486
2509
|
try {
|
|
2487
|
-
|
|
2488
|
-
if ((result as any)?.then) {
|
|
2489
|
-
(result as any).catch((error) => {
|
|
2490
|
-
harperLogger.debug?.(`Error committing timed out transaction: ${error.message}`);
|
|
2491
|
-
});
|
|
2492
|
-
}
|
|
2510
|
+
result = txn.commit();
|
|
2493
2511
|
} catch (error) {
|
|
2494
|
-
|
|
2512
|
+
result = Promise.reject(error);
|
|
2513
|
+
}
|
|
2514
|
+
if ((result as any)?.then) {
|
|
2515
|
+
const monitorCommit = result as Promise<CommitResolution>;
|
|
2516
|
+
txn.monitorCommit = monitorCommit;
|
|
2517
|
+
monitorCommit.then(
|
|
2518
|
+
() => {
|
|
2519
|
+
if (txn.monitorCommit === monitorCommit) txn.monitorCommit = undefined;
|
|
2520
|
+
},
|
|
2521
|
+
(error) => {
|
|
2522
|
+
harperLogger.debug?.(`Error committing timed out transaction: ${error.message}`);
|
|
2523
|
+
}
|
|
2524
|
+
);
|
|
2495
2525
|
}
|
|
2496
2526
|
txn.timeout = Math.max(txnExpiration, txn.timeoutBudget ?? 0);
|
|
2497
2527
|
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Full-text search
|
|
2
|
+
|
|
3
|
+
Declare a `FullText` field to name an index over stored text sources. Search that field with a full-text comparator; read the original source fields and optional search metadata in the results.
|
|
4
|
+
|
|
5
|
+
## Declare an index
|
|
6
|
+
|
|
7
|
+
```graphql
|
|
8
|
+
type Product @table(audit: true) @export {
|
|
9
|
+
id: ID @primaryKey
|
|
10
|
+
title: String
|
|
11
|
+
description: String
|
|
12
|
+
tags: [String]
|
|
13
|
+
catalogSearch: FullText
|
|
14
|
+
@fullText(
|
|
15
|
+
fields: [{ name: "title", weight: 3, highlight: true }, { name: "description" }, { name: "tags" }]
|
|
16
|
+
highlighting: { maxFragments: 2, fragmentLength: 120 }
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The field name, `catalogSearch`, identifies the index. `@fullText` accepts no `name` argument and is supported only on a `FullText` field. Keep the source order stable: reordering the `fields` entries is treated as a storage configuration change and rebuilds the index.
|
|
22
|
+
|
|
23
|
+
Sources may be stored `String`, `[String]`, or `Blob` fields. A Blob source requires `mediaType: "text/plain"` in its `fields` entry. Computed fields, relationships, and other full-text fields cannot be sources. Weights must be positive finite numbers and default to `1`.
|
|
24
|
+
|
|
25
|
+
The supported analyzer is `english@2`. `stopWords`, `positions`, and `surfaceTerms` default to `true`. Phrase queries require positions; prefix and fuzzy-prefix queries require surface terms. Highlighting also requires surface terms, a `highlighting` configuration, and at least one source with `highlight: true`.
|
|
26
|
+
|
|
27
|
+
## Search
|
|
28
|
+
|
|
29
|
+
From an authenticated Resource handler, request table permission checks and pass its context through to `Product.search()`:
|
|
30
|
+
|
|
31
|
+
```javascript
|
|
32
|
+
return Product.search(
|
|
33
|
+
{
|
|
34
|
+
checkPermission: true,
|
|
35
|
+
conditions: [
|
|
36
|
+
{
|
|
37
|
+
attribute: 'catalogSearch',
|
|
38
|
+
comparator: 'matches',
|
|
39
|
+
value: 'trail shoes',
|
|
40
|
+
maxIndexLagMilliseconds: 0,
|
|
41
|
+
waitForIndexMilliseconds: 30_000,
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
select: ['id', 'title', '$score', '$highlights'],
|
|
45
|
+
limit: 20,
|
|
46
|
+
},
|
|
47
|
+
this.getContext()
|
|
48
|
+
);
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Selecting `$highlights` requests highlighting; a structured condition may also set `includeHighlights: true`. `$score` contains the relevance score. Highlights are grouped by source field and value, with character spans and optional fragments. Only sources configured with `highlight: true` contribute highlights.
|
|
52
|
+
|
|
53
|
+
A REST search uses the exported table path:
|
|
54
|
+
|
|
55
|
+
```text
|
|
56
|
+
GET /Product/?catalogSearch=matches=trail%20shoes&select(id,title,$score,$highlights)&limit(20)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
| Comparator | Query mode |
|
|
60
|
+
| ---------------------- | --------------- |
|
|
61
|
+
| `matches` | Any query term |
|
|
62
|
+
| `matches_all` | All query terms |
|
|
63
|
+
| `matches_phrase` | Phrase |
|
|
64
|
+
| `matches_prefix` | Prefix |
|
|
65
|
+
| `matches_fuzzy` | Fuzzy |
|
|
66
|
+
| `matches_fuzzy_prefix` | Fuzzy prefix |
|
|
67
|
+
|
|
68
|
+
Use `fields: ['title']` on a structured condition to search a subset of an index's sources. Combine ordinary record filters with full-text conditions using `and`. Full-text Boolean groups must use one index; an `or` group cannot mix full-text and ordinary record conditions. Negated full-text conditions require at least one positive full-text condition.
|
|
69
|
+
|
|
70
|
+
Full-text predicates must name an index directly on the queried table; relationship and nested-path full-text predicates are unsupported.
|
|
71
|
+
|
|
72
|
+
Indexes follow committed record changes asynchronously. `maxIndexLagMilliseconds` defaults to `3000`; set it to `0` to require current coverage. `waitForIndexMilliseconds` defaults to `0` and may be set as high as `30000` to wait for writes committed before the search begins. A query can fail while its index is unavailable, rebuilding, or behind the requested coverage. A non-waiting REST response includes `Harper-Index-Coverage`. Waiting for coverage does not promise a global snapshot across concurrent record changes.
|
|
73
|
+
|
|
74
|
+
## Fields, permissions, and results
|
|
75
|
+
|
|
76
|
+
`FullText` is declaration-only: `catalogSearch` has no stored or selectable record value. Records written under this schema and record input/output schemas omit it. Selecting it, sorting on it, comparing it as an ordinary scalar, or writing it returns an error. New-write protection also applies to unsealed tables and persists while the index is unavailable. Use `$score` and `$highlights` for search results.
|
|
77
|
+
|
|
78
|
+
A read-through source must also omit the declaration-only name. A source response that includes it fails with a 502 response and is not returned, cached, indexed, or audited.
|
|
79
|
+
On HTTP-sourced caching tables, avoid index names that collide with response wrapper fields: `data`, `headers`, `body`, and `status`.
|
|
80
|
+
|
|
81
|
+
Use the nullable `FullText` type exactly. Lists, non-null forms, and additional directives such as `@computed`, `@indexed`, or `@allow` are rejected. `FullText` without `@fullText` is also invalid.
|
|
82
|
+
|
|
83
|
+
Authorization uses the searched source fields. A caller must be allowed to read every source searched by the condition; specifying `fields` narrows that set. Configure permissions on sources such as `title`, not on `catalogSearch`. A permission entry for the virtual index name does not grant access to its sources. Normal table authorization and application row filters still apply. Internal calls without a user or explicit permissions are trusted. Custom endpoints must preserve the authenticated context and set `checkPermission: true` when delegating to the table; context propagation alone does not request its table permission check.
|
|
84
|
+
|
|
85
|
+
`describe_table` exposes the declaration under `full_text_indexes`, including its name, source configuration, supported query modes, and readiness. Source lists are filtered by the caller's read permissions. The declaration is absent from the ordinary `attributes` list and record schemas, including generated OpenAPI and MCP schemas.
|
|
86
|
+
|
|
87
|
+
Weight and highlighting changes preserve the physical index and refresh query readers. Changing source membership, order, or media type, or changing the analyzer, stop words, synonyms, positions, or surface terms requires rebuilding. Renaming the index creates a new identity.
|
|
88
|
+
|
|
89
|
+
## Native package and limits
|
|
90
|
+
|
|
91
|
+
Harper pins `@harperfast/fulltext` to **0.3.0** and validates the native runtime capabilities before activation. Full-text activation requires RocksDB and an audited table. Declare new schema tables with `@table(audit: true)` and keep audit logging enabled while an index is declared. LMDB is rejected. A missing or incompatible native package prevents activation.
|
|
92
|
+
|
|
93
|
+
Earlier beta declarations and indexes are unsupported. This field-only API does not provide a compatibility or upgrade path for them.
|
|
94
|
+
|
|
95
|
+
Native queries have finite result windows and execution budgets. Reduce the requested offset/limit or narrow the query when a window is exceeded; filtering can also exhaust the window. Prefix modes use the native autocomplete window. Highlight tracing has separate record and source-byte bounds. These are functional constraints, not catalog-scale performance guarantees.
|
|
96
|
+
|
|
97
|
+
For implementation details, see the [full-text invariants in the Resource design guide](DESIGN.md#full-text-declarations-and-reader-snapshots). The schema contract lives in [schema.graphql](../schema.graphql); the compiler and generation rules are in [fullTextSchema.ts](fullTextSchema.ts).
|
|
@@ -5,6 +5,7 @@ import { IterableEventQueue } from './IterableEventQueue.ts';
|
|
|
5
5
|
import type { Entry, RecordObject } from './RecordEncoder.ts';
|
|
6
6
|
import { RequestTarget } from './RequestTarget.ts';
|
|
7
7
|
import type { RecordLockOptions } from './recordLock.ts';
|
|
8
|
+
import { FULL_TEXT_COMPARATORS } from './indexes/fullTextQueryProtocol.ts';
|
|
8
9
|
|
|
9
10
|
export interface ResourceInterface<Record extends object = any>
|
|
10
11
|
extends Partial<RecordObject>, Pick<UpdatableRecord<Record>, 'addTo' | 'subtractFrom'> {
|
|
@@ -185,6 +186,7 @@ export const COMPARATORS = [
|
|
|
185
186
|
'in',
|
|
186
187
|
'less_than',
|
|
187
188
|
'less_than_equal',
|
|
189
|
+
...FULL_TEXT_COMPARATORS,
|
|
188
190
|
'ne',
|
|
189
191
|
'not_equal',
|
|
190
192
|
'starts_with',
|
|
@@ -201,7 +203,11 @@ interface TypedDirectCondition<Record extends object, Property extends keyof Rec
|
|
|
201
203
|
search_type?: Comparator;
|
|
202
204
|
value?: Record[Property] | Record[Property][];
|
|
203
205
|
search_value?: Record[Property] | Record[Property][];
|
|
204
|
-
/**
|
|
206
|
+
/** Optional source-field restriction for a named full-text index. */
|
|
207
|
+
fields?: string[];
|
|
208
|
+
/** Return configured full-text match spans and snippets; disabled by default. */
|
|
209
|
+
includeHighlights?: boolean;
|
|
210
|
+
/** Native derived-index coverage tolerance in milliseconds; defaults to 3000, with 0 requiring current coverage. */
|
|
205
211
|
maxIndexLagMilliseconds?: number;
|
|
206
212
|
/** Wait for coverage of prior committed writes, up to 30,000 ms; 0 (default) does not wait. */
|
|
207
213
|
waitForIndexMilliseconds?: number;
|
|
@@ -215,7 +221,7 @@ interface TypedDirectCondition<Record extends object, Property extends keyof Rec
|
|
|
215
221
|
* companion conditions and caller `vectorFilter`/`rowFilter` predicates, pushed into a filterable
|
|
216
222
|
* custom index (HNSW) so filtering happens during traversal. Not part of the public query surface.
|
|
217
223
|
*/
|
|
218
|
-
recordFilter?: (primaryKey: Id) => boolean;
|
|
224
|
+
recordFilter?: (primaryKey: Id, entry?: unknown) => boolean;
|
|
219
225
|
}
|
|
220
226
|
|
|
221
227
|
interface ConditionGroup<Record extends object = any> {
|