[{"data":1,"prerenderedAt":1972},["ShallowReactive",2],{"navigation_docs_en":3,"-en-developer-extensions-data-connectors":445,"-en-developer-extensions-data-connectors-surround":1967},[4,30,72,132,260,436],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":6},"Getting Started",false,"\u002Fen\u002Fgetting-started","en\u002F1.getting-started",[10,15,20,25],{"title":11,"path":12,"stem":13,"icon":14},"Introduction","\u002Fen\u002Fgetting-started\u002Fintroduction","en\u002F1.getting-started\u002F2.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Quickstart","\u002Fen\u002Fgetting-started\u002Finstallation","en\u002F1.getting-started\u002F3.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":24},"Use Cases","\u002Fen\u002Fgetting-started\u002Fuse-cases","en\u002F1.getting-started\u002F4.use-cases","i-lucide-layers",{"title":26,"path":27,"stem":28,"icon":29},"Concepts","\u002Fen\u002Fgetting-started\u002Fconcepts","en\u002F1.getting-started\u002F5.concepts","i-lucide-book",{"title":26,"path":31,"stem":32,"children":33,"page":6},"\u002Fen\u002Fconcepts","en\u002F2.concepts",[34,38,43,48,53,58,63,68],{"title":35,"path":36,"stem":37,"icon":14},"Organization","\u002Fen\u002Fconcepts\u002Forganization","en\u002F2.concepts\u002F1.organization",{"title":39,"path":40,"stem":41,"icon":42},"Data Model","\u002Fen\u002Fconcepts\u002Fdata-model","en\u002F2.concepts\u002F2.data-model","i-lucide-database",{"title":44,"path":45,"stem":46,"icon":47},"Access Control","\u002Fen\u002Fconcepts\u002Faccess-permissions","en\u002F2.concepts\u002F3.access-permissions","i-lucide-user-key",{"title":49,"path":50,"stem":51,"icon":52},"Audit Logs","\u002Fen\u002Fconcepts\u002Faudit-logs","en\u002F2.concepts\u002F4.audit-logs","i-lucide-scroll-text",{"title":54,"path":55,"stem":56,"icon":57},"Introspection","\u002Fen\u002Fconcepts\u002Fintrospection","en\u002F2.concepts\u002F6.introspection","i-lucide-database-search",{"title":59,"path":60,"stem":61,"icon":62},"Query Engine","\u002Fen\u002Fconcepts\u002Fquery-engine","en\u002F2.concepts\u002F7.query-engine","i-lucide-workflow",{"title":64,"path":65,"stem":66,"icon":67},"AI","\u002Fen\u002Fconcepts\u002Fai","en\u002F2.concepts\u002F8.ai","i-lucide-sparkles",{"title":69,"path":70,"stem":71,"icon":42},"Caching","\u002Fen\u002Fconcepts\u002Fcaching","en\u002F2.concepts\u002F9.caching",{"title":73,"path":74,"stem":75,"children":76,"page":6},"Guides","\u002Fen\u002Fguides","en\u002F4.guides",[77,82,87,92,97,102,107,112],{"title":78,"path":79,"stem":80,"icon":81},"REST API Quickstart","\u002Fen\u002Fguides\u002Frest-api","en\u002F4.guides\u002F1.rest-api","i-lucide-plug",{"title":83,"path":84,"stem":85,"icon":86},"SDK Quickstart","\u002Fen\u002Fguides\u002Fsdk","en\u002F4.guides\u002F2.sdk","i-lucide-terminal",{"title":88,"path":89,"stem":90,"icon":91},"Configure SSO","\u002Fen\u002Fguides\u002Fconfigure-sso","en\u002F4.guides\u002F3.configure-sso","i-lucide-key-round",{"title":93,"path":94,"stem":95,"icon":96},"Configure MCP","\u002Fen\u002Fguides\u002Fmcp","en\u002F4.guides\u002F4.mcp","i-lucide-brain-cog",{"title":98,"path":99,"stem":100,"icon":101},"Customize Content Space","\u002Fen\u002Fguides\u002Fcustomize-content-space","en\u002F4.guides\u002F5.customize-content-space","i-lucide-columns-3-cog",{"title":103,"path":104,"stem":105,"icon":106},"Build an Application with AI Assistance","\u002Fen\u002Fguides\u002Fbuild-an-application","en\u002F4.guides\u002F6.build-an-application","i-lucide-route",{"title":108,"path":109,"stem":110,"icon":111},"Horizontal Scaling","\u002Fen\u002Fguides\u002Fhorizontal-scaling","en\u002F4.guides\u002F7.horizontal-scaling","i-lucide-network",{"title":113,"icon":114,"path":115,"stem":116,"children":117,"page":6},"Data Connectors","i-lucide-cable","\u002Fen\u002Fguides\u002Fdata-connectors","en\u002F4.guides\u002F8.data-connectors",[118,122,127],{"title":16,"path":119,"stem":120,"icon":121},"\u002Fen\u002Fguides\u002Fdata-connectors\u002Fquickstart","en\u002F4.guides\u002F8.data-connectors\u002F1.quickstart","i-lucide-rocket",{"title":123,"path":124,"stem":125,"icon":126},"Build a Stripe Connector","\u002Fen\u002Fguides\u002Fdata-connectors\u002Fstripe","en\u002F4.guides\u002F8.data-connectors\u002F2.stripe","i-lucide-hammer",{"title":128,"path":129,"stem":130,"icon":131},"Build with AI Agents","\u002Fen\u002Fguides\u002Fdata-connectors\u002Fai-agents","en\u002F4.guides\u002F8.data-connectors\u002F3.ai-agents","i-lucide-bot",{"title":133,"path":134,"stem":135,"children":136,"page":6},"Developer","\u002Fen\u002Fdeveloper","en\u002F5.developer",[137,191,215,220],{"title":138,"path":139,"stem":140,"children":141,"page":6},"Data Access","\u002Fen\u002Fdeveloper\u002Fapi","en\u002F5.developer\u002F1.api",[142,147,152,157,162,167,172,177,182,186],{"title":143,"path":144,"stem":145,"icon":146},"Overview","\u002Fen\u002Fdeveloper\u002Fapi\u002Foverview","en\u002F5.developer\u002F1.api\u002F1.overview","i-lucide-globe",{"title":148,"path":149,"stem":150,"icon":151},"Errors","\u002Fen\u002Fdeveloper\u002Fapi\u002Ferrors","en\u002F5.developer\u002F1.api\u002F10.errors","i-lucide-alert-triangle",{"title":153,"path":154,"stem":155,"icon":156},"Authentication","\u002Fen\u002Fdeveloper\u002Fapi\u002Fauthentication","en\u002F5.developer\u002F1.api\u002F2.authentication","i-lucide-lock",{"title":158,"path":159,"stem":160,"icon":161},"Reading Data","\u002Fen\u002Fdeveloper\u002Fapi\u002Freading-data","en\u002F5.developer\u002F1.api\u002F3.reading-data","i-lucide-book-open",{"title":163,"path":164,"stem":165,"icon":166},"Writing Data","\u002Fen\u002Fdeveloper\u002Fapi\u002Fwriting-data","en\u002F5.developer\u002F1.api\u002F4.writing-data","i-lucide-pencil",{"title":168,"path":169,"stem":170,"icon":171},"Filtering","\u002Fen\u002Fdeveloper\u002Fapi\u002Ffiltering","en\u002F5.developer\u002F1.api\u002F5.filtering","i-lucide-filter",{"title":173,"path":174,"stem":175,"icon":176},"Field Selection","\u002Fen\u002Fdeveloper\u002Fapi\u002Ffield-selection","en\u002F5.developer\u002F1.api\u002F6.field-selection","i-lucide-list-checks",{"title":178,"path":179,"stem":180,"icon":181},"Sorting & Pagination","\u002Fen\u002Fdeveloper\u002Fapi\u002Fsorting-pagination","en\u002F5.developer\u002F1.api\u002F7.sorting-pagination","i-lucide-arrow-up-down",{"title":183,"path":184,"stem":185,"icon":111},"Relational Data","\u002Fen\u002Fdeveloper\u002Fapi\u002Frelational-data","en\u002F5.developer\u002F1.api\u002F8.relational-data",{"title":187,"path":188,"stem":189,"icon":190},"Files & Assets","\u002Fen\u002Fdeveloper\u002Fapi\u002Ffiles","en\u002F5.developer\u002F1.api\u002F9.files","i-lucide-file-up",{"title":192,"path":193,"stem":194,"children":195,"page":6},"Client SDK","\u002Fen\u002Fdeveloper\u002Fsdk","en\u002F5.developer\u002F2.sdk",[196,200,205,210],{"title":197,"path":198,"stem":199,"icon":19},"Installation","\u002Fen\u002Fdeveloper\u002Fsdk\u002Finstallation","en\u002F5.developer\u002F2.sdk\u002F1.installation",{"title":201,"path":202,"stem":203,"icon":204},"Client Setup","\u002Fen\u002Fdeveloper\u002Fsdk\u002Fclient-setup","en\u002F5.developer\u002F2.sdk\u002F2.client-setup","i-lucide-settings",{"title":206,"path":207,"stem":208,"icon":209},"Type System","\u002Fen\u002Fdeveloper\u002Fsdk\u002Ftype-system","en\u002F5.developer\u002F2.sdk\u002F3.type-system","i-lucide-braces",{"title":211,"path":212,"stem":213,"icon":214},"Advanced","\u002Fen\u002Fdeveloper\u002Fsdk\u002Fadvanced","en\u002F5.developer\u002F2.sdk\u002F5.advanced","i-lucide-puzzle",{"title":216,"path":217,"stem":218,"icon":219},"Application Users","\u002Fen\u002Fdeveloper\u002Fapplication-users","en\u002F5.developer\u002F3.application-users","i-lucide-users",{"title":221,"path":222,"stem":223,"children":224,"icon":214},"Extensions","\u002Fen\u002Fdeveloper\u002Fextensions","en\u002F5.developer\u002F3.extensions\u002Findex",[225,226,231],{"title":143,"path":222,"stem":223,"icon":214},{"title":227,"path":228,"stem":229,"icon":230},"Install and Manage Extensions","\u002Fen\u002Fdeveloper\u002Fextensions\u002Finstall","en\u002F5.developer\u002F3.extensions\u002F1.install","i-lucide-package-plus",{"title":113,"path":232,"stem":233,"children":234,"icon":114},"\u002Fen\u002Fdeveloper\u002Fextensions\u002Fdata-connectors","en\u002F5.developer\u002F3.extensions\u002F2.data-connectors\u002Findex",[235,236,241,245,250,255],{"title":143,"path":232,"stem":233,"icon":114},{"title":237,"path":238,"stem":239,"icon":240},"How Data Connectors Run","\u002Fen\u002Fdeveloper\u002Fextensions\u002Fdata-connectors\u002Fruntime","en\u002F5.developer\u002F3.extensions\u002F2.data-connectors\u002F2.runtime","i-lucide-cpu",{"title":242,"path":243,"stem":244,"icon":42},"Data Sources","\u002Fen\u002Fdeveloper\u002Fextensions\u002Fdata-connectors\u002Fdata-sources","en\u002F5.developer\u002F3.extensions\u002F2.data-connectors\u002F3.data-sources",{"title":246,"path":247,"stem":248,"icon":249},"Map an External Data Source","\u002Fen\u002Fdeveloper\u002Fextensions\u002Fdata-connectors\u002Fdata-source-mapping","en\u002F5.developer\u002F3.extensions\u002F2.data-connectors\u002F4.data-source-mapping","i-lucide-map",{"title":251,"path":252,"stem":253,"icon":254},"Handle Errors","\u002Fen\u002Fdeveloper\u002Fextensions\u002Fdata-connectors\u002Ferrors","en\u002F5.developer\u002F3.extensions\u002F2.data-connectors\u002F5.errors","i-lucide-shield-alert",{"title":256,"path":257,"stem":258,"icon":259},"Test a Data Connector","\u002Fen\u002Fdeveloper\u002Fextensions\u002Fdata-connectors\u002Ftesting","en\u002F5.developer\u002F3.extensions\u002F2.data-connectors\u002F6.testing","i-lucide-flask-conical",{"title":261,"path":262,"stem":263,"children":264,"page":6},"Reference","\u002Fen\u002Freference","en\u002F6.reference",[265,269,274,279,295,299,304,340,369,374],{"title":266,"path":267,"stem":268,"icon":204},"Configuration","\u002Fen\u002Freference\u002Fenvironment-variables","en\u002F6.reference\u002F1.environment-variables",{"title":270,"path":271,"stem":272,"icon":273},"System Requirements","\u002Fen\u002Freference\u002Fsystem-requirements","en\u002F6.reference\u002F2.system-requirements","i-lucide-server",{"title":275,"path":276,"stem":277,"icon":278},"Licensing","\u002Fen\u002Freference\u002Flicensing","en\u002F6.reference\u002F3.licensing","i-lucide-gem",{"title":280,"path":281,"stem":282,"children":283,"icon":81},"Connectors","\u002Fen\u002Freference\u002Fconnectors","en\u002F6.reference\u002F4.connectors\u002Findex",[284,285,290],{"title":280,"path":281,"stem":282,"icon":81},{"title":286,"path":287,"stem":288,"icon":289},"PostgreSQL and Supabase","\u002Fen\u002Freference\u002Fconnectors\u002Fpostgresql-supabase","en\u002F6.reference\u002F4.connectors\u002F1.postgresql-supabase","i-simple-icons-postgresql",{"title":291,"path":292,"stem":293,"icon":294},"MySQL and MariaDB","\u002Fen\u002Freference\u002Fconnectors\u002Fmysql-mariadb","en\u002F6.reference\u002F4.connectors\u002F2.mysql-mariadb","i-simple-icons-mysql",{"title":296,"path":297,"stem":298,"icon":209},"Data Types Representation","\u002Fen\u002Freference\u002Fdata-types","en\u002F6.reference\u002F5.data-types",{"title":300,"path":301,"stem":302,"icon":303},"Permissions Reference","\u002Fen\u002Freference\u002Fpermissions","en\u002F6.reference\u002F6.permissions","i-lucide-shield",{"title":305,"path":306,"stem":307,"children":308,"page":6},"API Reference","\u002Fen\u002Freference\u002Fapi-reference","en\u002F6.reference\u002F7.api-reference",[309,313,318],{"title":310,"path":311,"stem":312,"icon":273},"System Endpoints","\u002Fen\u002Freference\u002Fapi-reference\u002Fsystem-endpoints","en\u002F6.reference\u002F7.api-reference\u002F1.system-endpoints",{"title":314,"path":315,"stem":316,"icon":317},"OpenAPI Spec","\u002Fen\u002Freference\u002Fapi-reference\u002Fopenapi-spec","en\u002F6.reference\u002F7.api-reference\u002F2.openapi-spec","i-lucide-file-code",{"title":319,"path":320,"stem":321,"children":322,"icon":324},"Schema Migration","\u002Fen\u002Freference\u002Fapi-reference\u002Fschema-migration","en\u002F6.reference\u002F7.api-reference\u002F3.schema-migration\u002Findex",[323,325,330,335],{"title":319,"path":320,"stem":321,"icon":324},"i-lucide-database-zap",{"title":326,"path":327,"stem":328,"icon":329},"Apply Migrations","\u002Fen\u002Freference\u002Fapi-reference\u002Fschema-migration\u002Fapply-migrations","en\u002F6.reference\u002F7.api-reference\u002F3.schema-migration\u002F1.apply-migrations","i-lucide-upload",{"title":331,"path":332,"stem":333,"icon":334},"Import Changes","\u002Fen\u002Freference\u002Fapi-reference\u002Fschema-migration\u002Fimport-changes","en\u002F6.reference\u002F7.api-reference\u002F3.schema-migration\u002F2.import-changes","i-lucide-refresh-cw",{"title":336,"path":337,"stem":338,"icon":339},"Operation Reference","\u002Fen\u002Freference\u002Fapi-reference\u002Fschema-migration\u002Foperation-reference","en\u002F6.reference\u002F7.api-reference\u002F3.schema-migration\u002F3.operation-reference","i-lucide-list-tree",{"title":341,"path":342,"stem":343,"children":344,"page":6},"Design Considerations","\u002Fen\u002Freference\u002Fdesign-considerations","en\u002F6.reference\u002F8.design-considerations",[345,349,354,359,364],{"title":143,"path":346,"stem":347,"icon":348},"\u002Fen\u002Freference\u002Fdesign-considerations\u002Foverview","en\u002F6.reference\u002F8.design-considerations\u002F1.overview","i-lucide-compass",{"title":350,"path":351,"stem":352,"icon":353},"Instance Configuration","\u002Fen\u002Freference\u002Fdesign-considerations\u002Finstance-configuration-related-problems","en\u002F6.reference\u002F8.design-considerations\u002F3.instance-configuration-related-problems","i-lucide-wrench",{"title":355,"path":356,"stem":357,"icon":358},"Overly Permissive Public Access","\u002Fen\u002Freference\u002Fdesign-considerations\u002Foverly-permissive","en\u002F6.reference\u002F8.design-considerations\u002F4.overly-permissive","i-lucide-shield-off",{"title":360,"path":361,"stem":362,"icon":363},"No Aggregates","\u002Fen\u002Freference\u002Fdesign-considerations\u002Fno-aggregates","en\u002F6.reference\u002F8.design-considerations\u002F5.no-aggregates","i-lucide-sigma",{"title":365,"path":366,"stem":367,"icon":368},"Cross-Data-Source Referential Integrity","\u002Fen\u002Freference\u002Fdesign-considerations\u002Fcross-data-source-referential-integrity","en\u002F6.reference\u002F8.design-considerations\u002F6.cross-data-source-referential-integrity","i-lucide-unlink",{"title":370,"path":371,"stem":372,"icon":373},"CLI","\u002Fen\u002Freference\u002Fcli","en\u002F6.reference\u002F9.cli","i-lucide-square-terminal",{"title":221,"path":375,"stem":376,"children":377,"page":6},"\u002Fen\u002Freference\u002Fextensions","en\u002F6.reference\u002F9.extensions",[378,383,386,405],{"title":379,"path":380,"stem":381,"icon":382},"Extension Config and Manifest","\u002Fen\u002Freference\u002Fextensions\u002Fmanifest","en\u002F6.reference\u002F9.extensions\u002F1.manifest","i-lucide-file-json",{"title":370,"path":384,"stem":385,"icon":86},"\u002Fen\u002Freference\u002Fextensions\u002Fcli","en\u002F6.reference\u002F9.extensions\u002F2.cli",{"title":387,"path":388,"stem":389,"children":390,"page":6},"Extension Kit","\u002Fen\u002Freference\u002Fextensions\u002Fextension-kit","en\u002F6.reference\u002F9.extensions\u002F3.extension-kit",[391,395,400],{"title":392,"path":393,"stem":394,"icon":81},"Data Connector","\u002Fen\u002Freference\u002Fextensions\u002Fextension-kit\u002Fdata-connector","en\u002F6.reference\u002F9.extensions\u002F3.extension-kit\u002F1.data-connector",{"title":396,"path":397,"stem":398,"icon":399},"Protocol","\u002Fen\u002Freference\u002Fextensions\u002Fextension-kit\u002Fprotocol","en\u002F6.reference\u002F9.extensions\u002F3.extension-kit\u002F2.protocol","i-lucide-arrow-left-right",{"title":401,"path":402,"stem":403,"icon":404},"Schema Helpers","\u002Fen\u002Freference\u002Fextensions\u002Fextension-kit\u002Fexperimental","en\u002F6.reference\u002F9.extensions\u002F3.extension-kit\u002F3.experimental","i-lucide-blocks",{"title":113,"path":406,"stem":407,"children":408,"page":6},"\u002Fen\u002Freference\u002Fextensions\u002Fdata-connectors","en\u002F6.reference\u002F9.extensions\u002F4.data-connectors",[409,413,417,421,426,431],{"title":410,"path":411,"stem":412,"icon":81},"Data Connector API","\u002Fen\u002Freference\u002Fextensions\u002Fdata-connectors\u002Fapi","en\u002F6.reference\u002F9.extensions\u002F4.data-connectors\u002F1.api",{"title":414,"path":415,"stem":416,"icon":176},"Operations and Operators","\u002Fen\u002Freference\u002Fextensions\u002Fdata-connectors\u002Foperations","en\u002F6.reference\u002F9.extensions\u002F4.data-connectors\u002F2.operations",{"title":148,"path":418,"stem":419,"icon":420},"\u002Fen\u002Freference\u002Fextensions\u002Fdata-connectors\u002Ferrors","en\u002F6.reference\u002F9.extensions\u002F4.data-connectors\u002F3.errors","i-lucide-triangle-alert",{"title":422,"path":423,"stem":424,"icon":425},"Runtime Limits","\u002Fen\u002Freference\u002Fextensions\u002Fdata-connectors\u002Flimits","en\u002F6.reference\u002F9.extensions\u002F4.data-connectors\u002F4.limits","i-lucide-gauge",{"title":427,"path":428,"stem":429,"icon":430},"Limitations","\u002Fen\u002Freference\u002Fextensions\u002Fdata-connectors\u002Flimitations","en\u002F6.reference\u002F9.extensions\u002F4.data-connectors\u002F5.limitations","i-lucide-ban",{"title":432,"path":433,"stem":434,"icon":435},"Network Permissions","\u002Fen\u002Freference\u002Fextensions\u002Fdata-connectors\u002Fpermissions","en\u002F6.reference\u002F9.extensions\u002F4.data-connectors\u002F6.permissions","i-lucide-shield-check",{"title":437,"icon":121,"path":438,"stem":439,"children":440,"page":6},"Release Notes","\u002Fen\u002Frelease-notes","en\u002F7.release-notes",[441],{"title":442,"path":443,"stem":444,"icon":121},"Changelog","\u002Fen\u002Frelease-notes\u002Fchangelog","en\u002F7.release-notes\u002F1.changelog",{"id":446,"title":113,"body":447,"description":1960,"extension":1961,"links":1962,"meta":1963,"navigation":1964,"path":232,"seo":1965,"stem":233,"__hash__":1966},"docs_en\u002Fen\u002F5.developer\u002F3.extensions\u002F2.data-connectors\u002Findex.md",{"type":448,"value":449,"toc":1944},"minimark",[450,453,457,466,489,496,500,508,583,587,590,691,695,703,706,955,962,1495,1563,1581,1585,1612,1615,1690,1701,1705,1708,1863,1866,1870,1873,1880,1884,1887,1940],[451,452],"preview",{},[454,455,143],"h2",{"id":456},"overview",[458,459,460,461,465],"p",{},"A data connector extension teaches Monospace to work with a system it has no built-in connector for: a SaaS API, an internal service, or a database without a native connector. These docs call that system the ",[462,463,464],"strong",{},"external data source",".",[458,467,468,469,472,473,478,479,483,484,488],{},"Think of a data connector as a translator. Callers ask Monospace for the ",[462,470,471],{},"items"," (single data objects) in ",[474,475,477],"a",{"href":476},"\u002Fconcepts\u002Fdata-model#collections","collections"," of a ",[474,480,482],{"href":481},"\u002Fconcepts\u002Forganization#glossary","workspace",", through the REST API, the SDK, or Studio. Each item carries named values called ",[474,485,487],{"href":486},"\u002Fconcepts\u002Fdata-model#fields","fields",". Monospace hands each question to your connector in a structured form. Your connector answers it by calling the external data source, and Monospace returns the result like any other collection's.",[458,490,491,492,495],{},"You make a connector available to a workspace by creating a ",[462,493,494],{},"data source",": the connector plus its configuration (e.g., an API key) and the hosts it's allowed to reach.",[454,497,499],{"id":498},"live-queries-not-sync","Live Queries, Not Sync",[458,501,502,503,507],{},"A data connector doesn't import anything. Monospace never syncs or replicates external data. Query results are ",[474,504,506],{"href":505},"\u002Fconcepts\u002Fcaching","cached"," like any data source's. Engine translates each request the cache doesn't answer into calls to the connector, and the connector makes the requests to the external data source that each call needs.",[509,510,511,524],"table",{},[512,513,514],"thead",{},[515,516,517,521],"tr",{},[518,519,520],"th",{},"Consequence",[518,522,523],{},"What it means for you",[525,526,527,546,559,567,575],"tbody",{},[515,528,529,533],{},[530,531,532],"td",{},"Freshness",[530,534,535,536,540,541,545],{},"A cached result is served until it expires (5 minutes by default) or a write through Monospace invalidates it. Changes made directly in the external data source appear after the cache entry expires, or immediately with a ",[474,537,539],{"href":538},"\u002Fconcepts\u002Fcaching#bypass-caching","cache bypass",". See ",[474,542,544],{"href":543},"\u002Fconcepts\u002Fcaching#limitations","Caching Limitations"," for the edge cases",[515,547,548,551],{},[530,549,550],{},"Load on the external data source",[530,552,553,554,558],{},"Uncached reads cost requests to it. A total count can add a separate count read, and including a to-many relation, which returns several related items, adds ",[474,555,557],{"href":556},"\u002Freference\u002Fextensions\u002Fdata-connectors\u002Fapi#relation-reads","one read per parent item"," by default",[515,560,561,564],{},[530,562,563],{},"Rate limits",[530,565,566],{},"Monospace traffic counts against the external data source's rate limits and quotas. Engine doesn't retry: when it throttles and the connector doesn't retry, the request fails",[515,568,569,572],{},[530,570,571],{},"Availability",[530,573,574],{},"When the external data source is down, requests that need it fail unless the cache answers them",[515,576,577,580],{},[530,578,579],{},"Query power",[530,581,582],{},"Callers can ask a collection only for what the connector declares. The connector can answer more than the external data source supports natively (e.g., by filtering fetched items itself), at the cost of extra reads",[454,584,586],{"id":585},"how-a-request-flows","How a Request Flows",[458,588,589],{},"A read against a connector collection passes through Engine before it reaches your code.",[591,592,593,598,624,628,661,665,684,688],"steps",{},[594,595,597],"h3",{"id":596},"engine-checks-the-request","Engine Checks the Request",[458,599,600,601,605,606,609,610,613,614,616,617,619,620,465],{},"Engine authenticates the caller, applies their permissions, and checks the request against the collection's declared operations. A request outside the declaration fails with a validation error before the connector sees it. A few caller operators are derived rather than declared (e.g., ",[602,603,604],"code",{},"_neq"," arrives as ",[602,607,608],{},"not"," around ",[602,611,612],{},"equals",", and Engine offers it only where the filter declares ",[602,615,612],{}," and ",[602,618,608],{},"). See ",[474,621,623],{"href":622},"\u002Freference\u002Fextensions\u002Fdata-connectors\u002Foperations#map-caller-operators-to-the-wire","Map Caller Operators to the Wire",[594,625,627],{"id":626},"engine-sends-an-operation","Engine Sends an Operation",[458,629,630,631,634,635,638,639,642,643,645,646,649,650,653,654,656,657,465],{},"Each call to the connector carries one operation (e.g., ",[602,632,633],{},"readMany"," with a filter, sort, ",[602,636,637],{},"limit",", and ",[602,640,641],{},"offset","). One caller request can produce several calls. Engine adds shapes of its own: a default ",[602,644,637],{}," (100 unless the ",[462,647,648],{},"instance",", your Monospace deployment, changes it), the caller's permission rules as filters, count reads, and extra reads to resolve relations. Several filtered permission rules arrive joined by ",[602,651,652],{},"or",", and a field-level update rule can arrive wrapped in ",[602,655,608],{},", even when the collection declares neither. Engine doesn't check the filters it sends against the called operation's declaration, so a permission rule's condition can also compare a field the operation doesn't declare. The connector refuses what it can't answer. See ",[474,658,660],{"href":659},"\u002Freference\u002Fextensions\u002Fdata-connectors\u002Fapi#handle-requests-you-didnt-declare","Handle Requests You Didn't Declare",[594,662,664],{"id":663},"connector-calls-the-external-data-source","Connector Calls the External Data Source",[458,666,667,668,671,672,675,676,679,680,683],{},"The connector's ",[602,669,670],{},"query"," handler maps the operation to requests to the external data source, pages through its results as needed, and returns exactly the matching items. An operation on one item by its key answers ",[602,673,674],{},"{ record: \u003Citem> }",", or ",[602,677,678],{},"{ record: null }"," when there's none. Each item carries every field the operation selects, with an explicit ",[602,681,682],{},"null"," for a missing value; an item without a selected field fails the request. Engine doesn't check the returned items against the filter or the sort, so the connector alone is responsible for returning exactly the items the operation asks for.",[594,685,687],{"id":686},"engine-answers-the-caller","Engine Answers the Caller",[458,689,690],{},"Engine combines the connector's items with related data, shapes the response, and returns it.",[454,692,694],{"id":693},"what-you-build","What You Build",[458,696,697,698,702],{},"A data connector extension has two parts you write: an extension config and a connector module. The module can import other source files of yours; the build bundles them. The examples below come from the ",[474,699,701],{"href":700},"\u002Fguides\u002Fdata-connectors\u002Fquickstart","Data Connector Quickstart",", which reads the Art Institute of Chicago API.",[458,704,705],{},"The extension config names the extension and its one entry, and declares the one host the connector may reach:",[707,708,714],"pre",{"className":709,"code":710,"filename":711,"language":712,"meta":713,"style":713},"language-json shiki shiki-themes monospace-light monospace-light monospace-dark","{\n    \"$schema\": \".\u002Fnode_modules\u002F@monospace\u002Fcli\u002Fschemas\u002Fextension.config.schema.json\",\n    \"entries\": [\n        {\n            \"engine\": {\n                \"entrypoint\": \".\u002Fsrc\u002Fdata-connectors\u002Fartic\u002Findex.ts\",\n                \"permissions\": [\n                    { \"permission\": \"net:api.artic.edu\", \"reason\": \"Read artworks and artists from the Art Institute of Chicago API\" }\n                ]\n            },\n            \"icon\": \"lucide:landmark\",\n            \"id\": \"example\u002Fartic-connector\",\n            \"name\": \"Art Institute of Chicago\",\n            \"type\": \"dataConnector\",\n            \"version\": \"0.1.0\"\n        }\n    ],\n    \"icon\": \"lucide:landmark\",\n    \"id\": \"example\u002Fartic\",\n    \"name\": \"Art Institute of Chicago\",\n    \"version\": \"0.1.0\"\n}\n","extension.config.json","json","",[602,715,716,725,742,751,757,766,779,787,815,821,827,840,853,866,879,890,896,902,914,927,939,949],{"__ignoreMap":713},[717,718,721],"span",{"class":719,"line":720},"line",1,[717,722,724],{"class":723},"sTMul","{\n",[717,726,728,732,735,739],{"class":719,"line":727},2,[717,729,731],{"class":730},"snHjA","    \"$schema\"",[717,733,734],{"class":723},": ",[717,736,738],{"class":737},"suKVh","\".\u002Fnode_modules\u002F@monospace\u002Fcli\u002Fschemas\u002Fextension.config.schema.json\"",[717,740,741],{"class":723},",\n",[717,743,745,748],{"class":719,"line":744},3,[717,746,747],{"class":730},"    \"entries\"",[717,749,750],{"class":723},": [\n",[717,752,754],{"class":719,"line":753},4,[717,755,756],{"class":723},"        {\n",[717,758,760,763],{"class":719,"line":759},5,[717,761,762],{"class":730},"            \"engine\"",[717,764,765],{"class":723},": {\n",[717,767,769,772,774,777],{"class":719,"line":768},6,[717,770,771],{"class":730},"                \"entrypoint\"",[717,773,734],{"class":723},[717,775,776],{"class":737},"\".\u002Fsrc\u002Fdata-connectors\u002Fartic\u002Findex.ts\"",[717,778,741],{"class":723},[717,780,782,785],{"class":719,"line":781},7,[717,783,784],{"class":730},"                \"permissions\"",[717,786,750],{"class":723},[717,788,790,793,796,798,801,804,807,809,812],{"class":719,"line":789},8,[717,791,792],{"class":723},"                    { ",[717,794,795],{"class":730},"\"permission\"",[717,797,734],{"class":723},[717,799,800],{"class":737},"\"net:api.artic.edu\"",[717,802,803],{"class":723},", ",[717,805,806],{"class":730},"\"reason\"",[717,808,734],{"class":723},[717,810,811],{"class":737},"\"Read artworks and artists from the Art Institute of Chicago API\"",[717,813,814],{"class":723}," }\n",[717,816,818],{"class":719,"line":817},9,[717,819,820],{"class":723},"                ]\n",[717,822,824],{"class":719,"line":823},10,[717,825,826],{"class":723},"            },\n",[717,828,830,833,835,838],{"class":719,"line":829},11,[717,831,832],{"class":730},"            \"icon\"",[717,834,734],{"class":723},[717,836,837],{"class":737},"\"lucide:landmark\"",[717,839,741],{"class":723},[717,841,843,846,848,851],{"class":719,"line":842},12,[717,844,845],{"class":730},"            \"id\"",[717,847,734],{"class":723},[717,849,850],{"class":737},"\"example\u002Fartic-connector\"",[717,852,741],{"class":723},[717,854,856,859,861,864],{"class":719,"line":855},13,[717,857,858],{"class":730},"            \"name\"",[717,860,734],{"class":723},[717,862,863],{"class":737},"\"Art Institute of Chicago\"",[717,865,741],{"class":723},[717,867,869,872,874,877],{"class":719,"line":868},14,[717,870,871],{"class":730},"            \"type\"",[717,873,734],{"class":723},[717,875,876],{"class":737},"\"dataConnector\"",[717,878,741],{"class":723},[717,880,882,885,887],{"class":719,"line":881},15,[717,883,884],{"class":730},"            \"version\"",[717,886,734],{"class":723},[717,888,889],{"class":737},"\"0.1.0\"\n",[717,891,893],{"class":719,"line":892},16,[717,894,895],{"class":723},"        }\n",[717,897,899],{"class":719,"line":898},17,[717,900,901],{"class":723},"    ],\n",[717,903,905,908,910,912],{"class":719,"line":904},18,[717,906,907],{"class":730},"    \"icon\"",[717,909,734],{"class":723},[717,911,837],{"class":737},[717,913,741],{"class":723},[717,915,917,920,922,925],{"class":719,"line":916},19,[717,918,919],{"class":730},"    \"id\"",[717,921,734],{"class":723},[717,923,924],{"class":737},"\"example\u002Fartic\"",[717,926,741],{"class":723},[717,928,930,933,935,937],{"class":719,"line":929},20,[717,931,932],{"class":730},"    \"name\"",[717,934,734],{"class":723},[717,936,863],{"class":737},[717,938,741],{"class":723},[717,940,942,945,947],{"class":719,"line":941},21,[717,943,944],{"class":730},"    \"version\"",[717,946,734],{"class":723},[717,948,889],{"class":737},[717,950,952],{"class":719,"line":951},22,[717,953,954],{"class":723},"}\n",[458,956,957,958,961],{},"The entry's code is the connector module. Its default export is the connector. It imports the schema, the function that calls the Art Institute API, and the read handlers from sibling files, which the ",[474,959,701],{"href":960},"\u002Fguides\u002Fdata-connectors\u002Fquickstart#step-declare-artworks"," builds one by one:",[707,963,968],{"className":964,"code":965,"filename":966,"language":967,"meta":713,"style":713},"language-ts shiki shiki-themes monospace-light monospace-light monospace-dark","import { defineDataConnector } from '@monospace\u002Fextension-kit\u002Fdata-connector';\nimport { search } from '.\u002Fapi';\nimport { readMany, readOne } from '.\u002Fread';\nimport { schema } from '.\u002Fschema';\n\nconst COLLECTIONS = new Set\u003Cstring>(schema.collections.map((collection) => collection.name));\n\nexport default defineDataConnector({\n    setup() {\n        return {\n            introspect() {\n                return schema.toSchemaDocument();\n            },\n\n            async query({ query }) {\n                \u002F\u002F Monospace sends only declared collections, and this connector declares no namespaces.\n                \u002F\u002F For any other collection, throw a plain `Error`.\n                if (query.namespace !== undefined || !COLLECTIONS.has(query.collection)) {\n                    throw new Error(`Unknown collection \\`${query.collection}\\`.`);\n                }\n\n                switch (query.op) {\n                    case 'readMany':\n                        return await readMany(query);\n                    case 'readOne':\n                        return await readOne(query);\n                    default:\n                        \u002F\u002F The schema declares no writes, so Monospace offers callers none.\n                        throw new Error('The Art Institute of Chicago API is read-only.');\n                }\n            },\n\n            async testConnection() {\n                await search('artworks', { size: 0 });\n                return { ok: true };\n            },\n        };\n    },\n});\n","src\u002Fdata-connectors\u002Fartic\u002Findex.ts","ts",[602,969,970,995,1013,1035,1053,1059,1120,1124,1138,1146,1154,1161,1177,1181,1185,1201,1207,1212,1259,1297,1302,1306,1323,1335,1353,1363,1379,1387,1393,1410,1415,1420,1425,1435,1458,1472,1477,1483,1489],{"__ignoreMap":713},[717,971,972,976,979,983,986,989,992],{"class":719,"line":720},[717,973,975],{"class":974},"sLVBU","import",[717,977,978],{"class":723}," { ",[717,980,982],{"class":981},"sNJ9c","defineDataConnector",[717,984,985],{"class":723}," } ",[717,987,988],{"class":974},"from",[717,990,991],{"class":737}," '@monospace\u002Fextension-kit\u002Fdata-connector'",[717,993,994],{"class":723},";\n",[717,996,997,999,1001,1004,1006,1008,1011],{"class":719,"line":727},[717,998,975],{"class":974},[717,1000,978],{"class":723},[717,1002,1003],{"class":981},"search",[717,1005,985],{"class":723},[717,1007,988],{"class":974},[717,1009,1010],{"class":737}," '.\u002Fapi'",[717,1012,994],{"class":723},[717,1014,1015,1017,1019,1021,1023,1026,1028,1030,1033],{"class":719,"line":744},[717,1016,975],{"class":974},[717,1018,978],{"class":723},[717,1020,633],{"class":981},[717,1022,803],{"class":723},[717,1024,1025],{"class":981},"readOne",[717,1027,985],{"class":723},[717,1029,988],{"class":974},[717,1031,1032],{"class":737}," '.\u002Fread'",[717,1034,994],{"class":723},[717,1036,1037,1039,1041,1044,1046,1048,1051],{"class":719,"line":753},[717,1038,975],{"class":974},[717,1040,978],{"class":723},[717,1042,1043],{"class":981},"schema",[717,1045,985],{"class":723},[717,1047,988],{"class":974},[717,1049,1050],{"class":737}," '.\u002Fschema'",[717,1052,994],{"class":723},[717,1054,1055],{"class":719,"line":759},[717,1056,1058],{"emptyLinePlaceholder":1057},true,"\n",[717,1060,1061,1064,1068,1071,1074,1077,1080,1083,1086,1088,1090,1092,1094,1097,1100,1103,1106,1109,1112,1114,1117],{"class":719,"line":768},[717,1062,1063],{"class":974},"const",[717,1065,1067],{"class":1066},"ssBNi"," COLLECTIONS",[717,1069,1070],{"class":974}," =",[717,1072,1073],{"class":974}," new",[717,1075,1076],{"class":1066}," Set",[717,1078,1079],{"class":723},"\u003C",[717,1081,1082],{"class":730},"string",[717,1084,1085],{"class":723},">(",[717,1087,1043],{"class":981},[717,1089,465],{"class":723},[717,1091,477],{"class":981},[717,1093,465],{"class":723},[717,1095,1096],{"class":1066},"map",[717,1098,1099],{"class":723},"((",[717,1101,1102],{"class":974},"collection",[717,1104,1105],{"class":723},") ",[717,1107,1108],{"class":974},"=>",[717,1110,1111],{"class":981}," collection",[717,1113,465],{"class":723},[717,1115,1116],{"class":981},"name",[717,1118,1119],{"class":723},"));\n",[717,1121,1122],{"class":719,"line":781},[717,1123,1058],{"emptyLinePlaceholder":1057},[717,1125,1126,1129,1132,1135],{"class":719,"line":789},[717,1127,1128],{"class":974},"export",[717,1130,1131],{"class":974}," default",[717,1133,1134],{"class":1066}," defineDataConnector",[717,1136,1137],{"class":723},"({\n",[717,1139,1140,1143],{"class":719,"line":817},[717,1141,1142],{"class":1066},"    setup",[717,1144,1145],{"class":723},"() {\n",[717,1147,1148,1151],{"class":719,"line":823},[717,1149,1150],{"class":974},"        return",[717,1152,1153],{"class":723}," {\n",[717,1155,1156,1159],{"class":719,"line":829},[717,1157,1158],{"class":1066},"            introspect",[717,1160,1145],{"class":723},[717,1162,1163,1166,1169,1171,1174],{"class":719,"line":842},[717,1164,1165],{"class":974},"                return",[717,1167,1168],{"class":981}," schema",[717,1170,465],{"class":723},[717,1172,1173],{"class":1066},"toSchemaDocument",[717,1175,1176],{"class":723},"();\n",[717,1178,1179],{"class":719,"line":855},[717,1180,826],{"class":723},[717,1182,1183],{"class":719,"line":868},[717,1184,1058],{"emptyLinePlaceholder":1057},[717,1186,1187,1190,1193,1196,1198],{"class":719,"line":881},[717,1188,1189],{"class":974},"            async",[717,1191,1192],{"class":1066}," query",[717,1194,1195],{"class":723},"({ ",[717,1197,670],{"class":974},[717,1199,1200],{"class":723}," }) {\n",[717,1202,1203],{"class":719,"line":892},[717,1204,1206],{"class":1205},"seNfP","                \u002F\u002F Monospace sends only declared collections, and this connector declares no namespaces.\n",[717,1208,1209],{"class":719,"line":898},[717,1210,1211],{"class":1205},"                \u002F\u002F For any other collection, throw a plain `Error`.\n",[717,1213,1214,1217,1220,1222,1224,1227,1230,1233,1236,1239,1242,1244,1247,1250,1252,1254,1256],{"class":719,"line":904},[717,1215,1216],{"class":974},"                if",[717,1218,1219],{"class":723}," (",[717,1221,670],{"class":981},[717,1223,465],{"class":723},[717,1225,1226],{"class":981},"namespace",[717,1228,1229],{"class":974}," !==",[717,1231,1232],{"class":1066}," undefined",[717,1234,1235],{"class":974}," ||",[717,1237,1238],{"class":974}," !",[717,1240,1241],{"class":1066},"COLLECTIONS",[717,1243,465],{"class":723},[717,1245,1246],{"class":1066},"has",[717,1248,1249],{"class":723},"(",[717,1251,670],{"class":981},[717,1253,465],{"class":723},[717,1255,1102],{"class":981},[717,1257,1258],{"class":723},")) {\n",[717,1260,1261,1264,1266,1269,1271,1274,1277,1280,1282,1284,1286,1289,1291,1294],{"class":719,"line":916},[717,1262,1263],{"class":974},"                    throw",[717,1265,1073],{"class":974},[717,1267,1268],{"class":1066}," Error",[717,1270,1249],{"class":723},[717,1272,1273],{"class":737},"`Unknown collection ",[717,1275,1276],{"class":1066},"\\`",[717,1278,1279],{"class":737},"${",[717,1281,670],{"class":981},[717,1283,465],{"class":737},[717,1285,1102],{"class":981},[717,1287,1288],{"class":737},"}",[717,1290,1276],{"class":1066},[717,1292,1293],{"class":737},".`",[717,1295,1296],{"class":723},");\n",[717,1298,1299],{"class":719,"line":929},[717,1300,1301],{"class":723},"                }\n",[717,1303,1304],{"class":719,"line":941},[717,1305,1058],{"emptyLinePlaceholder":1057},[717,1307,1308,1311,1313,1315,1317,1320],{"class":719,"line":951},[717,1309,1310],{"class":974},"                switch",[717,1312,1219],{"class":723},[717,1314,670],{"class":981},[717,1316,465],{"class":723},[717,1318,1319],{"class":981},"op",[717,1321,1322],{"class":723},") {\n",[717,1324,1326,1329,1332],{"class":719,"line":1325},23,[717,1327,1328],{"class":974},"                    case",[717,1330,1331],{"class":737}," 'readMany'",[717,1333,1334],{"class":723},":\n",[717,1336,1338,1341,1344,1347,1349,1351],{"class":719,"line":1337},24,[717,1339,1340],{"class":974},"                        return",[717,1342,1343],{"class":974}," await",[717,1345,1346],{"class":1066}," readMany",[717,1348,1249],{"class":723},[717,1350,670],{"class":981},[717,1352,1296],{"class":723},[717,1354,1356,1358,1361],{"class":719,"line":1355},25,[717,1357,1328],{"class":974},[717,1359,1360],{"class":737}," 'readOne'",[717,1362,1334],{"class":723},[717,1364,1366,1368,1370,1373,1375,1377],{"class":719,"line":1365},26,[717,1367,1340],{"class":974},[717,1369,1343],{"class":974},[717,1371,1372],{"class":1066}," readOne",[717,1374,1249],{"class":723},[717,1376,670],{"class":981},[717,1378,1296],{"class":723},[717,1380,1382,1385],{"class":719,"line":1381},27,[717,1383,1384],{"class":974},"                    default",[717,1386,1334],{"class":723},[717,1388,1390],{"class":719,"line":1389},28,[717,1391,1392],{"class":1205},"                        \u002F\u002F The schema declares no writes, so Monospace offers callers none.\n",[717,1394,1396,1399,1401,1403,1405,1408],{"class":719,"line":1395},29,[717,1397,1398],{"class":974},"                        throw",[717,1400,1073],{"class":974},[717,1402,1268],{"class":1066},[717,1404,1249],{"class":723},[717,1406,1407],{"class":737},"'The Art Institute of Chicago API is read-only.'",[717,1409,1296],{"class":723},[717,1411,1413],{"class":719,"line":1412},30,[717,1414,1301],{"class":723},[717,1416,1418],{"class":719,"line":1417},31,[717,1419,826],{"class":723},[717,1421,1423],{"class":719,"line":1422},32,[717,1424,1058],{"emptyLinePlaceholder":1057},[717,1426,1428,1430,1433],{"class":719,"line":1427},33,[717,1429,1189],{"class":974},[717,1431,1432],{"class":1066}," testConnection",[717,1434,1145],{"class":723},[717,1436,1438,1441,1444,1446,1449,1452,1455],{"class":719,"line":1437},34,[717,1439,1440],{"class":974},"                await",[717,1442,1443],{"class":1066}," search",[717,1445,1249],{"class":723},[717,1447,1448],{"class":737},"'artworks'",[717,1450,1451],{"class":723},", { size: ",[717,1453,1454],{"class":1066},"0",[717,1456,1457],{"class":723}," });\n",[717,1459,1461,1463,1466,1469],{"class":719,"line":1460},35,[717,1462,1165],{"class":974},[717,1464,1465],{"class":723}," { ok: ",[717,1467,1468],{"class":1066},"true",[717,1470,1471],{"class":723}," };\n",[717,1473,1475],{"class":719,"line":1474},36,[717,1476,826],{"class":723},[717,1478,1480],{"class":719,"line":1479},37,[717,1481,1482],{"class":723},"        };\n",[717,1484,1486],{"class":719,"line":1485},38,[717,1487,1488],{"class":723},"    },\n",[717,1490,1492],{"class":719,"line":1491},39,[717,1493,1494],{"class":723},"});\n",[509,1496,1497,1507],{},[512,1498,1499],{},[515,1500,1501,1504],{},[518,1502,1503],{},"Part",[518,1505,1506],{},"Role",[525,1508,1509,1519,1529,1543,1553],{},[515,1510,1511,1516],{},[530,1512,1513],{},[602,1514,1515],{},"setup",[530,1517,1518],{},"Runs when a data source starts. Receives the data source's configuration and returns the handlers",[515,1520,1521,1526],{},[530,1522,1523],{},[602,1524,1525],{},"introspect",[530,1527,1528],{},"Returns the schema: the collections, their fields, and the operations each collection accepts",[515,1530,1531,1535],{},[530,1532,1533],{},[602,1534,670],{},[530,1536,1537,1538,803,1540,1542],{},"Receives one operation per call (e.g., ",[602,1539,633],{},[602,1541,1025],{},") and answers it by calling the external data source. Calls can run concurrently",[515,1544,1545,1550],{},[530,1546,1547],{},[602,1548,1549],{},"testConnection",[530,1551,1552],{},"Optional. Checks that the external data source is reachable. Engine runs it on a connection test, and before it creates a data source or previews its schema. Without it, a connection test fails as unsupported",[515,1554,1555,1560],{},[530,1556,1557],{},[602,1558,1559],{},"permissions",[530,1561,1562],{},"The hosts this data connector may reach. Any other network request from its code fails",[458,1564,1565,1566,1569,1570,1572,1573,1577,1578,1580],{},"The ",[602,1567,1568],{},"monospace"," CLI builds these into a manifest and one self-contained JavaScript file, and you place the output in your instance's install location. You then create a ",[462,1571,494],{}," (the connector configured in a workspace), approve its ",[474,1574,1576],{"href":1575},"\u002Freference\u002Fextensions\u002Fdata-connectors\u002Fpermissions#approve-permissions","network permissions",", and query its collections like any other. The ",[474,1579,701],{"href":700}," walks through each step.",[454,1582,1584],{"id":1583},"operations-contract","Operations Contract",[458,1586,1587,1588,1591,1592,803,1594,803,1596,803,1599,803,1602,803,1605,638,1608,1611],{},"Each collection a connector exposes declares its ",[462,1589,1590],{},"operations",": which of ",[602,1593,633],{},[602,1595,1025],{},[602,1597,1598],{},"create",[602,1600,1601],{},"updateMany",[602,1603,1604],{},"updateOne",[602,1606,1607],{},"deleteMany",[602,1609,1610],{},"deleteOne"," it serves, and which filters, sorts, and fields each one accepts.",[458,1613,1614],{},"The declaration is a promise that gates callers. Engine builds the API schema, the OpenAPI document, and Studio's controls from it.",[509,1616,1617,1627],{},[512,1618,1619],{},[515,1620,1621,1624],{},[518,1622,1623],{},"Declaration",[518,1625,1626],{},"Effect",[525,1628,1629,1659,1682],{},[515,1630,1631,1634],{},[530,1632,1633],{},"You declare less than the external data source supports",[530,1635,1636,1637,1639,1640,1644,1645,1648,1649,675,1652,1648,1654,616,1656,1658],{},"Studio hides the control, and the API rejects the request. Engine still needs some declarations for its own calls: an update on a collection with a stable ID needs ",[602,1638,633],{}," to carry its read-backs, a connector without ",[474,1641,1643],{"href":1642},"\u002Freference\u002Fextensions\u002Fmanifest#capabilities","query capabilities"," needs more for its writes, and a relation needs the target to declare a filter on its key (",[602,1646,1647],{},"in"," joined by ",[602,1650,1651],{},"and",[602,1653,612],{},[602,1655,1651],{},[602,1657,652],{},"), unless the key's type can't declare one. Without them, data source creation fails, or the relation isn't offered and Engine logs \"The engine offers less than the collection declares.\"",[515,1660,1661,1664],{},[530,1662,1663],{},"You declare exactly what the external data source supports",[530,1665,1666,1667,1669,1670,1672,1673,1675,1676,1678,1679,1681],{},"Callers can still send requests the contract can't restrict, such as an unfiltered read or a large ",[602,1668,637],{},". An instance-wide maximum ",[602,1671,637],{},", when set, bounds only a ",[602,1674,637],{}," the caller sends. The default ",[602,1677,637],{}," isn't checked against it, and Engine's own relation reads can arrive without ",[602,1680,637],{},". The connector refuses or pages through those at runtime",[515,1683,1684,1687],{},[530,1685,1686],{},"You declare more than the external data source supports",[530,1688,1689],{},"Callers send requests the connector must refuse at runtime, or answer by scanning external data",[458,1691,1692,1693,1696,1697,465],{},"Declare only what the external data source answers efficiently and correctly. See ",[474,1694,414],{"href":1695},"\u002Freference\u002Fextensions\u002Fdata-connectors\u002Foperations"," for the declaration format and the rules Engine enforces, including ",[474,1698,1700],{"href":1699},"\u002Freference\u002Fextensions\u002Fdata-connectors\u002Foperations#rules-for-engines-own-calls","Rules for Engine's Own Calls",[454,1702,1704],{"id":1703},"fit-check","Fit Check",[458,1706,1707],{},"Answer these questions about your external data source before you build. Each \"yes\" points to a limitation to design around.",[509,1709,1710,1720],{},[512,1711,1712],{},[515,1713,1714,1717],{},[518,1715,1716],{},"Question",[518,1718,1719],{},"If yes",[525,1721,1722,1734,1754,1772,1784,1800,1827,1839,1851],{},[515,1723,1724,1727],{},[530,1725,1726],{},"Can some collections only be listed when scoped by a parent or a filter (e.g., a channel, a customer, a date range)?",[530,1728,1729,1730],{},"A connector can't declare a required filter. It refuses unscoped reads at runtime. See ",[474,1731,1733],{"href":1732},"\u002Freference\u002Fextensions\u002Fdata-connectors\u002Flimitations#required-filters","Required Filters",[515,1735,1736,1739],{},[530,1737,1738],{},"Is paging cursor-only, or does the external data source stop at a maximum depth?",[530,1740,1741,1742,616,1744,1746,1747,1749,1750],{},"Callers page by ",[602,1743,637],{},[602,1745,641],{},". On a cursor-only source the connector walks pages and discards items up to ",[602,1748,641],{},". Past a maximum depth it refuses. See ",[474,1751,1753],{"href":1752},"\u002Freference\u002Fextensions\u002Fdata-connectors\u002Flimitations#paging","Paging",[515,1755,1756,1759],{},[530,1757,1758],{},"Do callers need aggregates, grouping, full-text search, or vector search?",[530,1760,1761,1762,540,1768],{},"The query API has none of these yet; its only aggregate is a total count. Keep up with what's coming on our ",[474,1763,1767],{"href":1764,"rel":1765},"https:\u002F\u002Ffeedback.monospace.io",[1766],"nofollow","Roadmap",[474,1769,1771],{"href":1770},"\u002Freference\u002Fextensions\u002Fdata-connectors\u002Flimitations#query-shapes","Query Shapes",[515,1773,1774,1777],{},[530,1775,1776],{},"Are items keyed by more than one field?",[530,1778,1779,1780],{},"Single-item operations need a single-field primary key. See ",[474,1781,1783],{"href":1782},"\u002Freference\u002Fextensions\u002Fdata-connectors\u002Flimitations#keys","Keys",[515,1785,1786,1789],{},[530,1787,1788],{},"Do references point at things that may not exist in the external data source (e.g., external phone numbers, deleted objects)?",[530,1790,1791,1792,1795,1796],{},"Engine doesn't check that a ",[602,1793,1794],{},"_connect"," target exists when the key sits on the written item, so the external data source decides whether to accept it. See ",[474,1797,1799],{"href":1798},"\u002Freference\u002Fextensions\u002Fdata-connectors\u002Flimitations#relations","Relations",[515,1801,1802,1805],{},[530,1803,1804],{},"Does a write to the external data source answer without the written object?",[530,1806,1807,1808,1811,1812,1814,1815,616,1817,1819,1820,1822,1823],{},"Leave that write's ",[474,1809,1810],{"href":1642},"query capability"," undeclared. Engine then makes extra calls by stable ID: it asks ",[602,1813,1598],{}," for the stable ID only and reads the created items back, and it sends updates and deletes through ",[602,1816,1601],{},[602,1818,1607],{},". ",[602,1821,1598],{}," must still answer with each created item's stable ID. A collection with such a write needs a primary or unique index and declarations that carry those calls. See ",[474,1824,1826],{"href":1825},"\u002Freference\u002Fextensions\u002Fdata-connectors\u002Foperations#declare-query-capabilities","Declare Query Capabilities",[515,1828,1829,1832],{},[530,1830,1831],{},"Must several writes succeed or fail together?",[530,1833,1834,1835],{},"Engine runs no transaction across connector writes, so a failure partway leaves earlier writes applied. See ",[474,1836,1838],{"href":1837},"\u002Freference\u002Fextensions\u002Fdata-connectors\u002Flimitations#writes","Writes",[515,1840,1841,1844],{},[530,1842,1843],{},"Will credentials, hosts, or permissions change after the data source is created?",[530,1845,1846,1847],{},"Configuration and permissions are fixed at creation. Once a connector version that changes its required permissions is loaded, every request that reaches an existing data source's connector fails. Cached results are still served. We're working on letting you change a data source's configuration after it's created. See ",[474,1848,1850],{"href":1849},"\u002Freference\u002Fextensions\u002Fdata-connectors\u002Flimitations#configuration-and-network","Configuration and Network",[515,1852,1853,1856],{},[530,1854,1855],{},"Does the external data source's schema change often?",[530,1857,1858,1859],{},"Data sources keep the schema from creation until you reintrospect. See ",[474,1860,1862],{"href":1861},"\u002Freference\u002Fextensions\u002Fdata-connectors\u002Flimitations#lifecycle","Lifecycle",[458,1864,1865],{},"A few \"yes\" answers are normal for SaaS APIs. Many \"yes\" answers on the collections you need most mean the external data source is a poor fit.",[594,1867,1869],{"id":1868},"built-in-database-connectors","Built-In Database Connectors",[458,1871,1872],{},"If the external data source is a PostgreSQL, Supabase, MySQL, or MariaDB database, use a built-in database connector instead of an extension. Built-in connectors introspect the database directly and support capabilities data connector extensions don't have, including filters across relations and transactions.",[458,1874,1875,1876,1879],{},"See ",[474,1877,280],{"href":1878},"\u002Freference\u002Fconnectors"," for the supported databases.",[454,1881,1883],{"id":1882},"next-steps","Next Steps",[458,1885,1886],{},"More example connectors are available on request.",[1888,1889,1890,1903,1920,1926,1933],"ul",{},[1891,1892,1893,1895,1896,803,1899,1902],"li",{},[474,1894,701],{"href":700},": build a read-only connector for the Art Institute of Chicago API, with ",[602,1897,1898],{},"artworks",[602,1900,1901],{},"artists",", and a relation between them",[1891,1904,1905,1909,1910,803,1913,638,1916,1919],{},[474,1906,1908],{"href":1907},"\u002Fguides\u002Fdata-connectors\u002Fstripe","Build a Stripe Data Connector",": build a Stripe test-mode connector with ",[602,1911,1912],{},"customers",[602,1914,1915],{},"products",[602,1917,1918],{},"prices",", including writes",[1891,1921,1922,1925],{},[474,1923,246],{"href":1924},"\u002Fdeveloper\u002Fextensions\u002Fdata-connectors\u002Fdata-source-mapping",": translate filters, paging, and keys onto a real external data source",[1891,1927,1928,1932],{},[474,1929,1931],{"href":1930},"\u002Fdeveloper\u002Fextensions\u002Fdata-connectors\u002Fdata-sources","Manage Data Sources",": create, update, and delete the data sources that use a connector",[1891,1934,1935,1939],{},[474,1936,1938],{"href":1937},"\u002Freference\u002Fextensions\u002Fdata-connectors\u002Flimitations","Data Connector Limitations",": every current limitation, with workarounds",[1941,1942,1943],"style",{},"html pre.shiki code .sTMul, html code.shiki .sTMul{--shiki-light:#1F2937;--shiki-default:#1F2937;--shiki-dark:#94A3B8}html pre.shiki code .snHjA, html code.shiki .snHjA{--shiki-light:#124BC4;--shiki-default:#124BC4;--shiki-dark:#5B8EF4}html pre.shiki code .suKVh, html code.shiki .suKVh{--shiki-light:#032F62;--shiki-default:#032F62;--shiki-dark:#F8FAFC}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sLVBU, html code.shiki .sLVBU{--shiki-light:#0891B2;--shiki-default:#0891B2;--shiki-dark:#22D3EE}html pre.shiki code .sNJ9c, html code.shiki .sNJ9c{--shiki-light:#24292E;--shiki-default:#24292E;--shiki-dark:#E2E8F0}html pre.shiki code .ssBNi, html code.shiki .ssBNi{--shiki-light:#1659E9;--shiki-default:#1659E9;--shiki-dark:#94B3F5}html pre.shiki code .seNfP, html code.shiki .seNfP{--shiki-light:#64748B;--shiki-default:#64748B;--shiki-dark:#94A3B8}",{"title":713,"searchDepth":727,"depth":727,"links":1945},[1946,1947,1948,1954,1955,1956,1959],{"id":456,"depth":727,"text":143},{"id":498,"depth":727,"text":499},{"id":585,"depth":727,"text":586,"children":1949},[1950,1951,1952,1953],{"id":596,"depth":744,"text":597},{"id":626,"depth":744,"text":627},{"id":663,"depth":744,"text":664},{"id":686,"depth":744,"text":687},{"id":693,"depth":727,"text":694},{"id":1583,"depth":727,"text":1584},{"id":1703,"depth":727,"text":1704,"children":1957},[1958],{"id":1868,"depth":744,"text":1869},{"id":1882,"depth":727,"text":1883},"Understand how data connector extensions serve live queries, what their operations contract promises, and whether your external data source fits.","md",null,{},{"title":143,"icon":114},{"title":113,"description":1960},"0JCGWQwTYsDmVRdHzTpnwf-JsS7ZHNSLhmy2v8-O-RM",[1968,1970],{"title":227,"path":228,"stem":229,"description":1969,"icon":230,"children":-1},"Learn where a self-hosted instance loads extensions from, and how to install, reload, update, and remove them.",{"title":237,"path":238,"stem":239,"description":1971,"icon":240,"children":-1},"Learn where data connector code runs, what it can use, how it reaches the network, and how data sources start, reload, and restart.",1790840121508]