[{"data":1,"prerenderedAt":9018},["ShallowReactive",2],{"navigation_docs_en":3,"-en-guides-data-connectors-stripe":445,"-en-guides-data-connectors-stripe-surround":9013},[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":447,"body":448,"description":9006,"extension":9007,"links":9008,"meta":9009,"navigation":9010,"path":124,"seo":9011,"stem":125,"__hash__":9012},"docs_en\u002Fen\u002F4.guides\u002F8.data-connectors\u002F2.stripe.md","Build a Stripe Data Connector",{"type":449,"value":450,"toc":8981},"minimark",[451,454,458,496,507,609,627,643,646,650,720,727,738,749,753,756,803,806,994,1001,1159,1172,1185,1189,1192,1314,1332,1335,1659,1686,1692,1706,1836,1845,1848,1921,1930,1949,1953,1960,2048,2063,2089,2108,2113,2133,2144,2785,2834,2846,2849,3071,3082,3087,3129,3133,3136,3888,3948,3965,3987,3991,4001,4345,4354,4397,4408,4411,4608,4615,4633,4640,4644,4650,4654,4660,5188,5243,5247,5271,5277,5613,5717,5723,5727,5737,6200,6217,6230,6234,6245,6248,6251,6273,6300,6312,6320,6329,6336,6668,6681,6817,6832,6836,6850,7250,7310,7319,7631,7639,7643,7650,7998,8031,8034,8103,8115,8128,8483,8499,8502,8512,8578,8581,8588,8599,8603,8648,8652,8659,8783,8800,8803,8882,8897,8900,8934,8943,8947,8977],[452,453],"preview",{},[455,456,143],"h2",{"id":457},"overview",[459,460,461,462,466,467,470,471,476,477,481,482,486,487,491,492,495],"p",{},"This guide builds a ",[463,464,465],"strong",{},"data connector extension"," for Stripe in test mode. The connector exposes the Stripe API, its ",[463,468,469],{},"external data source",", as three ",[472,473,475],"a",{"href":474},"\u002Fconcepts\u002Fdata-model#collections","collections"," in a Monospace ",[472,478,480],{"href":479},"\u002Fconcepts\u002Forganization#glossary","workspace",". Each item in ",[483,484,485],"code",{},"customers"," is one Stripe customer, with ",[472,488,490],{"href":489},"\u002Fconcepts\u002Fdata-model#fields","fields"," such as ",[483,493,494],{},"email",".",[459,497,498,499,502,503,495],{},"Stripe is a harder case than the ",[472,500,16],{"href":501},"\u002Fguides\u002Fdata-connectors\u002Fquickstart","'s Art Institute API: it has no filter language, needs a secret key, and accepts writes. The same patterns serve any external data source with a ",[472,504,506],{"href":505},"\u002Fdeveloper\u002Fextensions\u002Fdata-connectors\u002Fdata-source-mapping#match-the-read-path-to-the-grammar","weak grammar",[508,509,510,530],"table",{},[511,512,513],"thead",{},[514,515,516,520,523],"tr",{},[517,518,519],"th",{},"Collection",[517,521,522],{},"Reads",[517,524,525,526,529],{},"Writes (with ",[483,527,528],{},"enableWrites",")",[531,532,533,557,579],"tbody",{},[514,534,535,540,554],{},[536,537,538],"td",{},[483,539,485],{},[536,541,542,543,546,547,549,550,553],{},"Filter by ",[483,544,545],{},"id",", ",[483,548,494],{}," and ",[483,551,552],{},"created","; newest first",[536,555,556],{},"Create, update, delete",[514,558,559,564,573],{},[536,560,561],{},[483,562,563],{},"products",[536,565,542,566,546,568,549,571,553],{},[483,567,545],{},[483,569,570],{},"active",[483,572,552],{},[536,574,575,576,578],{},"Create (optionally with your own ",[483,577,545],{},"), update, delete",[514,580,581,586,600],{},[536,582,583],{},[483,584,585],{},"prices",[536,587,542,588,546,590,546,593,546,595,549,598,553],{},[483,589,545],{},[483,591,592],{},"productId",[483,594,570],{},[483,596,597],{},"type",[483,599,552],{},[536,601,602,603,549,605,608],{},"Create; update ",[483,604,570],{},[483,606,607],{},"nickname"," only. Stripe can't delete prices",[459,610,611,612,615,616,619,620,623,624,626],{},"A relation links ",[483,613,614],{},"prices.productId"," to ",[483,617,618],{},"products.id",". A price has a to-one ",[483,621,622],{},"product"," field, which returns a single related item, and a product has a to-many ",[483,625,585],{}," field, which returns several.",[628,629,631,639,640,642],"tip",{"title":630},"Download",[463,632,633],{},[472,634,638],{"href":635,"download":636,"external":637},"\u002Fguides\u002Fdata-connectors\u002Fstripe-connector.zip","stripe-connector.zip","","Download the finished project"," (",[483,641,636],{},"): the eleven source files, the unit tests, and the seed and smoke scripts.",[459,644,645],{},"This guide explains the decisions behind those files and shows only the code that carries a Stripe-specific decision.",[455,647,649],{"id":648},"prerequisites","Prerequisites",[508,651,652,662],{},[511,653,654],{},[514,655,656,659],{},[517,657,658],{},"Requirement",[517,660,661],{},"Check",[531,663,664,675,690,700],{},[514,665,666,669],{},[536,667,668],{},"A Stripe test-mode secret key",[536,670,671,672],{},"The key starts with ",[483,673,674],{},"sk_test_",[514,676,677,684],{},[536,678,679,680,683],{},"A self-hosted Monospace ",[463,681,682],{},"instance"," (a running Monospace deployment) whose extensions install location you can write to",[536,685,686,687],{},"See ",[472,688,227],{"href":689},"\u002Fdeveloper\u002Fextensions\u002Finstall",[514,691,692,695],{},[536,693,694],{},"Node.js 22.12 or later and a package manager",[536,696,697],{},[483,698,699],{},"node --version",[514,701,702,709],{},[536,703,704,705],{},"A Monospace API key for a user who can create data sources and read and write items, such as a workspace ",[472,706,708],{"href":707},"\u002Freference\u002Fpermissions#administrator-role","Administrator",[536,710,711,712,715,716],{},"Create one under ",[463,713,714],{},"Account Settings > Access"," in Studio. See ",[472,717,719],{"href":718},"\u002Fdeveloper\u002Fapi\u002Fauthentication#get-an-api-key","Get an API Key",[459,721,722,723,726],{},"Build the ",[472,724,725],{"href":501},"Data Connector Quickstart"," first if you haven't built a connector before. This guide explains its concepts only briefly.",[459,728,729,730,733,734,737],{},"Code blocks on this page are excerpts of the files in the download, and ",[483,731,732],{},"\u002F\u002F …"," marks the lines an excerpt leaves out. Each step ends with a ",[463,735,736],{},"Done when"," list: run those checks against the complete project.",[459,739,740,741,745,746,495],{},"Query results are ",[472,742,744],{"href":743},"\u002Fconcepts\u002Fcaching","cached",". When you compare a response with Stripe after a change, send ",[483,747,748],{},"Cache-Control: no-cache",[455,750,752],{"id":751},"_1-probe-the-stripe-api","1. Probe the Stripe API",[459,754,755],{},"Design against what Stripe does, not what its reference says. Call every endpoint and parameter you might rely on, and record what comes back:",[757,758,763],"pre",{"className":759,"code":760,"filename":761,"language":762,"meta":637,"style":637},"language-bash shiki shiki-themes monospace-light monospace-light monospace-dark","curl -g \"https:\u002F\u002Fapi.stripe.com\u002Fv1\u002Fcustomers?limit=3&offset=5\" \\\n  -H \"Authorization: Bearer sk_test_YOUR_STRIPE_KEY\" \\\n  -H \"Stripe-Version: 2026-08-26.dahlia\"\n","terminal","bash",[483,764,765,784,795],{"__ignoreMap":637},[766,767,770,774,777,781],"span",{"class":768,"line":769},"line",1,[766,771,773],{"class":772},"ssBNi","curl",[766,775,776],{"class":772}," -g",[766,778,780],{"class":779},"suKVh"," \"https:\u002F\u002Fapi.stripe.com\u002Fv1\u002Fcustomers?limit=3&offset=5\"",[766,782,783],{"class":772}," \\\n",[766,785,787,790,793],{"class":768,"line":786},2,[766,788,789],{"class":772},"  -H",[766,791,792],{"class":779}," \"Authorization: Bearer sk_test_YOUR_STRIPE_KEY\"",[766,794,783],{"class":772},[766,796,798,800],{"class":768,"line":797},3,[766,799,789],{"class":772},[766,801,802],{"class":779}," \"Stripe-Version: 2026-08-26.dahlia\"\n",[459,804,805],{},"Probe each filter with a value that must match nothing, and probe unknown parameters, sorts, page sizes, counts and error paths. The connector's design rests on these results:",[508,807,808,818],{},[511,809,810],{},[514,811,812,815],{},[517,813,814],{},"Probe",[517,816,817],{},"Result",[531,819,820,836,850,864,874,891,901,911,928,943,963,971,983],{},[514,821,822,830],{},[536,823,824,546,827],{},[483,825,826],{},"customers?sort=created",[483,828,829],{},"customers?foo=1",[536,831,832,833,835],{},"Refused. Stripe rejects unknown parameters, and lists return newest ",[483,834,552],{}," first with no other order",[514,837,838,843],{},[536,839,840],{},[483,841,842],{},"limit=101",[536,844,845,846,849],{},"100 objects and ",[483,847,848],{},"has_more: true",", no error. The page size is capped at 100 without warning",[514,851,852,857],{},[536,853,854],{},[483,855,856],{},"customers?limit=3&offset=5",[536,858,859,860,863],{},"Objects 6 to 8. Stripe's list endpoints also accept an undocumented ",[483,861,862],{},"offset"," parameter; its reference documents only cursors",[514,865,866,871],{},[536,867,868],{},[483,869,870],{},"include[]=total_count",[536,872,873],{},"Refused. Lists have no total count",[514,875,876,885],{},[536,877,878,881,882],{},[483,879,880],{},"email=ada@…"," vs. ",[483,883,884],{},"email=ADA@…",[536,886,887,888,890],{},"1 vs. 0 customers. The ",[483,889,494],{}," filter is exact and case-sensitive",[514,892,893,898],{},[536,894,895],{},[483,896,897],{},"created[gte]=t&created[lte]=t",[536,899,900],{},"Inclusive, in whole seconds",[514,902,903,908],{},[536,904,905],{},[483,906,907],{},"prices?type=bogus",[536,909,910],{},"HTTP 400. Enum parameters reject values outside their domain",[514,912,913,918],{},[536,914,915],{},[483,916,917],{},"prices?product=prod_does_not_exist",[536,919,920,921,546,924,927],{},"HTTP 400, ",[483,922,923],{},"code: resource_missing",[483,925,926],{},"param: product",": an error, not an empty list",[514,929,930,935],{},[536,931,932],{},[483,933,934],{},"GET customers\u002Fcus_missing",[536,936,937,938,546,940],{},"HTTP 404, ",[483,939,923],{},[483,941,942],{},"param: id",[514,944,945,951],{},[536,946,947,950],{},[483,948,949],{},"DELETE products\u002F{id}"," for a product with prices",[536,952,920,953,956,957,959,960],{},[483,954,955],{},"type: invalid_request_error",", with no ",[483,958,483],{}," and no ",[483,961,962],{},"param",[514,964,965,968],{},[536,966,967],{},"A wrong key",[536,969,970],{},"HTTP 401. The message echoes the key's last characters",[514,972,973,976],{},[536,974,975],{},"A 400 or 404 error body",[536,977,978,979,982],{},"Carries a ",[483,980,981],{},"request_log_url",", which names the Stripe account",[514,984,985,988],{},[536,986,987],{},"A deleted customer by id",[536,989,990,991],{},"Still returned, with ",[483,992,993],{},"deleted: true",[459,995,996,997,1000],{},"Turn the results into a ",[463,998,999],{},"capability table",". Every filter operator, sort and paging argument you offer names the Stripe request that answers it. If nothing answers it, you don't offer it.",[508,1002,1003,1015],{},[511,1004,1005],{},[514,1006,1007,1009,1012],{},[517,1008,519],{},[517,1010,1011],{},"Offered",[517,1013,1014],{},"Stripe request",[531,1016,1017,1039,1064,1082,1102,1123],{},[514,1018,1019,1022,1033],{},[536,1020,1021],{},"all",[536,1023,1024,1026,1027,546,1030],{},[483,1025,545],{},": ",[483,1028,1029],{},"equals",[483,1031,1032],{},"in",[536,1034,1035,1038],{},[483,1036,1037],{},"GET \u002F{collection}\u002F{id}",", one per id",[514,1040,1041,1043,1055],{},[536,1042,1021],{},[536,1044,1045,1026,1047,546,1049,546,1052],{},[483,1046,552],{},[483,1048,1029],{},[483,1050,1051],{},"lessThan[OrEquals]",[483,1053,1054],{},"greaterThan[OrEquals]",[536,1056,1057,546,1060,1063],{},[483,1058,1059],{},"created[gte]",[483,1061,1062],{},"created[lte]"," in whole seconds",[514,1065,1066,1068,1079],{},[536,1067,1021],{},[536,1069,1070,1071,1073,1074,546,1077],{},"sort ",[483,1072,552],{}," descending; ",[483,1075,1076],{},"limit",[483,1078,862],{},[536,1080,1081],{},"the list endpoint, paged by 100",[514,1083,1084,1088,1096],{},[536,1085,1086],{},[483,1087,485],{},[536,1089,1090,1026,1092,546,1094],{},[483,1091,494],{},[483,1093,1029],{},[483,1095,1032],{},[536,1097,1098,1101],{},[483,1099,1100],{},"?email=…",", one request per value",[514,1103,1104,1108,1114],{},[536,1105,1106],{},[483,1107,563],{},[536,1109,1110,1026,1112],{},[483,1111,570],{},[483,1113,1029],{},[536,1115,1116,1119,1120],{},[483,1117,1118],{},"?active=true"," or ",[483,1121,1122],{},"?active=false",[514,1124,1125,1129,1148],{},[536,1126,1127],{},[483,1128,585],{},[536,1130,1131,1026,1133,546,1135,1137,1138,1026,1140,1137,1142,1026,1144,546,1146],{},[483,1132,592],{},[483,1134,1029],{},[483,1136,1032],{},"; ",[483,1139,570],{},[483,1141,1029],{},[483,1143,597],{},[483,1145,1029],{},[483,1147,1032],{},[536,1149,1150,546,1153,546,1156],{},[483,1151,1152],{},"?product=…",[483,1154,1155],{},"?active=…",[483,1157,1158],{},"?type=…",[459,1160,1161,1162,546,1165,546,1168,1171],{},"Filters on ",[483,1163,1164],{},"name",[483,1166,1167],{},"phone",[483,1169,1170],{},"unitAmount"," and most other fields aren't in the table. Stripe has no list parameter for them, and answering one would mean reading every item. Total counts, other sort orders and negation are out for the same reason.",[459,1173,1174,1176,1177,1180,1181,495],{},[463,1175,736],{}," every entry in the table names a Stripe request you ran, and you know which entries match exactly. See ",[472,1178,246],{"href":1179},"\u002Fdeveloper\u002Fextensions\u002Fdata-connectors\u002Fdata-source-mapping"," for the full probing checklist and the ",[472,1182,1184],{"href":1183},"\u002Fdeveloper\u002Fextensions\u002Fdata-connectors#fit-check","Fit Check",[455,1186,1188],{"id":1187},"_2-set-up-the-project","2. Set Up the Project",[459,1190,1191],{},"Unzip the download and install its dependencies, or scaffold a project with the CLI and add the files yourself:",[1193,1194,1196,1231,1258,1287],"code-group",{"sync":1195},"pm",[757,1197,1200],{"className":759,"code":1198,"filename":1199,"language":762,"meta":637,"style":637},"npx @monospace\u002Fcli@0.2 extension create .\u002Fstripe-connector --id example\u002Fstripe --name Stripe\n","npm",[483,1201,1202],{"__ignoreMap":637},[766,1203,1204,1207,1210,1213,1216,1219,1222,1225,1228],{"class":768,"line":769},[766,1205,1206],{"class":772},"npx",[766,1208,1209],{"class":779}," @monospace\u002Fcli@0.2",[766,1211,1212],{"class":779}," extension",[766,1214,1215],{"class":779}," create",[766,1217,1218],{"class":779}," .\u002Fstripe-connector",[766,1220,1221],{"class":772}," --id",[766,1223,1224],{"class":779}," example\u002Fstripe",[766,1226,1227],{"class":772}," --name",[766,1229,1230],{"class":779}," Stripe\n",[757,1232,1235],{"className":759,"code":1233,"filename":1234,"language":762,"meta":637,"style":637},"pnpx @monospace\u002Fcli@0.2 extension create .\u002Fstripe-connector --id example\u002Fstripe --name Stripe\n","pnpm",[483,1236,1237],{"__ignoreMap":637},[766,1238,1239,1242,1244,1246,1248,1250,1252,1254,1256],{"class":768,"line":769},[766,1240,1241],{"class":772},"pnpx",[766,1243,1209],{"class":779},[766,1245,1212],{"class":779},[766,1247,1215],{"class":779},[766,1249,1218],{"class":779},[766,1251,1221],{"class":772},[766,1253,1224],{"class":779},[766,1255,1227],{"class":772},[766,1257,1230],{"class":779},[757,1259,1262],{"className":759,"code":1260,"filename":1261,"language":762,"meta":637,"style":637},"yarn dlx @monospace\u002Fcli@0.2 extension create .\u002Fstripe-connector --id example\u002Fstripe --name Stripe\n","yarn",[483,1263,1264],{"__ignoreMap":637},[766,1265,1266,1268,1271,1273,1275,1277,1279,1281,1283,1285],{"class":768,"line":769},[766,1267,1261],{"class":772},[766,1269,1270],{"class":779}," dlx",[766,1272,1209],{"class":779},[766,1274,1212],{"class":779},[766,1276,1215],{"class":779},[766,1278,1218],{"class":779},[766,1280,1221],{"class":772},[766,1282,1224],{"class":779},[766,1284,1227],{"class":772},[766,1286,1230],{"class":779},[757,1288,1291],{"className":759,"code":1289,"filename":1290,"language":762,"meta":637,"style":637},"bunx @monospace\u002Fcli@0.2 extension create .\u002Fstripe-connector --id example\u002Fstripe --name Stripe\n","bun",[483,1292,1293],{"__ignoreMap":637},[766,1294,1295,1298,1300,1302,1304,1306,1308,1310,1312],{"class":768,"line":769},[766,1296,1297],{"class":772},"bunx",[766,1299,1209],{"class":779},[766,1301,1212],{"class":779},[766,1303,1215],{"class":779},[766,1305,1218],{"class":779},[766,1307,1221],{"class":772},[766,1309,1224],{"class":779},[766,1311,1227],{"class":772},[766,1313,1230],{"class":779},[459,1315,1316,1317,1320,1321,1324,1325,1328,1329,495],{},"The CLI prints ",[483,1318,1319],{},"Created the Stripe extension"," and two ",[463,1322,1323],{},"Next steps",". Run the first, which installs the dependencies. The scaffold puts its source in ",[483,1326,1327],{},"src\u002Fdata-connectors\u002Fexample\u002F",": delete that directory, because this connector's source goes in ",[483,1330,1331],{},"src\u002Fdata-connectors\u002Fstripe\u002F",[459,1333,1334],{},"Give the entry its own id, so a second extension from the same namespace doesn't collide with it. This is the finished extension config:",[757,1336,1341],{"className":1337,"code":1338,"filename":1339,"language":1340,"meta":637,"style":637},"language-json shiki shiki-themes monospace-light monospace-light monospace-dark","{\n    \"$schema\": \".\u002Fnode_modules\u002F@monospace\u002Fcli\u002Fschemas\u002Fextension.config.schema.json\",\n    \"id\": \"example\u002Fstripe\",\n    \"version\": \"0.1.0\",\n    \"name\": \"Stripe\",\n    \"icon\": \"simple-icons:stripe\",\n    \"iconBackground\": \"#635BFF\",\n    \"iconForeground\": \"#ffffff\",\n    \"entries\": [\n        {\n            \"type\": \"dataConnector\",\n            \"id\": \"example\u002Fstripe-connector\",\n            \"version\": \"0.1.0\",\n            \"name\": \"Stripe\",\n            \"icon\": \"simple-icons:stripe\",\n            \"iconBackground\": \"#635BFF\",\n            \"iconForeground\": \"#ffffff\",\n            \"engine\": {\n                \"capabilities\": { \"query\": [\"insertReturning\", \"updateReturning\", \"deleteReturning\"] },\n                \"entrypoint\": \".\u002Fsrc\u002Fdata-connectors\u002Fstripe\u002Findex.ts\",\n                \"permissions\": [\n                    { \"permission\": \"net:api.stripe.com\", \"reason\": \"Read and write customers, products and prices through the Stripe API\" }\n                ]\n            }\n        }\n    ]\n}\n","extension.config.json","json",[483,1342,1343,1349,1363,1375,1388,1401,1414,1427,1440,1449,1455,1468,1481,1493,1505,1517,1529,1541,1550,1581,1594,1602,1629,1635,1641,1647,1653],{"__ignoreMap":637},[766,1344,1345],{"class":768,"line":769},[766,1346,1348],{"class":1347},"sTMul","{\n",[766,1350,1351,1355,1357,1360],{"class":768,"line":786},[766,1352,1354],{"class":1353},"snHjA","    \"$schema\"",[766,1356,1026],{"class":1347},[766,1358,1359],{"class":779},"\".\u002Fnode_modules\u002F@monospace\u002Fcli\u002Fschemas\u002Fextension.config.schema.json\"",[766,1361,1362],{"class":1347},",\n",[766,1364,1365,1368,1370,1373],{"class":768,"line":797},[766,1366,1367],{"class":1353},"    \"id\"",[766,1369,1026],{"class":1347},[766,1371,1372],{"class":779},"\"example\u002Fstripe\"",[766,1374,1362],{"class":1347},[766,1376,1378,1381,1383,1386],{"class":768,"line":1377},4,[766,1379,1380],{"class":1353},"    \"version\"",[766,1382,1026],{"class":1347},[766,1384,1385],{"class":779},"\"0.1.0\"",[766,1387,1362],{"class":1347},[766,1389,1391,1394,1396,1399],{"class":768,"line":1390},5,[766,1392,1393],{"class":1353},"    \"name\"",[766,1395,1026],{"class":1347},[766,1397,1398],{"class":779},"\"Stripe\"",[766,1400,1362],{"class":1347},[766,1402,1404,1407,1409,1412],{"class":768,"line":1403},6,[766,1405,1406],{"class":1353},"    \"icon\"",[766,1408,1026],{"class":1347},[766,1410,1411],{"class":779},"\"simple-icons:stripe\"",[766,1413,1362],{"class":1347},[766,1415,1417,1420,1422,1425],{"class":768,"line":1416},7,[766,1418,1419],{"class":1353},"    \"iconBackground\"",[766,1421,1026],{"class":1347},[766,1423,1424],{"class":779},"\"#635BFF\"",[766,1426,1362],{"class":1347},[766,1428,1430,1433,1435,1438],{"class":768,"line":1429},8,[766,1431,1432],{"class":1353},"    \"iconForeground\"",[766,1434,1026],{"class":1347},[766,1436,1437],{"class":779},"\"#ffffff\"",[766,1439,1362],{"class":1347},[766,1441,1443,1446],{"class":768,"line":1442},9,[766,1444,1445],{"class":1353},"    \"entries\"",[766,1447,1448],{"class":1347},": [\n",[766,1450,1452],{"class":768,"line":1451},10,[766,1453,1454],{"class":1347},"        {\n",[766,1456,1458,1461,1463,1466],{"class":768,"line":1457},11,[766,1459,1460],{"class":1353},"            \"type\"",[766,1462,1026],{"class":1347},[766,1464,1465],{"class":779},"\"dataConnector\"",[766,1467,1362],{"class":1347},[766,1469,1471,1474,1476,1479],{"class":768,"line":1470},12,[766,1472,1473],{"class":1353},"            \"id\"",[766,1475,1026],{"class":1347},[766,1477,1478],{"class":779},"\"example\u002Fstripe-connector\"",[766,1480,1362],{"class":1347},[766,1482,1484,1487,1489,1491],{"class":768,"line":1483},13,[766,1485,1486],{"class":1353},"            \"version\"",[766,1488,1026],{"class":1347},[766,1490,1385],{"class":779},[766,1492,1362],{"class":1347},[766,1494,1496,1499,1501,1503],{"class":768,"line":1495},14,[766,1497,1498],{"class":1353},"            \"name\"",[766,1500,1026],{"class":1347},[766,1502,1398],{"class":779},[766,1504,1362],{"class":1347},[766,1506,1508,1511,1513,1515],{"class":768,"line":1507},15,[766,1509,1510],{"class":1353},"            \"icon\"",[766,1512,1026],{"class":1347},[766,1514,1411],{"class":779},[766,1516,1362],{"class":1347},[766,1518,1520,1523,1525,1527],{"class":768,"line":1519},16,[766,1521,1522],{"class":1353},"            \"iconBackground\"",[766,1524,1026],{"class":1347},[766,1526,1424],{"class":779},[766,1528,1362],{"class":1347},[766,1530,1532,1535,1537,1539],{"class":768,"line":1531},17,[766,1533,1534],{"class":1353},"            \"iconForeground\"",[766,1536,1026],{"class":1347},[766,1538,1437],{"class":779},[766,1540,1362],{"class":1347},[766,1542,1544,1547],{"class":768,"line":1543},18,[766,1545,1546],{"class":1353},"            \"engine\"",[766,1548,1549],{"class":1347},": {\n",[766,1551,1553,1556,1559,1562,1565,1568,1570,1573,1575,1578],{"class":768,"line":1552},19,[766,1554,1555],{"class":1353},"                \"capabilities\"",[766,1557,1558],{"class":1347},": { ",[766,1560,1561],{"class":1353},"\"query\"",[766,1563,1564],{"class":1347},": [",[766,1566,1567],{"class":779},"\"insertReturning\"",[766,1569,546],{"class":1347},[766,1571,1572],{"class":779},"\"updateReturning\"",[766,1574,546],{"class":1347},[766,1576,1577],{"class":779},"\"deleteReturning\"",[766,1579,1580],{"class":1347},"] },\n",[766,1582,1584,1587,1589,1592],{"class":768,"line":1583},20,[766,1585,1586],{"class":1353},"                \"entrypoint\"",[766,1588,1026],{"class":1347},[766,1590,1591],{"class":779},"\".\u002Fsrc\u002Fdata-connectors\u002Fstripe\u002Findex.ts\"",[766,1593,1362],{"class":1347},[766,1595,1597,1600],{"class":768,"line":1596},21,[766,1598,1599],{"class":1353},"                \"permissions\"",[766,1601,1448],{"class":1347},[766,1603,1605,1608,1611,1613,1616,1618,1621,1623,1626],{"class":768,"line":1604},22,[766,1606,1607],{"class":1347},"                    { ",[766,1609,1610],{"class":1353},"\"permission\"",[766,1612,1026],{"class":1347},[766,1614,1615],{"class":779},"\"net:api.stripe.com\"",[766,1617,546],{"class":1347},[766,1619,1620],{"class":1353},"\"reason\"",[766,1622,1026],{"class":1347},[766,1624,1625],{"class":779},"\"Read and write customers, products and prices through the Stripe API\"",[766,1627,1628],{"class":1347}," }\n",[766,1630,1632],{"class":768,"line":1631},23,[766,1633,1634],{"class":1347},"                ]\n",[766,1636,1638],{"class":768,"line":1637},24,[766,1639,1640],{"class":1347},"            }\n",[766,1642,1644],{"class":768,"line":1643},25,[766,1645,1646],{"class":1347},"        }\n",[766,1648,1650],{"class":768,"line":1649},26,[766,1651,1652],{"class":1347},"    ]\n",[766,1654,1656],{"class":768,"line":1655},27,[766,1657,1658],{"class":1347},"}\n",[1660,1661,1662,1674],"ul",{},[1663,1664,1665,1026,1670,1673],"li",{},[463,1666,1667],{},[483,1668,1669],{},"permissions",[483,1671,1672],{},"net:api.stripe.com"," is the only host the connector calls.",[1663,1675,1676,1681,1682,495],{},[463,1677,1678],{},[483,1679,1680],{},"capabilities",": the connector answers every write with the items it wrote. See ",[472,1683,1685],{"href":1684},"#declare-what-writes-return","Declare What Writes Return",[459,1687,686,1688,1691],{},[472,1689,379],{"href":1690},"\u002Freference\u002Fextensions\u002Fmanifest"," for every field.",[459,1693,1694,1695,1698,1699,549,1702,1705],{},"The project's ",[483,1696,1697],{},"tsconfig.json"," turns on ",[483,1700,1701],{},"noUncheckedIndexedAccess",[483,1703,1704],{},"exactOptionalPropertyTypes",", which the kit type-checks under. The connector is split by what changes together:",[508,1707,1708,1718],{},[511,1709,1710],{},[514,1711,1712,1715],{},[517,1713,1714],{},"File",[517,1716,1717],{},"Job",[531,1719,1720,1730,1740,1750,1760,1770,1780,1790,1800,1816,1826],{},[514,1721,1722,1727],{},[536,1723,1724],{},[483,1725,1726],{},"index.ts",[536,1728,1729],{},"Parses configuration, builds the client, and dispatches each operation",[514,1731,1732,1737],{},[536,1733,1734],{},[483,1735,1736],{},"config.ts",[536,1738,1739],{},"Validates the configuration and applies defaults",[514,1741,1742,1747],{},[536,1743,1744],{},[483,1745,1746],{},"client.ts",[536,1748,1749],{},"Every Stripe request: deadline, paging, and error mapping",[514,1751,1752,1757],{},[536,1753,1754],{},[483,1755,1756],{},"collections.ts",[536,1758,1759],{},"The declared collections and their relation",[514,1761,1762,1767],{},[536,1763,1764],{},[483,1765,1766],{},"resources.ts",[536,1768,1769],{},"The Stripe mapping: paths, form keys, list parameters",[514,1771,1772,1777],{},[536,1773,1774],{},[483,1775,1776],{},"plan.ts",[536,1778,1779],{},"Turns a filter into Stripe requests, or refuses it",[514,1781,1782,1787],{},[536,1783,1784],{},[483,1785,1786],{},"filter.ts",[536,1788,1789],{},"Evaluates a filter in memory, and parses timestamps",[514,1791,1792,1797],{},[536,1793,1794],{},[483,1795,1796],{},"items.ts",[536,1798,1799],{},"Converts between Stripe objects and items",[514,1801,1802,1807],{},[536,1803,1804],{},[483,1805,1806],{},"read.ts",[536,1808,1809,546,1812,1815],{},[483,1810,1811],{},"readMany",[483,1813,1814],{},"readOne",", keyed lookups, and the fetch budget",[514,1817,1818,1823],{},[536,1819,1820],{},[483,1821,1822],{},"write.ts",[536,1824,1825],{},"Every write operation",[514,1827,1828,1833],{},[536,1829,1830],{},[483,1831,1832],{},"concurrency.ts",[536,1834,1835],{},"Runs a fan-out with at most four requests in flight",[459,1837,1838,1839,1841,1842,1844],{},"A new collection touches its declaration in ",[483,1840,1756],{}," and its mapping in ",[483,1843,1766],{},". Keeping planning apart from execution lets you test which requests a filter produces without calling Stripe.",[459,1846,1847],{},"Build the project and install it into your instance's install location:",[1193,1849,1850,1874,1889,1904],{"sync":1195},[757,1851,1853],{"className":759,"code":1852,"filename":1199,"language":762,"meta":637,"style":637},"npm run build -- --install-to ..\u002Fmonospace\u002Fextensions\n",[483,1854,1855],{"__ignoreMap":637},[766,1856,1857,1859,1862,1865,1868,1871],{"class":768,"line":769},[766,1858,1199],{"class":772},[766,1860,1861],{"class":779}," run",[766,1863,1864],{"class":779}," build",[766,1866,1867],{"class":772}," --",[766,1869,1870],{"class":772}," --install-to",[766,1872,1873],{"class":779}," ..\u002Fmonospace\u002Fextensions\n",[757,1875,1877],{"className":759,"code":1876,"filename":1234,"language":762,"meta":637,"style":637},"pnpm build --install-to ..\u002Fmonospace\u002Fextensions\n",[483,1878,1879],{"__ignoreMap":637},[766,1880,1881,1883,1885,1887],{"class":768,"line":769},[766,1882,1234],{"class":772},[766,1884,1864],{"class":779},[766,1886,1870],{"class":772},[766,1888,1873],{"class":779},[757,1890,1892],{"className":759,"code":1891,"filename":1261,"language":762,"meta":637,"style":637},"yarn build --install-to ..\u002Fmonospace\u002Fextensions\n",[483,1893,1894],{"__ignoreMap":637},[766,1895,1896,1898,1900,1902],{"class":768,"line":769},[766,1897,1261],{"class":772},[766,1899,1864],{"class":779},[766,1901,1870],{"class":772},[766,1903,1873],{"class":779},[757,1905,1907],{"className":759,"code":1906,"filename":1290,"language":762,"meta":637,"style":637},"bun run build --install-to ..\u002Fmonospace\u002Fextensions\n",[483,1908,1909],{"__ignoreMap":637},[766,1910,1911,1913,1915,1917,1919],{"class":768,"line":769},[766,1912,1290],{"class":772},[766,1914,1861],{"class":779},[766,1916,1864],{"class":779},[766,1918,1870],{"class":772},[766,1920,1873],{"class":779},[757,1922,1928],{"className":1923,"code":1925,"filename":1926,"language":1927,"meta":637},[1924],"language-text","example\u002Fstripe-connector  example\u002Fstripe-connector.js\nArtifact                  …\u002Fstripe-connector\u002Fdist\nInstalled                 …\u002Fmonospace\u002Fextensions\u002Fexample__stripe\nRestart the engine to load it, unless it runs with MONOSPACE_EXTENSIONS__AUTO_RELOAD=true.\n","output","text",[483,1929,1925],{"__ignoreMap":637},[459,1931,1932,1934,1935,1938,1939,1942,1943,1946,1947,495],{},[463,1933,736],{}," the build installs as ",[483,1936,1937],{},"example__stripe\u002F"," and the instance lists ",[483,1940,1941],{},"example\u002Fstripe-connector"," in ",[483,1944,1945],{},"GET \u002Fapi\u002F{workspace}\u002Fconnectors\u002Fdata",". An extension can load and still contribute no connector, so check this list, not only the log. See ",[472,1948,227],{"href":689},[455,1950,1952],{"id":1951},"_3-parse-configuration-and-build-the-client","3. Parse Configuration and Build the Client",[459,1954,1955,1956,1959],{},"A data source's configuration reaches ",[483,1957,1958],{},"setup"," as unchecked JSON. The Stripe connector reads three keys:",[508,1961,1962,1978],{},[511,1963,1964],{},[514,1965,1966,1969,1972,1975],{},[517,1967,1968],{},"Key",[517,1970,1971],{},"Type",[517,1973,1974],{},"Default",[517,1976,1977],{},"Meaning",[531,1979,1980,2004,2026],{},[514,1981,1982,1987,1990,1993],{},[536,1983,1984],{},[483,1985,1986],{},"apiKey",[536,1988,1989],{},"string",[536,1991,1992],{},"(required)",[536,1994,1995,1996,1999,2000,2003],{},"A secret (",[483,1997,1998],{},"sk_",") or restricted (",[483,2001,2002],{},"rk_",") key, test or live mode",[514,2005,2006,2010,2013,2023],{},[536,2007,2008],{},[483,2009,528],{},[536,2011,2012],{},"boolean",[536,2014,2015,2018,2019,2022],{},[483,2016,2017],{},"true"," for a test-mode key, ",[483,2020,2021],{},"false"," otherwise",[536,2024,2025],{},"Declares and allows writes",[514,2027,2028,2033,2036,2041],{},[536,2029,2030],{},[483,2031,2032],{},"maxItemsPerQuery",[536,2034,2035],{},"positive integer",[536,2037,2038],{},[483,2039,2040],{},"5000",[536,2042,2043,2044],{},"The most Stripe objects one read may fetch before the connector refuses it. See ",[472,2045,2047],{"href":2046},"#refuse-what-you-cant-answer","Refuse What You Can't Answer",[459,2049,2050,1942,2053,2055,2056,2062],{},[483,2051,2052],{},"parseConfig",[483,2054,1736],{}," returns typed configuration or throws ",[472,2057,2059],{"href":2058},"\u002Freference\u002Fextensions\u002Fextension-kit\u002Fdata-connector#invalidconfiguration",[483,2060,2061],{},"InvalidConfiguration",":",[1660,2064,2065,2071,2083],{},[1663,2066,2067,2070],{},[463,2068,2069],{},"A malformed key fails before any request."," Anything not shaped like a Stripe secret or restricted key is refused, such as a publishable key.",[1663,2072,2073,2078,2079,2082],{},[463,2074,2075,2076,495],{},"A wrong key passes ",[483,2077,1958],{}," Stripe rejects a well-formed key it doesn't recognize with a ",[483,2080,2081],{},"401",", on the connection test or the first query.",[1663,2084,2085,2088],{},[463,2086,2087],{},"Writes default to off for live keys."," A live key gets a read-only data source unless its configuration turns writes on.",[459,2090,2091,2093,2094,2096,2097,2099,2100,2103,2104,2107],{},[483,2092,1726],{}," builds the client once in ",[483,2095,1958],{}," and dispatches each operation to its handler. ",[483,2098,1958],{}," makes no requests, so it stays fast and can't fail on a network error. ",[483,2101,2102],{},"testConnection"," lists one customer, so a key Stripe rejects fails the connection test. There's no ",[483,2105,2106],{},"preflight",", because the only host is fixed and declared in the extension config.",[2109,2110,2112],"h3",{"id":2111},"map-every-stripe-failure","Map Every Stripe Failure",[459,2114,2115,2116,2119,2120,2124,2125,2128,2129,2132],{},"The client owns every Stripe request. Its one ",[483,2117,2118],{},"fetch"," call pins the API version and sets a 10-second deadline, because Engine sets none (see ",[472,2121,2123],{"href":2122},"\u002Freference\u002Fextensions\u002Fdata-connectors\u002Flimits#per-request-deadline","Per-Request Deadline","). It keeps a rejected request as the ",[483,2126,2127],{},"cause"," of its ",[483,2130,2131],{},"ConnectionFailed",", so a request the data source's permissions refused reaches the caller as a permission error.",[459,2134,2135,2138,2139,549,2141,2143],{},[483,2136,2137],{},"toConnectorError"," classifies every error response. It reads Stripe's error body by its ",[483,2140,483],{},[483,2142,962],{},", after special cases for rejected keys and rate limits:",[757,2145,2150],{"className":2146,"code":2147,"filename":2148,"language":2149,"meta":637,"style":637},"language-ts shiki shiki-themes monospace-light monospace-light monospace-dark","function toConnectorError(response: StripeResponse, method: Method, path: string): Error {\n    const detail = readError(response.body);\n    const { status } = response;\n    \u002F\u002F The path without the query string, which can hold the caller's filter values.\n    const message = detail.message ?? `Stripe answered HTTP ${status} to ${method} ${new URL(path, BASE_URL).pathname}.`;\n\n    \u002F\u002F Only someone with access to the Stripe account can fix the key. Stripe's message for a rejected\n    \u002F\u002F key echoes part of the key, so it stays out.\n    if (status === 401 || status === 403) return new AccessDenied(`Stripe rejected the API key (HTTP ${status}).`);\n    if (status === 429) return new RateLimited(`Stripe rate limited the connector.${retryAfter(response.headers)}`);\n\n    switch (detail.code) {\n        case 'resource_missing':\n            \u002F\u002F `param` names what is missing: `id` for the object in the path. On a write, any other\n            \u002F\u002F field is an object the written values refer to, such as a new price's `product`.\n            if (method === 'POST' && detail.param !== undefined && detail.param !== 'id') return new ForeignKeyConstraintViolation(message);\n            return new StripeObjectMissing(message);\n        case 'resource_already_exists':\n            return new UniqueConstraintViolation(message);\n        case 'parameter_missing':\n            return new NullConstraintViolation(message);\n    }\n\n    \u002F\u002F Stripe refuses to delete a product that still has prices with no error code, only a message.\n    if (method === 'DELETE' && detail.type === 'invalid_request_error' && \u002F\\bprices\\b\u002Fu.test(message)) {\n        return new ForeignKeyConstraintViolation(message);\n    }\n\n    \u002F\u002F Treat a server error as an outage: a later request may work.\n    if (status >= 500) return new ConnectionFailed(message);\n    \u002F\u002F Stripe answers 400 to values it refuses, such as an invalid email: the caller can change them.\n    if (status === 400 && detail.type === 'invalid_request_error') return new QueryRejected(message);\n    return new Error(message);\n}\n","src\u002Fdata-connectors\u002Fstripe\u002Fclient.ts","ts",[483,2151,2152,2196,2224,2246,2252,2312,2318,2323,2328,2378,2424,2428,2445,2456,2461,2466,2523,2539,2548,2563,2572,2587,2592,2596,2601,2657,2672,2676,2681,2687,2717,2723,2764,2780],{"__ignoreMap":637},[766,2153,2154,2158,2161,2164,2167,2170,2172,2175,2178,2180,2183,2186,2188,2190,2193],{"class":768,"line":769},[766,2155,2157],{"class":2156},"sLVBU","function",[766,2159,2160],{"class":772}," toConnectorError",[766,2162,2163],{"class":1347},"(",[766,2165,2166],{"class":2156},"response:",[766,2168,2169],{"class":772}," StripeResponse",[766,2171,546],{"class":1347},[766,2173,2174],{"class":2156},"method:",[766,2176,2177],{"class":772}," Method",[766,2179,546],{"class":1347},[766,2181,2182],{"class":2156},"path:",[766,2184,2185],{"class":1353}," string",[766,2187,529],{"class":1347},[766,2189,2062],{"class":2156},[766,2191,2192],{"class":772}," Error",[766,2194,2195],{"class":1347}," {\n",[766,2197,2198,2201,2204,2207,2210,2212,2216,2218,2221],{"class":768,"line":786},[766,2199,2200],{"class":2156},"    const",[766,2202,2203],{"class":772}," detail",[766,2205,2206],{"class":2156}," =",[766,2208,2209],{"class":772}," readError",[766,2211,2163],{"class":1347},[766,2213,2215],{"class":2214},"sNJ9c","response",[766,2217,495],{"class":1347},[766,2219,2220],{"class":2214},"body",[766,2222,2223],{"class":1347},");\n",[766,2225,2226,2228,2231,2234,2237,2240,2243],{"class":768,"line":797},[766,2227,2200],{"class":2156},[766,2229,2230],{"class":1347}," { ",[766,2232,2233],{"class":772},"status",[766,2235,2236],{"class":1347}," } ",[766,2238,2239],{"class":2156},"=",[766,2241,2242],{"class":2214}," response",[766,2244,2245],{"class":1347},";\n",[766,2247,2248],{"class":768,"line":1377},[766,2249,2251],{"class":2250},"seNfP","    \u002F\u002F The path without the query string, which can hold the caller's filter values.\n",[766,2253,2254,2256,2259,2261,2263,2265,2268,2271,2274,2276,2279,2282,2285,2288,2291,2293,2296,2298,2301,2304,2307,2310],{"class":768,"line":1390},[766,2255,2200],{"class":2156},[766,2257,2258],{"class":772}," message",[766,2260,2206],{"class":2156},[766,2262,2203],{"class":2214},[766,2264,495],{"class":1347},[766,2266,2267],{"class":2214},"message",[766,2269,2270],{"class":2156}," ??",[766,2272,2273],{"class":779}," `Stripe answered HTTP ${",[766,2275,2233],{"class":2214},[766,2277,2278],{"class":779},"} to ${",[766,2280,2281],{"class":2214},"method",[766,2283,2284],{"class":779},"} ${",[766,2286,2287],{"class":2156},"new",[766,2289,2290],{"class":772}," URL",[766,2292,2163],{"class":779},[766,2294,2295],{"class":2214},"path",[766,2297,546],{"class":779},[766,2299,2300],{"class":772},"BASE_URL",[766,2302,2303],{"class":779},").",[766,2305,2306],{"class":2214},"pathname",[766,2308,2309],{"class":779},"}.`",[766,2311,2245],{"class":1347},[766,2313,2314],{"class":768,"line":1403},[766,2315,2317],{"emptyLinePlaceholder":2316},true,"\n",[766,2319,2320],{"class":768,"line":1416},[766,2321,2322],{"class":2250},"    \u002F\u002F Only someone with access to the Stripe account can fix the key. Stripe's message for a rejected\n",[766,2324,2325],{"class":768,"line":1429},[766,2326,2327],{"class":2250},"    \u002F\u002F key echoes part of the key, so it stays out.\n",[766,2329,2330,2333,2335,2337,2340,2343,2346,2349,2351,2354,2357,2360,2363,2366,2368,2371,2373,2376],{"class":768,"line":1442},[766,2331,2332],{"class":2156},"    if",[766,2334,639],{"class":1347},[766,2336,2233],{"class":2214},[766,2338,2339],{"class":2156}," ===",[766,2341,2342],{"class":772}," 401",[766,2344,2345],{"class":2156}," ||",[766,2347,2348],{"class":2214}," status",[766,2350,2339],{"class":2156},[766,2352,2353],{"class":772}," 403",[766,2355,2356],{"class":1347},") ",[766,2358,2359],{"class":2156},"return",[766,2361,2362],{"class":2156}," new",[766,2364,2365],{"class":772}," AccessDenied",[766,2367,2163],{"class":1347},[766,2369,2370],{"class":779},"`Stripe rejected the API key (HTTP ${",[766,2372,2233],{"class":2214},[766,2374,2375],{"class":779},"}).`",[766,2377,2223],{"class":1347},[766,2379,2380,2382,2384,2386,2388,2391,2393,2395,2397,2400,2402,2405,2408,2410,2412,2414,2417,2419,2422],{"class":768,"line":1451},[766,2381,2332],{"class":2156},[766,2383,639],{"class":1347},[766,2385,2233],{"class":2214},[766,2387,2339],{"class":2156},[766,2389,2390],{"class":772}," 429",[766,2392,2356],{"class":1347},[766,2394,2359],{"class":2156},[766,2396,2362],{"class":2156},[766,2398,2399],{"class":772}," RateLimited",[766,2401,2163],{"class":1347},[766,2403,2404],{"class":779},"`Stripe rate limited the connector.${",[766,2406,2407],{"class":772},"retryAfter",[766,2409,2163],{"class":779},[766,2411,2215],{"class":2214},[766,2413,495],{"class":779},[766,2415,2416],{"class":2214},"headers",[766,2418,529],{"class":779},[766,2420,2421],{"class":779},"}`",[766,2423,2223],{"class":1347},[766,2425,2426],{"class":768,"line":1457},[766,2427,2317],{"emptyLinePlaceholder":2316},[766,2429,2430,2433,2435,2438,2440,2442],{"class":768,"line":1470},[766,2431,2432],{"class":2156},"    switch",[766,2434,639],{"class":1347},[766,2436,2437],{"class":2214},"detail",[766,2439,495],{"class":1347},[766,2441,483],{"class":2214},[766,2443,2444],{"class":1347},") {\n",[766,2446,2447,2450,2453],{"class":768,"line":1483},[766,2448,2449],{"class":2156},"        case",[766,2451,2452],{"class":779}," 'resource_missing'",[766,2454,2455],{"class":1347},":\n",[766,2457,2458],{"class":768,"line":1495},[766,2459,2460],{"class":2250},"            \u002F\u002F `param` names what is missing: `id` for the object in the path. On a write, any other\n",[766,2462,2463],{"class":768,"line":1507},[766,2464,2465],{"class":2250},"            \u002F\u002F field is an object the written values refer to, such as a new price's `product`.\n",[766,2467,2468,2471,2473,2475,2477,2480,2483,2485,2487,2489,2492,2495,2497,2499,2501,2503,2505,2508,2510,2512,2514,2517,2519,2521],{"class":768,"line":1519},[766,2469,2470],{"class":2156},"            if",[766,2472,639],{"class":1347},[766,2474,2281],{"class":2214},[766,2476,2339],{"class":2156},[766,2478,2479],{"class":779}," 'POST'",[766,2481,2482],{"class":2156}," &&",[766,2484,2203],{"class":2214},[766,2486,495],{"class":1347},[766,2488,962],{"class":2214},[766,2490,2491],{"class":2156}," !==",[766,2493,2494],{"class":772}," undefined",[766,2496,2482],{"class":2156},[766,2498,2203],{"class":2214},[766,2500,495],{"class":1347},[766,2502,962],{"class":2214},[766,2504,2491],{"class":2156},[766,2506,2507],{"class":779}," 'id'",[766,2509,2356],{"class":1347},[766,2511,2359],{"class":2156},[766,2513,2362],{"class":2156},[766,2515,2516],{"class":772}," ForeignKeyConstraintViolation",[766,2518,2163],{"class":1347},[766,2520,2267],{"class":2214},[766,2522,2223],{"class":1347},[766,2524,2525,2528,2530,2533,2535,2537],{"class":768,"line":1531},[766,2526,2527],{"class":2156},"            return",[766,2529,2362],{"class":2156},[766,2531,2532],{"class":772}," StripeObjectMissing",[766,2534,2163],{"class":1347},[766,2536,2267],{"class":2214},[766,2538,2223],{"class":1347},[766,2540,2541,2543,2546],{"class":768,"line":1543},[766,2542,2449],{"class":2156},[766,2544,2545],{"class":779}," 'resource_already_exists'",[766,2547,2455],{"class":1347},[766,2549,2550,2552,2554,2557,2559,2561],{"class":768,"line":1552},[766,2551,2527],{"class":2156},[766,2553,2362],{"class":2156},[766,2555,2556],{"class":772}," UniqueConstraintViolation",[766,2558,2163],{"class":1347},[766,2560,2267],{"class":2214},[766,2562,2223],{"class":1347},[766,2564,2565,2567,2570],{"class":768,"line":1583},[766,2566,2449],{"class":2156},[766,2568,2569],{"class":779}," 'parameter_missing'",[766,2571,2455],{"class":1347},[766,2573,2574,2576,2578,2581,2583,2585],{"class":768,"line":1596},[766,2575,2527],{"class":2156},[766,2577,2362],{"class":2156},[766,2579,2580],{"class":772}," NullConstraintViolation",[766,2582,2163],{"class":1347},[766,2584,2267],{"class":2214},[766,2586,2223],{"class":1347},[766,2588,2589],{"class":768,"line":1604},[766,2590,2591],{"class":1347},"    }\n",[766,2593,2594],{"class":768,"line":1631},[766,2595,2317],{"emptyLinePlaceholder":2316},[766,2597,2598],{"class":768,"line":1637},[766,2599,2600],{"class":2250},"    \u002F\u002F Stripe refuses to delete a product that still has prices with no error code, only a message.\n",[766,2602,2603,2605,2607,2609,2611,2614,2616,2618,2620,2622,2624,2627,2629,2632,2635,2637,2639,2642,2645,2647,2650,2652,2654],{"class":768,"line":1643},[766,2604,2332],{"class":2156},[766,2606,639],{"class":1347},[766,2608,2281],{"class":2214},[766,2610,2339],{"class":2156},[766,2612,2613],{"class":779}," 'DELETE'",[766,2615,2482],{"class":2156},[766,2617,2203],{"class":2214},[766,2619,495],{"class":1347},[766,2621,597],{"class":2214},[766,2623,2339],{"class":2156},[766,2625,2626],{"class":779}," 'invalid_request_error'",[766,2628,2482],{"class":2156},[766,2630,2631],{"class":779}," \u002F",[766,2633,2634],{"class":2156},"\\b",[766,2636,585],{"class":779},[766,2638,2634],{"class":2156},[766,2640,2641],{"class":779},"\u002F",[766,2643,2644],{"class":2156},"u",[766,2646,495],{"class":1347},[766,2648,2649],{"class":772},"test",[766,2651,2163],{"class":1347},[766,2653,2267],{"class":2214},[766,2655,2656],{"class":1347},")) {\n",[766,2658,2659,2662,2664,2666,2668,2670],{"class":768,"line":1649},[766,2660,2661],{"class":2156},"        return",[766,2663,2362],{"class":2156},[766,2665,2516],{"class":772},[766,2667,2163],{"class":1347},[766,2669,2267],{"class":2214},[766,2671,2223],{"class":1347},[766,2673,2674],{"class":768,"line":1655},[766,2675,2591],{"class":1347},[766,2677,2679],{"class":768,"line":2678},28,[766,2680,2317],{"emptyLinePlaceholder":2316},[766,2682,2684],{"class":768,"line":2683},29,[766,2685,2686],{"class":2250},"    \u002F\u002F Treat a server error as an outage: a later request may work.\n",[766,2688,2690,2692,2694,2696,2699,2702,2704,2706,2708,2711,2713,2715],{"class":768,"line":2689},30,[766,2691,2332],{"class":2156},[766,2693,639],{"class":1347},[766,2695,2233],{"class":2214},[766,2697,2698],{"class":2156}," >=",[766,2700,2701],{"class":772}," 500",[766,2703,2356],{"class":1347},[766,2705,2359],{"class":2156},[766,2707,2362],{"class":2156},[766,2709,2710],{"class":772}," ConnectionFailed",[766,2712,2163],{"class":1347},[766,2714,2267],{"class":2214},[766,2716,2223],{"class":1347},[766,2718,2720],{"class":768,"line":2719},31,[766,2721,2722],{"class":2250},"    \u002F\u002F Stripe answers 400 to values it refuses, such as an invalid email: the caller can change them.\n",[766,2724,2726,2728,2730,2732,2734,2737,2739,2741,2743,2745,2747,2749,2751,2753,2755,2758,2760,2762],{"class":768,"line":2725},32,[766,2727,2332],{"class":2156},[766,2729,639],{"class":1347},[766,2731,2233],{"class":2214},[766,2733,2339],{"class":2156},[766,2735,2736],{"class":772}," 400",[766,2738,2482],{"class":2156},[766,2740,2203],{"class":2214},[766,2742,495],{"class":1347},[766,2744,597],{"class":2214},[766,2746,2339],{"class":2156},[766,2748,2626],{"class":779},[766,2750,2356],{"class":1347},[766,2752,2359],{"class":2156},[766,2754,2362],{"class":2156},[766,2756,2757],{"class":772}," QueryRejected",[766,2759,2163],{"class":1347},[766,2761,2267],{"class":2214},[766,2763,2223],{"class":1347},[766,2765,2767,2770,2772,2774,2776,2778],{"class":768,"line":2766},33,[766,2768,2769],{"class":2156},"    return",[766,2771,2362],{"class":2156},[766,2773,2192],{"class":772},[766,2775,2163],{"class":1347},[766,2777,2267],{"class":2214},[766,2779,2223],{"class":1347},[766,2781,2783],{"class":768,"line":2782},34,[766,2784,1658],{"class":1347},[1660,2786,2787,2804,2822],{},[1663,2788,2789,2795,2796,2799,2800,2803],{},[463,2790,2791,2792,495],{},"A rate limit is ",[483,2793,2794],{},"RateLimited"," Stripe answers too many requests per second with a ",[483,2797,2798],{},"429",". The message adds \"Retry after 2 seconds.\" when ",[483,2801,2802],{},"Retry-After"," is a whole number of seconds.",[1663,2805,2806,2813,2814,2817,2818,2821],{},[463,2807,2808,2809,2812],{},"A plain ",[483,2810,2811],{},"Error"," is a failure the caller can't fix,"," such as a changed API. Engine reports it as a failed query. ",[483,2815,2816],{},"StripeObjectMissing"," is one, which ",[483,2819,2820],{},"retrieve"," and the keyed writes answer as a miss instead.",[1663,2823,2824,2827,2828,2830,2831,2833],{},[463,2825,2826],{},"Only the error's code and message reach Engine."," So no message carries the key, the query string, or the account's ",[483,2829,981],{},". Stripe's own ",[483,2832,2267],{}," passes through, and it can quote a value the caller sent.",[459,2835,686,2836,2840,2841,2845],{},[472,2837,2839],{"href":2838},"\u002Fdeveloper\u002Fextensions\u002Fdata-connectors\u002Ferrors","Handle Data Connector Errors"," for choosing error classes and ",[472,2842,2844],{"href":2843},"\u002Freference\u002Fextensions\u002Fdata-connectors\u002Ferrors","Data Connector Errors"," for what each one does.",[459,2847,2848],{},"Test the connection with the permissions included. The SDK has no method for data sources, so call the endpoint directly:",[1193,2850,2851,2926],{},[757,2852,2854],{"className":759,"code":2853,"filename":773,"language":762,"meta":637,"style":637},"curl -X POST https:\u002F\u002Fexample.monospace.io\u002Fapi\u002Fblog\u002Fsources\u002Fdata\u002Ftest \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"provider\": \"example\u002Fstripe-connector\",\n    \"config\": { \"apiKey\": \"sk_test_YOUR_STRIPE_KEY\" },\n    \"permissions\": [\n      { \"permission\": \"net:api.stripe.com\", \"reason\": \"Read and write customers, products and prices through the Stripe API\" }\n    ]\n  }'\n",[483,2855,2856,2871,2880,2889,2897,2902,2907,2912,2917,2921],{"__ignoreMap":637},[766,2857,2858,2860,2863,2866,2869],{"class":768,"line":769},[766,2859,773],{"class":772},[766,2861,2862],{"class":772}," -X",[766,2864,2865],{"class":779}," POST",[766,2867,2868],{"class":779}," https:\u002F\u002Fexample.monospace.io\u002Fapi\u002Fblog\u002Fsources\u002Fdata\u002Ftest",[766,2870,783],{"class":772},[766,2872,2873,2875,2878],{"class":768,"line":786},[766,2874,789],{"class":772},[766,2876,2877],{"class":779}," \"Authorization: Bearer YOUR_API_KEY\"",[766,2879,783],{"class":772},[766,2881,2882,2884,2887],{"class":768,"line":797},[766,2883,789],{"class":772},[766,2885,2886],{"class":779}," \"Content-Type: application\u002Fjson\"",[766,2888,783],{"class":772},[766,2890,2891,2894],{"class":768,"line":1377},[766,2892,2893],{"class":772},"  -d",[766,2895,2896],{"class":779}," '{\n",[766,2898,2899],{"class":768,"line":1390},[766,2900,2901],{"class":779},"    \"provider\": \"example\u002Fstripe-connector\",\n",[766,2903,2904],{"class":768,"line":1403},[766,2905,2906],{"class":779},"    \"config\": { \"apiKey\": \"sk_test_YOUR_STRIPE_KEY\" },\n",[766,2908,2909],{"class":768,"line":1416},[766,2910,2911],{"class":779},"    \"permissions\": [\n",[766,2913,2914],{"class":768,"line":1429},[766,2915,2916],{"class":779},"      { \"permission\": \"net:api.stripe.com\", \"reason\": \"Read and write customers, products and prices through the Stripe API\" }\n",[766,2918,2919],{"class":768,"line":1442},[766,2920,1652],{"class":779},[766,2922,2923],{"class":768,"line":1451},[766,2924,2925],{"class":779},"  }'\n",[757,2927,2929],{"className":2146,"code":2928,"filename":2118,"language":2149,"meta":637,"style":637},"const response = await fetch('https:\u002F\u002Fexample.monospace.io\u002Fapi\u002Fblog\u002Fsources\u002Fdata\u002Ftest', {\n  method: 'POST',\n  headers: {\n    'Authorization': 'Bearer YOUR_API_KEY',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({\n    provider: 'example\u002Fstripe-connector',\n    config: { apiKey: 'sk_test_YOUR_STRIPE_KEY' },\n    permissions: [\n      { permission: 'net:api.stripe.com', reason: 'Read and write customers, products and prices through the Stripe API' },\n    ],\n  }),\n});\n",[483,2930,2931,2954,2964,2969,2981,2993,2998,3014,3024,3035,3040,3056,3061,3066],{"__ignoreMap":637},[766,2932,2933,2936,2938,2940,2943,2946,2948,2951],{"class":768,"line":769},[766,2934,2935],{"class":2156},"const",[766,2937,2242],{"class":772},[766,2939,2206],{"class":2156},[766,2941,2942],{"class":2156}," await",[766,2944,2945],{"class":772}," fetch",[766,2947,2163],{"class":1347},[766,2949,2950],{"class":779},"'https:\u002F\u002Fexample.monospace.io\u002Fapi\u002Fblog\u002Fsources\u002Fdata\u002Ftest'",[766,2952,2953],{"class":1347},", {\n",[766,2955,2956,2959,2962],{"class":768,"line":786},[766,2957,2958],{"class":1347},"  method: ",[766,2960,2961],{"class":779},"'POST'",[766,2963,1362],{"class":1347},[766,2965,2966],{"class":768,"line":797},[766,2967,2968],{"class":1347},"  headers: {\n",[766,2970,2971,2974,2976,2979],{"class":768,"line":1377},[766,2972,2973],{"class":779},"    'Authorization'",[766,2975,1026],{"class":1347},[766,2977,2978],{"class":779},"'Bearer YOUR_API_KEY'",[766,2980,1362],{"class":1347},[766,2982,2983,2986,2988,2991],{"class":768,"line":1390},[766,2984,2985],{"class":779},"    'Content-Type'",[766,2987,1026],{"class":1347},[766,2989,2990],{"class":779},"'application\u002Fjson'",[766,2992,1362],{"class":1347},[766,2994,2995],{"class":768,"line":1403},[766,2996,2997],{"class":1347},"  },\n",[766,2999,3000,3003,3006,3008,3011],{"class":768,"line":1416},[766,3001,3002],{"class":1347},"  body: ",[766,3004,3005],{"class":772},"JSON",[766,3007,495],{"class":1347},[766,3009,3010],{"class":772},"stringify",[766,3012,3013],{"class":1347},"({\n",[766,3015,3016,3019,3022],{"class":768,"line":1429},[766,3017,3018],{"class":1347},"    provider: ",[766,3020,3021],{"class":779},"'example\u002Fstripe-connector'",[766,3023,1362],{"class":1347},[766,3025,3026,3029,3032],{"class":768,"line":1442},[766,3027,3028],{"class":1347},"    config: { apiKey: ",[766,3030,3031],{"class":779},"'sk_test_YOUR_STRIPE_KEY'",[766,3033,3034],{"class":1347}," },\n",[766,3036,3037],{"class":768,"line":1451},[766,3038,3039],{"class":1347},"    permissions: [\n",[766,3041,3042,3045,3048,3051,3054],{"class":768,"line":1457},[766,3043,3044],{"class":1347},"      { permission: ",[766,3046,3047],{"class":779},"'net:api.stripe.com'",[766,3049,3050],{"class":1347},", reason: ",[766,3052,3053],{"class":779},"'Read and write customers, products and prices through the Stripe API'",[766,3055,3034],{"class":1347},[766,3057,3058],{"class":768,"line":1470},[766,3059,3060],{"class":1347},"    ],\n",[766,3062,3063],{"class":768,"line":1483},[766,3064,3065],{"class":1347},"  }),\n",[766,3067,3068],{"class":768,"line":1495},[766,3069,3070],{"class":1347},"});\n",[459,3072,3073,3074,3077,3078,3081],{},"A successful test answers ",[483,3075,3076],{},"204"," with an empty body. A wrong key fails with ",[483,3079,3080],{},"422",", and the error nests the connector's message: \"Stripe rejected the API key (HTTP 401).\"",[459,3083,3084],{},[463,3085,3086],{},"Done when:",[1660,3088,3089,3109,3126],{},[1663,3090,3091,3093,3094,3096,3097,3100,3101,3104,3105,3108],{},[483,3092,1958],{}," throws ",[483,3095,2061],{}," for ",[483,3098,3099],{},"{}",", for a publishable key such as ",[483,3102,3103],{},"pk_test_123",", and for ",[483,3106,3107],{},"\"maxItemsPerQuery\": 0",", without making a request;",[1663,3110,3111,3112,3114,3115,3117,3118,3121,3122,3125],{},"a connection test without ",[483,3113,1669],{}," answers ",[483,3116,3080],{}," with code ",[483,3119,3120],{},"7001",", then succeeds with the returned set (see ",[472,3123,432],{"href":3124},"\u002Freference\u002Fextensions\u002Fdata-connectors\u002Fpermissions#approve-permissions",");",[1663,3127,3128],{},"a connection test with a wrong key fails, and one with your test key succeeds.",[455,3130,3132],{"id":3131},"_4-declare-the-schema-and-create-a-data-source","4. Declare the Schema and Create a Data Source",[459,3134,3135],{},"Stripe has no metadata API, so the connector declares its collections statically, pinned to one Stripe API version. The filters come straight from the capability table:",[757,3137,3140],{"className":2146,"code":3138,"filename":3139,"language":2149,"meta":637,"style":637},"\u002F**\n * Stripe has no metadata API, so its objects are declared here and pinned to one API version:\n * `STRIPE_API_VERSION` and the field paths in `resources.ts` change together.\n *\u002F\nexport const STRIPE_API_VERSION = '2026-08-26.dahlia';\n\n\u002F\u002F The filters below declare only what Stripe answers exactly, and `plan.ts` sends a filter to\n\u002F\u002F Stripe only when it's declared here: `id` by retrieving it, `created` through `created[gte]` and\n\u002F\u002F `created[lte]`, and every other field through its list parameter in `resources.ts`.\nconst exact = filter.field('equals', 'in');\n\u002F** Engine executes only `equals` on booleans. *\u002F\nconst booleanExact = filter.field('equals');\nconst createdRange = filter.field('equals', 'lessThan', 'lessThanOrEquals', 'greaterThan', 'greaterThanOrEquals');\nconst andOr = filter.logical('and', 'or');\n\u002F** Stripe lists newest first and can't sort any other way. *\u002F\nconst newestFirst = { created: sort.field('descending') };\n\n\u002F\u002F Values Stripe sets itself: callers never have to supply them on create.\nconst setByStripe = { defaultValue: defaultValue.connectorManaged() };\nconst id = field.string(setByStripe);\nconst created = field.dateTimeWithTimezone(setByStripe);\nconst nullableText = field.string({ nullable: true });\n\n\u002F\u002F A field is writable exactly when a `data` list below names it: the kit derives the read-only\n\u002F\u002F flags from these lists. `balance` and `unitAmount` are 64-bit integers, which travel as strings.\nconst customerFields = {\n    id,\n    name: nullableText,\n    email: nullableText,\n    phone: nullableText,\n    description: nullableText,\n    balance: field.int64(setByStripe),\n    created,\n};\nconst customerFilter = { fields: { id: exact, email: exact, created: createdRange }, logicalOperators: andOr };\nconst customerData = fieldsOf(customerFields).pick('name', 'email', 'phone', 'description', 'balance');\n\nexport const customers = defineCollection({\n    name: 'customers',\n    fields: customerFields,\n    indexes: { customers_pkey: index.primary(['id']) },\n    operations: {\n        readMany: { filter: customerFilter, sort: newestFirst, limit: paging.limit(), offset: paging.offset(), output: fields.all() },\n        readOne: { filter: customerFilter, output: fields.all() },\n        create: { data: customerData, output: fields.all() },\n        updateMany: { filter: customerFilter, data: customerData, output: fields.all() },\n        updateOne: { filter: customerFilter, data: customerData, output: fields.all() },\n        deleteMany: { filter: customerFilter, output: fields.all() },\n        deleteOne: { filter: customerFilter, output: fields.all() },\n    },\n});\n","src\u002Fdata-connectors\u002Fstripe\u002Fcollections.ts",[483,3141,3142,3147,3152,3157,3162,3180,3184,3189,3194,3199,3228,3233,3254,3295,3323,3328,3355,3359,3364,3387,3410,3432,3455,3459,3464,3469,3480,3487,3497,3506,3515,3524,3543,3550,3555,3591,3641,3646,3663,3673,3683,3706,3712,3758,3777,3796,3819,3841,3859,3877,3883],{"__ignoreMap":637},[766,3143,3144],{"class":768,"line":769},[766,3145,3146],{"class":2250},"\u002F**\n",[766,3148,3149],{"class":768,"line":786},[766,3150,3151],{"class":2250}," * Stripe has no metadata API, so its objects are declared here and pinned to one API version:\n",[766,3153,3154],{"class":768,"line":797},[766,3155,3156],{"class":2250}," * `STRIPE_API_VERSION` and the field paths in `resources.ts` change together.\n",[766,3158,3159],{"class":768,"line":1377},[766,3160,3161],{"class":2250}," *\u002F\n",[766,3163,3164,3167,3170,3173,3175,3178],{"class":768,"line":1390},[766,3165,3166],{"class":2156},"export",[766,3168,3169],{"class":2156}," const",[766,3171,3172],{"class":772}," STRIPE_API_VERSION",[766,3174,2206],{"class":2156},[766,3176,3177],{"class":779}," '2026-08-26.dahlia'",[766,3179,2245],{"class":1347},[766,3181,3182],{"class":768,"line":1403},[766,3183,2317],{"emptyLinePlaceholder":2316},[766,3185,3186],{"class":768,"line":1416},[766,3187,3188],{"class":2250},"\u002F\u002F The filters below declare only what Stripe answers exactly, and `plan.ts` sends a filter to\n",[766,3190,3191],{"class":768,"line":1429},[766,3192,3193],{"class":2250},"\u002F\u002F Stripe only when it's declared here: `id` by retrieving it, `created` through `created[gte]` and\n",[766,3195,3196],{"class":768,"line":1442},[766,3197,3198],{"class":2250},"\u002F\u002F `created[lte]`, and every other field through its list parameter in `resources.ts`.\n",[766,3200,3201,3203,3206,3208,3211,3213,3216,3218,3221,3223,3226],{"class":768,"line":1451},[766,3202,2935],{"class":2156},[766,3204,3205],{"class":772}," exact",[766,3207,2206],{"class":2156},[766,3209,3210],{"class":2214}," filter",[766,3212,495],{"class":1347},[766,3214,3215],{"class":772},"field",[766,3217,2163],{"class":1347},[766,3219,3220],{"class":779},"'equals'",[766,3222,546],{"class":1347},[766,3224,3225],{"class":779},"'in'",[766,3227,2223],{"class":1347},[766,3229,3230],{"class":768,"line":1457},[766,3231,3232],{"class":2250},"\u002F** Engine executes only `equals` on booleans. *\u002F\n",[766,3234,3235,3237,3240,3242,3244,3246,3248,3250,3252],{"class":768,"line":1470},[766,3236,2935],{"class":2156},[766,3238,3239],{"class":772}," booleanExact",[766,3241,2206],{"class":2156},[766,3243,3210],{"class":2214},[766,3245,495],{"class":1347},[766,3247,3215],{"class":772},[766,3249,2163],{"class":1347},[766,3251,3220],{"class":779},[766,3253,2223],{"class":1347},[766,3255,3256,3258,3261,3263,3265,3267,3269,3271,3273,3275,3278,3280,3283,3285,3288,3290,3293],{"class":768,"line":1483},[766,3257,2935],{"class":2156},[766,3259,3260],{"class":772}," createdRange",[766,3262,2206],{"class":2156},[766,3264,3210],{"class":2214},[766,3266,495],{"class":1347},[766,3268,3215],{"class":772},[766,3270,2163],{"class":1347},[766,3272,3220],{"class":779},[766,3274,546],{"class":1347},[766,3276,3277],{"class":779},"'lessThan'",[766,3279,546],{"class":1347},[766,3281,3282],{"class":779},"'lessThanOrEquals'",[766,3284,546],{"class":1347},[766,3286,3287],{"class":779},"'greaterThan'",[766,3289,546],{"class":1347},[766,3291,3292],{"class":779},"'greaterThanOrEquals'",[766,3294,2223],{"class":1347},[766,3296,3297,3299,3302,3304,3306,3308,3311,3313,3316,3318,3321],{"class":768,"line":1495},[766,3298,2935],{"class":2156},[766,3300,3301],{"class":772}," andOr",[766,3303,2206],{"class":2156},[766,3305,3210],{"class":2214},[766,3307,495],{"class":1347},[766,3309,3310],{"class":772},"logical",[766,3312,2163],{"class":1347},[766,3314,3315],{"class":779},"'and'",[766,3317,546],{"class":1347},[766,3319,3320],{"class":779},"'or'",[766,3322,2223],{"class":1347},[766,3324,3325],{"class":768,"line":1507},[766,3326,3327],{"class":2250},"\u002F** Stripe lists newest first and can't sort any other way. *\u002F\n",[766,3329,3330,3332,3335,3337,3340,3343,3345,3347,3349,3352],{"class":768,"line":1519},[766,3331,2935],{"class":2156},[766,3333,3334],{"class":772}," newestFirst",[766,3336,2206],{"class":2156},[766,3338,3339],{"class":1347}," { created: ",[766,3341,3342],{"class":2214},"sort",[766,3344,495],{"class":1347},[766,3346,3215],{"class":772},[766,3348,2163],{"class":1347},[766,3350,3351],{"class":779},"'descending'",[766,3353,3354],{"class":1347},") };\n",[766,3356,3357],{"class":768,"line":1531},[766,3358,2317],{"emptyLinePlaceholder":2316},[766,3360,3361],{"class":768,"line":1543},[766,3362,3363],{"class":2250},"\u002F\u002F Values Stripe sets itself: callers never have to supply them on create.\n",[766,3365,3366,3368,3371,3373,3376,3379,3381,3384],{"class":768,"line":1552},[766,3367,2935],{"class":2156},[766,3369,3370],{"class":772}," setByStripe",[766,3372,2206],{"class":2156},[766,3374,3375],{"class":1347}," { defaultValue: ",[766,3377,3378],{"class":2214},"defaultValue",[766,3380,495],{"class":1347},[766,3382,3383],{"class":772},"connectorManaged",[766,3385,3386],{"class":1347},"() };\n",[766,3388,3389,3391,3394,3396,3399,3401,3403,3405,3408],{"class":768,"line":1583},[766,3390,2935],{"class":2156},[766,3392,3393],{"class":772}," id",[766,3395,2206],{"class":2156},[766,3397,3398],{"class":2214}," field",[766,3400,495],{"class":1347},[766,3402,1989],{"class":772},[766,3404,2163],{"class":1347},[766,3406,3407],{"class":2214},"setByStripe",[766,3409,2223],{"class":1347},[766,3411,3412,3414,3417,3419,3421,3423,3426,3428,3430],{"class":768,"line":1596},[766,3413,2935],{"class":2156},[766,3415,3416],{"class":772}," created",[766,3418,2206],{"class":2156},[766,3420,3398],{"class":2214},[766,3422,495],{"class":1347},[766,3424,3425],{"class":772},"dateTimeWithTimezone",[766,3427,2163],{"class":1347},[766,3429,3407],{"class":2214},[766,3431,2223],{"class":1347},[766,3433,3434,3436,3439,3441,3443,3445,3447,3450,3452],{"class":768,"line":1604},[766,3435,2935],{"class":2156},[766,3437,3438],{"class":772}," nullableText",[766,3440,2206],{"class":2156},[766,3442,3398],{"class":2214},[766,3444,495],{"class":1347},[766,3446,1989],{"class":772},[766,3448,3449],{"class":1347},"({ nullable: ",[766,3451,2017],{"class":772},[766,3453,3454],{"class":1347}," });\n",[766,3456,3457],{"class":768,"line":1631},[766,3458,2317],{"emptyLinePlaceholder":2316},[766,3460,3461],{"class":768,"line":1637},[766,3462,3463],{"class":2250},"\u002F\u002F A field is writable exactly when a `data` list below names it: the kit derives the read-only\n",[766,3465,3466],{"class":768,"line":1643},[766,3467,3468],{"class":2250},"\u002F\u002F flags from these lists. `balance` and `unitAmount` are 64-bit integers, which travel as strings.\n",[766,3470,3471,3473,3476,3478],{"class":768,"line":1649},[766,3472,2935],{"class":2156},[766,3474,3475],{"class":772}," customerFields",[766,3477,2206],{"class":2156},[766,3479,2195],{"class":1347},[766,3481,3482,3485],{"class":768,"line":1655},[766,3483,3484],{"class":2214},"    id",[766,3486,1362],{"class":1347},[766,3488,3489,3492,3495],{"class":768,"line":2678},[766,3490,3491],{"class":1347},"    name: ",[766,3493,3494],{"class":2214},"nullableText",[766,3496,1362],{"class":1347},[766,3498,3499,3502,3504],{"class":768,"line":2683},[766,3500,3501],{"class":1347},"    email: ",[766,3503,3494],{"class":2214},[766,3505,1362],{"class":1347},[766,3507,3508,3511,3513],{"class":768,"line":2689},[766,3509,3510],{"class":1347},"    phone: ",[766,3512,3494],{"class":2214},[766,3514,1362],{"class":1347},[766,3516,3517,3520,3522],{"class":768,"line":2719},[766,3518,3519],{"class":1347},"    description: ",[766,3521,3494],{"class":2214},[766,3523,1362],{"class":1347},[766,3525,3526,3529,3531,3533,3536,3538,3540],{"class":768,"line":2725},[766,3527,3528],{"class":1347},"    balance: ",[766,3530,3215],{"class":2214},[766,3532,495],{"class":1347},[766,3534,3535],{"class":772},"int64",[766,3537,2163],{"class":1347},[766,3539,3407],{"class":2214},[766,3541,3542],{"class":1347},"),\n",[766,3544,3545,3548],{"class":768,"line":2766},[766,3546,3547],{"class":2214},"    created",[766,3549,1362],{"class":1347},[766,3551,3552],{"class":768,"line":2782},[766,3553,3554],{"class":1347},"};\n",[766,3556,3558,3560,3563,3565,3568,3571,3574,3576,3579,3582,3585,3588],{"class":768,"line":3557},35,[766,3559,2935],{"class":2156},[766,3561,3562],{"class":772}," customerFilter",[766,3564,2206],{"class":2156},[766,3566,3567],{"class":1347}," { fields: { id: ",[766,3569,3570],{"class":2214},"exact",[766,3572,3573],{"class":1347},", email: ",[766,3575,3570],{"class":2214},[766,3577,3578],{"class":1347},", created: ",[766,3580,3581],{"class":2214},"createdRange",[766,3583,3584],{"class":1347}," }, logicalOperators: ",[766,3586,3587],{"class":2214},"andOr",[766,3589,3590],{"class":1347}," };\n",[766,3592,3594,3596,3599,3601,3604,3606,3609,3611,3614,3616,3619,3621,3624,3626,3629,3631,3634,3636,3639],{"class":768,"line":3593},36,[766,3595,2935],{"class":2156},[766,3597,3598],{"class":772}," customerData",[766,3600,2206],{"class":2156},[766,3602,3603],{"class":772}," fieldsOf",[766,3605,2163],{"class":1347},[766,3607,3608],{"class":2214},"customerFields",[766,3610,2303],{"class":1347},[766,3612,3613],{"class":772},"pick",[766,3615,2163],{"class":1347},[766,3617,3618],{"class":779},"'name'",[766,3620,546],{"class":1347},[766,3622,3623],{"class":779},"'email'",[766,3625,546],{"class":1347},[766,3627,3628],{"class":779},"'phone'",[766,3630,546],{"class":1347},[766,3632,3633],{"class":779},"'description'",[766,3635,546],{"class":1347},[766,3637,3638],{"class":779},"'balance'",[766,3640,2223],{"class":1347},[766,3642,3644],{"class":768,"line":3643},37,[766,3645,2317],{"emptyLinePlaceholder":2316},[766,3647,3649,3651,3653,3656,3658,3661],{"class":768,"line":3648},38,[766,3650,3166],{"class":2156},[766,3652,3169],{"class":2156},[766,3654,3655],{"class":772}," customers",[766,3657,2206],{"class":2156},[766,3659,3660],{"class":772}," defineCollection",[766,3662,3013],{"class":1347},[766,3664,3666,3668,3671],{"class":768,"line":3665},39,[766,3667,3491],{"class":1347},[766,3669,3670],{"class":779},"'customers'",[766,3672,1362],{"class":1347},[766,3674,3676,3679,3681],{"class":768,"line":3675},40,[766,3677,3678],{"class":1347},"    fields: ",[766,3680,3608],{"class":2214},[766,3682,1362],{"class":1347},[766,3684,3686,3689,3692,3694,3697,3700,3703],{"class":768,"line":3685},41,[766,3687,3688],{"class":1347},"    indexes: { customers_pkey: ",[766,3690,3691],{"class":2214},"index",[766,3693,495],{"class":1347},[766,3695,3696],{"class":772},"primary",[766,3698,3699],{"class":1347},"([",[766,3701,3702],{"class":779},"'id'",[766,3704,3705],{"class":1347},"]) },\n",[766,3707,3709],{"class":768,"line":3708},42,[766,3710,3711],{"class":1347},"    operations: {\n",[766,3713,3715,3718,3721,3724,3727,3730,3733,3735,3737,3740,3742,3744,3746,3749,3751,3753,3755],{"class":768,"line":3714},43,[766,3716,3717],{"class":1347},"        readMany: { filter: ",[766,3719,3720],{"class":2214},"customerFilter",[766,3722,3723],{"class":1347},", sort: ",[766,3725,3726],{"class":2214},"newestFirst",[766,3728,3729],{"class":1347},", limit: ",[766,3731,3732],{"class":2214},"paging",[766,3734,495],{"class":1347},[766,3736,1076],{"class":772},[766,3738,3739],{"class":1347},"(), offset: ",[766,3741,3732],{"class":2214},[766,3743,495],{"class":1347},[766,3745,862],{"class":772},[766,3747,3748],{"class":1347},"(), output: ",[766,3750,490],{"class":2214},[766,3752,495],{"class":1347},[766,3754,1021],{"class":772},[766,3756,3757],{"class":1347},"() },\n",[766,3759,3761,3764,3766,3769,3771,3773,3775],{"class":768,"line":3760},44,[766,3762,3763],{"class":1347},"        readOne: { filter: ",[766,3765,3720],{"class":2214},[766,3767,3768],{"class":1347},", output: ",[766,3770,490],{"class":2214},[766,3772,495],{"class":1347},[766,3774,1021],{"class":772},[766,3776,3757],{"class":1347},[766,3778,3780,3783,3786,3788,3790,3792,3794],{"class":768,"line":3779},45,[766,3781,3782],{"class":1347},"        create: { data: ",[766,3784,3785],{"class":2214},"customerData",[766,3787,3768],{"class":1347},[766,3789,490],{"class":2214},[766,3791,495],{"class":1347},[766,3793,1021],{"class":772},[766,3795,3757],{"class":1347},[766,3797,3799,3802,3804,3807,3809,3811,3813,3815,3817],{"class":768,"line":3798},46,[766,3800,3801],{"class":1347},"        updateMany: { filter: ",[766,3803,3720],{"class":2214},[766,3805,3806],{"class":1347},", data: ",[766,3808,3785],{"class":2214},[766,3810,3768],{"class":1347},[766,3812,490],{"class":2214},[766,3814,495],{"class":1347},[766,3816,1021],{"class":772},[766,3818,3757],{"class":1347},[766,3820,3822,3825,3827,3829,3831,3833,3835,3837,3839],{"class":768,"line":3821},47,[766,3823,3824],{"class":1347},"        updateOne: { filter: ",[766,3826,3720],{"class":2214},[766,3828,3806],{"class":1347},[766,3830,3785],{"class":2214},[766,3832,3768],{"class":1347},[766,3834,490],{"class":2214},[766,3836,495],{"class":1347},[766,3838,1021],{"class":772},[766,3840,3757],{"class":1347},[766,3842,3844,3847,3849,3851,3853,3855,3857],{"class":768,"line":3843},48,[766,3845,3846],{"class":1347},"        deleteMany: { filter: ",[766,3848,3720],{"class":2214},[766,3850,3768],{"class":1347},[766,3852,490],{"class":2214},[766,3854,495],{"class":1347},[766,3856,1021],{"class":772},[766,3858,3757],{"class":1347},[766,3860,3862,3865,3867,3869,3871,3873,3875],{"class":768,"line":3861},49,[766,3863,3864],{"class":1347},"        deleteOne: { filter: ",[766,3866,3720],{"class":2214},[766,3868,3768],{"class":1347},[766,3870,490],{"class":2214},[766,3872,495],{"class":1347},[766,3874,1021],{"class":772},[766,3876,3757],{"class":1347},[766,3878,3880],{"class":768,"line":3879},50,[766,3881,3882],{"class":1347},"    },\n",[766,3884,3886],{"class":768,"line":3885},51,[766,3887,3070],{"class":1347},[1660,3889,3890,3903,3912,3932],{},[1663,3891,3892,3898,3899,3902],{},[463,3893,3894,3895,3897],{},"Sort is ",[483,3896,552],{}," descending only,"," the one order Stripe lists in. No collection declares ",[483,3900,3901],{},"meta.totalCount",", because Stripe lists have no total count.",[1663,3904,3905,3908,3909,495],{},[463,3906,3907],{},"One read filter is reused by every member."," Engine requires write filters to stay within ",[483,3910,3911],{},"readMany.filter",[1663,3913,3914,3923,3924,546,3926,1119,3928,3931],{},[463,3915,3916,3917,3922],{},"Values Stripe sets carry a ",[472,3918,3920],{"href":3919},"\u002Freference\u002Fextensions\u002Fextension-kit\u002Fexperimental#defaultvalue",[483,3921,3383],{}," default,"," so callers never have to supply ",[483,3925,545],{},[483,3927,552],{},[483,3929,3930],{},"balance"," on create.",[1663,3933,3934,3941,3942,3944,3945,3947],{},[463,3935,3936,549,3938,3940],{},[483,3937,563],{},[483,3939,585],{}," follow the same pattern."," A product's create also takes a caller-chosen ",[483,3943,545],{},", and ",[483,3946,585],{}," declares no deletes, because Stripe can't delete prices.",[459,3949,3950,3953,3954,3957,3958,3964],{},[483,3951,3952],{},"schemaDocument(enableWrites)"," passes ",[483,3955,3956],{},"writes: enableWrites"," to the kit's ",[472,3959,3961],{"href":3960},"\u002Freference\u002Fextensions\u002Fextension-kit\u002Fexperimental#schemadocumentoptions",[483,3962,3963],{},"toSchemaDocument",". With writes off, every writing operation is dropped, and Engine refuses a write before it reaches the connector.",[459,3966,3967,3970,3971,3974,3975,549,3977,3979,3980,3982,3983,495],{},[483,3968,3969],{},"defineSchema"," also declares the ",[483,3972,3973],{},"prices_product"," relation. Engine resolves each direction of a relation by filtering the other collection by its key field. Both ",[483,3976,618],{},[483,3978,614],{}," declare ",[483,3981,1032],{},", so both directions work. See ",[472,3984,3986],{"href":3985},"\u002Freference\u002Fextensions\u002Fdata-connectors\u002Foperations#resolve-relations","Resolve Relations",[2109,3988,3990],{"id":3989},"map-fields-to-stripe","Map Fields to Stripe",[459,3992,3993,3994,3996,3997,4000],{},"The query code also needs each field's place in a Stripe object, its form key for writes, and its list parameter. ",[483,3995,1766],{}," keeps that mapping, keyed by the declared field names, so ",[483,3998,3999],{},"tsc"," reports a typo:",[757,4002,4005],{"className":2146,"code":4003,"filename":4004,"language":2149,"meta":637,"style":637},"\u002F** Where a field lives in Stripe, when that differs from its snake_case name. *\u002F\ninterface FieldMapping {\n    \u002F** Location in the Stripe object. Defaults to the field's name in snake_case. *\u002F\n    readonly path?: readonly string[];\n    \u002F** Form key for writes. Defaults to the field's name in snake_case. *\u002F\n    readonly formKey?: string;\n    \u002F** The list parameter that filters the field by exact value. *\u002F\n    readonly listParameter?: string;\n    \u002F**\n     * Values the list parameter accepts. Stripe rejects an unknown enum value with an error, where a\n     * filter on one matches no item, so the plan never sends other values.\n     *\u002F\n    readonly listValues?: RegExp;\n}\n\u002F\u002F …\nconst BOOLEAN_VALUES = \u002F^(?:true|false)$\u002Fu;\n\nconst RESOURCES: readonly ResourceSpec[] = [\n    toSpec(customers, 'customers', {\n        email: { listParameter: 'email' },\n    }),\n    toSpec(products, 'products', {\n        active: { listParameter: 'active', listValues: BOOLEAN_VALUES },\n    }),\n    toSpec(prices, 'prices', {\n        productId: { path: ['product'], formKey: 'product', listParameter: 'product' },\n        active: { listParameter: 'active', listValues: BOOLEAN_VALUES },\n        type: { listParameter: 'type', listValues: \u002F^(?:one_time|recurring)$\u002Fu },\n        recurringInterval: { path: ['recurring', 'interval'], formKey: 'recurring[interval]' },\n    }),\n];\n","src\u002Fdata-connectors\u002Fstripe\u002Fresources.ts",[483,4006,4007,4012,4022,4027,4043,4048,4059,4064,4075,4080,4085,4090,4095,4107,4111,4116,4148,4152,4174,4189,4198,4203,4218,4234,4238,4253,4273,4285,4316,4336,4340],{"__ignoreMap":637},[766,4008,4009],{"class":768,"line":769},[766,4010,4011],{"class":2250},"\u002F** Where a field lives in Stripe, when that differs from its snake_case name. *\u002F\n",[766,4013,4014,4017,4020],{"class":768,"line":786},[766,4015,4016],{"class":2156},"interface",[766,4018,4019],{"class":772}," FieldMapping",[766,4021,2195],{"class":1347},[766,4023,4024],{"class":768,"line":797},[766,4025,4026],{"class":2250},"    \u002F** Location in the Stripe object. Defaults to the field's name in snake_case. *\u002F\n",[766,4028,4029,4032,4035,4038,4040],{"class":768,"line":1377},[766,4030,4031],{"class":2156},"    readonly",[766,4033,4034],{"class":2156}," path?:",[766,4036,4037],{"class":2156}," readonly",[766,4039,2185],{"class":1353},[766,4041,4042],{"class":1347},"[];\n",[766,4044,4045],{"class":768,"line":1390},[766,4046,4047],{"class":2250},"    \u002F** Form key for writes. Defaults to the field's name in snake_case. *\u002F\n",[766,4049,4050,4052,4055,4057],{"class":768,"line":1403},[766,4051,4031],{"class":2156},[766,4053,4054],{"class":2156}," formKey?:",[766,4056,2185],{"class":1353},[766,4058,2245],{"class":1347},[766,4060,4061],{"class":768,"line":1416},[766,4062,4063],{"class":2250},"    \u002F** The list parameter that filters the field by exact value. *\u002F\n",[766,4065,4066,4068,4071,4073],{"class":768,"line":1429},[766,4067,4031],{"class":2156},[766,4069,4070],{"class":2156}," listParameter?:",[766,4072,2185],{"class":1353},[766,4074,2245],{"class":1347},[766,4076,4077],{"class":768,"line":1442},[766,4078,4079],{"class":2250},"    \u002F**\n",[766,4081,4082],{"class":768,"line":1451},[766,4083,4084],{"class":2250},"     * Values the list parameter accepts. Stripe rejects an unknown enum value with an error, where a\n",[766,4086,4087],{"class":768,"line":1457},[766,4088,4089],{"class":2250},"     * filter on one matches no item, so the plan never sends other values.\n",[766,4091,4092],{"class":768,"line":1470},[766,4093,4094],{"class":2250},"     *\u002F\n",[766,4096,4097,4099,4102,4105],{"class":768,"line":1483},[766,4098,4031],{"class":2156},[766,4100,4101],{"class":2156}," listValues?:",[766,4103,4104],{"class":772}," RegExp",[766,4106,2245],{"class":1347},[766,4108,4109],{"class":768,"line":1495},[766,4110,1658],{"class":1347},[766,4112,4113],{"class":768,"line":1507},[766,4114,4115],{"class":2250},"\u002F\u002F …\n",[766,4117,4118,4120,4123,4125,4127,4130,4133,4136,4139,4142,4144,4146],{"class":768,"line":1519},[766,4119,2935],{"class":2156},[766,4121,4122],{"class":772}," BOOLEAN_VALUES",[766,4124,2206],{"class":2156},[766,4126,2631],{"class":779},[766,4128,4129],{"class":2156},"^",[766,4131,4132],{"class":779},"(?:true",[766,4134,4135],{"class":2156},"|",[766,4137,4138],{"class":779},"false)",[766,4140,4141],{"class":2156},"$",[766,4143,2641],{"class":779},[766,4145,2644],{"class":2156},[766,4147,2245],{"class":1347},[766,4149,4150],{"class":768,"line":1531},[766,4151,2317],{"emptyLinePlaceholder":2316},[766,4153,4154,4156,4159,4161,4163,4166,4169,4171],{"class":768,"line":1543},[766,4155,2935],{"class":2156},[766,4157,4158],{"class":772}," RESOURCES",[766,4160,2062],{"class":2156},[766,4162,4037],{"class":2156},[766,4164,4165],{"class":772}," ResourceSpec",[766,4167,4168],{"class":1347},"[] ",[766,4170,2239],{"class":2156},[766,4172,4173],{"class":1347}," [\n",[766,4175,4176,4179,4181,4183,4185,4187],{"class":768,"line":1552},[766,4177,4178],{"class":772},"    toSpec",[766,4180,2163],{"class":1347},[766,4182,485],{"class":2214},[766,4184,546],{"class":1347},[766,4186,3670],{"class":779},[766,4188,2953],{"class":1347},[766,4190,4191,4194,4196],{"class":768,"line":1583},[766,4192,4193],{"class":1347},"        email: { listParameter: ",[766,4195,3623],{"class":779},[766,4197,3034],{"class":1347},[766,4199,4200],{"class":768,"line":1596},[766,4201,4202],{"class":1347},"    }),\n",[766,4204,4205,4207,4209,4211,4213,4216],{"class":768,"line":1604},[766,4206,4178],{"class":772},[766,4208,2163],{"class":1347},[766,4210,563],{"class":2214},[766,4212,546],{"class":1347},[766,4214,4215],{"class":779},"'products'",[766,4217,2953],{"class":1347},[766,4219,4220,4223,4226,4229,4232],{"class":768,"line":1631},[766,4221,4222],{"class":1347},"        active: { listParameter: ",[766,4224,4225],{"class":779},"'active'",[766,4227,4228],{"class":1347},", listValues: ",[766,4230,4231],{"class":772},"BOOLEAN_VALUES",[766,4233,3034],{"class":1347},[766,4235,4236],{"class":768,"line":1637},[766,4237,4202],{"class":1347},[766,4239,4240,4242,4244,4246,4248,4251],{"class":768,"line":1643},[766,4241,4178],{"class":772},[766,4243,2163],{"class":1347},[766,4245,585],{"class":2214},[766,4247,546],{"class":1347},[766,4249,4250],{"class":779},"'prices'",[766,4252,2953],{"class":1347},[766,4254,4255,4258,4261,4264,4266,4269,4271],{"class":768,"line":1649},[766,4256,4257],{"class":1347},"        productId: { path: [",[766,4259,4260],{"class":779},"'product'",[766,4262,4263],{"class":1347},"], formKey: ",[766,4265,4260],{"class":779},[766,4267,4268],{"class":1347},", listParameter: ",[766,4270,4260],{"class":779},[766,4272,3034],{"class":1347},[766,4274,4275,4277,4279,4281,4283],{"class":768,"line":1655},[766,4276,4222],{"class":1347},[766,4278,4225],{"class":779},[766,4280,4228],{"class":1347},[766,4282,4231],{"class":772},[766,4284,3034],{"class":1347},[766,4286,4287,4290,4293,4296,4298,4300,4303,4305,4308,4310,4312,4314],{"class":768,"line":2678},[766,4288,4289],{"class":1347},"        type: { listParameter: ",[766,4291,4292],{"class":779},"'type'",[766,4294,4295],{"class":1347},", listValues:",[766,4297,2631],{"class":779},[766,4299,4129],{"class":2156},[766,4301,4302],{"class":779},"(?:one_time",[766,4304,4135],{"class":2156},[766,4306,4307],{"class":779},"recurring)",[766,4309,4141],{"class":2156},[766,4311,2641],{"class":779},[766,4313,2644],{"class":2156},[766,4315,3034],{"class":1347},[766,4317,4318,4321,4324,4326,4329,4331,4334],{"class":768,"line":2683},[766,4319,4320],{"class":1347},"        recurringInterval: { path: [",[766,4322,4323],{"class":779},"'recurring'",[766,4325,546],{"class":1347},[766,4327,4328],{"class":779},"'interval'",[766,4330,4263],{"class":1347},[766,4332,4333],{"class":779},"'recurring[interval]'",[766,4335,3034],{"class":1347},[766,4337,4338],{"class":768,"line":2689},[766,4339,4202],{"class":1347},[766,4341,4342],{"class":768,"line":2719},[766,4343,4344],{"class":1347},"];\n",[459,4346,4347,4350,4351,4353],{},[483,4348,4349],{},"toSpec"," joins each declaration with its mapping, so the plan and the writes never disagree with the declaration. ",[483,4352,1796],{}," converts values in both directions:",[1660,4355,4356,4362,4371,4380],{},[1663,4357,4358,4361],{},[463,4359,4360],{},"Timestamps",": Stripe's Unix seconds become RFC 3339 strings.",[1663,4363,4364,4367,4368,4370],{},[463,4365,4366],{},"Missing or unexpected values"," fail with a plain ",[483,4369,2811],{},", unless the field is nullable and the value is missing.",[1663,4372,4373,4379],{},[463,4374,4375,4376],{},"Written ",[483,4377,4378],{},"null",": an update sends an empty string, which unsets the field in Stripe. A create omits the field.",[1663,4381,4382,4385,4386,4388,4389,549,4391,4393,4394,2303],{},[463,4383,4384],{},"64-bit integers",": Engine sends ",[483,4387,3535],{}," values, such as ",[483,4390,3930],{},[483,4392,1170],{},", as decimal strings. Callers read both fields as strings (e.g., ",[483,4395,4396],{},"\"balance\": \"0\"",[4398,4399,4400,4401,4404,4405,4407],"warning",{},"Never check ",[483,4402,4403],{},"typeof value === 'number'"," on an ",[483,4406,3535],{}," field or key. Engine sends a string, so such a check misses every value.",[459,4409,4410],{},"Create a data source now, before you write query code. Engine refuses a declaration that breaks its rules at create time, which is cheaper to fix before planning code depends on it:",[1193,4412,4413,4482],{},[757,4414,4416],{"className":759,"code":4415,"filename":773,"language":762,"meta":637,"style":637},"curl -X POST https:\u002F\u002Fexample.monospace.io\u002Fapi\u002Fblog\u002Fsources\u002Fdata \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"apiName\": \"stripe\",\n    \"provider\": \"example\u002Fstripe-connector\",\n    \"config\": { \"apiKey\": \"sk_test_YOUR_STRIPE_KEY\" },\n    \"permissions\": [\n      { \"permission\": \"net:api.stripe.com\", \"reason\": \"Read and write customers, products and prices through the Stripe API\" }\n    ]\n  }'\n",[483,4417,4418,4431,4439,4447,4453,4458,4462,4466,4470,4474,4478],{"__ignoreMap":637},[766,4419,4420,4422,4424,4426,4429],{"class":768,"line":769},[766,4421,773],{"class":772},[766,4423,2862],{"class":772},[766,4425,2865],{"class":779},[766,4427,4428],{"class":779}," https:\u002F\u002Fexample.monospace.io\u002Fapi\u002Fblog\u002Fsources\u002Fdata",[766,4430,783],{"class":772},[766,4432,4433,4435,4437],{"class":768,"line":786},[766,4434,789],{"class":772},[766,4436,2877],{"class":779},[766,4438,783],{"class":772},[766,4440,4441,4443,4445],{"class":768,"line":797},[766,4442,789],{"class":772},[766,4444,2886],{"class":779},[766,4446,783],{"class":772},[766,4448,4449,4451],{"class":768,"line":1377},[766,4450,2893],{"class":772},[766,4452,2896],{"class":779},[766,4454,4455],{"class":768,"line":1390},[766,4456,4457],{"class":779},"    \"apiName\": \"stripe\",\n",[766,4459,4460],{"class":768,"line":1403},[766,4461,2901],{"class":779},[766,4463,4464],{"class":768,"line":1416},[766,4465,2906],{"class":779},[766,4467,4468],{"class":768,"line":1429},[766,4469,2911],{"class":779},[766,4471,4472],{"class":768,"line":1442},[766,4473,2916],{"class":779},[766,4475,4476],{"class":768,"line":1451},[766,4477,1652],{"class":779},[766,4479,4480],{"class":768,"line":1457},[766,4481,2925],{"class":779},[757,4483,4485],{"className":2146,"code":4484,"filename":2118,"language":2149,"meta":637,"style":637},"const response = await fetch('https:\u002F\u002Fexample.monospace.io\u002Fapi\u002Fblog\u002Fsources\u002Fdata', {\n  method: 'POST',\n  headers: {\n    'Authorization': 'Bearer YOUR_API_KEY',\n    'Content-Type': 'application\u002Fjson',\n  },\n  body: JSON.stringify({\n    apiName: 'stripe',\n    provider: 'example\u002Fstripe-connector',\n    config: { apiKey: 'sk_test_YOUR_STRIPE_KEY' },\n    permissions: [\n      { permission: 'net:api.stripe.com', reason: 'Read and write customers, products and prices through the Stripe API' },\n    ],\n  }),\n});\n",[483,4486,4487,4506,4514,4518,4528,4538,4542,4554,4564,4572,4580,4584,4596,4600,4604],{"__ignoreMap":637},[766,4488,4489,4491,4493,4495,4497,4499,4501,4504],{"class":768,"line":769},[766,4490,2935],{"class":2156},[766,4492,2242],{"class":772},[766,4494,2206],{"class":2156},[766,4496,2942],{"class":2156},[766,4498,2945],{"class":772},[766,4500,2163],{"class":1347},[766,4502,4503],{"class":779},"'https:\u002F\u002Fexample.monospace.io\u002Fapi\u002Fblog\u002Fsources\u002Fdata'",[766,4505,2953],{"class":1347},[766,4507,4508,4510,4512],{"class":768,"line":786},[766,4509,2958],{"class":1347},[766,4511,2961],{"class":779},[766,4513,1362],{"class":1347},[766,4515,4516],{"class":768,"line":797},[766,4517,2968],{"class":1347},[766,4519,4520,4522,4524,4526],{"class":768,"line":1377},[766,4521,2973],{"class":779},[766,4523,1026],{"class":1347},[766,4525,2978],{"class":779},[766,4527,1362],{"class":1347},[766,4529,4530,4532,4534,4536],{"class":768,"line":1390},[766,4531,2985],{"class":779},[766,4533,1026],{"class":1347},[766,4535,2990],{"class":779},[766,4537,1362],{"class":1347},[766,4539,4540],{"class":768,"line":1403},[766,4541,2997],{"class":1347},[766,4543,4544,4546,4548,4550,4552],{"class":768,"line":1416},[766,4545,3002],{"class":1347},[766,4547,3005],{"class":772},[766,4549,495],{"class":1347},[766,4551,3010],{"class":772},[766,4553,3013],{"class":1347},[766,4555,4556,4559,4562],{"class":768,"line":1429},[766,4557,4558],{"class":1347},"    apiName: ",[766,4560,4561],{"class":779},"'stripe'",[766,4563,1362],{"class":1347},[766,4565,4566,4568,4570],{"class":768,"line":1442},[766,4567,3018],{"class":1347},[766,4569,3021],{"class":779},[766,4571,1362],{"class":1347},[766,4573,4574,4576,4578],{"class":768,"line":1451},[766,4575,3028],{"class":1347},[766,4577,3031],{"class":779},[766,4579,3034],{"class":1347},[766,4581,4582],{"class":768,"line":1457},[766,4583,3039],{"class":1347},[766,4585,4586,4588,4590,4592,4594],{"class":768,"line":1470},[766,4587,3044],{"class":1347},[766,4589,3047],{"class":779},[766,4591,3050],{"class":1347},[766,4593,3053],{"class":779},[766,4595,3034],{"class":1347},[766,4597,4598],{"class":768,"line":1483},[766,4599,3060],{"class":1347},[766,4601,4602],{"class":768,"line":1495},[766,4603,3065],{"class":1347},[766,4605,4606],{"class":768,"line":1507},[766,4607,3070],{"class":1347},[459,4609,4610,4611,4614],{},"In Studio, enter the same configuration in the data source's JSON configuration editor. Add ",[483,4612,4613],{},"\"enableWrites\": false"," for a read-only data source.",[459,4616,4617,4619,4620,4623,4624,4626,4627,549,4630,495],{},[463,4618,736],{}," the create answers ",[483,4621,4622],{},"200"," with the data source's id, and ",[483,4625,585],{}," offers every operation except ",[483,4628,4629],{},"deleteMany",[483,4631,4632],{},"deleteOne",[459,4634,4635,4636,495],{},"The data source keeps this schema. When you change a declaration later, rebuild and refresh the data source's schema; see ",[472,4637,4639],{"href":4638},"\u002Fdeveloper\u002Fextensions\u002Fdata-connectors\u002Fdata-sources#update-data-sources-after-an-extension-update","Update Data Sources After an Extension Update",[455,4641,4643],{"id":4642},"_5-implement-reads","5. Implement Reads",[459,4645,4646,4647,4649],{},"Stripe has a ",[463,4648,506],{},": a few list parameters with fixed meanings, and no filter language. The connector plans each filter into a union of exact Stripe requests, or refuses it before sending anything.",[2109,4651,4653],{"id":4652},"plan-the-filter","Plan the Filter",[459,4655,4656,4659],{},[483,4657,4658],{},"planRequests"," turns a filter into list requests with parameters, or retrieves by id. It makes no requests itself:",[757,4661,4664],{"className":2146,"code":4662,"filename":4663,"language":2149,"meta":637,"style":637},"\u002F**\n * One request to Stripe. A `list` request returns exactly the items of one filter branch, in\n * Stripe's newest-first order. A `retrieve` request fetches objects by id; the caller checks the\n * rest of the filter on them in memory, which stays cheap because the ids bound the work.\n *\u002F\nexport type StripeRequest =\n    | { readonly kind: 'list'; readonly parameters: Readonly\u003CRecord\u003Cstring, string>> }\n    | { readonly kind: 'retrieve'; readonly ids: readonly string[] };\n\u002F\u002F …\n\u002F**\n * Turns a filter into Stripe requests whose union is exactly the matching items. A filter Stripe\n * can't express is refused rather than answered by reading every item, unless top-level id\n * constraints bound the candidates.\n *\u002F\nexport function planRequests(resource: ResourceSpec, filter: FilterSerialized | undefined): StripeRequest[] {\n    requireDeclared(resource, filter);\n    const ids = topLevelIds(filter);\n\n    if (ids !== undefined) {\n        \u002F\u002F The retrieved objects are re-checked against the whole filter in memory. Refuse a filter that\n        \u002F\u002F check can't evaluate now, before any request.\n        requireEvaluable(resource, filter);\n        return ids.length === 0 ? [] : [{ kind: 'retrieve', ids }];\n    }\n\n    let branches: Branch[];\n\n    try {\n        branches = filter === undefined ? [EVERYTHING] : toBranches(resource, filter);\n    }\n    catch (error) {\n        if (!(error instanceof NotExpressible)) throw error;\n        throw new QueryRejected(`Stripe can't filter \\`${resource.name}\\` by ${error.message} without reading every item.`);\n    }\n\n    \u002F\u002F …\n    if (requests.size > MAX_REQUESTS) throw tooManyRequests(resource);\n    return [...requests.values()];\n}\n","src\u002Fdata-connectors\u002Fstripe\u002Fplan.ts",[483,4665,4666,4670,4675,4680,4685,4689,4702,4745,4772,4776,4780,4785,4790,4795,4799,4838,4855,4873,4877,4892,4897,4902,4917,4954,4958,4962,4977,4981,4988,5027,5031,5043,5074,5119,5123,5127,5132,5165,5184],{"__ignoreMap":637},[766,4667,4668],{"class":768,"line":769},[766,4669,3146],{"class":2250},[766,4671,4672],{"class":768,"line":786},[766,4673,4674],{"class":2250}," * One request to Stripe. A `list` request returns exactly the items of one filter branch, in\n",[766,4676,4677],{"class":768,"line":797},[766,4678,4679],{"class":2250}," * Stripe's newest-first order. A `retrieve` request fetches objects by id; the caller checks the\n",[766,4681,4682],{"class":768,"line":1377},[766,4683,4684],{"class":2250}," * rest of the filter on them in memory, which stays cheap because the ids bound the work.\n",[766,4686,4687],{"class":768,"line":1390},[766,4688,3161],{"class":2250},[766,4690,4691,4693,4696,4699],{"class":768,"line":1403},[766,4692,3166],{"class":2156},[766,4694,4695],{"class":2156}," type",[766,4697,4698],{"class":772}," StripeRequest",[766,4700,4701],{"class":2156}," =\n",[766,4703,4704,4707,4709,4712,4715,4718,4720,4722,4725,4728,4731,4734,4736,4738,4740,4742],{"class":768,"line":1416},[766,4705,4706],{"class":2156},"    |",[766,4708,2230],{"class":1347},[766,4710,4711],{"class":2156},"readonly",[766,4713,4714],{"class":2156}," kind:",[766,4716,4717],{"class":779}," 'list'",[766,4719,1137],{"class":1347},[766,4721,4711],{"class":2156},[766,4723,4724],{"class":2156}," parameters:",[766,4726,4727],{"class":772}," Readonly",[766,4729,4730],{"class":1347},"\u003C",[766,4732,4733],{"class":772},"Record",[766,4735,4730],{"class":1347},[766,4737,1989],{"class":1353},[766,4739,546],{"class":1347},[766,4741,1989],{"class":1353},[766,4743,4744],{"class":1347},">> }\n",[766,4746,4747,4749,4751,4753,4755,4758,4760,4762,4765,4767,4769],{"class":768,"line":1429},[766,4748,4706],{"class":2156},[766,4750,2230],{"class":1347},[766,4752,4711],{"class":2156},[766,4754,4714],{"class":2156},[766,4756,4757],{"class":779}," 'retrieve'",[766,4759,1137],{"class":1347},[766,4761,4711],{"class":2156},[766,4763,4764],{"class":2156}," ids:",[766,4766,4037],{"class":2156},[766,4768,2185],{"class":1353},[766,4770,4771],{"class":1347},"[] };\n",[766,4773,4774],{"class":768,"line":1442},[766,4775,4115],{"class":2250},[766,4777,4778],{"class":768,"line":1451},[766,4779,3146],{"class":2250},[766,4781,4782],{"class":768,"line":1457},[766,4783,4784],{"class":2250}," * Turns a filter into Stripe requests whose union is exactly the matching items. A filter Stripe\n",[766,4786,4787],{"class":768,"line":1470},[766,4788,4789],{"class":2250}," * can't express is refused rather than answered by reading every item, unless top-level id\n",[766,4791,4792],{"class":768,"line":1483},[766,4793,4794],{"class":2250}," * constraints bound the candidates.\n",[766,4796,4797],{"class":768,"line":1495},[766,4798,3161],{"class":2250},[766,4800,4801,4803,4806,4809,4811,4814,4816,4818,4821,4824,4827,4829,4831,4833,4835],{"class":768,"line":1507},[766,4802,3166],{"class":2156},[766,4804,4805],{"class":2156}," function",[766,4807,4808],{"class":772}," planRequests",[766,4810,2163],{"class":1347},[766,4812,4813],{"class":2156},"resource:",[766,4815,4165],{"class":772},[766,4817,546],{"class":1347},[766,4819,4820],{"class":2156},"filter:",[766,4822,4823],{"class":772}," FilterSerialized",[766,4825,4826],{"class":2156}," |",[766,4828,2494],{"class":1353},[766,4830,529],{"class":1347},[766,4832,2062],{"class":2156},[766,4834,4698],{"class":772},[766,4836,4837],{"class":1347},"[] {\n",[766,4839,4840,4843,4845,4848,4850,4853],{"class":768,"line":1519},[766,4841,4842],{"class":772},"    requireDeclared",[766,4844,2163],{"class":1347},[766,4846,4847],{"class":2214},"resource",[766,4849,546],{"class":1347},[766,4851,4852],{"class":2214},"filter",[766,4854,2223],{"class":1347},[766,4856,4857,4859,4862,4864,4867,4869,4871],{"class":768,"line":1531},[766,4858,2200],{"class":2156},[766,4860,4861],{"class":772}," ids",[766,4863,2206],{"class":2156},[766,4865,4866],{"class":772}," topLevelIds",[766,4868,2163],{"class":1347},[766,4870,4852],{"class":2214},[766,4872,2223],{"class":1347},[766,4874,4875],{"class":768,"line":1543},[766,4876,2317],{"emptyLinePlaceholder":2316},[766,4878,4879,4881,4883,4886,4888,4890],{"class":768,"line":1552},[766,4880,2332],{"class":2156},[766,4882,639],{"class":1347},[766,4884,4885],{"class":2214},"ids",[766,4887,2491],{"class":2156},[766,4889,2494],{"class":772},[766,4891,2444],{"class":1347},[766,4893,4894],{"class":768,"line":1583},[766,4895,4896],{"class":2250},"        \u002F\u002F The retrieved objects are re-checked against the whole filter in memory. Refuse a filter that\n",[766,4898,4899],{"class":768,"line":1596},[766,4900,4901],{"class":2250},"        \u002F\u002F check can't evaluate now, before any request.\n",[766,4903,4904,4907,4909,4911,4913,4915],{"class":768,"line":1604},[766,4905,4906],{"class":772},"        requireEvaluable",[766,4908,2163],{"class":1347},[766,4910,4847],{"class":2214},[766,4912,546],{"class":1347},[766,4914,4852],{"class":2214},[766,4916,2223],{"class":1347},[766,4918,4919,4921,4923,4925,4928,4930,4933,4936,4939,4941,4944,4947,4949,4951],{"class":768,"line":1631},[766,4920,2661],{"class":2156},[766,4922,4861],{"class":2214},[766,4924,495],{"class":1347},[766,4926,4927],{"class":1353},"length",[766,4929,2339],{"class":2156},[766,4931,4932],{"class":772}," 0",[766,4934,4935],{"class":2156}," ?",[766,4937,4938],{"class":1347}," [] ",[766,4940,2062],{"class":2156},[766,4942,4943],{"class":1347}," [{ kind: ",[766,4945,4946],{"class":779},"'retrieve'",[766,4948,546],{"class":1347},[766,4950,4885],{"class":2214},[766,4952,4953],{"class":1347}," }];\n",[766,4955,4956],{"class":768,"line":1637},[766,4957,2591],{"class":1347},[766,4959,4960],{"class":768,"line":1643},[766,4961,2317],{"emptyLinePlaceholder":2316},[766,4963,4964,4967,4970,4972,4975],{"class":768,"line":1649},[766,4965,4966],{"class":2156},"    let",[766,4968,4969],{"class":2214}," branches",[766,4971,2062],{"class":2156},[766,4973,4974],{"class":772}," Branch",[766,4976,4042],{"class":1347},[766,4978,4979],{"class":768,"line":1655},[766,4980,2317],{"emptyLinePlaceholder":2316},[766,4982,4983,4986],{"class":768,"line":2678},[766,4984,4985],{"class":2156},"    try",[766,4987,2195],{"class":1347},[766,4989,4990,4993,4995,4997,4999,5001,5003,5006,5009,5012,5014,5017,5019,5021,5023,5025],{"class":768,"line":2683},[766,4991,4992],{"class":2214},"        branches",[766,4994,2206],{"class":2156},[766,4996,3210],{"class":2214},[766,4998,2339],{"class":2156},[766,5000,2494],{"class":772},[766,5002,4935],{"class":2156},[766,5004,5005],{"class":1347}," [",[766,5007,5008],{"class":772},"EVERYTHING",[766,5010,5011],{"class":1347},"] ",[766,5013,2062],{"class":2156},[766,5015,5016],{"class":772}," toBranches",[766,5018,2163],{"class":1347},[766,5020,4847],{"class":2214},[766,5022,546],{"class":1347},[766,5024,4852],{"class":2214},[766,5026,2223],{"class":1347},[766,5028,5029],{"class":768,"line":2689},[766,5030,2591],{"class":1347},[766,5032,5033,5036,5038,5041],{"class":768,"line":2719},[766,5034,5035],{"class":2156},"    catch",[766,5037,639],{"class":1347},[766,5039,5040],{"class":2214},"error",[766,5042,2444],{"class":1347},[766,5044,5045,5048,5050,5053,5055,5057,5060,5063,5066,5069,5072],{"class":768,"line":2725},[766,5046,5047],{"class":2156},"        if",[766,5049,639],{"class":1347},[766,5051,5052],{"class":2156},"!",[766,5054,2163],{"class":1347},[766,5056,5040],{"class":2214},[766,5058,5059],{"class":2156}," instanceof",[766,5061,5062],{"class":772}," NotExpressible",[766,5064,5065],{"class":1347},")) ",[766,5067,5068],{"class":2156},"throw",[766,5070,5071],{"class":2214}," error",[766,5073,2245],{"class":1347},[766,5075,5076,5079,5081,5083,5085,5088,5091,5094,5096,5098,5100,5103,5105,5108,5110,5112,5114,5117],{"class":768,"line":2766},[766,5077,5078],{"class":2156},"        throw",[766,5080,2362],{"class":2156},[766,5082,2757],{"class":772},[766,5084,2163],{"class":1347},[766,5086,5087],{"class":779},"`Stripe can't filter ",[766,5089,5090],{"class":772},"\\`",[766,5092,5093],{"class":779},"${",[766,5095,4847],{"class":2214},[766,5097,495],{"class":779},[766,5099,1164],{"class":2214},[766,5101,5102],{"class":779},"}",[766,5104,5090],{"class":772},[766,5106,5107],{"class":779}," by ${",[766,5109,5040],{"class":2214},[766,5111,495],{"class":779},[766,5113,2267],{"class":2214},[766,5115,5116],{"class":779},"} without reading every item.`",[766,5118,2223],{"class":1347},[766,5120,5121],{"class":768,"line":2782},[766,5122,2591],{"class":1347},[766,5124,5125],{"class":768,"line":3557},[766,5126,2317],{"emptyLinePlaceholder":2316},[766,5128,5129],{"class":768,"line":3593},[766,5130,5131],{"class":2250},"    \u002F\u002F …\n",[766,5133,5134,5136,5138,5141,5143,5146,5149,5152,5154,5156,5159,5161,5163],{"class":768,"line":3643},[766,5135,2332],{"class":2156},[766,5137,639],{"class":1347},[766,5139,5140],{"class":2214},"requests",[766,5142,495],{"class":1347},[766,5144,5145],{"class":2214},"size",[766,5147,5148],{"class":2156}," >",[766,5150,5151],{"class":772}," MAX_REQUESTS",[766,5153,2356],{"class":1347},[766,5155,5068],{"class":2156},[766,5157,5158],{"class":772}," tooManyRequests",[766,5160,2163],{"class":1347},[766,5162,4847],{"class":2214},[766,5164,2223],{"class":1347},[766,5166,5167,5169,5171,5174,5176,5178,5181],{"class":768,"line":3648},[766,5168,2769],{"class":2156},[766,5170,5005],{"class":1347},[766,5172,5173],{"class":2156},"...",[766,5175,5140],{"class":2214},[766,5177,495],{"class":1347},[766,5179,5180],{"class":772},"values",[766,5182,5183],{"class":1347},"()];\n",[766,5185,5186],{"class":768,"line":3665},[766,5187,1658],{"class":1347},[1660,5189,5190,5213,5224,5234],{},[1663,5191,5192,5198,5199,5202,5203,549,5206,5208,5209,5212],{},[463,5193,5194,5197],{},[483,5195,5196],{},"toBranches"," walks the filter tree."," ",[483,5200,5201],{},"and"," intersects its children's constraints, and ",[483,5204,5205],{},"or",[483,5207,1032],{}," fan out into one branch per value. A negation, a field compared with a field, or ",[483,5210,5211],{},"field = null"," can't be expressed, so the plan refuses it.",[1663,5214,5215,5221,5222,495],{},[463,5216,5217,5220],{},[483,5218,5219],{},"requireDeclared"," runs first."," Engine sends filters to the connector without checking them against the declaration. So the connector refuses an undeclared field or operator itself, with a plain ",[483,5223,2811],{},[1663,5225,5226,5229,5230,5233],{},[463,5227,5228],{},"Values outside an enum match nothing."," The plan never sends ",[483,5231,5232],{},"type=bogus",", which Stripe would reject. It sends no request for that value instead.",[1663,5235,5236,5239,5240,495],{},[463,5237,5238],{},"Fan-out is bounded."," A filter that plans more than 250 requests is refused with ",[483,5241,5242],{},"QueryRejected",[2109,5244,5246],{"id":5245},"convert-timestamps-exactly","Convert Timestamps Exactly",[459,5248,5249,5250,5252,5253,1942,5256,5258,5259,5262,5263,5266,5267,5270],{},"Stripe stores ",[483,5251,552],{}," in whole seconds, and Engine sends RFC 3339 timestamps that can carry a fraction of a second. ",[483,5254,5255],{},"parseInstant",[483,5257,1786],{}," parses them strictly and keeps every fractional digit. ",[483,5260,5261],{},"Date.parse"," alone would accept ",[483,5264,5265],{},"2026",", drop digits below the millisecond, and roll ",[483,5268,5269],{},"2026-02-30"," over to March 2nd.",[459,5272,5273,5276],{},[483,5274,5275],{},"createdBranch"," turns each comparison into an exact inclusive range of whole seconds:",[757,5278,5280],{"className":2146,"code":5279,"filename":4663,"language":2149,"meta":637,"style":637},"\u002F**\n * Stripe stores `created` in whole seconds, so each comparison becomes an exact inclusive range.\n * A timestamp with a fraction lies between two whole seconds: `created >= 10.5` is `created >= 11`.\n *\u002F\nfunction createdBranch(operator: FilterOperator, value: Value): Branch {\n    const { seconds, nanoseconds } = parseInstant(value);\n    const hasFraction = nanoseconds > 0;\n\n    switch (operator) {\n        \u002F\u002F A whole second never equals a timestamp with a fraction: lower > upper, so no request is sent.\n        case 'equals': return { ...EVERYTHING, lower: hasFraction ? seconds + 1 : seconds, upper: seconds };\n        case 'greaterThan': return { ...EVERYTHING, lower: seconds + 1 };\n        case 'greaterThanOrEquals': return { ...EVERYTHING, lower: hasFraction ? seconds + 1 : seconds };\n        case 'lessThan': return { ...EVERYTHING, upper: hasFraction ? seconds : seconds - 1 };\n        case 'lessThanOrEquals': return { ...EVERYTHING, upper: seconds };\n        default: throw new NotExpressible(`\\`created\\` with \\`${operator}\\``);\n    }\n}\n",[483,5281,5282,5286,5291,5296,5300,5331,5359,5377,5381,5392,5397,5443,5470,5505,5541,5564,5605,5609],{"__ignoreMap":637},[766,5283,5284],{"class":768,"line":769},[766,5285,3146],{"class":2250},[766,5287,5288],{"class":768,"line":786},[766,5289,5290],{"class":2250}," * Stripe stores `created` in whole seconds, so each comparison becomes an exact inclusive range.\n",[766,5292,5293],{"class":768,"line":797},[766,5294,5295],{"class":2250}," * A timestamp with a fraction lies between two whole seconds: `created >= 10.5` is `created >= 11`.\n",[766,5297,5298],{"class":768,"line":1377},[766,5299,3161],{"class":2250},[766,5301,5302,5304,5307,5309,5312,5315,5317,5320,5323,5325,5327,5329],{"class":768,"line":1390},[766,5303,2157],{"class":2156},[766,5305,5306],{"class":772}," createdBranch",[766,5308,2163],{"class":1347},[766,5310,5311],{"class":2156},"operator:",[766,5313,5314],{"class":772}," FilterOperator",[766,5316,546],{"class":1347},[766,5318,5319],{"class":2156},"value:",[766,5321,5322],{"class":772}," Value",[766,5324,529],{"class":1347},[766,5326,2062],{"class":2156},[766,5328,4974],{"class":772},[766,5330,2195],{"class":1347},[766,5332,5333,5335,5337,5340,5342,5345,5347,5349,5352,5354,5357],{"class":768,"line":1403},[766,5334,2200],{"class":2156},[766,5336,2230],{"class":1347},[766,5338,5339],{"class":772},"seconds",[766,5341,546],{"class":1347},[766,5343,5344],{"class":772},"nanoseconds",[766,5346,2236],{"class":1347},[766,5348,2239],{"class":2156},[766,5350,5351],{"class":772}," parseInstant",[766,5353,2163],{"class":1347},[766,5355,5356],{"class":2214},"value",[766,5358,2223],{"class":1347},[766,5360,5361,5363,5366,5368,5371,5373,5375],{"class":768,"line":1416},[766,5362,2200],{"class":2156},[766,5364,5365],{"class":772}," hasFraction",[766,5367,2206],{"class":2156},[766,5369,5370],{"class":2214}," nanoseconds",[766,5372,5148],{"class":2156},[766,5374,4932],{"class":772},[766,5376,2245],{"class":1347},[766,5378,5379],{"class":768,"line":1429},[766,5380,2317],{"emptyLinePlaceholder":2316},[766,5382,5383,5385,5387,5390],{"class":768,"line":1442},[766,5384,2432],{"class":2156},[766,5386,639],{"class":1347},[766,5388,5389],{"class":2214},"operator",[766,5391,2444],{"class":1347},[766,5393,5394],{"class":768,"line":1451},[766,5395,5396],{"class":2250},"        \u002F\u002F A whole second never equals a timestamp with a fraction: lower > upper, so no request is sent.\n",[766,5398,5399,5401,5404,5406,5408,5410,5412,5414,5417,5420,5422,5425,5428,5431,5434,5436,5439,5441],{"class":768,"line":1457},[766,5400,2449],{"class":2156},[766,5402,5403],{"class":779}," 'equals'",[766,5405,1026],{"class":1347},[766,5407,2359],{"class":2156},[766,5409,2230],{"class":1347},[766,5411,5173],{"class":2156},[766,5413,5008],{"class":772},[766,5415,5416],{"class":1347},", lower: ",[766,5418,5419],{"class":2214},"hasFraction",[766,5421,4935],{"class":2156},[766,5423,5424],{"class":2214}," seconds",[766,5426,5427],{"class":2156}," +",[766,5429,5430],{"class":772}," 1",[766,5432,5433],{"class":2156}," :",[766,5435,5424],{"class":2214},[766,5437,5438],{"class":1347},", upper: ",[766,5440,5339],{"class":2214},[766,5442,3590],{"class":1347},[766,5444,5445,5447,5450,5452,5454,5456,5458,5460,5462,5464,5466,5468],{"class":768,"line":1470},[766,5446,2449],{"class":2156},[766,5448,5449],{"class":779}," 'greaterThan'",[766,5451,1026],{"class":1347},[766,5453,2359],{"class":2156},[766,5455,2230],{"class":1347},[766,5457,5173],{"class":2156},[766,5459,5008],{"class":772},[766,5461,5416],{"class":1347},[766,5463,5339],{"class":2214},[766,5465,5427],{"class":2156},[766,5467,5430],{"class":772},[766,5469,3590],{"class":1347},[766,5471,5472,5474,5477,5479,5481,5483,5485,5487,5489,5491,5493,5495,5497,5499,5501,5503],{"class":768,"line":1483},[766,5473,2449],{"class":2156},[766,5475,5476],{"class":779}," 'greaterThanOrEquals'",[766,5478,1026],{"class":1347},[766,5480,2359],{"class":2156},[766,5482,2230],{"class":1347},[766,5484,5173],{"class":2156},[766,5486,5008],{"class":772},[766,5488,5416],{"class":1347},[766,5490,5419],{"class":2214},[766,5492,4935],{"class":2156},[766,5494,5424],{"class":2214},[766,5496,5427],{"class":2156},[766,5498,5430],{"class":772},[766,5500,5433],{"class":2156},[766,5502,5424],{"class":2214},[766,5504,3590],{"class":1347},[766,5506,5507,5509,5512,5514,5516,5518,5520,5522,5524,5526,5528,5530,5532,5534,5537,5539],{"class":768,"line":1495},[766,5508,2449],{"class":2156},[766,5510,5511],{"class":779}," 'lessThan'",[766,5513,1026],{"class":1347},[766,5515,2359],{"class":2156},[766,5517,2230],{"class":1347},[766,5519,5173],{"class":2156},[766,5521,5008],{"class":772},[766,5523,5438],{"class":1347},[766,5525,5419],{"class":2214},[766,5527,4935],{"class":2156},[766,5529,5424],{"class":2214},[766,5531,5433],{"class":2156},[766,5533,5424],{"class":2214},[766,5535,5536],{"class":2156}," -",[766,5538,5430],{"class":772},[766,5540,3590],{"class":1347},[766,5542,5543,5545,5548,5550,5552,5554,5556,5558,5560,5562],{"class":768,"line":1507},[766,5544,2449],{"class":2156},[766,5546,5547],{"class":779}," 'lessThanOrEquals'",[766,5549,1026],{"class":1347},[766,5551,2359],{"class":2156},[766,5553,2230],{"class":1347},[766,5555,5173],{"class":2156},[766,5557,5008],{"class":772},[766,5559,5438],{"class":1347},[766,5561,5339],{"class":2214},[766,5563,3590],{"class":1347},[766,5565,5566,5569,5571,5573,5575,5577,5579,5582,5584,5586,5588,5591,5593,5595,5597,5599,5601,5603],{"class":768,"line":1519},[766,5567,5568],{"class":2156},"        default",[766,5570,1026],{"class":1347},[766,5572,5068],{"class":2156},[766,5574,2362],{"class":2156},[766,5576,5062],{"class":772},[766,5578,2163],{"class":1347},[766,5580,5581],{"class":779},"`",[766,5583,5090],{"class":772},[766,5585,552],{"class":779},[766,5587,5090],{"class":772},[766,5589,5590],{"class":779}," with ",[766,5592,5090],{"class":772},[766,5594,5093],{"class":779},[766,5596,5389],{"class":2214},[766,5598,5102],{"class":779},[766,5600,5090],{"class":772},[766,5602,5581],{"class":779},[766,5604,2223],{"class":1347},[766,5606,5607],{"class":768,"line":1531},[766,5608,2591],{"class":1347},[766,5610,5611],{"class":768,"line":1543},[766,5612,1658],{"class":1347},[508,5614,5615,5635],{},[511,5616,5617],{},[514,5618,5619,5624,5630],{},[517,5620,5621,5622],{},"Filter on ",[483,5623,552],{},[517,5625,5626,5629],{},[483,5627,5628],{},"t"," is a whole second",[517,5631,5632,5634],{},[483,5633,5628],{}," has a fraction",[531,5636,5637,5654,5670,5687,5703],{},[514,5638,5639,5644,5649],{},[536,5640,5641],{},[483,5642,5643],{},"> t",[536,5645,5646],{},[483,5647,5648],{},"created[gte]=t+1",[536,5650,5651],{},[483,5652,5653],{},"created[gte]=⌊t⌋+1",[514,5655,5656,5661,5666],{},[536,5657,5658],{},[483,5659,5660],{},">= t",[536,5662,5663],{},[483,5664,5665],{},"created[gte]=t",[536,5667,5668],{},[483,5669,5653],{},[514,5671,5672,5677,5682],{},[536,5673,5674],{},[483,5675,5676],{},"\u003C t",[536,5678,5679],{},[483,5680,5681],{},"created[lte]=t-1",[536,5683,5684],{},[483,5685,5686],{},"created[lte]=⌊t⌋",[514,5688,5689,5694,5699],{},[536,5690,5691],{},[483,5692,5693],{},"\u003C= t",[536,5695,5696],{},[483,5697,5698],{},"created[lte]=t",[536,5700,5701],{},[483,5702,5686],{},[514,5704,5705,5710,5714],{},[536,5706,5707],{},[483,5708,5709],{},"= t",[536,5711,5712],{},[483,5713,897],{},[536,5715,5716],{},"No request: no item can match",[459,5718,5719,5720,5722],{},"A value that isn't a strict RFC 3339 timestamp is refused with ",[483,5721,5242],{}," before any request.",[2109,5724,5726],{"id":5725},"page-and-fill-the-limit","Page and Fill the Limit",[459,5728,5729,5730,5732,5733,5736],{},"Stripe caps a page at 100, and Engine reads a page shorter than ",[483,5731,1076],{}," as the end of the data. So the client keeps paging with ",[483,5734,5735],{},"starting_after"," until it has what the caller asked for:",[757,5738,5740],{"className":2146,"code":5739,"filename":2148,"language":2149,"meta":637,"style":637},"    async* list(path: string, parameters: Readonly\u003CRecord\u003Cstring, string>>, offset = 0, wanted = Infinity): AsyncGenerator\u003CStripeObject> {\n        let startingAfter: string | undefined;\n        let remaining = wanted;\n\n        for (;;) {\n            const query = new URLSearchParams({ ...parameters, limit: String(Math.min(PAGE_SIZE, remaining)) });\n            if (startingAfter !== undefined) query.set('starting_after', startingAfter);\n            else if (offset > 0) query.set('offset', String(offset));\n\n            const response = await this.#send('GET', `${path}?${query}`);\n\n            \u002F\u002F Stripe answers a filter on a reference that doesn't exist, such as `prices?product=` with a\n            \u002F\u002F missing product, with `resource_missing` naming the parameter. No object can match it.\n            if (startingAfter === undefined && isMissingReference(response, parameters)) return;\n\n            const page = parseList(checked(response, 'GET', path));\n            remaining -= page.data.length;\n            yield* page.data;\n\n            const last = page.data.at(-1);\n            if (!page.hasMore || last === undefined || last.id === startingAfter || remaining \u003C= 0) return;\n            startingAfter = last.id;\n        }\n    }\n",[483,5741,5742,5820,5833,5848,5852,5860,5910,5942,5975,5979,6018,6022,6027,6032,6062,6066,6097,6102,6107,6111,6143,6176,6192,6196],{"__ignoreMap":637},[766,5743,5744,5747,5750,5753,5755,5757,5759,5761,5763,5766,5768,5771,5773,5775,5777,5779,5781,5783,5786,5788,5790,5792,5794,5796,5799,5801,5804,5807,5810,5812,5815,5818],{"class":768,"line":769},[766,5745,5746],{"class":2214},"    async",[766,5748,5749],{"class":2156},"*",[766,5751,5752],{"class":772}," list",[766,5754,2163],{"class":1347},[766,5756,2295],{"class":2214},[766,5758,1026],{"class":1347},[766,5760,1989],{"class":2214},[766,5762,546],{"class":1347},[766,5764,5765],{"class":2214},"parameters",[766,5767,1026],{"class":1347},[766,5769,5770],{"class":2214},"Readonly",[766,5772,4730],{"class":2156},[766,5774,4733],{"class":2214},[766,5776,4730],{"class":2156},[766,5778,1989],{"class":2214},[766,5780,546],{"class":1347},[766,5782,1989],{"class":2214},[766,5784,5785],{"class":2156},">>",[766,5787,546],{"class":1347},[766,5789,862],{"class":2214},[766,5791,2206],{"class":2156},[766,5793,4932],{"class":772},[766,5795,546],{"class":1347},[766,5797,5798],{"class":2214},"wanted",[766,5800,2206],{"class":2156},[766,5802,5803],{"class":772}," Infinity",[766,5805,5806],{"class":1347},"): ",[766,5808,5809],{"class":2214},"AsyncGenerator",[766,5811,4730],{"class":2156},[766,5813,5814],{"class":2214},"StripeObject",[766,5816,5817],{"class":2156},">",[766,5819,2195],{"class":1347},[766,5821,5822,5825,5827,5829,5831],{"class":768,"line":786},[766,5823,5824],{"class":1347},"        let startingAfter: ",[766,5826,1989],{"class":2214},[766,5828,4826],{"class":2156},[766,5830,2494],{"class":772},[766,5832,2245],{"class":1347},[766,5834,5835,5838,5841,5843,5846],{"class":768,"line":797},[766,5836,5837],{"class":2214},"        let",[766,5839,5840],{"class":2214}," remaining",[766,5842,2206],{"class":2156},[766,5844,5845],{"class":2214}," wanted",[766,5847,2245],{"class":1347},[766,5849,5850],{"class":768,"line":1377},[766,5851,2317],{"emptyLinePlaceholder":2316},[766,5853,5854,5857],{"class":768,"line":1390},[766,5855,5856],{"class":772},"        for",[766,5858,5859],{"class":1347}," (;;) {\n",[766,5861,5862,5865,5868,5870,5872,5875,5878,5880,5882,5884,5887,5889,5892,5894,5897,5899,5902,5904,5907],{"class":768,"line":1403},[766,5863,5864],{"class":1347},"            const ",[766,5866,5867],{"class":2214},"query",[766,5869,2206],{"class":2156},[766,5871,2362],{"class":2156},[766,5873,5874],{"class":772}," URLSearchParams",[766,5876,5877],{"class":1347},"({ ",[766,5879,5173],{"class":2156},[766,5881,5765],{"class":2214},[766,5883,3729],{"class":1347},[766,5885,5886],{"class":772},"String",[766,5888,2163],{"class":1347},[766,5890,5891],{"class":2214},"Math",[766,5893,495],{"class":1347},[766,5895,5896],{"class":772},"min",[766,5898,2163],{"class":1347},[766,5900,5901],{"class":772},"PAGE_SIZE",[766,5903,546],{"class":1347},[766,5905,5906],{"class":2214},"remaining",[766,5908,5909],{"class":1347},")) });\n",[766,5911,5912,5914,5916,5919,5922,5925,5928,5931,5933,5936,5938,5940],{"class":768,"line":1416},[766,5913,2470],{"class":772},[766,5915,639],{"class":1347},[766,5917,5918],{"class":2156},"startingAfter",[766,5920,5921],{"class":1347}," !== ",[766,5923,5924],{"class":2156},"undefined",[766,5926,5927],{"class":1347},") query.",[766,5929,5930],{"class":772},"set",[766,5932,2163],{"class":1347},[766,5934,5935],{"class":779},"'starting_after'",[766,5937,546],{"class":1347},[766,5939,5918],{"class":2156},[766,5941,2223],{"class":1347},[766,5943,5944,5947,5950,5952,5954,5957,5959,5961,5964,5966,5968,5970,5972],{"class":768,"line":1429},[766,5945,5946],{"class":1347},"            else ",[766,5948,5949],{"class":772},"if",[766,5951,639],{"class":1347},[766,5953,862],{"class":2156},[766,5955,5956],{"class":1347}," > 0) query.",[766,5958,5930],{"class":772},[766,5960,2163],{"class":1347},[766,5962,5963],{"class":779},"'offset'",[766,5965,546],{"class":1347},[766,5967,5886],{"class":2156},[766,5969,2163],{"class":1347},[766,5971,862],{"class":2156},[766,5973,5974],{"class":1347},"));\n",[766,5976,5977],{"class":768,"line":1442},[766,5978,2317],{"emptyLinePlaceholder":2316},[766,5980,5981,5983,5985,5987,5989,5992,5994,5997,5999,6002,6004,6007,6009,6012,6014,6016],{"class":768,"line":1451},[766,5982,5864],{"class":1347},[766,5984,2215],{"class":2214},[766,5986,2206],{"class":2156},[766,5988,2942],{"class":2156},[766,5990,5991],{"class":772}," this",[766,5993,495],{"class":1347},[766,5995,5996],{"class":772},"#send",[766,5998,2163],{"class":1347},[766,6000,6001],{"class":779},"'GET'",[766,6003,546],{"class":1347},[766,6005,6006],{"class":779},"`${",[766,6008,2295],{"class":2214},[766,6010,6011],{"class":779},"}?${",[766,6013,5867],{"class":2214},[766,6015,2421],{"class":779},[766,6017,2223],{"class":1347},[766,6019,6020],{"class":768,"line":1457},[766,6021,2317],{"emptyLinePlaceholder":2316},[766,6023,6024],{"class":768,"line":1470},[766,6025,6026],{"class":2250},"            \u002F\u002F Stripe answers a filter on a reference that doesn't exist, such as `prices?product=` with a\n",[766,6028,6029],{"class":768,"line":1483},[766,6030,6031],{"class":2250},"            \u002F\u002F missing product, with `resource_missing` naming the parameter. No object can match it.\n",[766,6033,6034,6036,6038,6040,6043,6045,6048,6051,6053,6055,6057,6059],{"class":768,"line":1495},[766,6035,2470],{"class":772},[766,6037,639],{"class":1347},[766,6039,5918],{"class":2156},[766,6041,6042],{"class":1347}," === ",[766,6044,5924],{"class":2156},[766,6046,6047],{"class":1347}," && ",[766,6049,6050],{"class":2156},"isMissingReference",[766,6052,2163],{"class":1347},[766,6054,2215],{"class":2156},[766,6056,546],{"class":1347},[766,6058,5765],{"class":2156},[766,6060,6061],{"class":1347},")) return;\n",[766,6063,6064],{"class":768,"line":1507},[766,6065,2317],{"emptyLinePlaceholder":2316},[766,6067,6068,6070,6073,6075,6078,6080,6083,6085,6087,6089,6091,6093,6095],{"class":768,"line":1519},[766,6069,5864],{"class":1347},[766,6071,6072],{"class":2214},"page",[766,6074,2206],{"class":2156},[766,6076,6077],{"class":772}," parseList",[766,6079,2163],{"class":1347},[766,6081,6082],{"class":772},"checked",[766,6084,2163],{"class":1347},[766,6086,2215],{"class":2214},[766,6088,546],{"class":1347},[766,6090,6001],{"class":779},[766,6092,546],{"class":1347},[766,6094,2295],{"class":2214},[766,6096,5974],{"class":1347},[766,6098,6099],{"class":768,"line":1531},[766,6100,6101],{"class":1347},"            remaining -= page.data.length;\n",[766,6103,6104],{"class":768,"line":1543},[766,6105,6106],{"class":1347},"            yield* page.data;\n",[766,6108,6109],{"class":768,"line":1552},[766,6110,2317],{"emptyLinePlaceholder":2316},[766,6112,6113,6115,6118,6120,6123,6125,6128,6130,6133,6135,6138,6141],{"class":768,"line":1583},[766,6114,5864],{"class":1347},[766,6116,6117],{"class":2214},"last",[766,6119,2206],{"class":2156},[766,6121,6122],{"class":2214}," page",[766,6124,495],{"class":1347},[766,6126,6127],{"class":2214},"data",[766,6129,495],{"class":1347},[766,6131,6132],{"class":772},"at",[766,6134,2163],{"class":1347},[766,6136,6137],{"class":2156},"-",[766,6139,6140],{"class":772},"1",[766,6142,2223],{"class":1347},[766,6144,6145,6147,6150,6152,6154,6156,6159,6161,6164,6166,6169,6171,6173],{"class":768,"line":1596},[766,6146,2470],{"class":772},[766,6148,6149],{"class":1347}," (!page.hasMore || ",[766,6151,6117],{"class":2156},[766,6153,6042],{"class":1347},[766,6155,5924],{"class":2156},[766,6157,6158],{"class":1347}," || last.id === ",[766,6160,5918],{"class":2156},[766,6162,6163],{"class":1347}," || ",[766,6165,5906],{"class":2156},[766,6167,6168],{"class":1347}," \u003C",[766,6170,2239],{"class":2156},[766,6172,4932],{"class":772},[766,6174,6175],{"class":1347},") return;\n",[766,6177,6178,6181,6183,6186,6188,6190],{"class":768,"line":1604},[766,6179,6180],{"class":2214},"            startingAfter",[766,6182,2206],{"class":2156},[766,6184,6185],{"class":2214}," last",[766,6187,495],{"class":1347},[766,6189,545],{"class":2214},[766,6191,2245],{"class":1347},[766,6193,6194],{"class":768,"line":1631},[766,6195,1646],{"class":1347},[766,6197,6198],{"class":768,"line":1637},[766,6199,2591],{"class":1347},[1660,6201,6202,6211],{},[1663,6203,6204,6207,6208,6210],{},[463,6205,6206],{},"A missing reference is no match."," A ",[483,6209,592],{}," filter naming a product that doesn't exist returns no prices, not an error.",[1663,6212,6213,6216],{},[463,6214,6215],{},"The loop can't spin."," It stops when Stripe has no more, the page is empty, the cursor doesn't advance, or it has what the caller wants.",[459,6218,6219,6220,1942,6223,6225,6226,6229],{},"With several requests, ",[483,6221,6222],{},"findItems",[483,6224,1806],{}," reads each list to ",[483,6227,6228],{},"offset + limit",", merges the results newest first, and slices. Stripe doesn't document its order within one second. So each list also reads every object created in the same second as its last one, and the merge breaks ties by id. Consecutive pages then never overlap or skip an item.",[2109,6231,6233],{"id":6232},"re-check-every-item-the-plan-doesnt-prove","Re-Check Every Item the Plan Doesn't Prove",[459,6235,6236,6237,6240,6241,495],{},"A single list request is exact by construction, so it needs no re-check. Retrieved ids and merged fan-outs pass through ",[483,6238,6239],{},"matches"," before they're sliced. It uses SQL three-valued logic and compares timestamps as nanoseconds. See ",[472,6242,6244],{"href":6243},"\u002Fdeveloper\u002Fextensions\u002Fdata-connectors\u002Fdata-source-mapping#re-check-every-item","Re-Check Every Item",[2109,6246,2047],{"id":6247},"refuse-what-you-cant-answer",[459,6249,6250],{},"Refuse a request you can't answer correctly, before any request to Stripe when you can. Never return a silently shortened page. Pick the class by whose request it is:",[1660,6252,6253,6263],{},[1663,6254,6255,6259,6260,6262],{},[463,6256,6257],{},[483,6258,5242],{}," for a valid request Stripe can't serve as asked, such as a negation without ids. Engine answers ",[483,6261,3080],{},", and the message tells the caller what to change.",[1663,6264,6265,6269,6270,495],{},[463,6266,2808,6267],{},[483,6268,2811],{}," for a request outside the declaration, such as another sort. Engine refuses those from callers, so they come from Engine itself or a schema not refreshed after an extension update. Engine answers ",[483,6271,6272],{},"500",[459,6274,6275,6276,6279,6280,6284,6285,1942,6288,6290,6291,6293,6294,6296,6297,6299],{},"The fetch budget covers reads Engine leaves unbounded, such as a caller's ",[483,6277,6278],{},"limit=-1"," or a relation read (see ",[472,6281,6283],{"href":6282},"\u002Freference\u002Fextensions\u002Fdata-connectors\u002Fapi#relation-reads","Relation Reads","). ",[483,6286,6287],{},"FetchBudget",[483,6289,1806],{}," counts every object a read fetches. Past ",[483,6292,2032],{},", it throws ",[483,6295,5242],{},". Each ",[483,6298,1811],{},", and each bulk write's pre-read, gets its own budget; keyed operations spend none.",[459,6301,6302,6303,6305,6306,6308,6309,6311],{},"The caller gets ",[483,6304,3080],{}," \"The data source rejected the query\", with the connector's message nested inside: \"Reading ",[483,6307,485],{}," would fetch more than 5000 Stripe objects. Narrow the filter, request a smaller page, or raise the connector's ",[483,6310,2032],{},".\"",[459,6313,6314,6315,6319],{},"The budget bounds one read, not a caller's whole query. A to-many include can send one read per parent item, up to 16 at once, each with its own budget. See ",[472,6316,6318],{"href":6317},"\u002Freference\u002Fextensions\u002Fdata-connectors\u002Fapi#handle-requests-you-didnt-declare","Handle Requests You Didn't Declare"," for every shape Engine sends on its own.",[459,6321,6322,6324,6325,495],{},[463,6323,736],{}," each read matches what Stripe returns for the same request. The names below assume the workspace's default camelCase naming; see ",[472,6326,6328],{"href":6327},"\u002Fconcepts\u002Fintrospection#api-names","API Names",[459,6330,6331,6332,2062],{},"Read one product with its prices across the relation. The SDK tab uses a client generated after the data source exists; see ",[472,6333,6335],{"href":6334},"\u002Fdeveloper\u002Fsdk\u002Finstallation","SDK Installation",[1193,6337,6338,6508,6531],{},[757,6339,6342],{"className":2146,"code":6340,"filename":6341,"language":2149,"meta":637,"style":637},"import { createClient } from '.\u002Fgenerated\u002Fmonospace';\n\nconst client = createClient({\n  url: 'https:\u002F\u002Fexample.monospace.io',\n  workspace: 'blog',\n  apiKey: 'YOUR_API_KEY',\n});\n\nconst product = await client.products.readOne({\n  key: 'prod_YOUR_PRODUCT',\n  fields: ['id', 'name', 'active'],\n  include: {\n    prices: { fields: ['id', 'unitAmount', 'currency', 'recurringInterval'] },\n  },\n});\n","SDK",[483,6343,6344,6364,6368,6382,6392,6402,6412,6416,6420,6443,6453,6471,6476,6500,6504],{"__ignoreMap":637},[766,6345,6346,6349,6351,6354,6356,6359,6362],{"class":768,"line":769},[766,6347,6348],{"class":2156},"import",[766,6350,2230],{"class":1347},[766,6352,6353],{"class":2214},"createClient",[766,6355,2236],{"class":1347},[766,6357,6358],{"class":2156},"from",[766,6360,6361],{"class":779}," '.\u002Fgenerated\u002Fmonospace'",[766,6363,2245],{"class":1347},[766,6365,6366],{"class":768,"line":786},[766,6367,2317],{"emptyLinePlaceholder":2316},[766,6369,6370,6372,6375,6377,6380],{"class":768,"line":797},[766,6371,2935],{"class":2156},[766,6373,6374],{"class":772}," client",[766,6376,2206],{"class":2156},[766,6378,6379],{"class":772}," createClient",[766,6381,3013],{"class":1347},[766,6383,6384,6387,6390],{"class":768,"line":1377},[766,6385,6386],{"class":1347},"  url: ",[766,6388,6389],{"class":779},"'https:\u002F\u002Fexample.monospace.io'",[766,6391,1362],{"class":1347},[766,6393,6394,6397,6400],{"class":768,"line":1390},[766,6395,6396],{"class":1347},"  workspace: ",[766,6398,6399],{"class":779},"'blog'",[766,6401,1362],{"class":1347},[766,6403,6404,6407,6410],{"class":768,"line":1403},[766,6405,6406],{"class":1347},"  apiKey: ",[766,6408,6409],{"class":779},"'YOUR_API_KEY'",[766,6411,1362],{"class":1347},[766,6413,6414],{"class":768,"line":1416},[766,6415,3070],{"class":1347},[766,6417,6418],{"class":768,"line":1429},[766,6419,2317],{"emptyLinePlaceholder":2316},[766,6421,6422,6424,6427,6429,6431,6433,6435,6437,6439,6441],{"class":768,"line":1442},[766,6423,2935],{"class":2156},[766,6425,6426],{"class":772}," product",[766,6428,2206],{"class":2156},[766,6430,2942],{"class":2156},[766,6432,6374],{"class":2214},[766,6434,495],{"class":1347},[766,6436,563],{"class":2214},[766,6438,495],{"class":1347},[766,6440,1814],{"class":772},[766,6442,3013],{"class":1347},[766,6444,6445,6448,6451],{"class":768,"line":1451},[766,6446,6447],{"class":1347},"  key: ",[766,6449,6450],{"class":779},"'prod_YOUR_PRODUCT'",[766,6452,1362],{"class":1347},[766,6454,6455,6458,6460,6462,6464,6466,6468],{"class":768,"line":1457},[766,6456,6457],{"class":1347},"  fields: [",[766,6459,3702],{"class":779},[766,6461,546],{"class":1347},[766,6463,3618],{"class":779},[766,6465,546],{"class":1347},[766,6467,4225],{"class":779},[766,6469,6470],{"class":1347},"],\n",[766,6472,6473],{"class":768,"line":1470},[766,6474,6475],{"class":1347},"  include: {\n",[766,6477,6478,6481,6483,6485,6488,6490,6493,6495,6498],{"class":768,"line":1483},[766,6479,6480],{"class":1347},"    prices: { fields: [",[766,6482,3702],{"class":779},[766,6484,546],{"class":1347},[766,6486,6487],{"class":779},"'unitAmount'",[766,6489,546],{"class":1347},[766,6491,6492],{"class":779},"'currency'",[766,6494,546],{"class":1347},[766,6496,6497],{"class":779},"'recurringInterval'",[766,6499,1580],{"class":1347},[766,6501,6502],{"class":768,"line":1495},[766,6503,2997],{"class":1347},[766,6505,6506],{"class":768,"line":1507},[766,6507,3070],{"class":1347},[757,6509,6511],{"className":759,"code":6510,"filename":773,"language":762,"meta":637,"style":637},"curl -g \"https:\u002F\u002Fexample.monospace.io\u002Fapi\u002Fblog\u002Fitems\u002Fproducts\u002Fprod_YOUR_PRODUCT?fields=id,name,active&include[prices][fields]=id,unitAmount,currency,recurringInterval\" \\\n  -H \"Authorization: Bearer YOUR_API_KEY\"\n",[483,6512,6513,6524],{"__ignoreMap":637},[766,6514,6515,6517,6519,6522],{"class":768,"line":769},[766,6516,773],{"class":772},[766,6518,776],{"class":772},[766,6520,6521],{"class":779}," \"https:\u002F\u002Fexample.monospace.io\u002Fapi\u002Fblog\u002Fitems\u002Fproducts\u002Fprod_YOUR_PRODUCT?fields=id,name,active&include[prices][fields]=id,unitAmount,currency,recurringInterval\"",[766,6523,783],{"class":772},[766,6525,6526,6528],{"class":768,"line":786},[766,6527,789],{"class":772},[766,6529,6530],{"class":779}," \"Authorization: Bearer YOUR_API_KEY\"\n",[757,6532,6534],{"className":2146,"code":6533,"filename":2118,"language":2149,"meta":637,"style":637},"const params = new URLSearchParams({\n  'fields': 'id,name,active',\n  'include[prices][fields]': 'id,unitAmount,currency,recurringInterval',\n});\n\nconst response = await fetch(\n  `https:\u002F\u002Fexample.monospace.io\u002Fapi\u002Fblog\u002Fitems\u002Fproducts\u002Fprod_YOUR_PRODUCT?${params}`,\n  {\n    headers: {\n      Authorization: 'Bearer YOUR_API_KEY',\n    },\n  },\n);\n\nconst { data } = await response.json();\n",[483,6535,6536,6551,6563,6575,6579,6583,6598,6610,6615,6620,6629,6633,6637,6641,6645],{"__ignoreMap":637},[766,6537,6538,6540,6543,6545,6547,6549],{"class":768,"line":769},[766,6539,2935],{"class":2156},[766,6541,6542],{"class":772}," params",[766,6544,2206],{"class":2156},[766,6546,2362],{"class":2156},[766,6548,5874],{"class":772},[766,6550,3013],{"class":1347},[766,6552,6553,6556,6558,6561],{"class":768,"line":786},[766,6554,6555],{"class":779},"  'fields'",[766,6557,1026],{"class":1347},[766,6559,6560],{"class":779},"'id,name,active'",[766,6562,1362],{"class":1347},[766,6564,6565,6568,6570,6573],{"class":768,"line":797},[766,6566,6567],{"class":779},"  'include[prices][fields]'",[766,6569,1026],{"class":1347},[766,6571,6572],{"class":779},"'id,unitAmount,currency,recurringInterval'",[766,6574,1362],{"class":1347},[766,6576,6577],{"class":768,"line":1377},[766,6578,3070],{"class":1347},[766,6580,6581],{"class":768,"line":1390},[766,6582,2317],{"emptyLinePlaceholder":2316},[766,6584,6585,6587,6589,6591,6593,6595],{"class":768,"line":1403},[766,6586,2935],{"class":2156},[766,6588,2242],{"class":772},[766,6590,2206],{"class":2156},[766,6592,2942],{"class":2156},[766,6594,2945],{"class":772},[766,6596,6597],{"class":1347},"(\n",[766,6599,6600,6603,6606,6608],{"class":768,"line":1416},[766,6601,6602],{"class":779},"  `https:\u002F\u002Fexample.monospace.io\u002Fapi\u002Fblog\u002Fitems\u002Fproducts\u002Fprod_YOUR_PRODUCT?${",[766,6604,6605],{"class":2214},"params",[766,6607,2421],{"class":779},[766,6609,1362],{"class":1347},[766,6611,6612],{"class":768,"line":1429},[766,6613,6614],{"class":1347},"  {\n",[766,6616,6617],{"class":768,"line":1442},[766,6618,6619],{"class":1347},"    headers: {\n",[766,6621,6622,6625,6627],{"class":768,"line":1451},[766,6623,6624],{"class":1347},"      Authorization: ",[766,6626,2978],{"class":779},[766,6628,1362],{"class":1347},[766,6630,6631],{"class":768,"line":1457},[766,6632,3882],{"class":1347},[766,6634,6635],{"class":768,"line":1470},[766,6636,2997],{"class":1347},[766,6638,6639],{"class":768,"line":1483},[766,6640,2223],{"class":1347},[766,6642,6643],{"class":768,"line":1495},[766,6644,2317],{"emptyLinePlaceholder":2316},[766,6646,6647,6649,6651,6653,6655,6657,6659,6661,6663,6665],{"class":768,"line":1507},[766,6648,2935],{"class":2156},[766,6650,2230],{"class":1347},[766,6652,6127],{"class":772},[766,6654,2236],{"class":1347},[766,6656,2239],{"class":2156},[766,6658,2942],{"class":2156},[766,6660,2242],{"class":2214},[766,6662,495],{"class":1347},[766,6664,1340],{"class":772},[766,6666,6667],{"class":1347},"();\n",[459,6669,6670,6671,6674,6675,6677,6678,6680],{},"The product arrives with its prices nested under ",[483,6672,6673],{},"prices.data",". ",[483,6676,1170],{}," is an ",[483,6679,3535],{}," field, so it arrives as a string:",[757,6682,6685],{"className":1337,"code":6683,"filename":6684,"language":1340,"meta":637,"style":637},"{\n  \"data\": {\n    \"id\": \"prod_msfx_starter\",\n    \"name\": \"Fixture Starter\",\n    \"active\": true,\n    \"prices\": {\n      \"data\": [\n        {\n          \"id\": \"price_1UIxWu9H5XlP98EJrPjZftI9\",\n          \"unitAmount\": \"900\",\n          \"currency\": \"eur\",\n          \"recurringInterval\": \"month\"\n        }\n      ]\n    }\n  }\n}\n","response.json",[483,6686,6687,6691,6698,6709,6720,6731,6738,6745,6749,6761,6773,6785,6795,6799,6804,6808,6813],{"__ignoreMap":637},[766,6688,6689],{"class":768,"line":769},[766,6690,1348],{"class":1347},[766,6692,6693,6696],{"class":768,"line":786},[766,6694,6695],{"class":1353},"  \"data\"",[766,6697,1549],{"class":1347},[766,6699,6700,6702,6704,6707],{"class":768,"line":797},[766,6701,1367],{"class":1353},[766,6703,1026],{"class":1347},[766,6705,6706],{"class":779},"\"prod_msfx_starter\"",[766,6708,1362],{"class":1347},[766,6710,6711,6713,6715,6718],{"class":768,"line":1377},[766,6712,1393],{"class":1353},[766,6714,1026],{"class":1347},[766,6716,6717],{"class":779},"\"Fixture Starter\"",[766,6719,1362],{"class":1347},[766,6721,6722,6725,6727,6729],{"class":768,"line":1390},[766,6723,6724],{"class":1353},"    \"active\"",[766,6726,1026],{"class":1347},[766,6728,2017],{"class":772},[766,6730,1362],{"class":1347},[766,6732,6733,6736],{"class":768,"line":1403},[766,6734,6735],{"class":1353},"    \"prices\"",[766,6737,1549],{"class":1347},[766,6739,6740,6743],{"class":768,"line":1416},[766,6741,6742],{"class":1353},"      \"data\"",[766,6744,1448],{"class":1347},[766,6746,6747],{"class":768,"line":1429},[766,6748,1454],{"class":1347},[766,6750,6751,6754,6756,6759],{"class":768,"line":1442},[766,6752,6753],{"class":1353},"          \"id\"",[766,6755,1026],{"class":1347},[766,6757,6758],{"class":779},"\"price_1UIxWu9H5XlP98EJrPjZftI9\"",[766,6760,1362],{"class":1347},[766,6762,6763,6766,6768,6771],{"class":768,"line":1451},[766,6764,6765],{"class":1353},"          \"unitAmount\"",[766,6767,1026],{"class":1347},[766,6769,6770],{"class":779},"\"900\"",[766,6772,1362],{"class":1347},[766,6774,6775,6778,6780,6783],{"class":768,"line":1457},[766,6776,6777],{"class":1353},"          \"currency\"",[766,6779,1026],{"class":1347},[766,6781,6782],{"class":779},"\"eur\"",[766,6784,1362],{"class":1347},[766,6786,6787,6790,6792],{"class":768,"line":1470},[766,6788,6789],{"class":1353},"          \"recurringInterval\"",[766,6791,1026],{"class":1347},[766,6793,6794],{"class":779},"\"month\"\n",[766,6796,6797],{"class":768,"line":1483},[766,6798,1646],{"class":1347},[766,6800,6801],{"class":768,"line":1495},[766,6802,6803],{"class":1347},"      ]\n",[766,6805,6806],{"class":768,"line":1507},[766,6807,2591],{"class":1347},[766,6809,6810],{"class":768,"line":1519},[766,6811,6812],{"class":1347},"  }\n",[766,6814,6815],{"class":768,"line":1531},[766,6816,1658],{"class":1347},[459,6818,6819,6820,6822,6823,5198,6825,6828,6829,6831],{},"Also check that a ",[483,6821,1076],{}," above 100 returns Stripe's first page plus the next, in order. A ",[483,6824,552],{},[483,6826,6827],{},"_gte"," filter one microsecond after a customer's ",[483,6830,552],{}," excludes that customer.",[455,6833,6835],{"id":6834},"_6-implement-keyed-operations-and-writes","6. Implement Keyed Operations and Writes",[459,6837,6838,546,6840,549,6843,6845,6846,6849],{},[483,6839,1814],{},[483,6841,6842],{},"updateOne",[483,6844,4632],{}," address one item by its key, plus an optional guard filter. ",[483,6847,6848],{},"findByKey"," retrieves the item by id, then checks the guard in memory:",[757,6851,6854],{"className":2146,"code":6852,"filename":6853,"language":2149,"meta":637,"style":637},"\u002F**\n * Retrieves the keyed item and checks the guard on it in memory. A missing object, a deleted one\n * and a guard miss all answer `undefined`: a miss, so a keyed write changes nothing.\n *\u002F\nexport async function findByKey(context: QueryContext, resource: ResourceSpec, query: KeyedOperation): Promise\u003CItem | undefined> {\n    const id = query.key.id;\n\n    if (Object.keys(query.key).length !== 1 || id === undefined) {\n        throw new Error(`\\`${resource.name}\\` keys are a single \\`id\\`.`);\n    }\n\n    \u002F\u002F The guard is checked in memory after the retrieve. Refuse one that isn't declared, or that the\n    \u002F\u002F check can't evaluate, first.\n    requireDeclared(resource, query.filter);\n    requireEvaluable(resource, query.filter);\n\n    \u002F\u002F Only a string can be a Stripe id. The client also skips ids Stripe can't have.\n    if (typeof id !== 'string') return undefined;\n\n    const object = await context.client.retrieve(resource.path, id);\n    if (object === undefined) return undefined;\n\n    const item = toItem(resource, object);\n    return matches(resource, query.filter, item) ? item : undefined;\n}\n","src\u002Fdata-connectors\u002Fstripe\u002Fread.ts",[483,6855,6856,6860,6865,6870,6874,6927,6949,6953,6993,7033,7037,7041,7046,7051,7069,7088,7092,7097,7121,7125,7162,7183,7187,7209,7246],{"__ignoreMap":637},[766,6857,6858],{"class":768,"line":769},[766,6859,3146],{"class":2250},[766,6861,6862],{"class":768,"line":786},[766,6863,6864],{"class":2250}," * Retrieves the keyed item and checks the guard on it in memory. A missing object, a deleted one\n",[766,6866,6867],{"class":768,"line":797},[766,6868,6869],{"class":2250}," * and a guard miss all answer `undefined`: a miss, so a keyed write changes nothing.\n",[766,6871,6872],{"class":768,"line":1377},[766,6873,3161],{"class":2250},[766,6875,6876,6878,6881,6883,6886,6888,6891,6894,6896,6898,6900,6902,6905,6908,6910,6912,6915,6917,6920,6922,6924],{"class":768,"line":1390},[766,6877,3166],{"class":2156},[766,6879,6880],{"class":2156}," async",[766,6882,4805],{"class":2156},[766,6884,6885],{"class":772}," findByKey",[766,6887,2163],{"class":1347},[766,6889,6890],{"class":2156},"context:",[766,6892,6893],{"class":772}," QueryContext",[766,6895,546],{"class":1347},[766,6897,4813],{"class":2156},[766,6899,4165],{"class":772},[766,6901,546],{"class":1347},[766,6903,6904],{"class":2156},"query:",[766,6906,6907],{"class":772}," KeyedOperation",[766,6909,529],{"class":1347},[766,6911,2062],{"class":2156},[766,6913,6914],{"class":772}," Promise",[766,6916,4730],{"class":1347},[766,6918,6919],{"class":772},"Item",[766,6921,4826],{"class":2156},[766,6923,2494],{"class":1353},[766,6925,6926],{"class":1347},"> {\n",[766,6928,6929,6931,6933,6935,6938,6940,6943,6945,6947],{"class":768,"line":1403},[766,6930,2200],{"class":2156},[766,6932,3393],{"class":772},[766,6934,2206],{"class":2156},[766,6936,6937],{"class":2214}," query",[766,6939,495],{"class":1347},[766,6941,6942],{"class":2214},"key",[766,6944,495],{"class":1347},[766,6946,545],{"class":2214},[766,6948,2245],{"class":1347},[766,6950,6951],{"class":768,"line":1416},[766,6952,2317],{"emptyLinePlaceholder":2316},[766,6954,6955,6957,6959,6962,6964,6967,6969,6971,6973,6975,6977,6979,6981,6983,6985,6987,6989,6991],{"class":768,"line":1429},[766,6956,2332],{"class":2156},[766,6958,639],{"class":1347},[766,6960,6961],{"class":2214},"Object",[766,6963,495],{"class":1347},[766,6965,6966],{"class":772},"keys",[766,6968,2163],{"class":1347},[766,6970,5867],{"class":2214},[766,6972,495],{"class":1347},[766,6974,6942],{"class":2214},[766,6976,2303],{"class":1347},[766,6978,4927],{"class":1353},[766,6980,2491],{"class":2156},[766,6982,5430],{"class":772},[766,6984,2345],{"class":2156},[766,6986,3393],{"class":2214},[766,6988,2339],{"class":2156},[766,6990,2494],{"class":772},[766,6992,2444],{"class":1347},[766,6994,6995,6997,6999,7001,7003,7005,7007,7009,7011,7013,7015,7017,7019,7022,7024,7026,7028,7031],{"class":768,"line":1442},[766,6996,5078],{"class":2156},[766,6998,2362],{"class":2156},[766,7000,2192],{"class":772},[766,7002,2163],{"class":1347},[766,7004,5581],{"class":779},[766,7006,5090],{"class":772},[766,7008,5093],{"class":779},[766,7010,4847],{"class":2214},[766,7012,495],{"class":779},[766,7014,1164],{"class":2214},[766,7016,5102],{"class":779},[766,7018,5090],{"class":772},[766,7020,7021],{"class":779}," keys are a single ",[766,7023,5090],{"class":772},[766,7025,545],{"class":779},[766,7027,5090],{"class":772},[766,7029,7030],{"class":779},".`",[766,7032,2223],{"class":1347},[766,7034,7035],{"class":768,"line":1451},[766,7036,2591],{"class":1347},[766,7038,7039],{"class":768,"line":1457},[766,7040,2317],{"emptyLinePlaceholder":2316},[766,7042,7043],{"class":768,"line":1470},[766,7044,7045],{"class":2250},"    \u002F\u002F The guard is checked in memory after the retrieve. Refuse one that isn't declared, or that the\n",[766,7047,7048],{"class":768,"line":1483},[766,7049,7050],{"class":2250},"    \u002F\u002F check can't evaluate, first.\n",[766,7052,7053,7055,7057,7059,7061,7063,7065,7067],{"class":768,"line":1495},[766,7054,4842],{"class":772},[766,7056,2163],{"class":1347},[766,7058,4847],{"class":2214},[766,7060,546],{"class":1347},[766,7062,5867],{"class":2214},[766,7064,495],{"class":1347},[766,7066,4852],{"class":2214},[766,7068,2223],{"class":1347},[766,7070,7071,7074,7076,7078,7080,7082,7084,7086],{"class":768,"line":1507},[766,7072,7073],{"class":772},"    requireEvaluable",[766,7075,2163],{"class":1347},[766,7077,4847],{"class":2214},[766,7079,546],{"class":1347},[766,7081,5867],{"class":2214},[766,7083,495],{"class":1347},[766,7085,4852],{"class":2214},[766,7087,2223],{"class":1347},[766,7089,7090],{"class":768,"line":1519},[766,7091,2317],{"emptyLinePlaceholder":2316},[766,7093,7094],{"class":768,"line":1531},[766,7095,7096],{"class":2250},"    \u002F\u002F Only a string can be a Stripe id. The client also skips ids Stripe can't have.\n",[766,7098,7099,7101,7103,7106,7108,7110,7113,7115,7117,7119],{"class":768,"line":1543},[766,7100,2332],{"class":2156},[766,7102,639],{"class":1347},[766,7104,7105],{"class":2156},"typeof",[766,7107,3393],{"class":2214},[766,7109,2491],{"class":2156},[766,7111,7112],{"class":779}," 'string'",[766,7114,2356],{"class":1347},[766,7116,2359],{"class":2156},[766,7118,2494],{"class":772},[766,7120,2245],{"class":1347},[766,7122,7123],{"class":768,"line":1552},[766,7124,2317],{"emptyLinePlaceholder":2316},[766,7126,7127,7129,7132,7134,7136,7139,7141,7144,7146,7148,7150,7152,7154,7156,7158,7160],{"class":768,"line":1583},[766,7128,2200],{"class":2156},[766,7130,7131],{"class":772}," object",[766,7133,2206],{"class":2156},[766,7135,2942],{"class":2156},[766,7137,7138],{"class":2214}," context",[766,7140,495],{"class":1347},[766,7142,7143],{"class":2214},"client",[766,7145,495],{"class":1347},[766,7147,2820],{"class":772},[766,7149,2163],{"class":1347},[766,7151,4847],{"class":2214},[766,7153,495],{"class":1347},[766,7155,2295],{"class":2214},[766,7157,546],{"class":1347},[766,7159,545],{"class":2214},[766,7161,2223],{"class":1347},[766,7163,7164,7166,7168,7171,7173,7175,7177,7179,7181],{"class":768,"line":1596},[766,7165,2332],{"class":2156},[766,7167,639],{"class":1347},[766,7169,7170],{"class":2214},"object",[766,7172,2339],{"class":2156},[766,7174,2494],{"class":772},[766,7176,2356],{"class":1347},[766,7178,2359],{"class":2156},[766,7180,2494],{"class":772},[766,7182,2245],{"class":1347},[766,7184,7185],{"class":768,"line":1604},[766,7186,2317],{"emptyLinePlaceholder":2316},[766,7188,7189,7191,7194,7196,7199,7201,7203,7205,7207],{"class":768,"line":1631},[766,7190,2200],{"class":2156},[766,7192,7193],{"class":772}," item",[766,7195,2206],{"class":2156},[766,7197,7198],{"class":772}," toItem",[766,7200,2163],{"class":1347},[766,7202,4847],{"class":2214},[766,7204,546],{"class":1347},[766,7206,7170],{"class":2214},[766,7208,2223],{"class":1347},[766,7210,7211,7213,7216,7218,7220,7222,7224,7226,7228,7230,7233,7235,7238,7240,7242,7244],{"class":768,"line":1637},[766,7212,2769],{"class":2156},[766,7214,7215],{"class":772}," matches",[766,7217,2163],{"class":1347},[766,7219,4847],{"class":2214},[766,7221,546],{"class":1347},[766,7223,5867],{"class":2214},[766,7225,495],{"class":1347},[766,7227,4852],{"class":2214},[766,7229,546],{"class":1347},[766,7231,7232],{"class":2214},"item",[766,7234,2356],{"class":1347},[766,7236,7237],{"class":2156},"?",[766,7239,7193],{"class":2214},[766,7241,5433],{"class":2156},[766,7243,2494],{"class":772},[766,7245,2245],{"class":1347},[766,7247,7248],{"class":768,"line":1643},[766,7249,1658],{"class":1347},[1660,7251,7252,7271,7297],{},[1663,7253,7254,7257,7258,7260,7261,7263,7264,7267,7268,7270],{},[463,7255,7256],{},"A miss is an answer, not an error."," An unknown id, a deleted customer, and a guard miss all answer ",[483,7259,5924],{},". The client's ",[483,7262,2820],{}," reads both Stripe's ",[483,7265,7266],{},"resource_missing"," and a ",[483,7269,993],{}," tombstone as missing.",[1663,7272,7273,5198,7279,3114,7281,7284,7285,7288,7289,7292,7293,495],{},[463,7274,7275,7276,495],{},"The answer is ",[483,7277,7278],{},"{ record }",[483,7280,1814],{},[483,7282,7283],{},"{ record: null }"," on a miss, and ",[483,7286,7287],{},"{ record: … }"," with the selected fields otherwise. Engine answers a keyed miss with ",[483,7290,7291],{},"404",". See ",[472,7294,7296],{"href":7295},"\u002Freference\u002Fextensions\u002Fdata-connectors\u002Fapi#keyed-operations","Keyed Operations",[1663,7298,7299,5198,7302,549,7304,7306,7307,7309],{},[463,7300,7301],{},"The guard is checked before any write.",[483,7303,6842],{},[483,7305,4632],{}," write only an item ",[483,7308,6848],{}," returned, so a guard miss writes nothing.",[459,7311,7312,7313,7315,7316,7318],{},"Another client can still delete the object between the retrieve and the write. Stripe then answers ",[483,7314,7266],{},", which the client throws as ",[483,7317,2816],{},", and the keyed write answers that as a miss too:",[757,7320,7323],{"className":2146,"code":7321,"filename":7322,"language":2149,"meta":637,"style":637},"export async function updateOne(context: QueryContext, resource: ResourceSpec, query: UpdateOneOperationSerialized): Promise\u003CQueryResultFor\u003C'updateOne'>> {\n    requireWrite(context, resource, resource.canUpdate, 'update');\n    const form = encodeForm(resource, query.data, 'update');\n    const target = await findByKey(context, resource, query);\n    if (target === undefined) return { record: null };\n\n    try {\n        const object = await context.client.update(resource.path, target.id, form);\n        return { record: project(toItem(resource, object), query.select) };\n    }\n    catch (error) {\n        \u002F\u002F Deleted since `findByKey` retrieved it: a miss like any other.\n        if (error instanceof StripeObjectMissing) return { record: null };\n        throw error;\n    }\n}\n","src\u002Fdata-connectors\u002Fstripe\u002Fwrite.ts",[483,7324,7325,7374,7404,7434,7461,7485,7489,7495,7540,7574,7578,7588,7593,7615,7623,7627],{"__ignoreMap":637},[766,7326,7327,7329,7331,7333,7336,7338,7340,7342,7344,7346,7348,7350,7352,7355,7357,7359,7361,7363,7366,7368,7371],{"class":768,"line":769},[766,7328,3166],{"class":2156},[766,7330,6880],{"class":2156},[766,7332,4805],{"class":2156},[766,7334,7335],{"class":772}," updateOne",[766,7337,2163],{"class":1347},[766,7339,6890],{"class":2156},[766,7341,6893],{"class":772},[766,7343,546],{"class":1347},[766,7345,4813],{"class":2156},[766,7347,4165],{"class":772},[766,7349,546],{"class":1347},[766,7351,6904],{"class":2156},[766,7353,7354],{"class":772}," UpdateOneOperationSerialized",[766,7356,529],{"class":1347},[766,7358,2062],{"class":2156},[766,7360,6914],{"class":772},[766,7362,4730],{"class":1347},[766,7364,7365],{"class":772},"QueryResultFor",[766,7367,4730],{"class":1347},[766,7369,7370],{"class":779},"'updateOne'",[766,7372,7373],{"class":1347},">> {\n",[766,7375,7376,7379,7381,7384,7386,7388,7390,7392,7394,7397,7399,7402],{"class":768,"line":786},[766,7377,7378],{"class":772},"    requireWrite",[766,7380,2163],{"class":1347},[766,7382,7383],{"class":2214},"context",[766,7385,546],{"class":1347},[766,7387,4847],{"class":2214},[766,7389,546],{"class":1347},[766,7391,4847],{"class":2214},[766,7393,495],{"class":1347},[766,7395,7396],{"class":2214},"canUpdate",[766,7398,546],{"class":1347},[766,7400,7401],{"class":779},"'update'",[766,7403,2223],{"class":1347},[766,7405,7406,7408,7411,7413,7416,7418,7420,7422,7424,7426,7428,7430,7432],{"class":768,"line":797},[766,7407,2200],{"class":2156},[766,7409,7410],{"class":772}," form",[766,7412,2206],{"class":2156},[766,7414,7415],{"class":772}," encodeForm",[766,7417,2163],{"class":1347},[766,7419,4847],{"class":2214},[766,7421,546],{"class":1347},[766,7423,5867],{"class":2214},[766,7425,495],{"class":1347},[766,7427,6127],{"class":2214},[766,7429,546],{"class":1347},[766,7431,7401],{"class":779},[766,7433,2223],{"class":1347},[766,7435,7436,7438,7441,7443,7445,7447,7449,7451,7453,7455,7457,7459],{"class":768,"line":1377},[766,7437,2200],{"class":2156},[766,7439,7440],{"class":772}," target",[766,7442,2206],{"class":2156},[766,7444,2942],{"class":2156},[766,7446,6885],{"class":772},[766,7448,2163],{"class":1347},[766,7450,7383],{"class":2214},[766,7452,546],{"class":1347},[766,7454,4847],{"class":2214},[766,7456,546],{"class":1347},[766,7458,5867],{"class":2214},[766,7460,2223],{"class":1347},[766,7462,7463,7465,7467,7470,7472,7474,7476,7478,7481,7483],{"class":768,"line":1390},[766,7464,2332],{"class":2156},[766,7466,639],{"class":1347},[766,7468,7469],{"class":2214},"target",[766,7471,2339],{"class":2156},[766,7473,2494],{"class":772},[766,7475,2356],{"class":1347},[766,7477,2359],{"class":2156},[766,7479,7480],{"class":1347}," { record: ",[766,7482,4378],{"class":772},[766,7484,3590],{"class":1347},[766,7486,7487],{"class":768,"line":1403},[766,7488,2317],{"emptyLinePlaceholder":2316},[766,7490,7491,7493],{"class":768,"line":1416},[766,7492,4985],{"class":2156},[766,7494,2195],{"class":1347},[766,7496,7497,7500,7502,7504,7506,7508,7510,7512,7514,7517,7519,7521,7523,7525,7527,7529,7531,7533,7535,7538],{"class":768,"line":1429},[766,7498,7499],{"class":2156},"        const",[766,7501,7131],{"class":772},[766,7503,2206],{"class":2156},[766,7505,2942],{"class":2156},[766,7507,7138],{"class":2214},[766,7509,495],{"class":1347},[766,7511,7143],{"class":2214},[766,7513,495],{"class":1347},[766,7515,7516],{"class":772},"update",[766,7518,2163],{"class":1347},[766,7520,4847],{"class":2214},[766,7522,495],{"class":1347},[766,7524,2295],{"class":2214},[766,7526,546],{"class":1347},[766,7528,7469],{"class":2214},[766,7530,495],{"class":1347},[766,7532,545],{"class":2214},[766,7534,546],{"class":1347},[766,7536,7537],{"class":2214},"form",[766,7539,2223],{"class":1347},[766,7541,7542,7544,7546,7549,7551,7554,7556,7558,7560,7562,7565,7567,7569,7572],{"class":768,"line":1442},[766,7543,2661],{"class":2156},[766,7545,7480],{"class":1347},[766,7547,7548],{"class":772},"project",[766,7550,2163],{"class":1347},[766,7552,7553],{"class":772},"toItem",[766,7555,2163],{"class":1347},[766,7557,4847],{"class":2214},[766,7559,546],{"class":1347},[766,7561,7170],{"class":2214},[766,7563,7564],{"class":1347},"), ",[766,7566,5867],{"class":2214},[766,7568,495],{"class":1347},[766,7570,7571],{"class":2214},"select",[766,7573,3354],{"class":1347},[766,7575,7576],{"class":768,"line":1451},[766,7577,2591],{"class":1347},[766,7579,7580,7582,7584,7586],{"class":768,"line":1457},[766,7581,5035],{"class":2156},[766,7583,639],{"class":1347},[766,7585,5040],{"class":2214},[766,7587,2444],{"class":1347},[766,7589,7590],{"class":768,"line":1470},[766,7591,7592],{"class":2250},"        \u002F\u002F Deleted since `findByKey` retrieved it: a miss like any other.\n",[766,7594,7595,7597,7599,7601,7603,7605,7607,7609,7611,7613],{"class":768,"line":1483},[766,7596,5047],{"class":2156},[766,7598,639],{"class":1347},[766,7600,5040],{"class":2214},[766,7602,5059],{"class":2156},[766,7604,2532],{"class":772},[766,7606,2356],{"class":1347},[766,7608,2359],{"class":2156},[766,7610,7480],{"class":1347},[766,7612,4378],{"class":772},[766,7614,3590],{"class":1347},[766,7616,7617,7619,7621],{"class":768,"line":1495},[766,7618,5078],{"class":2156},[766,7620,5071],{"class":2214},[766,7622,2245],{"class":1347},[766,7624,7625],{"class":768,"line":1507},[766,7626,2591],{"class":1347},[766,7628,7629],{"class":768,"line":1519},[766,7630,1658],{"class":1347},[459,7632,7633,7635,7636,7638],{},[483,7634,4632],{}," works the same way. It answers the item ",[483,7637,6848],{}," read, because Stripe answers a delete with a tombstone.",[2109,7640,7642],{"id":7641},"write-one-object-per-request","Write One Object per Request",[459,7644,7645,7646,7649],{},"Stripe writes one object per request and returns the written object. ",[483,7647,7648],{},"create"," checks every item before its first request, then creates them in order. A failure partway leaves the earlier items created, so the message says how far it got:",[757,7651,7653],{"className":2146,"code":7652,"filename":7322,"language":2149,"meta":637,"style":637},"export async function create(context: QueryContext, resource: ResourceSpec, query: CreateOperationSerialized): Promise\u003CQueryResultFor\u003C'create'>> {\n    requireWrite(context, resource, resource.canCreate, 'create');\n    \u002F\u002F Check every item before creating any.\n    const forms = query.data.map((data) => encodeForm(resource, data, 'create'));\n    const records: MonospaceObject[] = [];\n\n    \u002F\u002F One at a time, so a failure leaves the items before it created, in order.\n    for (const form of forms) {\n        try {\n            const object = await context.client.create(resource.path, form);\n            records.push(project(toItem(resource, object), query.select));\n        }\n        catch (error) {\n            throw withProgress(error, `Created ${records.length} of ${forms.length} ${resource.name}`, forms.length);\n        }\n    }\n\n    return { records };\n}\n",[483,7654,7655,7701,7728,7733,7779,7798,7802,7807,7825,7832,7867,7903,7907,7918,7972,7976,7980,7984,7994],{"__ignoreMap":637},[766,7656,7657,7659,7661,7663,7665,7667,7669,7671,7673,7675,7677,7679,7681,7684,7686,7688,7690,7692,7694,7696,7699],{"class":768,"line":769},[766,7658,3166],{"class":2156},[766,7660,6880],{"class":2156},[766,7662,4805],{"class":2156},[766,7664,1215],{"class":772},[766,7666,2163],{"class":1347},[766,7668,6890],{"class":2156},[766,7670,6893],{"class":772},[766,7672,546],{"class":1347},[766,7674,4813],{"class":2156},[766,7676,4165],{"class":772},[766,7678,546],{"class":1347},[766,7680,6904],{"class":2156},[766,7682,7683],{"class":772}," CreateOperationSerialized",[766,7685,529],{"class":1347},[766,7687,2062],{"class":2156},[766,7689,6914],{"class":772},[766,7691,4730],{"class":1347},[766,7693,7365],{"class":772},[766,7695,4730],{"class":1347},[766,7697,7698],{"class":779},"'create'",[766,7700,7373],{"class":1347},[766,7702,7703,7705,7707,7709,7711,7713,7715,7717,7719,7722,7724,7726],{"class":768,"line":786},[766,7704,7378],{"class":772},[766,7706,2163],{"class":1347},[766,7708,7383],{"class":2214},[766,7710,546],{"class":1347},[766,7712,4847],{"class":2214},[766,7714,546],{"class":1347},[766,7716,4847],{"class":2214},[766,7718,495],{"class":1347},[766,7720,7721],{"class":2214},"canCreate",[766,7723,546],{"class":1347},[766,7725,7698],{"class":779},[766,7727,2223],{"class":1347},[766,7729,7730],{"class":768,"line":797},[766,7731,7732],{"class":2250},"    \u002F\u002F Check every item before creating any.\n",[766,7734,7735,7737,7740,7742,7744,7746,7748,7750,7753,7756,7758,7760,7763,7765,7767,7769,7771,7773,7775,7777],{"class":768,"line":1377},[766,7736,2200],{"class":2156},[766,7738,7739],{"class":772}," forms",[766,7741,2206],{"class":2156},[766,7743,6937],{"class":2214},[766,7745,495],{"class":1347},[766,7747,6127],{"class":2214},[766,7749,495],{"class":1347},[766,7751,7752],{"class":772},"map",[766,7754,7755],{"class":1347},"((",[766,7757,6127],{"class":2156},[766,7759,2356],{"class":1347},[766,7761,7762],{"class":2156},"=>",[766,7764,7415],{"class":772},[766,7766,2163],{"class":1347},[766,7768,4847],{"class":2214},[766,7770,546],{"class":1347},[766,7772,6127],{"class":2214},[766,7774,546],{"class":1347},[766,7776,7698],{"class":779},[766,7778,5974],{"class":1347},[766,7780,7781,7783,7786,7788,7791,7793,7795],{"class":768,"line":1390},[766,7782,2200],{"class":2156},[766,7784,7785],{"class":772}," records",[766,7787,2062],{"class":2156},[766,7789,7790],{"class":772}," MonospaceObject",[766,7792,4168],{"class":1347},[766,7794,2239],{"class":2156},[766,7796,7797],{"class":1347}," [];\n",[766,7799,7800],{"class":768,"line":1403},[766,7801,2317],{"emptyLinePlaceholder":2316},[766,7803,7804],{"class":768,"line":1416},[766,7805,7806],{"class":2250},"    \u002F\u002F One at a time, so a failure leaves the items before it created, in order.\n",[766,7808,7809,7812,7814,7816,7818,7821,7823],{"class":768,"line":1429},[766,7810,7811],{"class":2156},"    for",[766,7813,639],{"class":1347},[766,7815,2935],{"class":2156},[766,7817,7410],{"class":772},[766,7819,7820],{"class":2156}," of",[766,7822,7739],{"class":2214},[766,7824,2444],{"class":1347},[766,7826,7827,7830],{"class":768,"line":1442},[766,7828,7829],{"class":2156},"        try",[766,7831,2195],{"class":1347},[766,7833,7834,7837,7839,7841,7843,7845,7847,7849,7851,7853,7855,7857,7859,7861,7863,7865],{"class":768,"line":1451},[766,7835,7836],{"class":2156},"            const",[766,7838,7131],{"class":772},[766,7840,2206],{"class":2156},[766,7842,2942],{"class":2156},[766,7844,7138],{"class":2214},[766,7846,495],{"class":1347},[766,7848,7143],{"class":2214},[766,7850,495],{"class":1347},[766,7852,7648],{"class":772},[766,7854,2163],{"class":1347},[766,7856,4847],{"class":2214},[766,7858,495],{"class":1347},[766,7860,2295],{"class":2214},[766,7862,546],{"class":1347},[766,7864,7537],{"class":2214},[766,7866,2223],{"class":1347},[766,7868,7869,7872,7874,7877,7879,7881,7883,7885,7887,7889,7891,7893,7895,7897,7899,7901],{"class":768,"line":1457},[766,7870,7871],{"class":2214},"            records",[766,7873,495],{"class":1347},[766,7875,7876],{"class":772},"push",[766,7878,2163],{"class":1347},[766,7880,7548],{"class":772},[766,7882,2163],{"class":1347},[766,7884,7553],{"class":772},[766,7886,2163],{"class":1347},[766,7888,4847],{"class":2214},[766,7890,546],{"class":1347},[766,7892,7170],{"class":2214},[766,7894,7564],{"class":1347},[766,7896,5867],{"class":2214},[766,7898,495],{"class":1347},[766,7900,7571],{"class":2214},[766,7902,5974],{"class":1347},[766,7904,7905],{"class":768,"line":1470},[766,7906,1646],{"class":1347},[766,7908,7909,7912,7914,7916],{"class":768,"line":1483},[766,7910,7911],{"class":2156},"        catch",[766,7913,639],{"class":1347},[766,7915,5040],{"class":2214},[766,7917,2444],{"class":1347},[766,7919,7920,7923,7926,7928,7930,7932,7935,7938,7940,7942,7945,7948,7950,7952,7954,7956,7958,7960,7962,7964,7966,7968,7970],{"class":768,"line":1495},[766,7921,7922],{"class":2156},"            throw",[766,7924,7925],{"class":772}," withProgress",[766,7927,2163],{"class":1347},[766,7929,5040],{"class":2214},[766,7931,546],{"class":1347},[766,7933,7934],{"class":779},"`Created ${",[766,7936,7937],{"class":2214},"records",[766,7939,495],{"class":779},[766,7941,4927],{"class":1353},[766,7943,7944],{"class":779},"} of ${",[766,7946,7947],{"class":2214},"forms",[766,7949,495],{"class":779},[766,7951,4927],{"class":1353},[766,7953,2284],{"class":779},[766,7955,4847],{"class":2214},[766,7957,495],{"class":779},[766,7959,1164],{"class":2214},[766,7961,2421],{"class":779},[766,7963,546],{"class":1347},[766,7965,7947],{"class":2214},[766,7967,495],{"class":1347},[766,7969,4927],{"class":1353},[766,7971,2223],{"class":1347},[766,7973,7974],{"class":768,"line":1507},[766,7975,1646],{"class":1347},[766,7977,7978],{"class":768,"line":1519},[766,7979,2591],{"class":1347},[766,7981,7982],{"class":768,"line":1531},[766,7983,2317],{"emptyLinePlaceholder":2316},[766,7985,7986,7988,7990,7992],{"class":768,"line":1543},[766,7987,2769],{"class":2156},[766,7989,2230],{"class":1347},[766,7991,7937],{"class":2214},[766,7993,3590],{"class":1347},[766,7995,7996],{"class":768,"line":1552},[766,7997,1658],{"class":1347},[1660,7999,8000,8013,8023],{},[1663,8001,8002,5198,8005,549,8008,8010,8011,495],{},[463,8003,8004],{},"Writes by filter read their targets first.",[483,8006,8007],{},"updateMany",[483,8009,4629],{}," read every match, then write each one, with at most four requests in flight. That bounds concurrency, not the rate, so Stripe can still answer ",[483,8012,2798],{},[1663,8014,8015,8018,8019,8022],{},[463,8016,8017],{},"Writes aren't atomic."," When a write of several items fails, ",[483,8020,8021],{},"withProgress"," prefixes the message with the count of acknowledged writes and keeps the error's class. A request that timed out can still have been applied, so the real count can be higher.",[1663,8024,8025,8030],{},[463,8026,8027,8029],{},[483,8028,4629],{}," answers the items it read before deleting,"," because Stripe answers each delete with a tombstone.",[459,8032,8033],{},"Deleting four products by filter, where one still has prices, deletes the other three and reports the failure:",[757,8035,8037],{"className":1337,"code":8036,"filename":6684,"language":1340,"meta":637,"style":637},"{\n  \"message\": \"Query failed\",\n  \"source\": {\n    \"message\": \"Foreign key constraint failed\",\n    \"source\": {\n      \"message\": \"the extension returned an error: Deleted 3 of 4 products before this error: This product cannot be deleted because it has one or more user-created prices.\"\n    }\n  }\n}\n",[483,8038,8039,8043,8055,8062,8074,8081,8091,8095,8099],{"__ignoreMap":637},[766,8040,8041],{"class":768,"line":769},[766,8042,1348],{"class":1347},[766,8044,8045,8048,8050,8053],{"class":768,"line":786},[766,8046,8047],{"class":1353},"  \"message\"",[766,8049,1026],{"class":1347},[766,8051,8052],{"class":779},"\"Query failed\"",[766,8054,1362],{"class":1347},[766,8056,8057,8060],{"class":768,"line":797},[766,8058,8059],{"class":1353},"  \"source\"",[766,8061,1549],{"class":1347},[766,8063,8064,8067,8069,8072],{"class":768,"line":1377},[766,8065,8066],{"class":1353},"    \"message\"",[766,8068,1026],{"class":1347},[766,8070,8071],{"class":779},"\"Foreign key constraint failed\"",[766,8073,1362],{"class":1347},[766,8075,8076,8079],{"class":768,"line":1390},[766,8077,8078],{"class":1353},"    \"source\"",[766,8080,1549],{"class":1347},[766,8082,8083,8086,8088],{"class":768,"line":1403},[766,8084,8085],{"class":1353},"      \"message\"",[766,8087,1026],{"class":1347},[766,8089,8090],{"class":779},"\"the extension returned an error: Deleted 3 of 4 products before this error: This product cannot be deleted because it has one or more user-created prices.\"\n",[766,8092,8093],{"class":768,"line":1416},[766,8094,2591],{"class":1347},[766,8096,8097],{"class":768,"line":1429},[766,8098,6812],{"class":1347},[766,8100,8101],{"class":768,"line":1442},[766,8102,1658],{"class":1347},[459,8104,8105,8106,8109,8110,8112,8113,495],{},"Every write passes the same gate before its first request. With ",[483,8107,8108],{},"enableWrites: false",", a write is a ",[483,8111,5242],{},", because it can still arrive while Engine holds a schema introspected before the setting changed. A write or field the collection doesn't declare is a plain ",[483,8114,2811],{},[459,8116,8117,8118,8120,8121,8124,8125,8127],{},"Creating a price sets its product through the relation. Engine doesn't accept the foreign-key field ",[483,8119,592],{}," in create input, so connect the existing product with ",[483,8122,8123],{},"_connect",". The SDK tab reuses the ",[483,8126,7143],{}," from step 5:",[1193,8129,8130,8233,8297],{},[757,8131,8133],{"className":2146,"code":8132,"filename":6341,"language":2149,"meta":637,"style":637},"const prices = await client.prices.createOne({\n  data: {\n    currency: 'usd',\n    unitAmount: 1500,\n    recurringInterval: 'month',\n    product: { _connect: { key: { id: 'prod_YOUR_PRODUCT' } } },\n  },\n  fields: ['id', 'productId', 'unitAmount', 'currency'],\n});\n",[483,8134,8135,8159,8164,8174,8184,8194,8204,8208,8229],{"__ignoreMap":637},[766,8136,8137,8139,8142,8144,8146,8148,8150,8152,8154,8157],{"class":768,"line":769},[766,8138,2935],{"class":2156},[766,8140,8141],{"class":772}," prices",[766,8143,2206],{"class":2156},[766,8145,2942],{"class":2156},[766,8147,6374],{"class":2214},[766,8149,495],{"class":1347},[766,8151,585],{"class":2214},[766,8153,495],{"class":1347},[766,8155,8156],{"class":772},"createOne",[766,8158,3013],{"class":1347},[766,8160,8161],{"class":768,"line":786},[766,8162,8163],{"class":1347},"  data: {\n",[766,8165,8166,8169,8172],{"class":768,"line":797},[766,8167,8168],{"class":1347},"    currency: ",[766,8170,8171],{"class":779},"'usd'",[766,8173,1362],{"class":1347},[766,8175,8176,8179,8182],{"class":768,"line":1377},[766,8177,8178],{"class":1347},"    unitAmount: ",[766,8180,8181],{"class":772},"1500",[766,8183,1362],{"class":1347},[766,8185,8186,8189,8192],{"class":768,"line":1390},[766,8187,8188],{"class":1347},"    recurringInterval: ",[766,8190,8191],{"class":779},"'month'",[766,8193,1362],{"class":1347},[766,8195,8196,8199,8201],{"class":768,"line":1403},[766,8197,8198],{"class":1347},"    product: { _connect: { key: { id: ",[766,8200,6450],{"class":779},[766,8202,8203],{"class":1347}," } } },\n",[766,8205,8206],{"class":768,"line":1416},[766,8207,2997],{"class":1347},[766,8209,8210,8212,8214,8216,8219,8221,8223,8225,8227],{"class":768,"line":1429},[766,8211,6457],{"class":1347},[766,8213,3702],{"class":779},[766,8215,546],{"class":1347},[766,8217,8218],{"class":779},"'productId'",[766,8220,546],{"class":1347},[766,8222,6487],{"class":779},[766,8224,546],{"class":1347},[766,8226,6492],{"class":779},[766,8228,6470],{"class":1347},[766,8230,8231],{"class":768,"line":1442},[766,8232,3070],{"class":1347},[757,8234,8236],{"className":759,"code":8235,"filename":773,"language":762,"meta":637,"style":637},"curl -X POST \"https:\u002F\u002Fexample.monospace.io\u002Fapi\u002Fblog\u002Fitems\u002Fprices?fields=id,productId,unitAmount,currency\" \\\n  -H \"Authorization: Bearer YOUR_API_KEY\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n    \"currency\": \"usd\",\n    \"unitAmount\": 1500,\n    \"recurringInterval\": \"month\",\n    \"product\": { \"_connect\": { \"key\": { \"id\": \"prod_YOUR_PRODUCT\" } } }\n  }'\n",[483,8237,8238,8251,8259,8267,8273,8278,8283,8288,8293],{"__ignoreMap":637},[766,8239,8240,8242,8244,8246,8249],{"class":768,"line":769},[766,8241,773],{"class":772},[766,8243,2862],{"class":772},[766,8245,2865],{"class":779},[766,8247,8248],{"class":779}," \"https:\u002F\u002Fexample.monospace.io\u002Fapi\u002Fblog\u002Fitems\u002Fprices?fields=id,productId,unitAmount,currency\"",[766,8250,783],{"class":772},[766,8252,8253,8255,8257],{"class":768,"line":786},[766,8254,789],{"class":772},[766,8256,2877],{"class":779},[766,8258,783],{"class":772},[766,8260,8261,8263,8265],{"class":768,"line":797},[766,8262,789],{"class":772},[766,8264,2886],{"class":779},[766,8266,783],{"class":772},[766,8268,8269,8271],{"class":768,"line":1377},[766,8270,2893],{"class":772},[766,8272,2896],{"class":779},[766,8274,8275],{"class":768,"line":1390},[766,8276,8277],{"class":779},"    \"currency\": \"usd\",\n",[766,8279,8280],{"class":768,"line":1403},[766,8281,8282],{"class":779},"    \"unitAmount\": 1500,\n",[766,8284,8285],{"class":768,"line":1416},[766,8286,8287],{"class":779},"    \"recurringInterval\": \"month\",\n",[766,8289,8290],{"class":768,"line":1429},[766,8291,8292],{"class":779},"    \"product\": { \"_connect\": { \"key\": { \"id\": \"prod_YOUR_PRODUCT\" } } }\n",[766,8294,8295],{"class":768,"line":1442},[766,8296,2925],{"class":779},[757,8298,8300],{"className":2146,"code":8299,"filename":2118,"language":2149,"meta":637,"style":637},"const params = new URLSearchParams({ fields: 'id,productId,unitAmount,currency' });\n\nconst response = await fetch(\n  `https:\u002F\u002Fexample.monospace.io\u002Fapi\u002Fblog\u002Fitems\u002Fprices?${params}`,\n  {\n    method: 'POST',\n    headers: {\n      'Authorization': 'Bearer YOUR_API_KEY',\n      'Content-Type': 'application\u002Fjson',\n    },\n    body: JSON.stringify([{\n      currency: 'usd',\n      unitAmount: 1500,\n      recurringInterval: 'month',\n      product: { _connect: { key: { id: 'prod_YOUR_PRODUCT' } } },\n    }]),\n  },\n);\n\nconst { data } = await response.json();\n",[483,8301,8302,8322,8326,8340,8351,8355,8364,8368,8379,8390,8394,8408,8417,8426,8435,8444,8449,8453,8457,8461],{"__ignoreMap":637},[766,8303,8304,8306,8308,8310,8312,8314,8317,8320],{"class":768,"line":769},[766,8305,2935],{"class":2156},[766,8307,6542],{"class":772},[766,8309,2206],{"class":2156},[766,8311,2362],{"class":2156},[766,8313,5874],{"class":772},[766,8315,8316],{"class":1347},"({ fields: ",[766,8318,8319],{"class":779},"'id,productId,unitAmount,currency'",[766,8321,3454],{"class":1347},[766,8323,8324],{"class":768,"line":786},[766,8325,2317],{"emptyLinePlaceholder":2316},[766,8327,8328,8330,8332,8334,8336,8338],{"class":768,"line":797},[766,8329,2935],{"class":2156},[766,8331,2242],{"class":772},[766,8333,2206],{"class":2156},[766,8335,2942],{"class":2156},[766,8337,2945],{"class":772},[766,8339,6597],{"class":1347},[766,8341,8342,8345,8347,8349],{"class":768,"line":1377},[766,8343,8344],{"class":779},"  `https:\u002F\u002Fexample.monospace.io\u002Fapi\u002Fblog\u002Fitems\u002Fprices?${",[766,8346,6605],{"class":2214},[766,8348,2421],{"class":779},[766,8350,1362],{"class":1347},[766,8352,8353],{"class":768,"line":1390},[766,8354,6614],{"class":1347},[766,8356,8357,8360,8362],{"class":768,"line":1403},[766,8358,8359],{"class":1347},"    method: ",[766,8361,2961],{"class":779},[766,8363,1362],{"class":1347},[766,8365,8366],{"class":768,"line":1416},[766,8367,6619],{"class":1347},[766,8369,8370,8373,8375,8377],{"class":768,"line":1429},[766,8371,8372],{"class":779},"      'Authorization'",[766,8374,1026],{"class":1347},[766,8376,2978],{"class":779},[766,8378,1362],{"class":1347},[766,8380,8381,8384,8386,8388],{"class":768,"line":1442},[766,8382,8383],{"class":779},"      'Content-Type'",[766,8385,1026],{"class":1347},[766,8387,2990],{"class":779},[766,8389,1362],{"class":1347},[766,8391,8392],{"class":768,"line":1451},[766,8393,3882],{"class":1347},[766,8395,8396,8399,8401,8403,8405],{"class":768,"line":1457},[766,8397,8398],{"class":1347},"    body: ",[766,8400,3005],{"class":772},[766,8402,495],{"class":1347},[766,8404,3010],{"class":772},[766,8406,8407],{"class":1347},"([{\n",[766,8409,8410,8413,8415],{"class":768,"line":1470},[766,8411,8412],{"class":1347},"      currency: ",[766,8414,8171],{"class":779},[766,8416,1362],{"class":1347},[766,8418,8419,8422,8424],{"class":768,"line":1483},[766,8420,8421],{"class":1347},"      unitAmount: ",[766,8423,8181],{"class":772},[766,8425,1362],{"class":1347},[766,8427,8428,8431,8433],{"class":768,"line":1495},[766,8429,8430],{"class":1347},"      recurringInterval: ",[766,8432,8191],{"class":779},[766,8434,1362],{"class":1347},[766,8436,8437,8440,8442],{"class":768,"line":1507},[766,8438,8439],{"class":1347},"      product: { _connect: { key: { id: ",[766,8441,6450],{"class":779},[766,8443,8203],{"class":1347},[766,8445,8446],{"class":768,"line":1519},[766,8447,8448],{"class":1347},"    }]),\n",[766,8450,8451],{"class":768,"line":1531},[766,8452,2997],{"class":1347},[766,8454,8455],{"class":768,"line":1543},[766,8456,2223],{"class":1347},[766,8458,8459],{"class":768,"line":1552},[766,8460,2317],{"emptyLinePlaceholder":2316},[766,8462,8463,8465,8467,8469,8471,8473,8475,8477,8479,8481],{"class":768,"line":1583},[766,8464,2935],{"class":2156},[766,8466,2230],{"class":1347},[766,8468,6127],{"class":772},[766,8470,2236],{"class":1347},[766,8472,2239],{"class":2156},[766,8474,2942],{"class":2156},[766,8476,2242],{"class":2214},[766,8478,495],{"class":1347},[766,8480,1340],{"class":772},[766,8482,6667],{"class":1347},[459,8484,8485,8486,8488,8489,8491,8492,8494,8495,615,8497,495],{},"Engine doesn't check that the product exists. Stripe answers a missing product with ",[483,8487,7266],{}," naming ",[483,8490,622],{},", and the caller gets ",[483,8493,3080],{}," \"Foreign key constraint failed\". Stripe can't delete prices: archive a price by updating ",[483,8496,570],{},[483,8498,2021],{},[2109,8500,1685],{"id":8501},"declare-what-writes-return",[459,8503,8504,8505,8507,8508,8511],{},"Every write handler answers the items it wrote, with exactly the fields the call's ",[483,8506,7571],{}," asks for. The extension config tells Engine so in ",[483,8509,8510],{},"engine.capabilities.query",", one value per kind of write:",[508,8513,8514,8527],{},[511,8515,8516],{},[514,8517,8518,8521,8524],{},[517,8519,8520],{},"Capability",[517,8522,8523],{},"Promise",[517,8525,8526],{},"How the Stripe connector keeps it",[531,8528,8529,8544,8561],{},[514,8530,8531,8536,8541],{},[536,8532,8533],{},[483,8534,8535],{},"insertReturning",[536,8537,8538,8540],{},[483,8539,7648],{}," answers the created items",[536,8542,8543],{},"Stripe answers each create with the new object",[514,8545,8546,8551,8558],{},[536,8547,8548],{},[483,8549,8550],{},"updateReturning",[536,8552,8553,549,8555,8557],{},[483,8554,8007],{},[483,8556,6842],{}," answer the updated items",[536,8559,8560],{},"Stripe answers each update with the updated object",[514,8562,8563,8568,8575],{},[536,8564,8565],{},[483,8566,8567],{},"deleteReturning",[536,8569,8570,549,8572,8574],{},[483,8571,4629],{},[483,8573,4632],{}," answer the deleted items",[536,8576,8577],{},"The handlers answer the item they read before deleting it",[459,8579,8580],{},"A write that fails partway throws, and never answers with a partial list, so the promise holds for every answer.",[459,8582,8583,8584,495],{},"Without the capabilities, Engine gets the written items from extra calls instead. A keyed update then costs five Stripe requests instead of two, and another writer can change an item between the calls. Each missing capability also adds declaration rules, which Engine checks when you create the data source. See ",[472,8585,8587],{"href":8586},"\u002Freference\u002Fextensions\u002Fdata-connectors\u002Foperations#declare-query-capabilities","Declare Query Capabilities",[459,8589,8590,8591,8594,8595,495],{},"With automatic reloading on, a build whose capabilities differ from the ones a data source was loaded with deactivates that data source. Every request that reaches its connector answers ",[483,8592,8593],{},"503"," until a restart or a workspace rebuild. See ",[472,8596,8598],{"href":8597},"\u002Freference\u002Fextensions\u002Fmanifest#capabilities","Capabilities",[459,8600,8601],{},[463,8602,3086],{},[1660,8604,8605,8611,8617,8627,8639],{},[1663,8606,8607,8608,8610],{},"a customer create, update and delete each return the selected fields, and a read after the delete answers ",[483,8609,7291],{},";",[1663,8612,8613,8614,8616],{},"an update with a guard that misses answers ",[483,8615,7291],{},", and a read shows nothing changed;",[1663,8618,8619,8620,8622,8623,8626],{},"deleting a product that has a price fails with ",[483,8621,3080],{}," \"Foreign key constraint failed\", with no ",[483,8624,8625],{},"dashboard.stripe.com"," link in the error;",[1663,8628,8629,8630,8632,8633,8635,8636,8610],{},"a data source created with ",[483,8631,4613],{}," refuses a create with ",[483,8634,3080],{}," and code ",[483,8637,8638],{},"4010",[1663,8640,8641,8642,8645,8646,495],{},"the built ",[483,8643,8644],{},"dist\u002Fmanifest.json"," lists all three capabilities under ",[483,8647,8510],{},[455,8649,8651],{"id":8650},"_7-test-the-connector","7. Test the Connector",[459,8653,8654,8655,8658],{},"Test in rungs, from cheapest to most realistic. The project's ",[483,8656,8657],{},"package.json"," has a script for each rung except the install:",[508,8660,8661,8674],{},[511,8662,8663],{},[514,8664,8665,8668,8671],{},[517,8666,8667],{},"Script",[517,8669,8670],{},"What it runs",[517,8672,8673],{},"What it asserts",[531,8675,8676,8693,8708,8720,8735,8751,8767],{},[514,8677,8678,8683,8690],{},[536,8679,8680],{},[483,8681,8682],{},"lint",[536,8684,8685,8686,8689],{},"ESLint with ",[483,8687,8688],{},"typescript-eslint","'s strict type-checked rules",[536,8691,8692],{},"No lint errors",[514,8694,8695,8700,8705],{},[536,8696,8697],{},[483,8698,8699],{},"typecheck",[536,8701,8702],{},[483,8703,8704],{},"tsc --noEmit",[536,8706,8707],{},"No type errors, including typos in field names and mapping keys",[514,8709,8710,8714,8717],{},[536,8711,8712],{},[483,8713,2649],{},[536,8715,8716],{},"Vitest, against a fake Stripe, with no network",[536,8718,8719],{},"110 tests: planning, the re-check, error mapping, timeouts, keyed operations, reads, and writes",[514,8721,8722,8727,8732],{},[536,8723,8724],{},[483,8725,8726],{},"build",[536,8728,8729],{},[483,8730,8731],{},"monospace extension build",[536,8733,8734],{},"A bundle and a manifest",[514,8736,8737,8742,8748],{},[536,8738,8739],{},[483,8740,8741],{},"seed",[536,8743,8744,8747],{},[483,8745,8746],{},"scripts\u002Fseed.mjs"," against your test-mode account",[536,8749,8750],{},"Creates the fixture customers, products and prices that are missing",[514,8752,8753,8758,8764],{},[536,8754,8755],{},[483,8756,8757],{},"smoke",[536,8759,8760,8763],{},[483,8761,8762],{},"scripts\u002Fsmoke.mjs",", which imports the built connector and calls Stripe",[536,8765,8766],{},"19 named checks, including results compared with Stripe's own answers",[514,8768,8769,8774,8780],{},[536,8770,8771],{},[483,8772,8773],{},"smoke:engine",[536,8775,8776,8779],{},[483,8777,8778],{},"scripts\u002Fengine-smoke.sh"," against a running instance",[536,8781,8782],{},"47 checks of status codes and response bodies through the REST API",[459,8784,8785,546,8787,546,8789,549,8791,8793,8794,8796,8797,8799],{},[483,8786,8682],{},[483,8788,8699],{},[483,8790,2649],{},[483,8792,8726],{}," need no Stripe key. The unit tests replace ",[483,8795,2118],{}," with a fake Stripe. So they cover what a live account can't produce on demand, such as a timeout, a ",[483,8798,2798],{},", or a bulk write that fails partway.",[459,8801,8802],{},"The live scripts take the key only from the environment, and the project stores none:",[508,8804,8805,8817],{},[511,8806,8807],{},[514,8808,8809,8812,8815],{},[517,8810,8811],{},"Variable",[517,8813,8814],{},"Used by",[517,8816,1977],{},[531,8818,8819,8841,8859],{},[514,8820,8821,8830,8838],{},[536,8822,8823,8826,8827],{},[483,8824,8825],{},"STRIPE_API_KEY",", or ",[483,8828,8829],{},"STRIPE_API_KEY_FILE",[536,8831,8832,546,8834,546,8836],{},[483,8833,8741],{},[483,8835,8757],{},[483,8837,8773],{},[536,8839,8840],{},"A test-mode key, or a file that holds only the key. The scripts refuse any other key",[514,8842,8843,8848,8852],{},[536,8844,8845],{},[483,8846,8847],{},"ENGINE_URL",[536,8849,8850],{},[483,8851,8773],{},[536,8853,8854,8855,8858],{},"The instance's base URL, ",[483,8856,8857],{},"http:\u002F\u002Flocalhost:8100"," by default",[514,8860,8861,8869,8873],{},[536,8862,8863,546,8866],{},[483,8864,8865],{},"ENGINE_EMAIL",[483,8867,8868],{},"ENGINE_PASSWORD",[536,8870,8871],{},[483,8872,8773],{},[536,8874,8875,8876,549,8879,8858],{},"An admin login, ",[483,8877,8878],{},"monospace@example.com",[483,8880,8881],{},"monospace",[459,8883,8884,8886,8887,549,8889,8892,8893,8896],{},[483,8885,8773],{}," also needs ",[483,8888,773],{},[483,8890,8891],{},"jq",". Each run leaves one archived price on ",[483,8894,8895],{},"prod_msfx_locked",", because Stripe can't delete prices.",[459,8898,8899],{},"Then break the connector on purpose and confirm a check fails:",[1660,8901,8902,8914,8926],{},[1663,8903,8904,8913],{},[463,8905,8906,8907,8910,8911],{},"A ",[483,8908,8909],{},"schemaDocument"," that ignores ",[483,8912,528],{}," still type-checks. It fails two unit tests and the Engine smoke.",[1663,8915,8916,8921,8922,8925],{},[463,8917,8918,8919],{},"Keyed writes that don't catch ",[483,8920,2816],{}," fail the unit test \"answers ",[483,8923,8924],{},"record: null"," when the object is deleted between the retrieve and a keyed write\", and the smoke.",[1663,8927,8928,8933],{},[463,8929,8930,8931],{},"An extension config without ",[483,8932,1680],{}," still builds, and Engine accepts the declaration. It fails the smoke's manifest check.",[459,8935,8936,8938,8939,8942],{},[463,8937,736],{}," every rung passes twice in a row against the test-mode account, and each deliberate break turns a specific check red. See ",[472,8940,256],{"href":8941},"\u002Fdeveloper\u002Fextensions\u002Fdata-connectors\u002Ftesting"," for the rungs, fixtures and techniques.",[455,8944,8946],{"id":8945},"next-steps","Next Steps",[1660,8948,8949,8954,8959,8964,8970],{},[1663,8950,8951,8953],{},[472,8952,246],{"href":1179},": rich and weak grammars, paging, keys and writes on other external data sources",[1663,8955,8956,8958],{},[472,8957,2839],{"href":2838},": map each failure from the external data source to the right error class",[1663,8960,8961,8963],{},[472,8962,256],{"href":8941},": the test rungs and fixtures in detail",[1663,8965,8966,8969],{},[472,8967,414],{"href":8968},"\u002Freference\u002Fextensions\u002Fdata-connectors\u002Foperations",": the declaration rules Engine enforces",[1663,8971,8972,8976],{},[472,8973,8975],{"href":8974},"\u002Freference\u002Fextensions\u002Fdata-connectors\u002Flimits","Data Connector Limits",": deadlines, page sizes and concurrency",[8978,8979,8980],"style",{},"html pre.shiki code .ssBNi, html code.shiki .ssBNi{--shiki-light:#1659E9;--shiki-default:#1659E9;--shiki-dark:#94B3F5}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 .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 .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 .seNfP, html code.shiki .seNfP{--shiki-light:#64748B;--shiki-default:#64748B;--shiki-dark:#94A3B8}",{"title":637,"searchDepth":786,"depth":786,"links":8982},[8983,8984,8985,8986,8987,8990,8993,9000,9004,9005],{"id":457,"depth":786,"text":143},{"id":648,"depth":786,"text":649},{"id":751,"depth":786,"text":752},{"id":1187,"depth":786,"text":1188},{"id":1951,"depth":786,"text":1952,"children":8988},[8989],{"id":2111,"depth":797,"text":2112},{"id":3131,"depth":786,"text":3132,"children":8991},[8992],{"id":3989,"depth":797,"text":3990},{"id":4642,"depth":786,"text":4643,"children":8994},[8995,8996,8997,8998,8999],{"id":4652,"depth":797,"text":4653},{"id":5245,"depth":797,"text":5246},{"id":5725,"depth":797,"text":5726},{"id":6232,"depth":797,"text":6233},{"id":6247,"depth":797,"text":2047},{"id":6834,"depth":786,"text":6835,"children":9001},[9002,9003],{"id":7641,"depth":797,"text":7642},{"id":8501,"depth":797,"text":1685},{"id":8650,"depth":786,"text":8651},{"id":8945,"depth":786,"text":8946},"Build a Stripe test-mode data connector extension with customers, products and prices, from probing the API to writes and tests.","md",null,{},{"title":123,"icon":126},{"title":447,"description":9006},"5UvfzwJ-CwSyyKkfAFPmFii3ZJAPYjpC55BqOUBKMo8",[9014,9016],{"title":16,"path":119,"stem":120,"description":9015,"icon":121,"children":-1},"Build a read-only data connector extension for the Art Institute of Chicago API step by step, install it, and query it in Studio.",{"title":128,"path":129,"stem":130,"description":9017,"icon":131,"children":-1},"Point a coding agent at the extension docs, give it a starter prompt, and know which steps still need you.",1790840104188]