├── .gitignore ├── LICENSE ├── README.md ├── docs ├── base │ ├── HTTP.md │ ├── about.md │ ├── async_sdk.md │ ├── base_ui.md │ ├── expiring_items.md │ ├── node_tutorial.md │ ├── py_tutorial.md │ ├── queries.md │ └── sdk.md ├── cli │ ├── auth.md │ ├── commands.md │ ├── install.md │ └── releases.md ├── common_issues.md ├── drive │ ├── HTTP.md │ ├── about.md │ ├── drive_ui.md │ ├── node_tutorial.md │ ├── py_tutorial.md │ └── sdk.md ├── faqs.md ├── home.md ├── micros │ ├── about.md │ ├── api_keys.md │ ├── cron.md │ ├── custom_domains.md │ ├── deploy.md │ ├── deploy_on_deta_button.md │ ├── env_vars.md │ ├── faqs.md │ ├── getting_started.md │ ├── run.md │ └── visor.md └── tutorials │ ├── cron.md │ ├── fast_api.md │ ├── forms.md │ └── webhooks.md ├── docusaurus.config.js ├── package-lock.json ├── package.json ├── sidebars.js ├── src ├── .DS_Store ├── css │ └── custom.css └── pages │ ├── .index.js │ └── styles.module.css ├── static ├── img │ ├── base_ui │ │ ├── base_ui_1.png │ │ ├── base_ui_2.png │ │ ├── base_ui_3.png │ │ ├── base_ui_4.png │ │ ├── base_ui_5.png │ │ ├── base_ui_6.png │ │ ├── base_ui_7.png │ │ └── base_ui_8.png │ ├── deploy_button │ │ ├── button.svg │ │ └── deta-topic.png │ ├── domains │ │ └── custom_domain.png │ ├── drive │ │ ├── drive-py-tut-1.png │ │ ├── drive-py-tut.png │ │ └── drive_ui │ │ │ ├── drive_ui_1.png │ │ │ ├── drive_ui_2.png │ │ │ ├── drive_ui_3.png │ │ │ ├── drive_ui_4.png │ │ │ ├── drive_ui_5.png │ │ │ └── drive_ui_6.png │ ├── favicon.ico │ ├── logo.svg │ ├── quickstart │ │ └── contact_form.png │ ├── undraw_docusaurus_mountain.svg │ ├── undraw_docusaurus_react.svg │ ├── undraw_docusaurus_tree.svg │ └── visor │ │ ├── visor_1.png │ │ ├── visor_10.png │ │ ├── visor_11.png │ │ ├── visor_2.png │ │ ├── visor_3.png │ │ ├── visor_4.png │ │ ├── visor_5.png │ │ ├── visor_6.png │ │ ├── visor_7.png │ │ ├── visor_8.png │ │ └── visor_9.png └── index.html └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | .* 4 | *.log 5 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using [Docusaurus 2](https://v2.docusaurus.io/), a modern static website generator. 4 | 5 | ### Installation 6 | 7 | ``` 8 | $ yarn 9 | ``` 10 | 11 | ### Local Development 12 | 13 | ``` 14 | $ yarn start 15 | ``` 16 | 17 | This command starts a local development server and open up a browser window. Most changes are reflected live without having to restart the server. 18 | 19 | ### Build 20 | 21 | ``` 22 | $ yarn build 23 | ``` 24 | 25 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 26 | 27 | ### Deployment 28 | 29 | ``` 30 | $ GIT_USER= USE_SSH=true yarn deploy 31 | ``` 32 | 33 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. 34 | -------------------------------------------------------------------------------- /docs/base/HTTP.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: http 3 | title: HTTP API 4 | sidebar_label: HTTP API 5 | --- 6 | import Tabs from '@theme/Tabs'; 7 | import TabItem from '@theme/TabItem'; 8 | 9 | export let Bubble = ({ item }) => { 10 | return ( 11 |
12 |
13 | {item} 14 |
15 |
16 |
17 | ); 18 | } 19 | 20 | ## General & Auth 21 | 22 | :::note 23 | You can get your **Project Key** and your **Project ID** from your [Deta dashboard](https://web.deta.sh). You need these to talk with the Deta API. 24 | ::: 25 | 26 | :::info 27 | Base currently supports **maximum 16 digit numbers** (integers and floating points), please store larger numbers as a string. 28 | ::: 29 | 30 | ### Root URL 31 | This URL is the base for all your HTTP requests: 32 | 33 | **`https://database.deta.sh/v1/{project_id}/{base_name}`** 34 | 35 | > The `base_name` is the name given to your database. If you already have a **Base**, then you can go ahead and provide it's name here. Additionally, you could provide any name here when doing any `PUT` or `POST` request and our backend will automatically create a new base for you if it does not exist. There is no limit on how many "Bases" you can create. 36 | 37 | ### Auth 38 | A **Project Key** _must_ to be provided in the request **headers** as a value for the `X-API-Key` key for authentication. This is how we authorize your requests. 39 | 40 | Example `'X-API-Key: a0abcyxz_aSecretValue'`. 41 | 42 | ### Content Type 43 | 44 | We only accept JSON payloads. Make sure you set the headers correctly: `'Content-Type: application/json'` 45 | 46 | ## Endpoints 47 | 48 | ### Put Items 49 | 50 | **`PUT /items`** 51 | 52 | Stores multiple items in a single request. This request overwrites an item if the key already exists. 53 | 54 | 61 | 62 | 63 | 64 | | JSON Payload | Required | Type | Description | 65 | |--------------|----------|---------|------------------------------------------| 66 | | `items` | Yes | `array` | An array of items `object` to be stored. | 67 | 68 | 69 | 70 | #### Example 71 | 72 | ```json 73 | { 74 | // array of items to put 75 | "items": [ 76 | { 77 | "key": {key}, // optional, a random key is generated if not provided 78 | "field1": "value1", 79 | // rest of item 80 | }, 81 | // rest of items 82 | ] 83 | } 84 | ``` 85 | 86 | 87 | 88 | 89 | #### `207 Multi Status` 90 | 91 | ```js 92 | { 93 | "processed": { 94 | "items": [ 95 | // items which were stored 96 | ] 97 | }, 98 | "failed": { 99 | "items": [ 100 | // items failed because of internal processing 101 | ] 102 | } 103 | } 104 | ``` 105 | 106 | #### Client errors 107 | 108 | In case of client errors, **no items** in the request are stored. 109 | 110 | #### `400 Bad Request` 111 | 112 | ```js 113 | { 114 | "errors" : [ 115 | // error messages 116 | ] 117 | } 118 | ``` 119 | 120 | Bad requests occur in the following cases: 121 | - if an item has a non-string key 122 | - if the number of items in the requests exceeds 25 123 | - if total request size exceeds 16 MB 124 | - if any individual item exceeds 400KB 125 | - if there are two items with identical keys 126 | 127 | :::info 128 | Empty keys in objects/dictionaries/structs, like `{"": "value"}` are invalid and will fail to be added during the backend processing stage. 129 | ::: 130 | 131 | 132 | 133 | 134 | ### Get Item 135 | 136 | **`GET /items/{key}`** 137 | 138 | Get a stored item. 139 | 140 | :::note 141 | If the *key* contains url unsafe or reserved characters, make sure to url-encode the *key*. Otherwise, it will lead to unexpected behavior. 142 | ::: 143 | 144 | 151 | 152 | 153 | | URL Parameter | Required | Type | Description | 154 | |---------------|----------|----------|----------------------------------------------------| 155 | | `key` | Yes | `string` | The key (aka. ID) of the item you want to retrieve | 156 | 157 | 158 | 159 | 160 | 161 | 162 | #### `200 OK` 163 | 164 | ```js 165 | { 166 | "key": {key}, 167 | // the rest of the item 168 | } 169 | ``` 170 | 171 | #### `404 Not Found` 172 | ```js 173 | { 174 | "key": {key} 175 | } 176 | ``` 177 | 178 | 179 | 180 | 181 | 182 | ### Delete Item 183 | 184 | **`DELETE /items/{key}`** 185 | 186 | Delete a stored item. 187 | 188 | :::note 189 | If the *key* contains url unsafe or reserved characters, make sure to url-encode the *key*. Otherwise, it will lead to unexpected behavior. 190 | ::: 191 | 192 | 199 | 200 | 201 | | URL Parameter | Required | Type | Description | 202 | |---------------|----------|----------|---------------------------------------------------| 203 | | `key` | Yes | `string` | The key (aka. ID) of the item you want to delete. | 204 | 205 | 206 | 207 | 208 | The server will always return `200` regardless if an item with that `key` existed or not. 209 | 210 | #### `200 OK` 211 | 212 | ```json 213 | { 214 | "key": {key} 215 | } 216 | ``` 217 | 218 | 219 | 220 | 221 | ### Insert Item 222 | 223 | **`POST /items`** 224 | 225 | Creates a new item only if no item with the same `key` exists. 226 | 227 | 234 | 235 | 236 | 237 | | JSON Payload | Required | Type | Description | 238 | |--------------|----------|----------|------------------------| 239 | | `item` | Yes | `object` | The item to be stored. | 240 | 241 | #### Example 242 | 243 | ```json 244 | { 245 | "item": { 246 | "key": {key}, // optional 247 | // rest of item 248 | } 249 | } 250 | ``` 251 | 252 | 253 | 254 | 255 | #### `201 Created` 256 | 257 | ```json 258 | { 259 | "key": {key}, // auto generated key if key was not provided in the request 260 | "field1": "value1", 261 | // the rest of the item 262 | } 263 | ``` 264 | 265 | #### Client errors 266 | 267 | #### `409 Conflict` (if key already exists) 268 | 269 | ```json 270 | { 271 | "errors": ["Key already exists"] 272 | } 273 | ``` 274 | 275 | #### `400 Bad Request` 276 | 277 | ```json 278 | { 279 | "errors": [ 280 | // error messages 281 | ] 282 | } 283 | ``` 284 | 285 | Bad requests occur in the following cases: 286 | - if the item has a non-string key 287 | - if size of the item exceeds 400KB 288 | 289 | 290 | 291 | 292 | ### Update Item 293 | 294 | **`PATCH /items/{key}`** 295 | 296 | Updates an item only if an item with `key` exists. 297 | 298 | :::note 299 | If the *key* contains url unsafe or reserved characters, make sure to url-encode the *key*. Otherwise, it will lead to unexpected behavior. 300 | ::: 301 | 302 | 309 | 310 | 311 | 312 | | JSON Payload | Required | Type | Description | 313 | |--------------|----------|-------------------|----------------------------------------------------------------------| 314 | | `set` | no | `object` | The attributes to be updated or created. | 315 | | `increment` | no | `object` | The attributes to be incremented. Increment value can be negative. | 316 | | `append` | no | `object` | The attributes to append a value to. Appended value must be a list. | 317 | | `prepend` | no | `object` | The attributes to prepend a value to. Prepended value must be a list.| 318 | | `delete` | no | `string array` | The attributes to be deleted. | 319 | 320 | #### Example 321 | 322 | If the following item exists in the database 323 | 324 | ```json 325 | { 326 | "key": "user-a", 327 | "username": "jimmy", 328 | "profile": { 329 | "age": 32, 330 | "active": false, 331 | "hometown": "pittsburgh" 332 | }, 333 | "on_mobile": true, 334 | "likes": ["anime"], 335 | "purchases": 1 336 | } 337 | ``` 338 | 339 | Then the request 340 | 341 | ```json 342 | { 343 | "set" : { 344 | // change ages to 33 345 | "profile.age": 33, 346 | // change active to true 347 | "profile.active": true, 348 | // add a new attribute `profile.email` 349 | "profile.email": "jimmy@deta.sh" 350 | }, 351 | 352 | "increment" :{ 353 | // increment purchases by 2 354 | "purchases": 2 355 | }, 356 | 357 | "append": { 358 | // append to 'likes' 359 | "likes": ["ramen"] 360 | }, 361 | 362 | // remove attributes 'profile.hometown' and 'on_mobile' 363 | "delete": ["profile.hometown", "on_mobile"] 364 | } 365 | ``` 366 | 367 | results in the following item in the database: 368 | 369 | ```json 370 | { 371 | "key": "user-a", 372 | "username": "jimmy", 373 | "profile": { 374 | "age": 33, 375 | "active": true, 376 | "email": "jimmy@deta.sh" 377 | }, 378 | "likes": ["anime", "ramen"], 379 | "purchases": 3 380 | } 381 | ``` 382 | 383 | 384 | 385 | 386 | #### `200 OK` 387 | 388 | ```json 389 | { 390 | "key": {key}, 391 | "set": { 392 | // identical to the request 393 | }, 394 | "delete": ["field1", ..] // identical to the request 395 | } 396 | ``` 397 | 398 | #### Client errors 399 | 400 | #### `404 Not Found` (if key does not exist) 401 | 402 | ```json 403 | { 404 | "errors": ["Key not found"] 405 | } 406 | ``` 407 | 408 | #### `400 Bad Request` 409 | 410 | ```json 411 | { 412 | "errors": [ 413 | // error messages 414 | ] 415 | } 416 | ``` 417 | 418 | Bad requests occur in the following cases: 419 | - if you're updating or deleting the `key` 420 | - if `set` and `delete` have conflicting attributes 421 | - if you're setting a hierarchical attribute but an upper level attribute does not exist, for eg. `{"set": {"user.age": 22}}` but `user` is not an attribute of the item. 422 | 423 | 424 | 425 | 426 | 427 | ### Query Items 428 | 429 | **`POST /query`** 430 | 431 | List items that match a [query](https://docs.deta.sh/docs/base/queries/). 432 | 433 | 440 | 441 | 442 | | JSON Payload | Required | Type | Description | 443 | |-----------------|----------|----------|------------------------------------------------| 444 | | `query` | No | `list` | list of a [query](https://docs.deta.sh/docs/base/queries/)| 445 | | `limit` | No | `int` | no of items to return. min value 1 if used | 446 | | `last` | No | `string` | last key seen in a previous paginated response | 447 | 448 | 449 | #### Example 450 | 451 | ```json 452 | { 453 | "query": [ 454 | // separate objects in the list are ORed 455 | // query evaluates to list all users whose hometown is Berlin and is active OR all users who age less than 40 456 | {"user.hometown": "Berlin", "user.active": true}, 457 | {"user.age?lt": 40} 458 | ], 459 | "limit": 5, 460 | "last": "afsefasd" // last key if applicable 461 | } 462 | ``` 463 | 464 | 465 | 466 | 467 | The response is paginated if data process size exceeds 1 MB (before the query is applied) or the total number of items matching the `query` exceeds the `limit` provided in the request. 468 | 469 | For paginated responses, `last` will return the last key seen in the response. You must use this `key` in the following request to continue retreival of items. If the response does not have the `last` key, then no further items are to be retreived. 470 | 471 | :::note 472 | Upto 1 MB of data is retrieved before filtering with the query. Thus, in some cases you might get an empty list of items but still the `last` key evaluated in the response. 473 | 474 | To apply the query through all the items in your base, you have to call fetch until `last` is empty. 475 | ::: 476 | 477 | #### `200 OK` 478 | 479 | ```json 480 | { 481 | "paging": { 482 | "size": 5, // size of items returned 483 | "last": "adfjie" // last key seen if paginated, provide this key in the following request 484 | }, 485 | "items": [ 486 | { 487 | "key": {key}, 488 | // rest of the item 489 | }, 490 | // rest of the items 491 | ] 492 | } 493 | ``` 494 | 495 | #### Client Errors 496 | 497 | #### `400 Bad Request` 498 | 499 | ```json 500 | { 501 | "errors": [ 502 | // error messages 503 | ] 504 | } 505 | ``` 506 | 507 | Bad requests occur in the following cases: 508 | - if a query is made on the `key` 509 | - if a query is not of the right format 510 | - if `limit` is provided in the request and is less than 1 511 | 512 | 513 | 514 | 515 | ## Issues 516 | 517 | If you run into any issues, consider reporting them in our [Github Discussions](https://github.com/orgs/deta/discussions). -------------------------------------------------------------------------------- /docs/base/about.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: about 3 | title: About Deta Base 4 | sidebar_label: About 5 | --- 6 | Deta Base is a fully-managed, fast, scalable and secure NoSQL database with a focus on end-user simplicity. It offers a [UI](base_ui.md) through which you can easily see, query, update and delete records in the database. 7 | 8 | ## What can Deta Base be used for? 9 | 10 | Deta Base is great for projects where configuring and maintaining a database is overkill. 11 | 12 | Examples: 13 | - Serverless Applications 14 | - Internal Tools 15 | - Stateful Integrations 16 | - Hackathons and Side Projects 17 | - Prototyping 18 | 19 | ## Is my data secure? 20 | 21 | Your data is encrypted and stored safely on AWS. Encryption keys are managed by AWS; AWS manages Exabytes of the world's most sensitive data. 22 | 23 | ## How do I start? 24 | 25 | 1. Log in to [Deta](https://web.deta.sh). 26 | 2. Grab your **Project Key** and your **Project ID** and start writing code in [Python](sdk.md), [Node.js](sdk.md), or over [HTTP](HTTP.md) wherever you need persistent data storage. 27 | -------------------------------------------------------------------------------- /docs/base/async_sdk.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: async_sdk 3 | title: Deta Base Python Async SDK 4 | --- 5 | 6 | The Deta Base Python Async SDK can be used for reading and writing data asynchronously with Deta Base in Python. 7 | 8 | :::warning 9 | These are docs for an alpha version of the Python Deta Base Async SDK. The SDK API may change in a stable release. 10 | ::: 11 | 12 | ## Installing 13 | 14 | ``` 15 | pip install deta[async]==1.1.0a2 16 | ``` 17 | 18 | ## Instantiating 19 | 20 | ```py 21 | from deta import Deta 22 | 23 | # initialize with a project key 24 | # you can also init without specfying the project key explicitly 25 | # the sdk looks for the DETA_PROJECT_KEY env var in that case 26 | deta = Deta("project_key") 27 | 28 | # create an async base client 29 | async_db = deta.AsyncBase("base_name") 30 | ``` 31 | 32 | ## Methods 33 | 34 | The **`AsyncBase`** class offers the same API to interact with your Base as the **`Base`** class: 35 | 36 | ### Put 37 | 38 | ```py 39 | put( 40 | data: typing.Union[dict, list, str, int, float, bool], 41 | key: str = None, 42 | *, 43 | expire_in: int = None, 44 | expire_at: typing.Union[int, float, datetime.datetime] 45 | ) 46 | ``` 47 | 48 | - **data** (required): The data to be stored. 49 | - **key** (optional): The key to store the data under. It will be auto-generated if not provided. 50 | - **expire_in** (optional) - Accepts: `int` and `None` 51 | - Description: seconds after which the item will expire in, see also [expiring items](#./expiring_items) 52 | - **expire_at** (optional) - Accepts: `int`, `float`, `datetime.datetime` and `None` 53 | - Description: time at which the item will expire in, can provide the timestamp directly(`int` or `float`) or a [datetime.datetime](https://docs.python.org/3/library/datetime.html) object, see also [expiring items](./expiring_items) 54 | 55 | 56 | #### Example 57 | 58 | ```py 59 | import asyncio 60 | from deta import Deta 61 | 62 | async_db = Deta("project_key").AsyncBase("base_name") 63 | 64 | async def put_item(): 65 | item = {"msg": "hello"} 66 | await async_db.put(item, "test") 67 | print("put item:", item) 68 | 69 | # put expiring items 70 | # expire item in 300 seconds 71 | await async_db.put(item, expire_in=300) 72 | 73 | # with expire at 74 | expire_at = datetime.datetime.fromisoformat("2023-01-01T00:00:00") 75 | await async_db.put({"name": "max", "age": 28}, "max28", expire_at=expire_at) 76 | 77 | # close connection 78 | await async_db.close() 79 | 80 | loop = asyncio.get_event_loop() 81 | loop.run_until_complete(put_item()) 82 | ``` 83 | 84 | ### Get 85 | 86 | ```py 87 | get(key: str) 88 | ``` 89 | 90 | - **key** (required): The key of the item to be retrieved. 91 | 92 | #### Example 93 | 94 | ```py 95 | import asyncio 96 | from deta import Deta 97 | 98 | async_db = Deta("project_key").AsyncBase("base_name") 99 | 100 | async def get_item(): 101 | item = await async_db.get("my_key") 102 | print("got item:", item) 103 | 104 | # close connection 105 | await async_db.close() 106 | 107 | loop = asyncio.get_event_loop() 108 | loop.run_until_complete(get_item()) 109 | ``` 110 | 111 | ### Delete 112 | 113 | ```py 114 | delete(key: str) 115 | ``` 116 | 117 | - **key** (required): The key of the item to delete. 118 | 119 | #### Example 120 | 121 | ```py 122 | import asyncio 123 | from deta import Deta 124 | 125 | async_db = Deta("project_key").AsyncBase("base_name") 126 | 127 | async def del_item(): 128 | await async_db.delete("my-key") 129 | print("Deleted item") 130 | 131 | # close connection 132 | await async_db.close() 133 | 134 | loop = asyncio.get_event_loop() 135 | loop.run_until_complete(del_item()) 136 | ``` 137 | 138 | ### Insert 139 | 140 | `insert` is unique from `put` in that it will raise an error if the `key` already exists in the database, whereas `put` overwrites the item. 141 | 142 | ```py 143 | insert( 144 | data: typing.Union[dict, list, str, int, float, bool], 145 | key: str = None, 146 | *, 147 | expire_in: int = None, 148 | expire_at: typing.Union[int, float, datetime.datetime] = None 149 | ) 150 | ``` 151 | 152 | - **data** (required): The data to be stored. 153 | - **key** (optional): The key to store the data under, will be auto generated if not provided. 154 | - **expire_in** (optional) - Accepts: `int` and `None` 155 | - Description: seconds after which the item will expire in, see also [expiring items](./expiring_items) 156 | - **expire_at** (optional) - Accepts: `int`, `float`, `datetime.datetime` and `None` 157 | - Description: time at which the item will expire in, can provide the timestamp directly(`int` or `float`) or a [datetime.datetime](https://docs.python.org/3/library/datetime.html) object, see also [expiring items](./expiring_items) 158 | 159 | 160 | #### Example 161 | 162 | ```py 163 | import asyncio 164 | from deta import Deta 165 | 166 | async_db = Deta("project_key").AsyncBase("base_name") 167 | 168 | async def insert_item(): 169 | item = {"msg": "hello"} 170 | await async_db.insert(item, "test") 171 | print("inserted item:", item) 172 | 173 | # put expiring items 174 | # expire item in 300 seconds 175 | await async_db.insert(item, expire_in=300) 176 | 177 | # with expire at 178 | expire_at = datetime.datetime.fromisoformat("2023-01-01T00:00:00") 179 | await async_db.insert({"name": "max", "age": 28}, "max28", expire_at=expire_at) 180 | 181 | # close connection 182 | await async_db.close() 183 | 184 | loop = asyncio.get_event_loop() 185 | loop.run_until_complete(insert_item()) 186 | ``` 187 | 188 | ### Put Many 189 | 190 | ```py 191 | put_many( 192 | items: typing.List[typing.Union[dict, list, str, int, bool]], 193 | *, 194 | expire_in: int = None, 195 | expire_at: typing.Union[int, float, datetime.datetime] = None 196 | ) 197 | ``` 198 | 199 | - **items** (required): list of items to be stored. 200 | - **expire_in** (optional) - Accepts: `int` and `None` 201 | - Description: seconds after which the item will expire in, see also [expiring items](./expiring_items) 202 | - **expire_at** (optional) - Accepts: `int`, `float`, `datetime.datetime` and `None` 203 | - Description: time at which the item will expire in, can provide the timestamp directly(`int` or `float`) or a [datetime.datetime](https://docs.python.org/3/library/datetime.html) object, see also [expiring items](./expiring_items) 204 | 205 | #### Example 206 | 207 | ```py 208 | import asyncio 209 | from deta import Deta 210 | 211 | async_db = Deta("project_key").AsyncBase("base_name") 212 | 213 | async def put_items(): 214 | items = [{"key": "one", "value": 1}, {"key": "two", "value": 2}] 215 | await async_db.put_many(items) 216 | print("put items:", items) 217 | 218 | # put with expiring items 219 | # expire in 300 seconds 220 | await async_db.put_many(items, expire_in=300) 221 | 222 | # with expire at 223 | expire_at = datetime.datetime.fromisoformat("2023-01-01T00:00:00") 224 | await async_db.put_many(items, expire_at=expire_at) 225 | 226 | # close connection 227 | await async_db.close() 228 | 229 | loop = asyncio.get_event_loop() 230 | loop.run_until_complete(put_items()) 231 | ``` 232 | 233 | ### Update 234 | 235 | ```py 236 | update( 237 | updates:dict, 238 | key:str, 239 | *, 240 | expire_in: int = None, 241 | expire_at: typing.Union[int, float, datetime.datetime] = None 242 | ) 243 | ``` 244 | 245 | - **updates** (required): A dict describing the updates on the item, refer to [updates](/docs/base/sdk#update) for more details. 246 | - **key** (required): The key of the item to update. 247 | - **expire_in** (optional) - Accepts: `int` and `None` 248 | - Description: seconds after which the item will expire in, see also [expiring items](./expiring_items) 249 | - **expire_at** (optional) - Accepts: `int`, `float`, `datetime.datetime` and `None` 250 | - Description: time at which the item will expire in, can provide the timestamp directly(`int` or `float`) or a [datetime.datetime](https://docs.python.org/3/library/datetime.html) object, see also [expiring items](./expiring_items) 251 | 252 | #### Example 253 | 254 | ```py 255 | import asyncio 256 | from deta import Deta 257 | 258 | async_db = Deta("project_key").AsyncBase("base_name") 259 | 260 | async def update_item(): 261 | updates = {"profile.age": 20, "likes": async_db.util.append("ramen")} 262 | await async_db.update(updates, "jimmy") 263 | print("updated user jimmy") 264 | 265 | # close connection 266 | await async_db.close() 267 | 268 | loop = asyncio.get_event_loop() 269 | loop.run_until_complete(update_item()) 270 | ``` 271 | 272 | ### Fetch 273 | 274 | **`fetch(query=None, limit=1000, last=None)`** 275 | 276 | - **query** : a [query or a list of queries](https://docs.deta.sh/docs/base/sdk/queries/) 277 | - **limit** : the limit of the number of items you want to recieve, min value `1` if used. 278 | - **last**: the last key seen in a previous paginated response. 279 | 280 | #### Example 281 | 282 | ```py 283 | import asyncio 284 | from deta import Deta 285 | 286 | async_db = Deta("project_key").AsyncBase("base_name") 287 | 288 | async def fetch_items(): 289 | query = {"profile.age?gt": 20} 290 | res = await async_db.fetch(query) 291 | print("fetched items": res.items) 292 | 293 | # close connection 294 | await async_db.close() 295 | 296 | loop = asyncio.get_event_loop() 297 | loop.run_until_complete(fetch_items()) 298 | ``` 299 | 300 | ## Issues 301 | 302 | If you run into any issues, consider reporting them in our [Github Discussions](https://github.com/orgs/deta/discussions). We also appreciate any feedback. 303 | 304 | -------------------------------------------------------------------------------- /docs/base/base_ui.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: base_ui 3 | title: Base UI (Beta) 4 | sidebar_label: Base UI 5 | --- 6 | 7 | Base UI let's you inspect, add, modify and delete records from a Base via a GUI. 8 | 9 | ### Opening Base UI 10 | 11 | You can open an individual Base's UI within any project by clicking on the Base name in the project sidebar. 12 | 13 | base_ui_1 14 | 15 | All the data from your Base should load into the table view when clicked. You can edit individual cells, if they do not contain an array or an object. 16 | 17 | base_ui_2 18 | 19 | 20 | ### Advanced Editing 21 | 22 | You can expand any cell if you want to do advanced editing (like the editing of objects and arrays or type changes). 23 | 24 | base_ui_3 25 | 26 | ### Queries 27 | 28 | If you don't want to deal with all of your data at once, you can use Deta Base's queries to get a filtered view. Click the **Query** button, enter your query, and hit enter or click **Fetch**. 29 | 30 | base_ui_4 31 | 32 |
33 | 34 | base_ui_5 35 | 36 | ### Adding Items 37 | 38 | You can add new items by clicking **+ Add**. 39 | 40 | base_ui_6 41 | 42 | New rows and edited rows will appear in yellow. 43 | 44 | You can permanently save these modifications by clicking **Save edits**. 45 | 46 | ### Deleting Items 47 | 48 | To delete items, click on the checkbox(es) for any item(s) and then click the **Delete** button. 49 | 50 | base_ui_7 51 | 52 | ### Undoing Changes 53 | 54 | You can revert your local changes, restoring the BaseUI state to the last fetch by clicking the **Undo** button. 55 | 56 | base_ui_8 57 | 58 | ### Final Notes 59 | 60 | We hope you enjoy Base UI! 61 | 62 | Base UI is still in Beta; it has been internally tested but may have some uncaught bugs or issues. 63 | 64 | If you run into any issues, consider reporting them in our [Github Discussions](https://github.com/orgs/deta/discussions). We also take suggestions! -------------------------------------------------------------------------------- /docs/base/expiring_items.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: expiring_items 3 | title: Expiring Items 4 | --- 5 | 6 | import Tabs from '@theme/Tabs'; 7 | import TabItem from '@theme/TabItem'; 8 | 9 | Deta Base supports storing items with an expiration timestamp. Items with an expired timestamp will be automatically deleted from your Base. 10 | 11 | ## Storing 12 | 13 | Items specify the expiration timestamp value in a field name `__expires` in the item itself. The value is a [Unix time](https://en.wikipedia.org/wiki/Unix_time), a number. 14 | 15 | For e.g. 16 | ```json 17 | { 18 | "key": "item_key", 19 | "msg": "this will be deleted", 20 | "__expires": 1672531200 21 | } 22 | ``` 23 | 24 | The item above will be deleted automatically on `2023-01-01 00:00:00 GMT` (the equivalent date of the timestamp above). 25 | 26 | You can use the [Base SDK](./sdk.md) to [`put`](./sdk#put), [`put_many`](./sdk#put_many) or [`insert`](./sdk#insert) items with an expiration timestamp (or the [HTTP API](./HTTP.md) directly). 27 | 28 | :::warning 29 | Storing an item with an already expired timestamp will not fail but the item will be immediately deleted. 30 | ::: 31 | 32 | :::info 33 | Base SDKs might offer higher level methods with easier APIs to specify the expiration timestamp. If they do so, they still store the timestamp in the item itself as mentioned above. 34 | ::: 35 | 36 | ### Examples 37 | 38 | 48 | 49 | 50 | 51 | ```js 52 | const Deta = require('deta'); 53 | const db = Deta("project_key").Base('examples'); 54 | 55 | const item = {'value': 'temp'}; 56 | 57 | // expire in 300 seconds 58 | await db.put(item, 'temp_key', {expireIn:300}) 59 | 60 | // expire at date 61 | await db.put(item, 'temp_key', {expireAt: new Date('2023-01-01T00:00:00')}) 62 | ``` 63 | 64 | 65 | 66 | 67 | ```py 68 | import datetime 69 | from deta import Deta 70 | 71 | db = Deta("project_key").Base("examples") 72 | 73 | item = {"key": "temp_key", "value": "temp"} 74 | 75 | # expire in 300 seconds 76 | db.put(item, expire_in=300) 77 | 78 | # expire at date 79 | expire_at = datetime.datetime.fromisoformat("2023-01-01T00:00:00") 80 | db.put(item, expire_at=expire_at) 81 | ``` 82 | 83 | 84 | 85 | 86 | 87 | ```go 88 | import ( 89 | "log" 90 | "time" 91 | 92 | "github.com/deta/deta-go/deta" 93 | "github.com/deta/deta-go/service/base" 94 | ) 95 | 96 | type TmpData struct { 97 | Key string `json: "key"` 98 | Value string `json:"value"` 99 | // json struct tag `__expires` for expiration timestamp 100 | // 'omitempty' to prevent default 0 value 101 | Expires int64 `json:"__expires,omitempty"` 102 | } 103 | 104 | func main() { 105 | // errors ignored for brevity 106 | d, _ := deta.New(deta.WithProjectKey("project_key")) 107 | db, _ := base.New(d, "examples") 108 | 109 | tmp := &TmpData{ 110 | Key: "temp_key", 111 | Value: "temp", 112 | Expires: time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC).Unix(), 113 | } 114 | _, err := db.Put(tmp) 115 | if err != nil { 116 | log.Fatal("failed to put item:", err) 117 | } 118 | } 119 | ``` 120 | 121 | 122 | 123 | 124 | 125 | ```shell 126 | curl -X PUT "https://database.deta.sh/v1/test_project_id/examples/items" \ 127 | -H "Content-Type: application/json" \ 128 | -H "X-Api-Key: test_project_key" \ 129 | -d {"items":[{"key": "temp_key", "value": "temp", "__expires": 1672531200}]} 130 | ``` 131 | 132 | 133 | 134 | 135 | 136 | ## Retrieving 137 | 138 | When you retrieve items with an expiration timestamp, the timestamp value will be present in the `__expires` field. The value is a [Unix time](https://en.wikipedia.org/wiki/Unix_time). 139 | 140 | `Get` and `Query` operations will not retrieve already expired items. 141 | 142 | ### Examples 143 | 144 | 154 | 155 | 156 | 157 | ```js 158 | const { __expires } = await db.get("temp_key"); 159 | ``` 160 | 161 | 162 | 163 | 164 | 165 | ```py 166 | expires = db.get("temp_key").get("__expires") 167 | ``` 168 | 169 | 170 | 171 | 172 | ```go 173 | dest := struct{ 174 | Key string `json:"key"` 175 | Expires int64 `json:"__expires,omitempty"` 176 | }{} 177 | 178 | if err := db.Get("temp_key", &dest); err != nil { 179 | log.Fatal("failed to get item:", err) 180 | } 181 | 182 | expires := dest.Expires 183 | ``` 184 | 185 | 186 | 187 | 188 | 189 | ```shell 190 | curl "https://database.deta.sh/v1/test_project_id/examples/items/temp_key" \ 191 | -H "X-Api-Key: test_project_key" 192 | 193 | {"key": "temp_key", "value": "temp", "__expires": 1672531200} 194 | ``` 195 | 196 | 197 | 198 | 199 | 200 | 201 | ## Updating 202 | 203 | You can update the expiration timestamp with a new timestamp by updating the value of the `__expires` as long as the item has not already expired. 204 | 205 | Updating other fields of the item **does not** update (or renew) the expiration timestamp. You **must** update the value of `__expires` field. 206 | 207 | You can use the [Base SDK](./sdk.md) to [`update`](./sdk#update) the expiration timestamp (or the [HTTP API](./HTTP.md) directly). 208 | 209 | ### Examples 210 | 211 | 221 | 222 | 223 | 224 | ```js 225 | // update item to expire in 300 seconds from now 226 | await db.update(null, "temp_key", {expireIn: 300}) 227 | 228 | // update item to expire at date 229 | await db.update(null, "temp_key", {expireAt: new Date('2023-01-01T00:00:00')}) 230 | ``` 231 | 232 | 233 | 234 | 235 | ```py 236 | # update item to expire in 300 seconds from now 237 | db.update(None, "temp_key", expire_in=300) 238 | 239 | # update item to expire at date 240 | expire_at = datetime.datetime.fromisoformat("2023-01-01T00:00:00") 241 | db.update(None, "temp_key", expire_at=expire_at) 242 | ``` 243 | 244 | 245 | 246 | 247 | 248 | ```go 249 | updates := base.Updates{ 250 | "__expires": 1672531200, 251 | } 252 | if err := db.Update("temp_key", updates); err != nil { 253 | log.Fatal("failed to update item:", err) 254 | } 255 | ``` 256 | 257 | 258 | 259 | 260 | 261 | ```shell 262 | curl -X PATCH "https://database.data.sh/v1/test_project_id/examples/items/temp_key" \ 263 | -H "Content-Type: application/json" \ 264 | -H "X-Api-Key: test_project_key" \ 265 | -d {"set": {"__expires": 1672531200}} 266 | ``` 267 | 268 | 269 | 270 | 271 | 272 | ## Issues 273 | 274 | If you run into any issues, consider reporting them in our [Github Discussions](https://github.com/orgs/deta/discussions). 275 | -------------------------------------------------------------------------------- /docs/base/node_tutorial.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: node_tutorial 3 | title: Node.js Tutorial 4 | --- 5 | import Tabs from '@theme/Tabs'; 6 | import TabItem from '@theme/TabItem'; 7 | 8 | 9 | ## Building a Simple CRUD with Deta Base 10 | 11 | 12 | ### Setup 13 | 14 | Two dependencies are needed for this project, `deta` and `express`: 15 | 16 | ```shell 17 | npm install deta express 18 | ``` 19 | 20 | 21 | To configure the app, import the dependencies and instantiate your database. 22 | 23 | ```js 24 | const express = require('express'); 25 | const { Deta } = require('deta'); 26 | 27 | const deta = Deta('myProjectKey'); // configure your Deta project 28 | const db = deta.Base('simpleDB'); // access your DB 29 | 30 | 31 | const app = express(); // instantiate express 32 | 33 | app.use(express.json()) // for parsing application/json bodies 34 | ``` 35 | 36 | 37 | ### Creating Records 38 | 39 | For our database we are going to store records of users under a unique `key`. Users can have three properties: 40 | 41 | ```js 42 | { 43 | "name": "string", 44 | "age": number, 45 | "hometown": "string" 46 | } 47 | 48 | ``` 49 | 50 | 51 | We'll expose a function that creates user records to HTTP `POST` requests on the route `/users`. 52 | 53 | ```js 54 | app.post('/users', async (req, res) => { 55 | const { name, age, hometown } = req.body; 56 | const toCreate = { name, age, hometown}; 57 | const insertedUser = await db.put(toCreate); // put() will autogenerate a key for us 58 | res.status(201).json(insertedUser); 59 | }); 60 | ``` 61 | 62 | #### Request 63 | 64 | `POST` a payload to the endpoint: 65 | 66 | ```json 67 | { 68 | "name": "Beverly", 69 | "age": 44, 70 | "hometown": "Copernicus City" 71 | } 72 | ``` 73 | 74 | #### Response 75 | 76 | Our server should respond with a status of `201` and a body of: 77 | 78 | ```json 79 | { 80 | "key": "dl9e6w6859a9", 81 | "name": "Beverly", 82 | "age": 44, 83 | "hometown": "Copernicus City" 84 | } 85 | ``` 86 | 87 | ### Reading Records 88 | 89 | To read records, we can simply use `Base.get(key)`. 90 | 91 | If we tie a `GET` request to the `/users` path with a path param giving a user id (i.e. `/users/dl9e6w6859a9`), we can return a record of the user over HTTP. 92 | 93 | ```js 94 | app.get('/users/:id', async (req, res) => { 95 | const { id } = req.params; 96 | const user = await db.get(id); 97 | if (user) { 98 | res.json(user); 99 | } else { 100 | res.status(404).json({"message": "user not found"}); 101 | } 102 | }); 103 | ``` 104 | 105 | Another option would to use `Base.fetch(query)` to search for records to return, like so: 106 | 107 | = 1.0.0', value: 'new', }, 113 | ] 114 | }> 115 | 116 | 117 | 118 | ```js 119 | app.get('/search-by-age/:age', async (req, res) => { 120 | const { age } = req.params; 121 | return (await db.fetch({'age': age}).next()).value; 122 | }); 123 | ``` 124 | 125 | 126 | 127 | 128 | 129 | ```js 130 | app.get('/search-by-age/:age', async (req, res) => { 131 | const { age } = req.params; 132 | const { items } = await db.fetch({'age': age}); 133 | return items; 134 | }); 135 | ``` 136 | 137 | 138 | 139 | 140 | #### Request 141 | 142 | Let's try reading the record we just created. 143 | 144 | Make a `GET` to the path `/users/dl9e6w6859a9`. 145 | 146 | #### Response 147 | 148 | The server should return the same record: 149 | 150 | ```json 151 | { 152 | "key": "dl9e6w6859a9", 153 | "name": "Beverly", 154 | "age": 44, 155 | "hometown": "Copernicus City" 156 | } 157 | ``` 158 | 159 | ### Updating Records 160 | 161 | To update records under a given `key`, we can use `Base.put()`, which will replace the record under a given key. 162 | 163 | We can tie a `PUT` request to the path `/users/{id}` to update a given user record over HTTP. 164 | 165 | ```js 166 | app.put('/users/:id', async (req, res) => { 167 | const { id } = req.params; 168 | const { name, age, hometown } = req.body; 169 | const toPut = { key: id, name, age, hometown }; 170 | const newItem = await db.put(toPut); 171 | return res.json(newItem) 172 | }); 173 | ``` 174 | 175 | #### Request 176 | 177 | We can update the record by passing a `PUT` to the path `/users/dl9e6w6859a9` with the following payload: 178 | 179 | ```json 180 | { 181 | "name": "Wesley", 182 | "age": 24, 183 | "hometown": "San Francisco" 184 | } 185 | ``` 186 | 187 | #### Response 188 | 189 | Our server should respond with the new body of: 190 | 191 | ```json 192 | { 193 | "key": "dl9e6w6859a9", 194 | "name": "Wesley", 195 | "age": 24, 196 | "hometown": "San Francisco" 197 | } 198 | ``` 199 | 200 | 201 | ### Deleting Records 202 | 203 | To delete records under a given `key`, we can use `Base.delete(key)`, which will remove the record under a given key. 204 | 205 | We can tie a `DELETE` request to the path `/users/{id}` to delete a given user record over HTTP. 206 | 207 | ```js 208 | app.delete('/users/:id', async (req, res) => { 209 | const { id } = req.params; 210 | await db.delete(id); 211 | res.json({"message": "deleted"}) 212 | }); 213 | ``` 214 | 215 | #### Request 216 | 217 | We can delete the record by passing a `DELETE` to the path `/users/dl9e6w6859a9`. 218 | 219 | ```json 220 | { 221 | "name": "Wesley", 222 | "age": 24, 223 | "hometown": "San Francisco" 224 | } 225 | ``` 226 | 227 | #### Response 228 | 229 | Our server should respond with: 230 | 231 | ```json 232 | { 233 | "message": "deleted" 234 | } 235 | ``` 236 | ## Issues 237 | 238 | If you run into any issues, consider reporting them in our [Github Discussions](https://github.com/orgs/deta/discussions). 239 | -------------------------------------------------------------------------------- /docs/base/py_tutorial.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: py_tutorial 3 | title: Python Tutorial 4 | --- 5 | import Tabs from '@theme/Tabs'; 6 | import TabItem from '@theme/TabItem'; 7 | 8 | 9 | ## Building a Simple CRUD with Deta Base 10 | 11 | 12 | ### Setup 13 | 14 | Two dependencies are needed for this project, `deta` and `flask`: 15 | 16 | ```shell 17 | pip install deta flask 18 | ``` 19 | 20 | 21 | To configure the app, import the dependencies and instantiate your database. 22 | 23 | ```py 24 | from flask import Flask, request, jsonify 25 | from deta import Deta 26 | 27 | 28 | deta = Deta('myProjectKey') # configure your Deta project 29 | db = deta.Base('simpleDB') # access your DB 30 | app = Flask(__name__) 31 | ``` 32 | 33 | 34 | ### Creating Records 35 | 36 | For our database we are going to store records of users under a unique `key`. Users can have three properties: 37 | 38 | ```py 39 | { 40 | "name": str, 41 | "age": int, 42 | "hometown": str 43 | } 44 | 45 | ``` 46 | 47 | 48 | We'll expose a function that creates user records to HTTP `POST` requests on the route `/users`. 49 | 50 | 51 | ```py 52 | @app.route('/users', methods=["POST"]) 53 | def create_user(): 54 | name = request.json.get("name") 55 | age = request.json.get("age") 56 | hometown = request.json.get("hometown") 57 | 58 | user = db.put({ 59 | "name": name, 60 | "age": age, 61 | "hometown": hometown 62 | }) 63 | 64 | return jsonify(user, 201) 65 | ``` 66 | 67 | #### Request 68 | 69 | `POST` a payload to the endpoint: 70 | 71 | ```json 72 | { 73 | "name": "Beverly", 74 | "age": 44, 75 | "hometown": "Copernicus City" 76 | } 77 | ``` 78 | 79 | #### Response 80 | 81 | Our server should respond with a status of `201` and a body of: 82 | 83 | ```json 84 | { 85 | "key": "dl9e6w6859a9", 86 | "name": "Beverly", 87 | "age": 44, 88 | "hometown": "Copernicus City" 89 | } 90 | ``` 91 | 92 | ### Reading Records 93 | 94 | To read records, we can simply use `db.get(key)`. 95 | 96 | If we tie a `GET` request to the `/users` path with a param giving a user id (i.e. `/users/dl9e6w6859a9`), we can return a record of the user over HTTP. 97 | 98 | 99 | ```py 100 | @app.route("/users/") 101 | def get_user(key): 102 | user = db.get(key) 103 | return user if user else jsonify({"error": "Not found"}, 404) 104 | ``` 105 | 106 | #### Request 107 | 108 | Let's try reading the record we just created. 109 | 110 | Make a `GET` to the path (for example) `/users/dl9e6w6859a9`. 111 | 112 | #### Response 113 | 114 | The server should return the same record: 115 | 116 | ```json 117 | { 118 | "key": "dl9e6w6859a9", 119 | "name": "Beverly", 120 | "age": 44, 121 | "hometown": "Copernicus City" 122 | } 123 | ``` 124 | 125 | ### Updating Records 126 | 127 | To update records under a given `key`, we can use `db.put()`, which will replace the record under a given key. 128 | 129 | We can tie a `PUT` request to the path `/users/{id}` to update a given user record over HTTP. 130 | 131 | 132 | ```py 133 | @app.route("/users/", methods=["PUT"]) 134 | def update_user(key): 135 | user = db.put(request.json, key) 136 | return user 137 | ``` 138 | 139 | #### Request 140 | 141 | We can update the record by passing a `PUT` to the path `/users/dl9e6w6859a9` with the following payload: 142 | 143 | ```json 144 | { 145 | "name": "Wesley", 146 | "age": 24, 147 | "hometown": "San Francisco" 148 | } 149 | ``` 150 | 151 | #### Response 152 | 153 | Our server should respond with the new body of: 154 | 155 | ```json 156 | { 157 | "key": "dl9e6w6859a9", 158 | "name": "Wesley", 159 | "age": 24, 160 | "hometown": "San Francisco" 161 | } 162 | ``` 163 | 164 | 165 | ### Deleting Records 166 | 167 | To delete records under a given `key`, we can use `Base.delete(key)`, which will remove the record under a given key. 168 | 169 | We can tie a `DELETE` request to the path `/users/{id}` to delete a given user record over HTTP. 170 | 171 | ```js 172 | @app.route("/users/", methods=["DELETE"]) 173 | def delete_user(key): 174 | db.delete(key) 175 | return jsonify({"status": "ok"}, 200) 176 | ``` 177 | 178 | #### Request 179 | 180 | We can delete the record by passing a `DELETE` to the path `/users/dl9e6w6859a9`. 181 | 182 | ```json 183 | { 184 | "name": "Wesley", 185 | "age": 24, 186 | "hometown": "San Francisco" 187 | } 188 | ``` 189 | 190 | #### Response 191 | 192 | Our server should respond with: 193 | 194 | ```json 195 | None 196 | ``` 197 | 198 | ## Issues 199 | 200 | If you run into any issues, consider reporting them in our [Github Discussions](https://github.com/orgs/deta/discussions). 201 | -------------------------------------------------------------------------------- /docs/base/queries.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: queries 3 | title: Queries 4 | --- 5 | 6 | Deta Base supports queries for fetching data that match certain conditions. Queries are regular objects/dicts/maps with conventions for different operators for specifying the conditions. 7 | 8 | ## Operators 9 | 10 | Queries support the following operators: 11 | 12 | ### Equal 13 | 14 | ```json 15 | {"age": 22, "name": "Beverly"} 16 | 17 | // hierarchical 18 | {"user.profile.age": 22, "user.profile.name": "Beverly"} 19 | ``` 20 | 21 | ```json 22 | {"fav_numbers": [2, 4, 8]} 23 | ``` 24 | 25 | ```json 26 | {"time": {"day": "Tuesday", "hour": "08:00"}} 27 | ``` 28 | 29 | ### Not Equal 30 | 31 | ```json 32 | {"user.profile.age?ne": 22} 33 | ``` 34 | 35 | ### Less Than 36 | 37 | ```json 38 | {"user.profile.age?lt": 22} 39 | ``` 40 | 41 | ### Greater Than 42 | 43 | ```json 44 | {"user.profile.age?gt": 22} 45 | ``` 46 | 47 | ### Less Than or Equal 48 | 49 | ```json 50 | {"user.profile.age?lte": 22} 51 | ``` 52 | 53 | ### Greater Than or Equal 54 | 55 | ```json 56 | {"user.profile.age?gte": 22} 57 | ``` 58 | 59 | ### Prefix 60 | 61 | ```json 62 | {"user.id?pfx": "afdk"} 63 | ``` 64 | 65 | ### Range 66 | 67 | ```json 68 | {"user.age?r": [22, 30]} 69 | ``` 70 | 71 | ### Contains 72 | 73 | ```json 74 | { 75 | // if user email contains the substring @deta.sh 76 | "user.email?contains": "@deta.sh" 77 | } 78 | ``` 79 | 80 | ```json 81 | { 82 | // if berlin is in a list of places lived 83 | "user.places_lived_list?contains": "berlin" 84 | } 85 | ``` 86 | 87 | ### Not Contains 88 | 89 | ```json 90 | { 91 | // if user email does not contain @deta.sh 92 | "user.email?not_contains": "@deta.sh" // 'user.email?!contains' also valid 93 | } 94 | ``` 95 | 96 | ```json 97 | { 98 | // if berlin is not in a list of places lived 99 | "user.places_lived_list?not_contains": "berlin" // 'user.places_lived_list?!contains' also valid 100 | } 101 | ``` 102 | 103 | :::note 104 | `?contains` and `?not_contains` only works for a list of strings if checking for membership in a list; it does not apply to list of other data types. You can store your lists always as a list of strings if you want to check for membership. 105 | ::: 106 | 107 | ## Logical Operators 108 | 109 | ### AND 110 | 111 | The entries in a single query object are `AND` ed together. For e.g. the query: 112 | 113 | ```json 114 | { 115 | "active": true, 116 | "age?gte": 22 117 | } 118 | ``` 119 | 120 | will retrieve items where `active` is `true` **and** `age` is greater than or equal to `22`. 121 | 122 | The query above would translate to `SQL` as: 123 | 124 | ```SQL 125 | SELECT * FROM base WHERE active=1 AND age>=22; 126 | ``` 127 | 128 | 129 | ### OR 130 | 131 | Multiple query objects in a list are `OR` ed together. For eg. the queries: 132 | 133 | ```json 134 | [{"age?lte": 30}, {"age?gte": 40}] 135 | ``` 136 | 137 | will retrieve items where `age` is less than equal to `30` **or** `age` is greater than equal to `40`. 138 | 139 | The query above would translate to `SQL` as: 140 | 141 | ```SQL 142 | SELECT * FROM base WHERE age<=30 OR age>=40; 143 | ``` 144 | 145 | 146 | ## Hierarchy 147 | 148 | You can use the period character `.` to query for hierarchical fields within the data. For instance if you have the following item in the base: 149 | 150 | ```json 151 | { 152 | "key": "user-key", 153 | "profile": { 154 | "age": 22, 155 | "active": true 156 | } 157 | } 158 | ``` 159 | 160 | Then you can query for the `active` and `age` within `profile` directly: 161 | 162 | ```json 163 | { 164 | "profile.age": 22, 165 | "profile.active": true 166 | } 167 | ``` 168 | 169 | ## Querying Keys 170 | 171 | You need to consider the following when querying on keys: 172 | 173 | - The keys must be strings hence the operation values **must** also be strings. 174 | - The [contains](#contains) and [not-contains](#not-contains) operators **are not supported**. 175 | - The [`AND`](#and) and [`OR`](#or) operations for different query values **are not supported**. 176 | For e.g. **the following queries are invalid**: 177 | ```json 178 | { 179 | // different AND key queries (invalid query) 180 | "key": "a", 181 | "key?pfx": "b" 182 | } 183 | ``` 184 | 185 | ```json 186 | { 187 | // different OR key queries (invalid query) 188 | [{"key?pfx":"a"}, {"key?pfx": "b"}] 189 | } 190 | ``` 191 | 192 | ## Issues 193 | 194 | If you run into any issues, consider reporting them in our [Github Discussions](https://github.com/orgs/deta/discussions). -------------------------------------------------------------------------------- /docs/cli/auth.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: auth 3 | title: Authentication 4 | sidebar_label: Authentication 5 | --- 6 | 7 | The deta cli authenticates in two ways: 8 | 9 | ### Login From The Browser 10 | 11 | Use deta command `deta login` to login from the web browser. It will open the login page in a web browser. 12 | 13 | :::note 14 | If the login page could not be opened automatically for some reason, the cli will display the login url. Open the link in a browser for the login to complete. 15 | ::: 16 | 17 | ### Deta Access Tokens 18 | 19 | The deta cli also authenticates with deta access tokens. You can create an access token under the `Settings` tab in your dashboard(https://web.deta.sh). The access tokens are **valid for a year**. 20 | 21 | :::note 22 | The access token can only be retreived once after creation. Please, store it in a safe place after the token has been created. 23 | ::: 24 | 25 | #### Token Provider Chain 26 | 27 | The access token (called *Access Token* when you create the token from the UI) can be set up to be used by the cli in the following ways in order of preference: 28 | - `DETA_ACCESS_TOKEN` environment variable: 29 | - provide the access token through the cli's environment under the environment variable `DETA_ACCESS_TOKEN` 30 | - `$HOME/.deta/tokens` file: 31 | - create a file called `tokens` in `$HOME/.deta/` 32 | - provide the token in the field `deta_access_token` in the file as *json* : 33 | 34 | ```json 35 | { 36 | "deta_access_token": "your_access_token" 37 | } 38 | ``` 39 | 40 | #### Using Deta in GitPod with Access Tokens 41 | 42 | To use the Deta CLI in GitPod, first install the Deta CLI to your GitPod terminal: 43 | 44 | ```shell 45 | curl -fsSL https://get.deta.dev/cli.sh | sh 46 | ``` 47 | 48 | Then add the `deta` command to the path of the Gitpod environment: 49 | 50 | ```shell 51 | source ~/.bashrc 52 | ``` 53 | 54 | Finally, add your authentication token to the GitPod environment, which will authenticate the Deta CLI commands against our backend: 55 | 56 | ```shell 57 | export DETA_ACCESS_TOKEN= 58 | ``` 59 | 60 | You are now free to use the `deta` command within GitPod! 61 | 62 | #### Using Deta in GitHub Actions with Access Tokens 63 | 64 | Use this ready-to-use [GitHub action](https://github.com/marketplace/actions/deploy-to-deta) to deploy your app to Deta. 65 | 66 | ## Issues 67 | 68 | If you run into any issues, consider reporting them in our [Github Discussions](https://github.com/orgs/deta/discussions). 69 | -------------------------------------------------------------------------------- /docs/cli/install.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: install 3 | title: Installing the Deta CLI 4 | sidebar_label: Install the Deta CLI 5 | --- 6 | 7 | import Tabs from '@theme/Tabs'; 8 | import TabItem from '@theme/TabItem'; 9 | 10 | ### Installing & Configuring the Deta CLI 11 | 12 | 13 | 21 | 22 | 23 | To install the Deta CLI, open a Terminal and enter: 24 | 25 | ```shell 26 | curl -fsSL https://get.deta.dev/cli.sh | sh 27 | ``` 28 | 29 | 30 | 31 | 32 | 33 | To install the Deta CLI, open a Terminal and enter: 34 | 35 | ```shell 36 | curl -fsSL https://get.deta.dev/cli.sh | sh 37 | ``` 38 | 39 | 40 | 41 | 42 | To install the Deta CLI, open PowerShell and enter: 43 | 44 | ```shell 45 | iwr https://get.deta.dev/cli.ps1 -useb | iex 46 | ``` 47 | 48 | 49 | 50 | 51 | 52 | This will download the binary which contains the CLI code. It will try to export the `deta` command to your path. If it does not succeed, follow the directions outputted by the install script to export `deta` to your path. 53 | 54 | ### Logging into Deta via the CLI 55 | 56 | Once you have successfully installed the Deta CLI, you'll need to log in to Deta. 57 | 58 | From a Terminal, type `deta login`. 59 | 60 | This command will open your browser and authenticate your CLI through Deta's web application. 61 | 62 | Upon a successful log-in, you are ready to start building [Micros](../micros/about.md). 63 | 64 | ## Issues 65 | 66 | If you run into any issues, consider reporting them in our [Github Discussions](https://github.com/orgs/deta/discussions). 67 | -------------------------------------------------------------------------------- /docs/cli/releases.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: releases 3 | title: CLI Releases 4 | sidebar_label: Releases 5 | --- 6 | 7 | ## v1.3.3-beta 8 | 9 | ### Updates 10 | - The CLI no longer checks the `Hidden File Attribute` in Windows systems 11 | 12 | ### Fixes 13 | - Fix overwriting files on `deta new` in Windows 14 | 15 | ## v1.3.2-beta 16 | 17 | ### Fixes 18 | - Fix bad file path bug for hidden file check in windows 19 | 20 | ## v1.3.1-beta 21 | 22 | ### Updates 23 | - `deta details`: show cron time in output if cron is set for Micro 24 | - `deta clone`: save `state` after cloning 25 | 26 | ## v1.3.0-beta 27 | 28 | ### New 29 | - `deta deploy purge-dependencies`: remove all installed dependencies from your micro 30 | 31 | ### Updates 32 | - `deta new`: support new runtime `python3.8` 33 | - `deta update`: support new runtime `python3.8` 34 | - `deta deploy`: purge all installed dependencies instead of uninstalling individual dependencies, if all of them are removed at the same time; use standard http lib to detect binary files and remove third party lib dependency 35 | - `deta new`, `deta pull`, `deta clone`: use new api to download micro code 36 | 37 | ### Fixes 38 | - Fix installation order bug when upgrading packages 39 | - Fix removal of `$HOME/.deta` folder bug on some cases in `deta new` 40 | 41 | ## v1.2.0-beta 42 | 43 | ### New 44 | - `deta new` : add `--runtime` flag, choose runtime when creating a new micro 45 | - `deta update`: add `--runtime` flag, update micro's runtime 46 | - `deta logs`: add `--follow` flag, follow logs 47 | 48 | ### Updates 49 | - `deta details`: add id, project and region to details output 50 | 51 | ### Fixes 52 | - Fix bad state file path in windows 53 | - Fix `deta version upgrade` in windows 54 | - Fix `.detaignore` issues in windows 55 | 56 | ## v1.1.4-beta 57 | 58 | ### Fixes 59 | - fix file parsing bug with end of line sequence on windows 60 | 61 | ## v1.1.3-beta 62 | 63 | ### Updates 64 | - add support for `.detaignore` file 65 | - always show login url when logging in with `deta login` 66 | - confirm a new version is not a pre-release version on new version check 67 | 68 | ### Fixes 69 | - fix parsing of environment variables with double quotes 70 | - fix issues with intermittent discrepancy of local and server state of a micros' details 71 | 72 | ## v1.1.2-beta 73 | 74 | ### Updates 75 | - add access token authentication 76 | - `deta watch` does an initial deployment 77 | - show login page url if failed to open login page in browser 78 | - suppress usage messages on errors 79 | 80 | ### Fixes 81 | - fix cases of corrupted deployments on `deta watch` 82 | - fix parsing environment key value pairs 83 | 84 | ## v1.1.1-beta 85 | 86 | ### Fixes 87 | - `deta new`: Fix issues with incomplete/failed deployment if application code already exists in the root directory 88 | - recognize `.mo` files as binary files 89 | 90 | ## v1.1.0-beta 91 | 92 | ### New Commands 93 | 94 | `deta clone`: Clone an existing micro 95 | 96 | `deta cron`: Set a micro to run on a schedule 97 | 98 | `deta run`: Run a micro from the CLI 99 | 100 | `deta version upgrade`: Upgrade Deta version 101 | 102 | `deta visor open`: Open the Visor page for a micro 103 | 104 | ### Updates 105 | 106 | `deta pull`: Pull only pulls latest code of an existing micro from the micro's root directory, add `--force` flag 107 | 108 | `deta deploy`: Checks for latest available version on successful deployments 109 | 110 | ### Fixes 111 | 112 | `deta pull`: Fix deta pull creating an empty directory even if pull fails 113 | 114 | `deta deploy`: Fix issues with deploying binary files (edited) 115 | 116 | `deta details`: Fix issue with displaying wrong values of visor and http_auth -------------------------------------------------------------------------------- /docs/common_issues.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: common_issues 3 | title: Common Issues 4 | --- 5 | 6 | ### Adding/Updating dependencies fails with no output 7 | 8 | On windows, if adding or updating dependencies fails with the following or similar error message but there is no further output: 9 | 10 | ``` 11 | Error: failed to update dependencies: error on one or more dependencies, 12 | no dependencies were added, see output for details. 13 | ``` 14 | 15 | Then, please make sure the requirements file encoding is `UTF-8`. 16 | 17 | :::note 18 | If you have used the command `pip freeze > requirements.txt` in `powershell` on Windows, 19 | the file created is not encoded in `UTF-8`. Please change the encoding or create a new file with the right encoding. 20 | ::: 21 | 22 | ### Nodejs Micros cannot serve binary files 23 | 24 | Serving some binary files (images, fonts etc) fails on nodejs micros currently because of a bug. We are sorry for this and will push a fix as soon as we can. 25 | 26 | As a workaround, please add the environment variable `BINARY_CONTENT_TYPES={file_mime_type}` in the micro's environment to serve the file. The `file_mime_type` can accept wildcards (`*`) 27 | and comma separated values. 28 | 29 | For instance, if you want to serve images and fonts from your nodejs micro, setting 30 | 31 | ``` 32 | BINARY_CONTENT_TYPES=image/*,font/* 33 | ``` 34 | 35 | will let the micro serve these files. 36 | 37 | Please, use the [`deta update -e [env_file_name]`](https://docs.deta.sh/docs/cli/commands#deta-update) command to update the environment variables of the Micro. 38 | 39 | ### Cannot login from the web browser after `deta login` 40 | 41 | If logging in with `deta login` from the [Brave Browser](https://brave.com/) fails, disable the shields for that page and try again. If it's not the [Brave Browser](https://brave.com/), please use a different browser to login (you can copy the link in a different browser after the login page opens up), or use [deta access tokens](https://docs.deta.sh/docs/cli/auth#deta-access-tokens) instead. 42 | 43 | ### Account is unconfirmed but I did not receive a confirmation email 44 | 45 | Please check your spam folder as well for the confirmation email. If you have not received one, please send us an email at team@deta.sh for activating your account with the email address you used at sign up. 46 | -------------------------------------------------------------------------------- /docs/drive/HTTP.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: http 3 | title: HTTP API 4 | sidebar_label: HTTP API 5 | --- 6 | 7 | import Tabs from '@theme/Tabs'; 8 | import TabItem from '@theme/TabItem'; 9 | 10 | ## General 11 | 12 | :::note 13 | You can get your **Project Key** and your **Project ID** from your [Deta dashboard](https://web.deta.sh). You need these to talk with the Deta Drive API. 14 | ::: 15 | 16 | ### Root URL 17 | This URL is the base for all your HTTP requests: 18 | 19 | **`https://drive.deta.sh/v1/{project_id}/{drive_name}`** 20 | 21 | > The `drive_name` is the name given to your drive. If you already have a **Drive**, then you can go ahead and provide it's name here. Additionally, you could provide any name here when doing any `PUT` or `POST` request and our backend will automatically create a new drive for you if it does not exist. There is no limit on how many "Drives" you can create. 22 | 23 | ### Auth 24 | A **Project Key** _must_ be provided in the request **headers** as a value for the `X-Api-Key` key for authentication and authorization. 25 | 26 | Example `X-Api-Key: a0kjsdfjda_thisIsYourSecretKey` 27 | 28 | ### File Names And Directories 29 | Each file needs a unique `name` which identifies the file. Directorial hierarchies are represented logically by the `name` of the file itself with the use of backslash `/`. 30 | 31 | For example, if you want to store a file `world.txt` under the directory `hello` , the `name` of the file should be `hello/world.txt`. 32 | 33 | The file name **must not** end with a `/`. This also means that you can not create an empty directory. 34 | 35 | A directory ceases to exist if there are no more files in it. 36 | ## Endpoints 37 | ### Put File 38 | `POST /files?name={name}` 39 | 40 | Stores a smaller file in a single request. Use this endpoint if the file size is small enough to be sent in a single request. The file is overwritten if the file with given `name` already exists. 41 | 42 | :::note 43 | We do not accept payloads larger than 10 MB on this endpoint. For larger uploads, use chunked uploads. 44 | ::: 45 | 46 | 53 | 54 | 55 | 56 | | Headers | Required | Description | 57 | | --------|----------|-------------| 58 | |`Content-Type` | No | The content type of the file. If the content type is not specified, the file `name` is used to figure out the content type. Defaults to `application/octet-stream` if the content type can not be figured out.| 59 | 60 | |Query Params | Required | Description | 61 | |-----|---|----| 62 | |`name`| Yes | The `name` of the file. More [here](#file-names-and-directories). 63 | 64 | 65 | 66 | 67 | #### `201 Created` 68 | 69 | ```js 70 | Content-Type: application/json 71 | 72 | { 73 | "name": "file name", 74 | "project_id": "deta project id", 75 | "drive_name": "deta drive_name" 76 | } 77 | ``` 78 | 79 | #### Client Errors 80 | 81 | `400 Bad Request` 82 | 83 | ```js 84 | Content-Type: "application/json" 85 | { 86 | "errors": [ 87 | // error messages 88 | ] 89 | } 90 | ``` 91 | 92 | `413 Payload Too Large` 93 | 94 | ```html 95 | Content-Type: text/html 96 |

413 - Request Entity Too Large

97 | ``` 98 | 99 |
100 |
101 | 102 | ### Initialize Chunked Upload 103 | 104 | Initializes a chunked file upload. If the file is larger than 10 MB, use this endpoint to initialize a chunked file upload. 105 | 106 | `POST /uploads?name={name}` 107 | 108 | 115 | 116 | 117 | 118 | |Params | Required | Description | 119 | |-----|---|----| 120 | |`name`| Yes | The `name` of the file. More [here](#file-names-and-directories). 121 | 122 | 123 | 124 | 125 | #### `202 Accepted` 126 | 127 | ```js 128 | Content-Type: application/json 129 | 130 | { 131 | "name": "file name", 132 | "upload_id": "a unique upload id" 133 | "project_id": "deta project id", 134 | "drive_name": "deta drive name" 135 | } 136 | ``` 137 | 138 | #### Client Errors 139 | 140 | `400 Bad Request` 141 | 142 | ```js 143 | Content-Type: application/json 144 | { 145 | "errors": [ 146 | // error messages 147 | ] 148 | } 149 | ``` 150 | 151 | 152 | 153 | ### Upload Chunked Part 154 | 155 | Uploads a chunked part. 156 | 157 | `POST /uploads/{upload_id}/parts?name={name}&part={part}` 158 | 159 | :::note 160 | Each chunk must be at least 5 MB and at most 10 MB. The final chunk can be less than 5 MB. 161 | ::: 162 | 163 | 170 | 171 | 172 | 173 | | Params | Required | Description | 174 | |----|---|---| 175 | |`upload_id`| Yes | The `upload_id` received after [initiating a chunked upload](#initialize-chunked-upload) | 176 | |`name`| Yes | The `name` of the file. More [here](#file-names-and-directories). | 177 | |`part`| Yes | The chunk part number, start with `1` | 178 | 179 | 180 | 181 | 182 | 183 | 184 | #### `200 Ok` 185 | 186 | ```js 187 | Content-Type: application/json 188 | 189 | { 190 | "name": "file name", 191 | "upload_id": "a unique upload id" 192 | "part": 1, // upload part number 193 | "project_id": "deta project id", 194 | "drive_name": "deta drive name" 195 | } 196 | ``` 197 | 198 | #### Client Errors 199 | 200 | `400 Bad Request` 201 | 202 | ```js 203 | Content-Type: application/json 204 | { 205 | "errors": [ 206 | // error messages 207 | ] 208 | } 209 | ``` 210 | 211 | `404 Not Found` 212 | ```js 213 | Content-Type: application/json 214 | { 215 | "errors": [ 216 | // error messages 217 | ] 218 | } 219 | ``` 220 | 221 | `413 Payload Too Large` 222 | 223 | ```html 224 | Content-Type: text/html 225 |

413 Request Entity Too Large

226 | ``` 227 |
228 |
229 | 230 | ### End Chunked Upload 231 | 232 | End a chunked upload. 233 | 234 | `PATCH /uploads/{upload_id}?name={name}` 235 | 236 | 243 | 244 | 245 | 246 | | Params | Required | Description | 247 | |----|---|---| 248 | |`upload_id`| Yes | The `upload_id` received after [initiating a chunked upload](#initialize-chunked-upload) | 249 | |`name`| Yes | The `name` of the file. More [here](#file-names-and-directories). | 250 | 251 | 252 | 253 | 254 | 255 | #### `200 Ok` 256 | 257 | ```js 258 | Content-Type: application/json 259 | 260 | { 261 | "name": "file name", 262 | "upload_id": "a unique upload id" 263 | "project_id": "deta project id", 264 | "drive_name": "deta drive name" 265 | } 266 | ``` 267 | 268 | #### Client Errors 269 | 270 | `400 Bad Request` 271 | 272 | ```js 273 | Content-Type: application/json 274 | { 275 | "errors": [ 276 | // error messages 277 | ] 278 | } 279 | ``` 280 | 281 | `404 Not Found` 282 | ```js 283 | Content-Type: application/json 284 | { 285 | "errors": [ 286 | // error messages 287 | ] 288 | } 289 | ``` 290 | 291 | 292 | 293 | ### Abort Chunked Upload 294 | 295 | Aboart a chunked upload. 296 | 297 | `DELETE /uploads/{upload_id}?name={name}` 298 | 299 | 306 | 307 | 308 | 309 | | Params | Required | Description | 310 | |----|---|---| 311 | |`upload_id`| Yes | The `upload_id` received after [initiating a chunked upload](#initialize-chunked-upload) | 312 | |`name`| Yes | The `name` of the file. More [here](#file-names-and-directories). | 313 | 314 | 315 | 316 | 317 | 318 | #### `200 Ok` 319 | 320 | ```js 321 | Content-Type: application/json 322 | 323 | { 324 | "name": "file name", 325 | "upload_id": "a unique upload id" 326 | "project_id": "deta project id", 327 | "drive_name": "deta drive name" 328 | } 329 | ``` 330 | 331 | #### Client Errors 332 | 333 | `400 Bad Request` 334 | 335 | ```js 336 | Content-Type: application/json 337 | { 338 | "errors": [ 339 | // error messages 340 | ] 341 | } 342 | ``` 343 | 344 | `404 Not Found` 345 | ```js 346 | Content-Type: application/json 347 | { 348 | "errors": [ 349 | // error messages 350 | ] 351 | } 352 | ``` 353 | 354 | 355 | 356 | ### Download File 357 | 358 | Download a file from drive. 359 | 360 | ` GET /files/download?name={name}` 361 | 362 | 369 | 370 | 371 | 372 | | Params | Required | Description | 373 | |----|---|---| 374 | |`name`| Yes | The `name` of the file. More [here](#file-names-and-directories). | 375 | 376 | 377 | 378 | 379 | 380 | #### `200 Ok` 381 | 382 | ``` 383 | Accept-Ranges: bytes 384 | Content-Type: {content_type} 385 | Content-Length: {content_length} 386 | {Body} 387 | ``` 388 | 389 | #### Client Errors 390 | 391 | `400 Bad Request` 392 | 393 | ```js 394 | Content-Type: application/json 395 | { 396 | "errors": [ 397 | // error messages 398 | ] 399 | } 400 | ``` 401 | 402 | `404 Not Found` 403 | ```js 404 | Content-Type: application/json 405 | { 406 | "errors": [ 407 | // error messages 408 | ] 409 | } 410 | ``` 411 | 412 | 413 | 414 | ### List Files 415 | 416 | List file names from drive. 417 | 418 | `GET /files?limit={limit}&prefix={prefix}&last={last}` 419 | 420 | 427 | 428 | 429 | 430 | | Params | Required | Description | 431 | |----|---|---| 432 | |`limit`| No | The `limit` of number of file names to get, defaults to `1000`| 433 | |`prefix`| No | The `prefix` that each file name must have. | 434 | |`last` | No | The `last` file name seen in a paginated response. | 435 | 436 | 437 | 438 | 439 | 440 | #### `200 Ok` 441 | 442 | The response is paginated based on the `limit` provided in the request. By default, maximum `1000` file names are sent. 443 | 444 | If the response is paginated, the response contains a `paging` object with `size` and `last` keys; `size` is the number of file 445 | names in the response, and `last` is the last file name seen in the response. The value of `last` should be used in subsequent 446 | requests to continue recieving further pages. 447 | 448 | ```js 449 | Content-Type: application/json 450 | 451 | { 452 | "paging": { 453 | "size": 1000, // the number of file names in the response 454 | "last": "last file name in response" 455 | }, 456 | "names": ["file1", "file2", ...] 457 | } 458 | ``` 459 | 460 | #### Client Errors 461 | 462 | `400 Bad Request` 463 | 464 | ```js 465 | Content-Type: application/json 466 | { 467 | "errors": [ 468 | // error messages 469 | ] 470 | } 471 | ``` 472 | 473 | `404 Not Found` 474 | ```js 475 | Content-Type: application/json 476 | { 477 | "errors": [ 478 | // error messages 479 | ] 480 | } 481 | ``` 482 | 483 | 484 | 485 | 486 | ### Delete Files 487 | 488 | Delete files from drive. 489 | 490 | `DELETE /files` 491 | 492 | 499 | 500 | 501 | 502 | ```js 503 | Content-Type: "application/json" 504 | { 505 | "names": ["file_1", "file_2"] 506 | } 507 | ``` 508 | 509 | | Params | Required | Description | 510 | |----|---|---| 511 | |`names`| Yes | The `names` of the files to delete, maximum `1000` file names| 512 | 513 | 514 | 515 | 516 | #### `200 Ok` 517 | 518 | 519 | ```js 520 | Content-Type: application/json 521 | 522 | { 523 | "deleted": ["file_1", "file_2", ...] // deleted file names 524 | "failed": { 525 | "file_3": "reason why file could not be deleted", 526 | "file_4": "reason why file could not be deleted", 527 | //... 528 | } 529 | } 530 | ``` 531 | 532 | :::note 533 | File names that did not exist will also be under `deleted`, `failed` will only contain names of files that existed but were not deleted for some reason 534 | ::: 535 | 536 | 537 | 538 | 539 | ## Issues 540 | 541 | If you run into any issues, consider reporting them in our [Github Discussions](https://github.com/orgs/deta/discussions). 542 | -------------------------------------------------------------------------------- /docs/drive/about.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: about 3 | title: About Deta Drive 4 | sidebar_label: About 5 | --- 6 | 7 | Deta Drive is a managed, secure and scalable file storage service with a focus on end-user simplicity. 8 | 9 | #### Is my data secure? 10 | 11 | Your data is encrypted and stored safely at rest. Encryption keys are managed by us. 12 | 13 | 14 | #### What's the storage limit? 15 | 16 | 10GB per Deta account. 17 | 18 | #### How do I start? 19 | 20 | 1. Log in to [Deta](https://web.deta.sh). 21 | 2. Grab your **Project Key** and start writing code in [Python](sdk.md), [Node.js](sdk.md), or use the [HTTP API](HTTP.md) where you need file storage. 22 | -------------------------------------------------------------------------------- /docs/drive/drive_ui.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: drive_ui 3 | title: Drive UI 4 | sidebar_label: Drive UI 5 | --- 6 | 7 | Drive UI lets you inspect, add, delete files from a Drive via a GUI. 8 | 9 | ### Opening Drive UI 10 | 11 | You can open an individual Drive's UI within any project by clicking on the Drive name in the project sidebar. 12 | 13 | drive_ui_1 14 | 15 | All the files and folders from within the path `/` should load into the table view when clicked. 16 | 17 | 18 | ### Preview and Navigation 19 | 20 | Files that are previewable (and folders) are marked in blue. 21 | 22 | drive_ui_2 23 | 24 | 25 | Clicking a folder will navigate to that folder, while clicking a file will open up a preview. 26 | 27 | drive_ui_3 28 | 29 |

30 | 31 | Your current location is highlighted in black in the navigation bar at the top of Drive UI. 32 | 33 | drive_ui_4 34 | 35 | You can click a parent folder, or the Drive name, to jump to that location. 36 | 37 | ### Uploading & Downloading Files 38 | 39 | You can upload a file by dragging it into the list of files & folders. This will upload the file in the current directory. 40 | 41 | drive_ui_5 42 | 43 | To download a file, click the download icon, which is on the right side of the the table. 44 | 45 | ### Deleting Files 46 | 47 | To delete files, click on the checkbox(es) for any files(s) and then click the trash icon in the top right corner of the Drive UI panel. 48 | 49 | drive_ui_6 50 | 51 | You will be asked to confirm you want to delete the file(s). 52 | 53 | 54 | ### Final Notes 55 | 56 | We hope you enjoy Drive UI! 57 | 58 | Drive UI is still in Beta; it has been internally tested but may have some uncaught bugs or issues. 59 | 60 | ## Issues 61 | 62 | If you run into any issues, consider reporting them in our [Github Discussions](https://github.com/orgs/deta/discussions). -------------------------------------------------------------------------------- /docs/drive/node_tutorial.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: node_tutorial 3 | title: Node Tutorial 4 | --- 5 | import Tabs from '@theme/Tabs'; 6 | import TabItem from '@theme/TabItem'; 7 | 8 | 9 | ## Building a Simple Image Server with Deta Drive 10 | 11 | 12 | ### Setup 13 | To get started, create a directory `image-server` and change the current directory into it. 14 | ```shell 15 | $ mkdir image-server && cd image-server 16 | ``` 17 | Before we begin, let's install all the necessary dependencies for this project. 18 | 19 | ```shell 20 | $ npm install deta express express-fileupload 21 | ``` 22 | In this tutorial, we are using `express` to build our server, and `express-fileupload` allows us to access the uploaded file data. 23 | 24 | To configure the app, import the dependencies and instantiate drive in `index.js` 25 | 26 | ```js 27 | const { Deta } = require("deta"); 28 | const express = require("express"); 29 | const upload = require("express-fileupload"); 30 | 31 | const app = express(); 32 | 33 | app.use(upload()); 34 | 35 | const deta = Deta("Project_Key"); 36 | const drive = deta.Drive("images"); 37 | ``` 38 | 39 | 40 | We have everything we need to 🚀 41 | 42 | ### Uploading Images 43 | First, we need to render a HTML snippet to display the file upload interface. 44 | 45 | We'll expose a function that renders the HTML snippet on the base route `/` 46 | ```javascript 47 | app.get('/', (req, res) => { 48 | res.send(` 49 |

50 | 51 | 52 |
`); 53 | }); 54 | ``` 55 | 56 | We are simply rendering a HTML form that sends a HTTP `POST` request to the route `/upload` with file data. 57 | 58 | Let's complete file upload by creating a function to handle `/upload` 59 | 60 | ```javascript 61 | app.post("/upload", async (req, res) => { 62 | const name = req.files.file.name; 63 | const contents = req.files.file.data; 64 | const img = await drive.put(name, {data: contents}); 65 | res.send(img); 66 | }); 67 | ``` 68 | We can access the image details from `req` and store it in Drive. 69 | 70 | ### Downloading Images 71 | To download images, we can simply use `drive.get(name)` 72 | 73 | If we tie a `GET` request to the `/download` path with a param giving a name (i.e `/download/space.png`), we can return the image over HTTP. 74 | 75 | ```javascript 76 | app.get("/download/:name", async (req, res) => { 77 | const name = req.params.name; 78 | const img = await drive.get(name); 79 | const buffer = await img.arrayBuffer(); 80 | res.send(Buffer.from(buffer)); 81 | }); 82 | 83 | app.listen(3000); 84 | ``` 85 | 86 | ### Running the server 87 | To run the server locally, navigate to the terminal in the project directory (`image-server`) and run the following command: 88 | ```shell 89 | $ node index.js 90 | ``` 91 | 92 | / 93 | /download/tut.jpg 94 | 95 | 96 | ```shell 97 | curl -X 'POST' \ 98 | 'http://127.0.0.1:3000/upload' \ 99 | -H 'accept: application/json' \ 100 | -H 'Content-Type: multipart/form-data' \ 101 | -F 'file=@space.png;type=image/png' 102 | 103 | Response 104 | "space.png" 105 | 106 | curl -X 'GET' \ 107 | 'http://127.0.0.1:3000/download/space.png' \ 108 | -H 'accept: application/json' 109 | 110 | Response 111 | The server should respond with the image. 112 | ``` 113 | 114 | ## Issues 115 | 116 | If you run into any issues, consider reporting them in our [Github Discussions](https://github.com/orgs/deta/discussions). -------------------------------------------------------------------------------- /docs/drive/py_tutorial.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: py_tutorial 3 | title: Python Tutorial 4 | --- 5 | import Tabs from '@theme/Tabs'; 6 | import TabItem from '@theme/TabItem'; 7 | 8 | 9 | ## Building a Simple Image Server with Deta Drive 10 | 11 | 12 | ### Setup 13 | To get started, create a directory `image-server` and change the current directory into it. 14 | ```shell 15 | $ mkdir image-server && cd image-server 16 | ``` 17 | Before we begin, let's install all the necessary dependencies for this project. Create a `requirements.txt` with the following lines: 18 | ```json 19 | fastapi 20 | uvicorn 21 | deta 22 | python-multipart 23 | ``` 24 | 25 | :::note If you are using Deta Drive within a Deta Micro, you should ignore `uvicorn`, but you must include `deta` in your `requirements.txt` file to install the lastest sdk version, other than that it won't work. 26 | 27 | ::: 28 | 29 | We are using `FastAPI` to build our simple image server, and `python-multipart` allows us access the uploaded files. 30 | 31 | Run the following command to install the dependencies. 32 | ```shell 33 | $ pip install -r requirements.txt 34 | ``` 35 | 36 | To configure the app, import the dependencies and instantiate drive in `main.py` 37 | 38 | ```python 39 | from fastapi import FastAPI, File, UploadFile 40 | from fastapi.responses import HTMLResponse, StreamingResponse 41 | from deta import Deta 42 | 43 | app = FastAPI() 44 | deta = Deta("Project_Key") # configure your Deta project 45 | drive = deta.Drive("images") # access to your drive 46 | ``` 47 | 48 | We have everything we need to 🚀 49 | 50 | ### Uploading Images 51 | First, we need to render a HTML snippet to display the file upload interface. 52 | 53 | We'll expose a function that renders the HTML snippet on the base route `/` 54 | ```python 55 | @app.get("/", response_class=HTMLResponse) 56 | def render(): 57 | return """ 58 |
59 | 60 | 61 |
62 | """ 63 | ``` 64 | 65 | We are simply rendering a form that sends a HTTP `POST` request to the route `/upload` with file data. 66 | 67 | Let's complete file upload by creating a function to handle `/upload` 68 | 69 | ```python 70 | @app.post("/upload") 71 | def upload_img(file: UploadFile = File(...)): 72 | name = file.filename 73 | f = file.file 74 | res = drive.put(name, f) 75 | return res 76 | ``` 77 | 78 | Thanks to the amazing tools from FastAPI, we can simply wrap the input around `UploadFile` and `File` to access the image data. We can retrieve the name as well as bytes from `file` and store it in Drive. 79 | 80 | ### Downloading images 81 | To download images, we can simply use `drive.get(name)` 82 | 83 | If we tie a `GET` request to the `/download` path with a param giving a name (i.e `/download/space.png`), we can return the image over HTTP. 84 | ```python 85 | @app.get("/download/{name}") 86 | def download_img(name: str): 87 | res = drive.get(name) 88 | return StreamingResponse(res.iter_chunks(1024), media_type="image/png") 89 | ``` 90 | 91 | You can learn more about `StreamingResponse` [here](https://fastapi.tiangolo.com/advanced/custom-response/#streamingresponse). 92 | 93 | ### Running the server 94 | To run the server locally, navigate to the terminal in the project directory (`image-server`) and run the following command: 95 | ```shell 96 | $ uvicorn main:app 97 | ``` 98 | 99 | Your image server is now ready! You can interact with it at `/` and check it out! 100 | 101 | / 102 | /download/tut.jpg 103 | 104 | 105 | ```shell 106 | 107 | curl -X 'POST' \ 108 | 'http://127.0.0.1:8000/upload' \ 109 | -H 'accept: application/json' \ 110 | -H 'Content-Type: multipart/form-data' \ 111 | -F 'file=@space.png;type=image/png' 112 | 113 | Response 114 | "space.png" 115 | 116 | 117 | curl -X 'GET' \ 118 | 'http://127.0.0.1:8000/download/space.png' \ 119 | -H 'accept: application/json' 120 | 121 | Response 122 | The server should respond with the image. 123 | ``` 124 | 125 | ## Issues 126 | 127 | If you run into any issues, consider reporting them in our [Github Discussions](https://github.com/orgs/deta/discussions). -------------------------------------------------------------------------------- /docs/faqs.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: faqs 3 | title: Frequently Asked Questions 4 | sidebar_label: FAQs 5 | --- 6 | 7 | ### What are all the different 'keys' for? 8 | 9 | Deta offers 3 types of secrets / keys / tokens: 10 | 11 | 1. **Project Keys**: Project keys interact with both your data and your resources inside a project (currently allowing reads and writes for the project's Bases and Drives). A project key will be created for you when you create a project, and you can manage all of a project's keys from the *'Project Keys'* option in any project's sidebar. If this key is leaked, the data stored in any of the connected project's Bases and Drives can be compromised. 12 | 13 | 2. **API Keys**: API Keys are optional keys to protect your Micro HTTP endpoint or to implement client-based rules. Creating API Keys from the Deta CLI is described [here](/docs/cli/commands#deta-auth-create-api-key). Read more about API Keys [here](https://en.wikipedia.org/wiki/Application_programming_interface_key). If this key is leaked, your Micro's http endpoint can be used by unwanted clients. 14 | 15 | 3. **Access Tokens**: Access tokens are used for authenticating the Deta CLI. Use cases: CI/CD, Gitpod, GitHub Actions. Information on Deta Access Tokens can be found [here](/docs/cli/auth#deta-access-tokens). If this key is leaked, your whole Deta account is compromised. 16 | 17 | These types of keys are not unique to Deta; all other cloud providers use some variant of them. 18 | 19 | ### Can I delete a project? 20 | 21 | No, sorry but deleting projects is not available yet. -------------------------------------------------------------------------------- /docs/home.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: home 3 | title: Home 4 | --- 5 | 6 | #### Intro 7 | 8 | Deta is a free cloud crafted with the developer and user experience at heart. 9 | 10 | It is our mission to dramatically reduce the gap between ideas and working cloud applications. 11 | 12 | 13 | #### Why is Deta Cloud free for ever? 14 | 15 | We want anyone, at any age from anywhere in the world to experiment and build their ideas without worrying about limits of credit cards. 16 | 17 | #### How are you going to make money? 18 | 19 | We're working on a big, parallel product that we will be announcing soon. This product will be responsible for generating revenue. 20 | Stay tuned! 21 | 22 | 23 | #### Resources 24 | 25 | To accomplish our mission, we offer a set of minimal-config cloud primitives: 26 | 27 | 1. **[Deta Base](#deta-base)** (beta): Instantly usable database with a feature-rich API. 28 | 2. **[Deta Micros](#deta-micros)** (beta): Deploy scalable Node & Python apps in seconds. 29 | 3. **[Deta Drive](#deta-drive)** (beta): Upload, host and serve images and files. 30 | 31 | 32 | #### Local Development and the Deta CLI 33 | 34 | Most developers like their local development flow. We provide a CLI that ties your local development workflow to your micro cloud, see: 35 | 36 | - [Deta CLI](#deta-cli) 37 | 38 | 39 | #### Support 40 | 41 | If you have any questions, we provide a few ways to get help ASAP: 42 | 43 | - [Getting Help](#getting-help) 44 | 45 | 46 | ### Deta Base 47 | 48 | Deta Base is our instantly usable NoSQL database. 49 | 50 | - [About Deta Base](base/about.md): General Information about Bases. 51 | - [Base SDK](base/sdk.md): SDK for using a Base in Node.js and Python. 52 | - [HTTP API](base/HTTP.md): API for interacting with a Base over HTTP. 53 | - [Node.js Tutorial](base/node_tutorial.md): Build a micro-crud in Node.js using Base and Express.js. 54 | - [Python Tutorial](base/py_tutorial.md): Build a micro-crud in Python using Base and Flask. 55 | 56 | 57 | ### Deta Micros 58 | 59 | Deta Micros(servers) are a lightweight but scalable cloud runtime tied to an HTTP endpoint. Currently Node.js and Python Micros are supported. 60 | 61 | - [About Deta Micros](micros/about.md): General Information about Micros. 62 | - [Getting Started with Micros](micros/getting_started.md): Get your first Micro live. 63 | 64 | ### Deta Drive 65 | 66 | Deta Drive is our easy-to-use file storage service. 67 | 68 | - [About Deta Drive](drive/about.md): General Information about Drive. 69 | - [Drive SDK](drive/sdk.md): SDK for using Drive in Node.js and Python. 70 | - [HTTP API](drive/HTTP.md): API for interacting with Drive over HTTP. 71 | - [Node.js Tutorial](drive/node_tutorial.md): Build a simple image server in Node.js using Drive. 72 | - [Python Tutorial](drive/py_tutorial.md): Build a simple image server in Python using Drive. 73 | 74 | 75 | ### Deta CLI 76 | 77 | The Deta CLI allows you to tie your local machine and dev setup to your own personal micro cloud. 78 | 79 | You create and update micros using the CLI. 80 | 81 | - [Install the Deta CLI](cli/install.md) 82 | - [Complete CLI Reference](cli/commands.md) 83 | 84 | 85 | ### Getting Help 86 | 87 | We have answered some [General FAQs](faqs.md) and [FAQs on Micros](micros/faqs.md) in these docs, but we are here to help and would love to hear what you think! 88 | 89 | If you have any questions or feedback, you can reach us: 90 | 91 | - [Github Discussions](https://github.com/orgs/deta/discussions) 92 | - [Discord](https://go.deta.dev/discord) 93 | 94 | ### Reporting Abuse 95 | 96 | If you detect any kind of fraudulent, abusive and/or malicious content hosted on Deta, please report the site(s) by sending an email to us at [abuse@deta.sh](mailto:abuse@deta.sh). 97 | 98 | We review each report manually. 99 | -------------------------------------------------------------------------------- /docs/micros/about.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: about 3 | title: Introduction to Deta Micros 4 | sidebar_label: Introduction 5 | --- 6 | 7 | ### Summary 8 | 9 | Deta Micros (micro servers) are a lightweight but scalable cloud runtime tied to an HTTP endpoint. They are meant to get your apps up and running *blazingly fast*. Focus on writing your code and Deta will take care of everything else. 10 | 11 | ### Technical Specifications 12 | 13 | 1. Micros support the following runtimes: 14 | a. Python: **3.7**, **3.8**, **3.9** 15 | b. Nodejs: **12.x**, **14.x** 16 | 17 | New micros will use `Python 3.9` or `Nodejs 14.x` by default. If you want to select a different runtime or update the runtime of your micro, please refer to [deta new](https://docs.deta.sh/docs/cli/commands#deta-new) and [deta update](https://docs.deta.sh/docs/cli/commands#deta-update). 18 | 2. Every Micro you use gets its own sandboxed Linux VM. 19 | 3. Each Micro has a key and secret keys set in the environment, these are specific to your Micro and not the Deta system. Make sure to not share them to keep your own data safe. 20 | 4. An execution times out after 10s. Request an increase. 21 | 5. 512 MB of RAM for *each* execution. Request an increase. 22 | 6. Read-only file system. **Only `/tmp` can be written to**. It has a 512 MB storage limit. 23 | 7. Invocations have an execution processes/threads limit of 1024. 24 | 8. HTTP Payload size limit is 5.5 MB. 25 | 26 | ### Important Notes 27 | 28 | 1. Micros automatically respond to your incoming requests and go to sleep when there's nothing to do. You do not have to manage their lifecycle manually. 29 | 2. You (and only you) have access to the VM, which means there's no SSH access. 30 | 3. You are supposed to see the VM filesystem, it's not a security vulnerability. 31 | 4. Deta Micros do not support connecting to MongoDB at the moment. We recommend using Deta Base instead. 32 | 5. We don't believe that Micros will work well with RDMBS like PostgreSQL and MySQL unless you use a pool manager. 33 | 6. Micros only support read-only SQLite, which you could deploy with your code. 34 | 7. The total upload size of your source code and assets is limited to 250 MB. 35 | 8. Dependencies (pip, npm, etc) also can't exceed a combined size of 250mb. 36 | 9. For unknown reasons, Google and Firebase packages for Python do not install successfully on Micros. 37 | 10. Currently, all requests received by Micros do not contain the client IP addresses. This makes most rate-limiting logic and other IP-dependant logic not work on Micros. 38 | 11. Micros support most micro web frameworks (Node.js: express, fastify, koa, etc && Python: FastAPI, Flask, etc.). Other frameworks are not likely to work. 39 | 12. Websockets and long-running processes do not work on Micros. (examples: socket.io or Discord bots won't work). 40 | 13. Features like [Background Tasks](https://www.starlette.io/background/) and [Startup/Shutdown Events](https://www.starlette.io/events/) will currently not work as expected on Micros. 41 | -------------------------------------------------------------------------------- /docs/micros/api_keys.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: api_keys 3 | title: API Keys 4 | sidebar_label: API Keys 5 | --- 6 | 7 | API keys are a great way to protect your APIs, which is why Deta has them built into Micros. API keys will work with any framework that runs on the Micros – no coding required from your end! 8 | 9 | 10 | ### 1. Enable Deta Access 11 | To use API keys with your Micro, first you need to enable __Deta Access__ by running the following command from the root directory of your Micro's source code. 12 | 13 | ``` 14 | deta auth enable 15 | ``` 16 | 17 | Now your API is protected by __Deta Access__ and only _accessible_ by you. Next, you need to create an API key to authenticate your requests. 18 | 19 | 20 | ### 2. Create an API key 21 | 22 | To create a new API key, run the following command, make sure to provide at least the `name` argument. 23 | 24 | > For more info, refer to the [`deta auth create-key`](../cli/commands.md/#deta-auth-create-api-key) docs. 25 | 26 | 27 | ``` 28 | deta auth create-api-key --name first_key --desc "api key for agent 1" 29 | ``` 30 | This will send a response similar to this: 31 | 32 | ```json 33 | { 34 | "name": "first_key", 35 | "description": "api key for agent 1", 36 | "prefix": "randomprefix", 37 | "api_key": "randomprefix.supersecretrandomstring", 38 | "created": "2021-04-22T11:50:08Z" 39 | } 40 | ``` 41 | 42 | In this example, the API key would be `randomprefix.supersecretrandomstring`. 43 | 44 | The key will only be shown to you once, make sure to save it in a secure place. 45 | 46 | :::note API keys are passwords 47 | Anyone with this API key can access your Micro, make sure to treat it as a password and save it in a secure place like a password manager. 48 | ::: 49 | 50 | 51 | ### 3. Using API keys 52 | 53 | Simply add this key to the header of every request you make to your Micro. 54 | 55 | For example, suppose your Micro has an endpoint `/tut` that responds with a simple string `Hello`. You can set the value of `X-API-Key` header along with your request like the following: 56 | ```json 57 | curl --request GET \ 58 | --url https://2kzkof.deta.dev/tut \ 59 | --header 'Content-Type: application/json' \ 60 | --header 'X-API-Key: awEGbjqg.D1sETRFJKHWtcxSRSmofY2-akZjqFPh7j' 61 | ``` 62 | 63 | That is all you need to protect your APIs! 64 | 65 | ## Issues 66 | 67 | If you run into any issues, consider reporting them in our [Github Discussions](https://github.com/orgs/deta/discussions). -------------------------------------------------------------------------------- /docs/micros/cron.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: cron 3 | title: Cron 4 | sidebar_lable: Run 5 | --- 6 | import Tabs from '@theme/Tabs'; 7 | import TabItem from '@theme/TabItem'; 8 | 9 | ### Deta Cron 10 | 11 | :::note 12 | Cron is a feature of Deta Micros. For the cron to trigger, your code must be deployed on a Micro. 13 | ::: 14 | 15 | A Deta Micro can be set to run on a schedule from the `deta cli` using the [deta cron set](../cli/commands#deta-cron-set) command. 16 | 17 | In order to set a micro to run on a schedule, the micro's code needs to define a function that will be run on the schedule with the help of our library `deta`. 18 | 19 | The `deta` library is pre-installed on a micro and can just be imported directly. 20 | 21 | ### Set Cron 22 | 23 | Use `deta cron set` to schedule the micro. 24 | 25 | You can set the cron in two ways: 26 | 27 | #### Rate 28 | You can define the `rate` at which a micro should run. It is comprised of a `value` and `unit`. 29 | 30 | - `value`: is a non-zero positive integer 31 | - `unit`: unit of time, can be `minute, minutes, hour, hours, day, days`. If the `value` is `1` the unit must be `minute`, `hour` or `day`. 32 | 33 | **Examples** 34 | 35 | - `deta cron set "1 minute"` : Run every minute 36 | - `deta cron set "2 hours"` : Run every two hours 37 | - `deta cron set "5 days"` : Run every five days 38 | 39 | #### Cron expressions 40 | 41 | Cron expressions allow you more flexibility and precision when setting a cron job. Cron expressions have six required fields, which are separated by white space. 42 | 43 | | Field | Values | Wildcards | 44 | |--------------|-------------------|-----------| 45 | | Minutes | 0-59 | ,-*/ | 46 | | Hours | 0-23 | ,-*/ | 47 | | Day-of-month | 1-31 | ,-*?/LW | 48 | | Month | 1-12 or JAN-DEC | ,-*/ | 49 | | Day-of-week | 1-7 or SUN-SAT | ,-*?L# | 50 | | Year | 1970-2199 | ,-*/ | 51 | 52 | **Wildcards** 53 | 54 | - The , (comma) wildcard includes additional values. In the Month field, JAN,FEB,MAR would include January, February, and March. 55 | 56 | - The - (dash) wildcard specifies ranges. In the Day field, 1-15 would include days 1 through 15 of the specified month. 57 | 58 | - The * (asterisk) wildcard includes all values in the field. In the Hours field, * would include every hour. You cannot use * in both the Day-of-month and Day-of-week fields. If you use it in one, you must use ? in the other. 59 | 60 | - The / (forward slash) wildcard specifies increments. In the Minutes field, you could enter 1/10 to specify every tenth minute, starting from the first minute of the hour (for example, the 11th, 21st, and 31st minute, and so on). 61 | 62 | - The ? (question mark) wildcard specifies one or another. In the Day-of-month field you could enter 7 and if you didn't care what day of the week the 7th was, you could enter ? in the Day-of-week field. 63 | 64 | - The L wildcard in the Day-of-month or Day-of-week fields specifies the last day of the month or week. 65 | 66 | - The W wildcard in the Day-of-month field specifies a weekday. In the Day-of-month field, 3W specifies the weekday closest to the third day of the month. 67 | 68 | - The # wildcard in the Day-of-week field specifies a certain instance of the specified day of the week within a month. For example, 3#2 would be the second Tuesday of the month: the 3 refers to Tuesday because it is the third day of each week, and the 2 refers to the second day of that type within the month. 69 | 70 | **Limits** 71 | 72 | - You can't specify the Day-of-month and Day-of-week fields in the same cron expression. If you specify a value (or a *) in one of the fields, you must use a ? (question mark) in the other. 73 | 74 | - Cron expressions that lead to rates faster than 1 minute are not supported. 75 | 76 | **Examples** 77 | 78 | - `deta cron set "0 10 * * ? *"` : Run at 10:00 am(UTC) every day 79 | - `deta cron set "15 12 * * ? *"` : Run at 12:15 pm(UTC) every day 80 | - `deta cron set "0 18 ? * MON-FRI *"` : Run at 6:00 pm(UTC) every Monday through Friday 81 | - `deta cron set "0 8 1 * ? *"` : Run at 8:00 am(UTC) every 1st day of the month 82 | - `deta cron set "0/15 * * * ? *"` : Run every 15 minutes 83 | - `deta cron set "0/5 8-17 ? * MON-FRI *"` : Run every 5 minutes Monday through Friday between 8:00 am and 5:55 pm(UTC) 84 | 85 | ### Code 86 | 87 | 95 | 96 | 97 | ```js 98 | const { app } = require('deta'); 99 | 100 | // define a function to run on a schedule 101 | // the function must take an event as an argument 102 | app.lib.cron(event => "running on a schedule"); 103 | 104 | module.exports = app; 105 | ``` 106 | 107 | 108 | 109 | 110 | ```python 111 | from deta import app 112 | 113 | # define a function to run on a schedule 114 | # the function must take an event as an argument 115 | @app.lib.cron() 116 | def cron_job(event): 117 | return "running on a schedule" 118 | ``` 119 | 120 | 121 | 122 | With this code deployed on a deta micro, the `deta cron set` commands will execute the function based on the cron rate or expression. For example 123 | 124 | ```shell 125 | $ deta cron set "10 minutes" 126 | ``` 127 | 128 | will set the function to run every 10 minutes. In order to see the execution logs, you can use the [visor](https://docs.deta.sh/docs/micros/visor) 129 | 130 | ### Events 131 | 132 | A function that is triggered from the cron must take an `event` as the only argument. The `event` will have the following attribute. 133 | 134 | - `event.type`: `string` type of an event, will be `cron` when triggered by a cron event 135 | 136 | ### Remove Cron 137 | 138 | Use `deta cron remove` to remove a schedule from the micro. 139 | 140 | ### Cron and HTTP 141 | 142 | You can combine both cron and HTTP triggers in the same deta micro. For this you need to instantiate your app using the `deta` library that is pre-installed on a micro. 143 | 144 | 152 | 153 | 154 | ```js 155 | const { App } = require('deta'); 156 | const express = require('express'); 157 | 158 | const app = App(express()); 159 | 160 | app.get('/', async(req, res) => { 161 | res.send('Hello Deta, I am running with HTTP'); 162 | }); 163 | 164 | app.lib.cron(event => { 165 | return 'Hello Deta, I am a cron job'; 166 | }); 167 | 168 | module.exports = app; 169 | ``` 170 | 171 | 172 | 173 | 174 | ```python 175 | from deta import App 176 | from fastapi import FastAPI 177 | 178 | app = App(FastAPI()) 179 | 180 | @app.get("/") 181 | def http(): 182 | return "Hello Deta, I am running with HTTP" 183 | 184 | @app.lib.cron() 185 | def cron_job(event): 186 | return "Hello Deta, I am a cron job" 187 | ``` 188 | 189 | 190 | 191 | ## Issues 192 | 193 | If you run into any issues, consider reporting them in our [Github Discussions](https://github.com/orgs/deta/discussions). 194 | 195 | 247 | -------------------------------------------------------------------------------- /docs/micros/custom_domains.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: custom_domains 3 | title: Custom Domains 4 | sidebar_label: Custom Domains 5 | --- 6 | 7 | 8 | You can set custom sub-domains and point your own domains to a Deta Micro. Navigate to the `domains` tab in your Micro's dashboard to set domains. 9 | 10 |
11 | custom_domain 12 |
13 | 14 | ## Sub-domains 15 | 16 | Deta provides your Micro a random sub-domain by default under `deta.dev`. You can assign a different sub-domain of your choice to your Micro. 17 | The Micro can be accessed from both the default sub-domain and the sub-domain you assign. 18 | 19 | 20 | You need to consider the following when assigning a sub-domain: 21 | 22 | - You can only assign a single sub-domain for each Micro. 23 | - The sub-domain must be at least `4` characters in length. 24 | - Only alphanumeric characters, dashes and underscores are allowed. The sub-domain must begin and end with an alphanumeric character. 25 | 26 | 27 | ## Custom Domains 28 | 29 | You can assign custom domains to a Micro. 30 | 31 | ### Assignment 32 | 33 | You need to consider the following when assigning a custom domain: 34 | - You can assign up to `5` custom domains for a single Micro. 35 | - After you have added a custom domain, we provide you with an IP Address. You need to add an `A record` in your DNS settings and point your domain to this IP Address. 36 | - We continously check if your domain is pointing to this IP Address. If it is, we will create an SSL certificate for your domain and serve your Micro from the domain. 37 | - The time taken for the DNS record changes to take effect depends on your DNS settings and provider. It may take up to 24 hours for your domain to go live. 38 | - If you get an SSL error after the DNS record changes have propagated, please wait until the system has created an SSL certificate for your domain. This is usually fast but sometimes it may take a few hours. 39 | - If you have a [CAA record](#caa-records) set up for you domain, make sure you have set `sectigo.com` as an allowed CA for your domain. 40 | 41 | :::note 42 | If you are using [Cloudflare](https://www.cloudflare.com) as your DNS provider, please make sure to turn the proxy off in your DNS settings when adding the Deta provided IP address. 43 | ::: 44 | 45 | ### Completion 46 | 47 | Your domain will be marked as `active` in your dashboard after the process is complete. 48 | 49 | 50 | ### CAA Records 51 | 52 | [CAA records](https://en.wikipedia.org/wiki/DNS_Certification_Authority_Authorization) specify which Certificate Authorities are allowed to issue certificates on your behalf. 53 | 54 | If you have a CAA record set up for your domain (check your DNS settings or use a tool to check your CAA records), add the following record so that we can issue certificates for your domain. 55 | 56 | ``` 57 | example.com. 3600 IN CAA 0 issue "sectigo.com" 58 | ``` 59 | 60 | This record allows us to issue certificates for `example.com` and all subdomains of `example.com`. For your domain, replace `example.com` with your domain. 61 | 62 | ### Troubleshoot 63 | 64 | Check the following if you are experiencing issues in setting up a custom domain: 65 | 66 | 1. [Check if your top level domain is supported](#unsupported-top-level-domains). 67 | 2. Make sure you have added an A record in your DNS settings with our IP address. You can use tools like [nslookup](https://linux.die.net/man/1/nslookup) or other online tools to check what IP address your domain is currently being resolved to. 68 | 3. If you are using `Cloudflare`, make sure to turn the proxy off in your DNS settings when adding the Deta provided IP address. 69 | 4. Check if there is a CAA record set up for your domain. If yes, make sure you have [set up the necessary CAA record](#caa-records). 70 | 71 | :::warning 72 | If you had to change something from the steps mentioned above, [email us]() or [let us know in discord](https://go.deta.dev/discord). This is important as our systems eventually stop trying to assign the custom domain on errors. Manual re-enabling of the domain might be required. 73 | ::: 74 | 75 | ### Unsupported Top Level Domains 76 | 77 | Our SSL provider does not support some country code top level domains. [Please check them out here](https://help.zerossl.com/hc/en-us/articles/360060119833-Restricted-Countries). 78 | 79 | ## Issues 80 | 81 | If you run into any issues, consider reporting them in our [Github Discussions](https://github.com/orgs/deta/discussions). -------------------------------------------------------------------------------- /docs/micros/deploy.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: deploy 3 | title: Deploy your app or API on Deta Micros 4 | sidebar_lable: Deploy your app or API on Deta Micros 5 | --- 6 | 7 | A Deta Micro is a micro server where you can deploy your Python or Node web app without worrying about ops. 8 | 9 | ## Python 10 | 11 | Most Python micro frameworks are supported, like FastAPI and Flask. Deta should run both pure WSGI & ASGI apps without any issue. 12 | Full frameworks like Django are not fully supported yet, as they require various other commands. 13 | 14 | For Deta to be able to run your code, you need to call your app instance `app` and it has to be in a file called `main.py`, which is the only required file for a Python Micro. Of course you could add more files and folders. 15 | 16 | No need to use a server like `uvicorn`, Deta has its own global server. 17 | Make sure you have the framework in your `requirements.txt`. 18 | 19 | ### Example code 20 | 21 | #### FastAPI 22 | 23 | ```py 24 | from fastapi import FastAPI 25 | 26 | app = FastAPI() # notice that the app instance is called `app`, this is very important. 27 | 28 | @app.get("/") 29 | async def read_root(): 30 | return {"Hello": "World"} 31 | 32 | ``` 33 | 34 | #### Bottlepy 35 | ```py 36 | from bottle import Bottle 37 | 38 | app = Bottle() # notice that the app instance is called `app`, this is very important. 39 | 40 | @app.route('/') 41 | def home(): 42 | return 'Hello, World!' 43 | ``` 44 | 45 | #### Flask 46 | 47 | ```py 48 | from flask import Flask 49 | 50 | app = Flask(__name__) # notice that the app instance is called `app`, this is very important. 51 | 52 | @app.route("/") 53 | def hello_world(): 54 | return "

Hello, World!

" 55 | ``` 56 | 57 | #### Starlette 58 | 59 | ```python 60 | from starlette.applications import Starlette 61 | from starlette.responses import JSONResponse 62 | from starlette.routing import Route 63 | 64 | 65 | async def homepage(request): 66 | return JSONResponse({'hello': 'world'}) 67 | 68 | 69 | # notice that the app instance is called `app`, this is very important. 70 | app = Starlette(debug=True, routes=[ 71 | Route('/', homepage), 72 | ]) 73 | ``` 74 | 75 | ## Node.js 76 | 77 | Most Node.js micro frameworks are supported, like Express, Koa, etc. 78 | 79 | For Deta to be able to run your code, you need to call your app instance `app` and it has to be in a file called `index.js`, which is the only required file for a Node Micro. You also need to export `app`. Of course you could add more files and folders. 80 | 81 | Make sure you have the framework in your `package.json`. 82 | 83 | ### Example code 84 | 85 | #### Express.js 86 | 87 | ```js 88 | const express = require('express'); 89 | const app = express(); // notice that the app instance is called `app`, this is very important. 90 | 91 | app.get('/', (req, res) => { 92 | res.send('Hello World!'); 93 | }); 94 | 95 | // no need for `app.listen()` on Deta, we run the app automatically. 96 | module.exports = app; // make sure to export your `app` instance. 97 | ``` 98 | 99 | #### Koa.js 100 | 101 | ```js 102 | const Koa = require('koa'); 103 | const app = new Koa(); 104 | 105 | app.use(async ctx => { 106 | ctx.body = 'Hello World'; 107 | }); 108 | 109 | // no need for `app.listen()` on Deta, we run the app automatically. 110 | module.exports = app; // make sure to export your `app` instance. 111 | ``` 112 | 113 | #### Fastify.js 114 | 115 | ```js 116 | const app = require('fastify')(); 117 | 118 | // Declare a route 119 | app.get('/', async (request, reply) => { 120 | return { hello: 'world' }; 121 | }); 122 | 123 | // no need for `app.listen()` on Deta, we run the app automatically. 124 | module.exports = app; // make sure to export your `app` instance. 125 | ``` 126 | 127 | ## Issues 128 | 129 | If you run into any issues, consider reporting them in our [Github Discussions](https://github.com/orgs/deta/discussions). 130 | -------------------------------------------------------------------------------- /docs/micros/deploy_on_deta_button.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: deploy_to_deta_button 3 | title: Deploy to Deta Button 4 | sidebar_lable: Deploy to Deta Button 5 | --- 6 | 7 | The __Deploy to Deta button__ provides users a quick way to deploy a public Git repo to a Deta Micro directly from the browser. 8 | 9 | It's an easy way to share your creations with the developer community. 10 | 11 | You can use the "Deploy To Deta Button" in open-source repositories, blog posts, landing pages etc, allowing other developers to quickly deploy and use your app on Deta. 12 | 13 | An example button that deploys a sample Python Micro to Deta: 14 | 15 | [![Deploy](/img/deploy_button/button.svg)](https://go.deta.dev/deploy?repo=https://github.com/deta/deploy-to-deta-button-example) 16 | 17 | ### Usage 18 | 19 | You can let users deploy your GitHub, Gitlab BitBucket (Git) repo quickly by adding the following markup: 20 | 21 | ```md 22 | [![Deploy](https://button.deta.dev/1/svg)](https://go.deta.dev/deploy?repo=your-repo-url) 23 | ``` 24 | 25 | :::note 26 | Specify the __exact__ branch url if you want to use a different branch for deployment. If you provide the repository url without specifying a branch, the default branch will be used. 27 | 28 | The repository **must be a public git repository url.** 29 | ::: --> 30 | 31 | 32 | ### Usage with HTML/JavaScript 33 | 34 | The button image is hosted in the following url: 35 | ``` 36 | https://button.deta.dev/1/svg 37 | ``` 38 | 39 | and can be easily added to HTML pages or JavaScript applications. Example usage: 40 | 41 | ```html 42 | 43 | Deploy 44 | 45 | ``` 46 | 47 | ### Metadata, Environment Variables And Cron 48 | 49 | You can optionally specify metadata, environment variables and a cron expression needed by the Micro in a `deta.json` file. Create this file in the root directory of your application. 50 | 51 | The `deta.json` file has the following schema: 52 | 53 | ```json 54 | { 55 | "name": "your app name", 56 | "description": "your app description", 57 | "runtime": "micro's runtime", 58 | "env": [ 59 | { 60 | "key": "ENV_VAR_KEY", 61 | "description": "Human friendly description of the env var", 62 | "value": "Default value of the env var", 63 | "required": true|false 64 | } 65 | ], 66 | "cron": "default cron expression (for eg. 3 minutes)" 67 | } 68 | 69 | ``` 70 | 71 | #### Fields 72 | 73 | - `name`: the application name, we will use the repositry name by default if this is not provided, users can change this value during deployment 74 | - `description`: the application description which will be shown to users on the deployment page 75 | - `runtime`: the micro's runtime, the default runtime (`python3.9` or `nodejs14.x`) will be used unless this value is set, supported values: 76 | - `Python`: `python3.7`, `python3.8`, `python3.9` 77 | - `Nodejs`: `nodejs12.x`, `nodejs14.x` 78 | 79 | - `env`: the environment variables your app uses 80 | - `key`: the environment variable key, users cannot change this value 81 | - `description`: the description of the environment variable so users know what it is used for 82 | - `value`: the default value of this variable, users can change this value 83 | - `required`: if the value of this variable _must be set_ by the user 84 | - `cron`: the default cron expression for the micro, if this is provided the deployed micro will have a cron job set with the provided value by default, users can change the value during deployment 85 | 86 | You can test your `deta.json` file by visiting `https://go.deta.dev/deploy?repo=your-repo-url` 87 | 88 | 89 | ### Get discovered 90 | 91 | Make sure to add the `deta` tag to your repo for it to show up in our [GitHub topic](https://github.com/topics/deta). 92 | 93 | Deta Tpoic on GitHub 94 | 95 | ## Issues 96 | 97 | If you run into any issues, consider reporting them in our [Github Discussions](https://github.com/orgs/deta/discussions). 98 | -------------------------------------------------------------------------------- /docs/micros/env_vars.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: env_vars 3 | title: Environment Variables 4 | sidebar_label: Environment Variables 5 | --- 6 | import Tabs from '@theme/Tabs'; 7 | import TabItem from '@theme/TabItem'; 8 | 9 | 10 | ### Setting Environment Variables 11 | 12 | Environment variables can be set to your Micro through the Deta cli's [update command](../cli/commands.md#deta-update). These variables are encrypted at rest. 13 | 14 | You need to create a file where you specify your environment variables with their values. 15 | 16 | :::note 17 | We strongly recommend creating a file called `.env` so that this file is skipped by the Deta cli and not deployed with your Micro's code. Also, please do not share/commit your env file publicly. 18 | ::: 19 | 20 | You can use the following command to update your environment variables: 21 | ```sh 22 | deta update -e 23 | ``` 24 | 25 | The environment variables must be defined in the following format: 26 | ``` 27 | VAR_NAME=VALUE 28 | ``` 29 | 30 | You should not change the value of the environment variables through your Micro's code, as the change will not persist in following invocations of your Micro. 31 | 32 | #### Example 33 | 34 | Suppose you want to make an environment variable `SECRET_TOKEN` with a value of `abcdefgh` accessible to your Micro's code. 35 | 36 | - Create a `.env` file with the following content: 37 | 38 | ``` 39 | SECRET_TOKEN=abcdefg 40 | ``` 41 | 42 | - Update the Micro's environment variables with the `deta update` command: 43 | 44 | ```sh 45 | deta update -e .env 46 | ``` 47 | 48 | 49 | ### Pre-Set Environment Variables 50 | 51 | Deta pre-sets some environment variables in your Micro's environment which are used by our runtime. 52 | 53 | :::note 54 | These pre-set variables are specific to your Micro and should not be shared publicly (unless we mention otherwise). These variables can not be updated from the cli. 55 | ::: 56 | 57 | The following pre-set environment variables could be useful for you: 58 | 59 | - **DETA_PATH** 60 | 61 | `DETA_PATH` stores a unique identifier for your Micro. This value is also used as the sub-domain under which your Micro is available through `http`. For example, if your `DETA_PATH` variable contained a value of `sdfgh` then your Micro is accessible at https://sdfgh.deta.dev. 62 | 63 | :::note 64 | This value does not store the self assigned sub-domain value at the moment. 65 | ::: 66 | 67 | - **DETA_RUNTIME** 68 | 69 | `DETA_RUNTIME` indicates if your code is running on a Micro, with a string value `"true"`. 70 | 71 | In some cases, you might need to run some code exclusively in local development and not in a Micro. For example, if you're running a FastAPI project on your Micro, and you've got an endpoint that dumps debug information like so: 72 | 73 | ```py 74 | @app.get("/debug_info") 75 | async def debug_info(): 76 | return get_debug_info() 77 | ``` 78 | 79 | If you want this endpoint to be only available locally, you can check the environment variable to selectively execute code: 80 | 81 | ```py 82 | import os 83 | 84 | @app.get("/debug_info") 85 | async def debug_info(): 86 | if (not os.getenv('DETA_RUNTIME')): 87 | return get_debug_info() 88 | raise HTTPException(status_code=404, detail="Not Found") 89 | ``` 90 | 91 | - **DETA_PROJECT_KEY** 92 | 93 | `DETA_PROJECT_KEY` is a project key generated for your Micro for authentication with [Deta Base](../base/about.md) and [Deta Drive](../drive/about.md). 94 | 95 | Each micro has its own project key and this **should not be shared publicly**. 96 | 97 | While using our SDKs(the latest versions) within a Deta Micro, you can omit specifying the project key when instantiating a service instance. 98 | 99 | 107 | 108 | 109 | ```js 110 | const { Base, Drive } = require('deta'); 111 | 112 | const base = Base('base_name'); 113 | const drive = Drive('drive_name'); 114 | ``` 115 | 116 | 117 | 118 | 119 | 120 | ```python 121 | from deta import Base, Drive 122 | 123 | base = Base('base_name') 124 | drive = Drive('drive_name') 125 | ``` 126 | 127 | 128 | 129 | 130 | ## Issues 131 | 132 | If you run into any issues, consider reporting them in our [Github Discussions](https://github.com/orgs/deta/discussions). -------------------------------------------------------------------------------- /docs/micros/faqs.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: faqs_micros 3 | title: Frequently Asked Questions 4 | sidebar_label: FAQs 5 | --- 6 | 7 | ### How can I request for a timeout or memory increase? 8 | 9 | Please, use the following forms to request for respective limit increases: 10 | - Timeout Limit Increase Request 11 | - Memory Limit Increase Request 12 | 13 | ### Can I use my own custom domain or subdomain with a Micro? 14 | 15 | Yes, please refer to the [documentation](./micros/custom_domains.md). 16 | 17 | ### Do Micros support websockets? 18 | 19 | No, Micros do not support websockets and other long-running processes. 20 | 21 | ### Why can I not write to the filesystem in a Micro? 22 | 23 | Micros have a read-only filesystem. Only `/tmp` can be written to, which is ephemeral and has a storage limit of 512 Mb. 24 | 25 | ### Why am I getting a `Request Entity Too Large` error when deploying a Micro? 26 | 27 | Micros have a maximum deployment size limit of 250 Mb. This limit includes the total size of your code and dependencies. 28 | 29 | ### Why does my Micro behave different locally and deployed? 30 | 31 | This can be because of a number of reasons. Please check out the [specifications](https://docs.deta.sh/docs/micros/about#technical-specifications) and [notes](https://docs.deta.sh/docs/micros/about#important-notes) for further information to find a possible reason. 32 | 33 | ### Why is my Micro returning a 502 Bad Gateway? 34 | 35 | The response comes from a reverse proxy between a client and your Micro. If there is a runtime error or a timeout when invoking a Micro, the proxy responds with a `502 Bad Gateway.` 36 | 37 | In order to debug `502` responses, you can use `deta visor` which show you real-time logs of your application. Navigate to your Micro's visor page from the UI or use the deta cli command `deta visor open` to view the error logs. 38 | 39 | If there are no logs in your visor and your Micro's response took roughly 10 seconds, then it's likely because of a timeout. 40 | 41 | If it is not because of a timeout, then please contact us. 42 | 43 | ### Is it safe to commit the `.deta` folder created by the cli? 44 | 45 | Yes it is safe to commit your `.deta` folder and push it to public repositories. 46 | -------------------------------------------------------------------------------- /docs/micros/getting_started.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: getting_started 3 | title: Getting Started 4 | sidebar_label: Getting Started 5 | --- 6 | import Tabs from '@theme/Tabs'; 7 | import TabItem from '@theme/TabItem'; 8 | 9 | ### Configuring & Installing the Deta CLI 10 | 11 | 12 | 20 | 21 | 22 | To install the Deta CLI, open a Terminal and enter: 23 | 24 | ```shell 25 | curl -fsSL https://get.deta.dev/cli.sh | sh 26 | ``` 27 | 28 | 29 | 30 | 31 | 32 | To install the Deta CLI, open a Terminal and enter: 33 | 34 | ```shell 35 | curl -fsSL https://get.deta.dev/cli.sh | sh 36 | ``` 37 | 38 | 39 | 40 | 41 | To install the Deta CLI, open PowerShell and enter: 42 | 43 | ```shell 44 | iwr https://get.deta.dev/cli.ps1 -useb | iex 45 | ``` 46 | 47 | 48 | 49 | 50 | 51 | This will download the binary which contains the CLI code. It will try to export the `deta` command to your path. If it does not succeed, follow the directions output by the install script to export `deta` to your path. 52 | 53 | ### Logging in to Deta via the CLI 54 | 55 | Once you have successfully installed the Deta CLI, you need to login to Deta. 56 | 57 | From a Terminal, type `deta login`. 58 | 59 | This command will open your browser and authenticate your CLI through Deta's web application. 60 | 61 | Upon a successful login, you are ready to start building [Micros](about.md). 62 | 63 | ### Creating Your First Micro 64 | 65 | To create a micro, navigate in your Terminal to a parent directory for your first micro and type: 66 | 67 | 75 | 76 | 77 | ```shell 78 | deta new --node first_micro 79 | ``` 80 | 81 | This will create a new Node.js Micro in the 'cloud' as well as a local copy inside a directory called `first_micro` which will contain an `index.js` file. 82 | 83 | The CLI should respond: 84 | 85 | ```json 86 | { 87 | "name": "first_micro", 88 | "runtime": "nodejs12.x", 89 | "endpoint": "https://.deta.dev", 90 | "visor": "enabled", 91 | "http_auth": "enabled" 92 | } 93 | ``` 94 | 95 | 96 | 97 | 98 | ```shell 99 | deta new --python first_micro 100 | ``` 101 | 102 | This will create a new Python Micro in the 'cloud' as well as a local copy inside a directory called `first_micro` which will contain a `main.py` file. 103 | 104 | 105 | The CLI should respond: 106 | 107 | ```json 108 | { 109 | "name": "first_micro", 110 | "runtime": "python3.7", 111 | "endpoint": "https://.deta.dev", 112 | "visor": "enabled", 113 | "http_auth": "enabled" 114 | } 115 | ``` 116 | 117 | 118 | 119 | 120 | Save this endpoint URL somewhere, as we will be visiting it shortly. 121 | 122 | ### Creating a Micro Under a Specific Project 123 | 124 | ```shell 125 | deta new --project 126 | ``` 127 | 128 | This will create a new Micro under `` in the 'cloud'. 129 | 130 | ### Updating your Micro: Dependencies and Code 131 | 132 | 140 | 141 | 142 | #### Setup and Dependencies 143 | 144 | Enter the directory `first_micro`, and then run the shell command: 145 | 146 | ```shell 147 | npm init -y 148 | ``` 149 | 150 | This will initialize a Node.js project in your current directory with npm's wizard. 151 | 152 | What is important is that the **main** file is `index.js`. 153 | 154 | After following the npm wizard, let's add a dependency by running: 155 | 156 | ```shell 157 | npm install express 158 | ``` 159 | 160 | #### Updating Code Locally 161 | Let's also edit and save the `index.js` file locally so that your Micro responds to `HTTP GET` requests with *Hello World*. 162 | 163 | ```js 164 | const express = require('express'); 165 | 166 | const app = express(); 167 | 168 | app.get('/', async (req, res) => { 169 | res.send('Hello World') 170 | }); 171 | 172 | module.exports = app; 173 | ``` 174 | 175 | #### Deploying Local Changes 176 | After you have updated your dependencies (documented in a `package.json` file) and / or your code locally, use a `deta deploy` command to update your Micro. 177 | 178 | ```shell 179 | deta deploy 180 | ``` 181 | The Deta CLI will notify you if your code has updated as well as if the dependencies were installed 182 | 183 | ```shell 184 | Deploying... 185 | Successfully deployed changes 186 | Updating dependencies... 187 | 188 | + express@4.17.1 189 | added 50 packages from 37 contributors and audited 50 packages in 1.967s 190 | found 0 vulnerabilities 191 | ``` 192 | 193 | 194 | 195 | 196 | #### Setup and Dependencies 197 | Enter the directory `first_micro`, and then create a file, `requirements.txt`, which tells Deta which dependencies to install. 198 | 199 | Let's add *flask* to `requirements.txt` and save this file locally. 200 | 201 | ```text 202 | flask 203 | ``` 204 | 205 | #### Updating Code Locally 206 | Let's also edit the `main.py` file so that your Micro responds to `HTTP GET` requests with *Hello World*. 207 | ```py 208 | from flask import Flask 209 | 210 | app = Flask(__name__) 211 | 212 | @app.route('/', methods=["GET"]) 213 | def hello_world(): 214 | return "Hello World" 215 | ``` 216 | 217 | 218 | 219 | #### Deploying Local Changes 220 | 221 | After you have updated your `requirements.txt` and / or your code locally, use a `deta deploy` command to update your Micro. 222 | 223 | ```shell 224 | deta deploy 225 | ``` 226 | The Deta CLI will notify you if your code has updated as well as if the dependencies were installed. 227 | 228 | ```shell 229 | Deploying... 230 | Successfully deployed changes 231 | Updating dependencies... 232 | Collecting flask 233 | Downloading https://files.pythonhosted.org/packages/f2/28/2a03252dfb9ebf377f40fba6a7841b47083260bf8bd8e737b0c6952df83f/Flask-1.1.2-py2.py3-none-any.whl (94kB) 234 | Collecting Werkzeug>=0.15 (from flask) 235 | Downloading https://files.pythonhosted.org/packages/cc/94/5f7079a0e00bd6863ef8f1da638721e9da21e5bacee597595b318f71d62e/Werkzeug-1.0.1-py2.py3-none-any.whl (298kB) 236 | Collecting itsdangerous>=0.24 (from flask) 237 | Downloading https://files.pythonhosted.org/packages/76/ae/44b03b253d6fade317f32c24d100b3b35c2239807046a4c953c7b89fa49e/itsdangerous-1.1.0-py2.py3-none-any.whl 238 | Collecting Jinja2>=2.10.1 (from flask) 239 | Downloading https://files.pythonhosted.org/packages/30/9e/f663a2aa66a09d838042ae1a2c5659828bb9b41ea3a6efa20a20fd92b121/Jinja2-2.11.2-py2.py3-none-any.whl (125kB) 240 | Collecting click>=5.1 (from flask) 241 | Downloading https://files.pythonhosted.org/packages/d2/3d/fa76db83bf75c4f8d338c2fd15c8d33fdd7ad23a9b5e57eb6c5de26b430e/click-7.1.2-py2.py3-none-any.whl (82kB) 242 | Collecting MarkupSafe>=0.23 (from Jinja2>=2.10.1->flask) 243 | Downloading https://files.pythonhosted.org/packages/98/7b/ff284bd8c80654e471b769062a9b43cc5d03e7a615048d96f4619df8d420/MarkupSafe-1.1.1-cp37-cp37m-manylinux1_x86_64.whl 244 | Installing collected packages: Werkzeug, itsdangerous, MarkupSafe, Jinja2, click, flask 245 | ``` 246 | 247 | 248 | 249 | #### Visiting our Endpoint 250 | Let's visit the endpoint (from the endpoint URL we saved earlier). 251 | 252 | (If you didn't save it, simply type `deta details` into the CLI, which will give you the endpoint alongside other information about your Micro). 253 | 254 | Open up your endpoint in a browser. You might be prompted to log in to your deta account on visiting your endpoint for the first time. 255 | 256 | You should see **Hello, World** 257 | 258 | If you're not accessing the endpoint from a browser (like from curl) or if you have disabled cookies in your browser, the response will be: 259 | ```json 260 | { 261 | "errors":["Unauthorized"] 262 | } 263 | ``` 264 | 265 | This is because *Deta Auth* is protecting the endpoint from unauthorized access. 266 | 267 | 268 | ### Opening Your Micro To the Public 269 | 270 | Let's use one last command to open up the endpoint to the public: 271 | 272 | ```shell 273 | deta auth disable 274 | ``` 275 | 276 | The CLI should respond: 277 | 278 | ```shell 279 | Successfully disabled http auth 280 | ``` 281 | 282 | Congratulations, you have just deployed and published your first Micro! 283 | 284 | ## Issues 285 | 286 | If you run into any issues, consider reporting them in our [Github Discussions](https://github.com/orgs/deta/discussions). -------------------------------------------------------------------------------- /docs/micros/run.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: run 3 | title: Run 4 | sidebar_lable: Run 5 | --- 6 | import Tabs from '@theme/Tabs'; 7 | import TabItem from '@theme/TabItem'; 8 | 9 | ### Run from the CLI 10 | 11 | A Deta Micro can be run directly from the `deta cli` using the command [deta run](../cli/commands#deta-run) with an input. 12 | 13 | In order to run a micro from the cli directly, the micro's code needs to define functions that will be run from the cli with the help of our library `deta`. 14 | 15 | The `deta` library is pre-installed on a micro and can just be imported directly. 16 | 17 | 25 | 26 | 27 | ```js 28 | const { app } = require('deta'); 29 | 30 | // define a function to run from the cli 31 | // the function must take an event as an argument 32 | app.lib.run(event => "Welcome to Deta!"); 33 | 34 | module.exports = app; 35 | ``` 36 | 37 | 38 | 39 | 40 | ```python 41 | from deta import app 42 | 43 | # define a function to run from the cli 44 | # the function must take an event as an argument 45 | @app.lib.run() 46 | def welcome(event): 47 | return "Welcome to Deta!" 48 | ``` 49 | 50 | 51 | 52 | With this code deployed on a micro, you can simply run 53 | 54 | ```shell 55 | $ deta run 56 | ``` 57 | 58 | And see the following output: 59 | ``` 60 | Response: 61 | "Welcome to Deta!" 62 | ``` 63 | 64 | ### Events 65 | 66 | A function that is triggered from the cli must take an `event` as the only argument. 67 | 68 | You can provide an input from the cli to the function which will be passed on as an `event`. It has four attributes: 69 | 70 | - `event.json`: `object` provides the JSON payload 71 | - `event.body`: `string` provides the raw JSON payload 72 | - `event.type`: `string` type of an event, `run` when running from the cli 73 | - `event.action`: `string` the [action](#Actions) provided from the cli, defaults to an empty string 74 | 75 | 76 | 84 | 85 | 86 | ```js 87 | const { app } = require('deta'); 88 | 89 | app.lib.run(event => { 90 | return { 91 | // access input to your function with event.json 92 | message: `hello ${event.json.name}!` 93 | }; 94 | }); 95 | 96 | module.exports = app; 97 | ``` 98 | 99 | 100 | 101 | 102 | ```python 103 | from deta import app 104 | 105 | @app.lib.run() 106 | def welcome(event): 107 | return { 108 | # access input to your function with event.json 109 | "message": f"hello {event.json.get('name')}!" 110 | } 111 | ``` 112 | 113 | 114 | 115 | With this code deployed on a micro, you can run 116 | 117 | ```shell 118 | $ deta run -- --name deta 119 | ``` 120 | 121 | And should see the following output. 122 | 123 | ```json 124 | Response: 125 | { 126 | "message": "hello deta!" 127 | } 128 | ``` 129 | 130 | ### Input 131 | 132 | The input to your function on a micro can be provided through the `deta cli` and accessed in the code from the `event` object. The input is a JSON object created from the arguments provided to the cli. 133 | 134 | An *important* consideration is that the values in key-value pairs in the input are always either *strings*, *list of strings* or *booleans*. 135 | 136 | Boolean flags are provided with a single dash, string arguments with double dash and if multiple values are provided for the same key, a list of strings will be provided. 137 | 138 | For instance: 139 | 140 | ```shell 141 | $ deta run -- --name jimmy --age 33 --emails jimmy@deta.sh --emails jim@deta.sh -active 142 | ``` 143 | 144 | will provide the micro with the following input: 145 | 146 | ```json 147 | { 148 | "name": "jimmy", 149 | "age": "33", // notice '33' here is a string not an int 150 | "emails": ["jimmy@deta.sh", "jim@deta.sh"], 151 | "active": true 152 | } 153 | ``` 154 | 155 | You need to explicitly convert the string values to other types in your code if needed. 156 | 157 | ### Actions 158 | 159 | Actions help you run different functions based on an `action` that you define for the function. 160 | 161 | The `action` defaults to an empty string if not provided. 162 | 163 | 171 | 172 | 173 | ```js 174 | const { app } = require('deta'); 175 | 176 | app.lib.run(event => { 177 | return { 178 | message: `hello ${event.json.name}!` 179 | }; 180 | // action 'hello' 181 | }, "hello"); 182 | 183 | app.lib.run(event => { 184 | return { 185 | message: `good morning ${event.json.name}!` 186 | }; 187 | // action 'greet' 188 | }, "greet"); 189 | 190 | module.exports = app; 191 | ``` 192 | 193 | 194 | 195 | 196 | ```python 197 | from deta import app 198 | 199 | # action 'hello' 200 | # the action does not need to have the same name as the function 201 | @app.lib.run(action="hello") 202 | def welcome(event): 203 | return { 204 | "message": f"hello {event.json.get('name')}!" 205 | } 206 | 207 | # action 'greet' 208 | @app.lib.run(action="greet") 209 | def greet(event): 210 | return { 211 | "message": f"good morning {event.json.get('name')}!" 212 | } 213 | ``` 214 | 215 | 216 | 217 | With this code deployed on a deta micro, if you run 218 | 219 | ```shell 220 | $ deta run hello -- --name deta 221 | ``` 222 | 223 | where you tell the cli to run action `hello` with `"name": "deta"` as input. You should see the following output: 224 | 225 | ```json 226 | Response: 227 | { 228 | "message": "hello deta!" 229 | } 230 | ``` 231 | 232 | And if you do `deta run` with action `greet` 233 | 234 | ```shell 235 | $ deta run greet -- --name deta 236 | ``` 237 | 238 | you should see the following output: 239 | 240 | ```json 241 | Response: 242 | { 243 | "message": "good morning deta!" 244 | } 245 | ``` 246 | 247 | ### Run and HTTP 248 | 249 | You can combine both run and HTTP triggers in the same deta micro. For this you need to instantiate your app using the `deta` library that is pre-installed on a micro. 250 | 251 | 259 | 260 | 261 | ```js 262 | const { App } = require('deta'); 263 | const express = require('express'); 264 | 265 | const app = App(express()); 266 | 267 | // triggered with an HTTP request 268 | app.get('/', async(req, res) => { 269 | res.send('Hello deta, i am running with HTTP'); 270 | }); 271 | 272 | // triggered from the cli 273 | app.lib.run(event => { 274 | return 'Hello deta, i am running from the cli'; 275 | }); 276 | 277 | module.exports = app; 278 | 279 | ``` 280 | 281 | 282 | 283 | 284 | ```python 285 | from deta import App 286 | from fastapi import FastAPI 287 | 288 | app = App(FastAPI()) 289 | 290 | # triggered with an HTTP request 291 | @app.get("/") 292 | def http(): 293 | return "Hello deta, i am running with HTTP" 294 | 295 | # triggered from the cli 296 | @app.lib.run() 297 | def run(event): 298 | return "Hello deta, i am running from the cli" 299 | ``` 300 | 301 | 302 | 303 | ### Run and Cron 304 | 305 | You can use both run and [cron](./cron) triggers in the same deta micro. You can also stack run and cron triggers for the same function. 306 | 307 | 315 | 316 | 317 | ```js 318 | const { app } = require('deta'); 319 | 320 | const sayHello = event => 'hello deta'; 321 | const printTime = event => `it is ${(new Date).toTimeString()}`; 322 | 323 | app.lib.run(sayHello); 324 | 325 | // stacking run and cron 326 | app.lib.run(printTime, 'time'); // action 'time' 327 | app.lib.cron(printTime); 328 | 329 | module.exports = app; 330 | ``` 331 | 332 | 333 | 334 | 335 | ```python 336 | from deta import app 337 | from datetime import datetime 338 | 339 | # only run 340 | @app.lib.run() 341 | def say_hello(event): 342 | return "hello deta" 343 | 344 | # stacking run and cron 345 | @app.lib.run(action='time') # action 'time' 346 | @app.lib.cron(): 347 | def print_time(event): 348 | return f"it is {datetime.now()}" 349 | ``` 350 | 351 | 352 | 353 | ## Issues 354 | 355 | If you run into any issues, consider reporting them in our [Github Discussions](https://github.com/orgs/deta/discussions). -------------------------------------------------------------------------------- /docs/micros/visor.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: visor 3 | title: Visor (Logs) 4 | sidebar_label: Visor (Logs) 5 | --- 6 | import Tabs from '@theme/Tabs'; 7 | import TabItem from '@theme/TabItem'; 8 | 9 | The Deta Visor offers a user interface for you to see a live view of all the events (logs) processed by your Micro. You can use it to monitor and debug your requests, test your endpoints by sending requests, and more. 10 | 11 | By default, Visor is disabled, to enable it run `deta visor enable` in your terminal inside you Micro's source code. 12 | 13 | 14 | ### Opening Visor 15 | 22 | 23 | 24 | Start by logging into your console at [deta.sh](https://deta.sh). You should be redirected to the following screen: 25 | 26 | visor_1 27 | 28 | Once that's done, choose a micro to view by clicking on its name (under the _"Micros"_ tab). 29 | 30 | visor_2 31 | 32 | Now click on _"Visor"_ 33 | 34 | visor_3 35 | 36 | 37 | 38 | 39 | Start your terminal in the root directory of your deployed Deta project. 40 | 41 | Run `deta visor open`. 42 | 43 | 44 | 45 | 46 | ### Navigating the Visor 47 | The Visor page has the link to your Micro in the top right, a button named _"HTTP Client"_ in the bottom left, and a list of all the events handled by your Micro! 48 | 49 | visor_4 50 | 51 | #### The Event List 52 | The Visor logs every single event made to your Micro, each event has the **HTTP Status Code**, the **HTTP Method**, and the **time** logged above it. Under this information are three tabs, letting you view the response, request, and logs of the event. 53 | 54 | Response: 55 | visor 56 | 57 | The Request sent to the Micro: 58 | 59 | request 60 | 61 | And logs (normally displaying errors if they were to occur): 62 | 63 | logs 64 | 65 | On the top right of every event are two icons: 66 | 67 | icons 68 | 69 | The _"pen"_ icon lets you edit the request before re-sending it to your micro and the _"redo"_ icon lets you send the same request again. 70 | 71 | 72 | #### The HTTP Client 73 | Visor also has a built in _"HTTP Client"_ to make requests to your Micro. You can use this by clicking on the _"HTTP Client"_ button. 74 | 75 | HTTP Client 76 | 77 | Simply specify the request method, path, headers and body and hit the _"Send"_ button to send it off! 78 | 79 | HTTP Client Modal 80 | 81 | The content-type can be changed from JSON to Text, using the selection box on the bottom left of this window. 82 | 83 | HTTP Client JSON to Text 84 | 85 | 86 | ### Video overview 87 | 88 | 89 | 90 | ### Logs Retention 91 | 92 | Visor logs are retained for two weeks (14 days). 93 | 94 | ### Visor doesn't show the error 95 | 96 | Sometimes you will get a `500` response from our server and no errors will show up in Visor, in that case you could quickly check our system logs for you Micro with `deta logs`. 97 | 98 | ## Issues 99 | 100 | If you run into any issues, consider reporting them in our [Github Discussions](https://github.com/orgs/deta/discussions). -------------------------------------------------------------------------------- /docs/tutorials/cron.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: cron-guide 3 | title: Cron Jobs 4 | sidebar_label: Cron Jobs 5 | --- 6 | import Tabs from '@theme/Tabs'; 7 | import TabItem from '@theme/TabItem'; 8 | 9 | A Deta Micro can be set to run on a schedule from the `deta cli` using the [deta cron set](../cli/commands#deta-cron-set) command. 10 | 11 | In this guide we are going to configure a deta micro to run every five minutes. 12 | 13 | The guide assumes you have already signed up for Deta and have the [Deta CLI](../cli/install.md) installed. 14 | 15 | 16 | 24 | 25 | 26 | 27 | 1. Create a directory `cron-job` and change the current directory to it. 28 | 29 | ```shell 30 | $ mkdir cron-job && cd cron-job 31 | ``` 32 | 33 | 2. In order to set a micro to run on a schedule, the micro's code needs to define a function that will be run on the schedule with the help of our library `deta`, which is pre-installed on a micro and can just be imported directly. 34 | 35 | Create a `index.js` file and define the function that should run on the schedule. 36 | 37 | ```javascript 38 | // import app from 'deta' 39 | const { app } = require('deta'); 40 | 41 | // use app.lib.cron to define the function that runs on the schedule 42 | // takes an `event` as an argument 43 | app.lib.cron(event => { 44 | console.log("running on a schedule"); 45 | }); 46 | 47 | module.exports = app; 48 | ``` 49 | 50 | 5. Create a new `nodejs` micro with `deta new`. 51 | 52 | ```shell 53 | $ deta new 54 | Successfully created a new micro 55 | { 56 | "name": "cron-job", 57 | "runtime": "nodejs12.x", 58 | "endpoint": "https://{micro_name}.deta.dev", 59 | "visor": "enabled", 60 | "http_auth": "enabled" 61 | } 62 | ``` 63 | 64 | Even though the output shows a HTTP endpoint, you do not need it for cron. 65 | 66 | 6. Set the micro to run on a schedule with the [deta cron set](../cli/commands#deta-cron-set) command. 67 | 68 | ```shell 69 | $ deta cron set "5 minutes" 70 | Scheduling micro... 71 | Successfully set micro to schedule for "5 minutes" 72 | ``` 73 | 74 | We have set the micro to run every five minutes. In order to see if a micro is running on a schedule, you can use the `deta details` command. 75 | 76 | ```shell 77 | $ deta details 78 | { 79 | "name": "cron-job", 80 | "runtime": "nodejs12.x", 81 | "endpoint": "https://{micro_name}.deta.dev", 82 | "visor": "enabled", 83 | "http_auth": "enabled", 84 | "cron": "5 minutes" 85 | } 86 | ``` 87 | 88 | The details show that the `cron` has ben set for `5 minutes` 89 | 90 | 91 | 7. In order to see logs of your cron-job, you can use `Deta Visor`, which enables you to see real-time logs of a Deta Micro. Open your micro's visor page with `deta visor open` from the cli or by navigating to your micro's visor page on the browser. 92 | 93 | ```shell 94 | $ deta visor open 95 | Opening visor in the browser... 96 | ``` 97 | 98 | We have a micro which prints "running on a schedule" every five minutes. You should see the execution logs in your micro's visor page every five minutes. 99 | 100 | 101 | 102 | 103 | 1. Create a directory `cron-job` and change the current directory to it. 104 | 105 | ```shell 106 | $ mkdir cron-job && cd cron-job 107 | ``` 108 | 109 | 2. In order to set a micro to run on a schedule, the micro's code needs to define a function that will be run on the schedule with the help of our library `deta`, which is pre-installed on a micro and can just be imported directly. 110 | 111 | Create a `main.py` file and define the function that should run on the schedule. 112 | 113 | ```python 114 | from deta import app 115 | 116 | # use app.lib.cron decorator for the function that runs on the schedule 117 | # the function takes an `event` as an argument 118 | @app.lib.cron() 119 | def cron_task(event): 120 | print("running on a schedule") 121 | ``` 122 | 123 | 5. Create a new `python` micro with `deta new`. 124 | 125 | ```shell 126 | $ deta new 127 | Successfully created a new micro 128 | { 129 | "name": "cron-job", 130 | "runtime": "python3.7", 131 | "endpoint": "https://{micro_name}.deta.dev", 132 | "visor": "enabled", 133 | "http_auth": "enabled" 134 | } 135 | ``` 136 | 137 | Even though the output shows a HTTP endpoint, you do not need it for cron. 138 | 139 | 6. Set the micro to run on a schedule with [deta cron set](../cli/commands#deta-cron-set) command. 140 | 141 | ```shell 142 | $ deta cron set "5 minutes" 143 | Scheduling micro... 144 | Successfully set micro to schedule for "5 minutes" 145 | ``` 146 | 147 | We have set the micro to run every five minutes. In order to see if a micro is running on a schedule, you can use the `deta details` command. 148 | 149 | ```shell 150 | $ deta details 151 | { 152 | "name": "cron-job" 153 | "runtime": "python3.7", 154 | "endpoint": "https://{micro_name}.deta.dev", 155 | "visor": "enabled", 156 | "http_auth": "enabled", 157 | "cron": "5 minutes" 158 | } 159 | ``` 160 | 161 | The details show that the `cron` has ben set for `5 minutes` 162 | 163 | 164 | 7. In order to see logs of your cron-job, you can use `Deta Visor`, which enables you to see real-time logs of a Deta Micro. Open your micro's visor page with `deta visor open` from the cli or by navigating to your micro's visor page on the browser. 165 | 166 | ```shell 167 | $ deta visor open 168 | Opening visor in the browser... 169 | ``` 170 | 171 | We have successfully deployed a micro which prints "running on a schedule" every five minutes. You should see the execution logs in your micro's visor page every five minutes. 172 | 173 | 174 | Full documentation on cron is available [here](https://docs.deta.sh/docs/micros/cron). 175 | 176 | 177 | 178 | -------------------------------------------------------------------------------- /docs/tutorials/fast_api.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: fast-api-guide 3 | title: FastAPI 4 | sidebar_label: FastAPI 5 | --- 6 | 7 | You can deploy a [FastAPI](https://fastapi.tiangolo.com/) application on Deta very easily in a few steps. 8 | 9 | The guide assumes you have already signed up for Deta and have the [Deta CLI](../cli/install.md) installed. 10 | 11 | 1. Create a directory `fastapi-app` and change the current directory to it. 12 | 13 | ```shell 14 | $ mkdir fastapi-app && cd fastapi-app 15 | ``` 16 | 17 | 2. Create a `main.py` file with a simple fastapi application. 18 | 19 | ```python 20 | from fastapi import FastAPI 21 | app = FastAPI() 22 | 23 | @app.get("/") 24 | async def root(): 25 | return "Hello World!" 26 | ``` 27 | 28 | 3. Create a `requirements.txt` file specifying `fastapi` as a dependecy. 29 | 30 | ``` 31 | fastapi 32 | ``` 33 | 34 | 4. Deploy your application with `deta new`. 35 | 36 | ```shell 37 | $ deta new 38 | Successfully created a new micro 39 | { 40 | "name": "fastapi-app", 41 | "runtime": "python3.7", 42 | "endpoint": "https://{micro_name}.deta.dev", 43 | "visor": "enabled", 44 | "http_auth": "enabled" 45 | } 46 | Adding dependencies... 47 | Collecting fastapi 48 | ... 49 | Successfully installed anyio-3.6.1 fastapi-0.85.0 idna-3.4 pydantic-1.10.2 sniffio-1.3.0 starlette-0.20.4 typing-extensions-4.3.0 50 | ``` 51 | 52 | We now have a FastAPI application deployed. 53 | 54 | If you visit the `endpoint` shown in the output (your endpoint will be different from this one) in your browser, you should see a `Hello World!` response. 55 | -------------------------------------------------------------------------------- /docs/tutorials/forms.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: form-endpoints-guide 3 | title: Form Endpoints 4 | sidebar_label: Form Endpoints 5 | --- 6 | import Tabs from '@theme/Tabs'; 7 | import TabItem from '@theme/TabItem'; 8 | 9 | [Deta Micros](../micros/about.md) can be used to easily deploy form endpoints and the form data can be stored easily with [Deta Base](../base/about.md). 10 | 11 | In this guide, we are going to deploy a Deta Micro that offers a form endpoint for a simple contact form and stores the information in a Deta Base. 12 | 13 | The guide assumes you have already signed up for Deta and have the [Deta CLI](../cli/install.md) installed. 14 | 15 | The contact form will store a `name`, `email` and a `message`. 16 | 17 | ```json 18 | { 19 | "name": str, 20 | "email": str, 21 | "message": str 22 | } 23 | ``` 24 | 25 | 33 | 34 | 35 | 36 | We are going to deploy an `express` app for the form endpoint. 37 | 38 | 1. Create a directory `express-form` and change the current directory to it. 39 | 40 | ```shell 41 | $ mkdir express-form && cd express-form 42 | ``` 43 | 44 | 2. Create an empty `index.js` file (we will add the code that handles the logic later). 45 | 46 | 3. Initialize a `nodejs` project with `npm init`. 47 | 48 | ```shell 49 | $ npm init -y 50 | ``` 51 | 52 | You can skip the `-y` flag, if you want to fill the details about the pacakge interactively through npm's wizard. 53 | 54 | 4. Install `express` locally for your project. 55 | 56 | ```shell 57 | $ npm install express 58 | ``` 59 | 60 | 5. Create a new `nodejs` micro with `deta new`. This will create a new `nodejs` micro for you and automatically install `express` as a dependecy. 61 | 62 | ```shell 63 | $ deta new 64 | Successfully created a new micro 65 | { 66 | "name": "express-form", 67 | "runtime": "nodejs12.x", 68 | "endpoint": "https://{micro_name}.deta.dev", 69 | "visor": "enabled", 70 | "http_auth": "enabled" 71 | } 72 | Adding dependencies... 73 | 74 | + express@4.17.1 75 | added 50 packages from 37 contributors and audited 50 packages in 1.967s 76 | found 0 vulnerabilities 77 | ``` 78 | 79 | Your micro's `endpoint` will be different from the output shown above. This `endpoint` will be the form endpoint. 80 | 81 | 6. You can also see that the `http_auth` is `enabled` by default. We will disable the `http_auth` so that form data can be sent to the micro. 82 | 83 | ```shell 84 | $ deta auth disable 85 | Successfully disabled http auth 86 | ``` 87 | 88 | This is only for the tutorial, we recommended that you protect your endpoint with some authentication. 89 | 90 | 5. Open `index.js` and add a `POST` endpoint for the form using `express`. 91 | 92 | ```javascript 93 | const express = require('express'); 94 | 95 | // express app 96 | const app = express(); 97 | 98 | // parse application/x-www-form-urlencoded 99 | app.use(express.urlencoded()); 100 | 101 | app.post("/", (req, res)=>{ 102 | const body = req.body; 103 | 104 | // validate input 105 | if (!body.name || !body.email || !body.message){ 106 | return res.status(400).send('Bad request: missing some required values'); 107 | } 108 | 109 | // TODO: save the data 110 | return res.send('ok'); 111 | }); 112 | 113 | 6. Update `index.js` to add logic to save the form data to a Deta Base. 114 | 115 | ```javascript 116 | const express = require('express'); 117 | const { Deta } = require('deta'); 118 | 119 | // express app 120 | const app = express(); 121 | 122 | // contact form base 123 | const formDB = Deta().Base("contact-form"); 124 | 125 | // parse application/x-www-form-urlencoded 126 | app.use(express.urlencoded()); 127 | 128 | app.post("/", (req, res)=>{ 129 | const body = req.body; 130 | 131 | // validate input 132 | if (!body.name || !body.email || !body.message){ 133 | return res.status(400).send('Bad request: missing some required values') 134 | } 135 | 136 | // save form data 137 | formDB.put({ 138 | name: body.name, 139 | email: body.email, 140 | message: body.message 141 | }); 142 | 143 | return res.status(201).send('ok'); 144 | }); 145 | ``` 146 | 147 | 7. Deploy the changes with `deta deploy` 148 | 149 | ```shell 150 | $ deta deploy 151 | Successfully deployed changes 152 | ``` 153 | 154 | Your endpoint will now accept form `POST` data and save it to a database. 155 | 156 | You can use [Deta Base's UI](../base/base_ui) to easily see what data has been stored in the database. Navigate to your `project` and click on your base name under `bases` in your browser to use the Base UI. 157 | 158 | Here's an example view of the UI. 159 | 160 | 161 | 162 | 163 | 164 | 165 | We are going to deploy a `flask` app for the form endpoint. 166 | 167 | 1. Create a directory `flask-form` and change the current directory to it. 168 | 169 | ```shell 170 | $ mkdir flask-form && cd flask-form 171 | ``` 172 | 173 | 2. Create an empty `main.py` file (we will add the code that handles the logic later). 174 | 175 | 4. Create a `requirements.txt` file and add `flask` as a dependency for your project. 176 | 177 | ``` 178 | flask 179 | ``` 180 | 181 | 5. Create a new `python` micro with `deta new`. This will create a new `python` micro for you and automatically install `flask` as a dependecy. 182 | 183 | ```shell 184 | $ deta new 185 | Successfully created a new micro 186 | { 187 | "name": "flask-form", 188 | "runtime": "python3.7", 189 | "endpoint": "https://{micro_name}.deta.dev", 190 | "visor": "enabled", 191 | "http_auth": "enabled" 192 | } 193 | Adding dependencies... 194 | Collecting flask 195 | ... 196 | Installing collected packages: Werkzeug, itsdangerous, MarkupSafe, Jinja2, click, flask 197 | ``` 198 | 199 | Your micro's `endpoint` will be different from the output shown above. This `endpoint` will be the form endpoint. 200 | 201 | 6. You can also see that the `http_auth` is `enabled` by default. We will disable the `http_auth` so that form data can be sent to the micro. 202 | 203 | ```shell 204 | $ deta auth disable 205 | Successfully disabled http auth 206 | ``` 207 | 208 | This is only for the tutorial, we recommended that you protect your endpoint with some authentication. 209 | 210 | 5. Open `main.py` and add a `POST` endpoint for the form using `flask`. 211 | 212 | ```python 213 | from flask import Flask, request 214 | 215 | #flask app 216 | app = Flask(__name__) 217 | 218 | @app.route("/", methods=["POST"]) 219 | def save_form_data(): 220 | # TODO: save data 221 | return "ok" 222 | ``` 223 | 224 | 6. Update `main.py` to add logic to save the form data to a Deta Base. 225 | 226 | ```python 227 | from flask import Flask, request 228 | from deta import Deta 229 | 230 | # flask app 231 | app = Flask(__name__) 232 | 233 | # contact form base 234 | form_db = Deta().Base("contact-form") 235 | 236 | @app.route("/", methods=["POST"]) 237 | def save_form_data(): 238 | form_db.put({ 239 | # flask sends a 400 automatically if there is a KeyError 240 | "name": request.form["name"], 241 | "email": request.form["email"], 242 | "message": request.form["message"] 243 | }) 244 | return "ok", 201 245 | ``` 246 | 247 | 7. Deploy the changes with `deta deploy`. 248 | 249 | ```shell 250 | $ deta deploy 251 | Successfully deployed changes 252 | ``` 253 | 254 | Your endpoint will now accept form `POST` data and save it to a database. 255 | 256 | You can use [Deta Base's UI](../base/base_ui) to easily see what data has been stored in the database. Navigate to your `project` and click on your base name under `bases` in your browser to use the Base UI. 257 | 258 | Here's an example view of the UI. 259 | 260 | 261 | 262 | 263 | 264 | -------------------------------------------------------------------------------- /docs/tutorials/webhooks.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: webhooks-guide 3 | title: Webhooks 4 | sidebar_label: Webhooks 5 | --- 6 | 7 | import Tabs from '@theme/Tabs'; 8 | import TabItem from '@theme/TabItem'; 9 | 10 | [Deta Micros](../micros/about.md) make it extremely easy to deploy webhook servers. 11 | 12 | Each Deta Micro has a unique HTTPS endpoint which can be used as the webhook URL. 13 | 14 | You can use your favorite web application framework for your webhook server. 15 | 16 | The guide assumes you have already signed up for Deta and have the [Deta CLI](../cli/install.md) installed. 17 | 18 | 26 | 27 | 28 | 29 | We are going to use `express` with our Deta Micro and deploy a simple `nodejs` webhook server. 30 | 31 | 1. Create a directory `express-webhook` and change the current directory to it. 32 | 33 | ```shell 34 | $ mkdir express-webhook && cd express-webhook 35 | ``` 36 | 37 | 2. Create an empty `index.js` file (we will add the code that handles the logic later). 38 | 39 | 3. Initialize a `nodejs` project with `npm init` 40 | 41 | ```shell 42 | $ npm init -y 43 | ``` 44 | 45 | You can skip the `-y` flag, if you want to fill the details about the package interactively through npm's wizard. 46 | 47 | 4. Install `express` locally for your project. 48 | 49 | ```shell 50 | $ npm install express 51 | ``` 52 | 53 | 5. Create a new `nodejs` micro with `deta new`. This will create a new `nodejs` micro for you and automatically install `express` as a dependency. 54 | 55 | ```shell 56 | $ deta new 57 | Successfully created a new micro 58 | { 59 | "name": "express-webhook", 60 | "runtime": "nodejs12.x", 61 | "endpoint": "https://{micro_name}.deta.dev", 62 | "visor": "enabled", 63 | "http_auth": "enabled" 64 | } 65 | Adding dependencies... 66 | 67 | + express@4.17.1 68 | added 50 packages from 37 contributors and audited 50 packages in 1.967s 69 | found 0 vulnerabilities 70 | ``` 71 | 72 | Your micro's `endpoint` will be different from the output shown above. This `endpoint` will be the webhook URL when you set up your webhooks. 73 | 74 | 6. You can also see that the `http_auth` is `enabled` by default. We will disable the `http_auth` so that webhook events can be sent to the micro. 75 | 76 | ```shell 77 | $ deta auth disable 78 | Successfully disabled http auth 79 | ``` 80 | 81 | :::note 82 | Usually for security, a secret token is shared between the sender and the receiver and a hmac signature is calculated from the payload and the shared secret. The algorithm to calculate the signature varies based on the sender. You should consult the documentation of how the signature is calculated for the system you are receiving events from. 83 | ::: 84 | 85 | 7. Add a `POST` route to `index.js`. Most webhook callbacks send a `POST` request on the webhook URL with the payload containing information about the event that triggered the webhook. 86 | 87 | Open `index.js` and add the handler to handle webhook events. 88 | 89 | ```javascript 90 | const express = require('express'); 91 | 92 | const app = express(); 93 | 94 | // a POST route for our webhook events 95 | app.post('/', (req, res) => { 96 | // verify signature if needed 97 | // add your logic to handle the request 98 | res.send("ok"); 99 | }); 100 | 101 | // you only need to export your app for the deta micro. You don't need to start the server on a port. 102 | module.exports = app; 103 | ``` 104 | 105 | 8. Deploy your changes with `deta deploy`. 106 | 107 | ```shell 108 | $ deta deploy 109 | Successfully deployed changes 110 | ``` 111 | 112 | Your micro will now trigger on `POST` requests to the micro's endpoint. Use your micro's endpoint as the webhook URL when you set up your webhooks elsewhere. 113 | 114 | In order to see the logs when the webhook is triggered, you can use `deta visor` to see real-time logs of your application. You can also replay your webhook events from `deta visor` to debug any issues. 115 | 116 | You can open your visor page with the command `deta visor open` from the cli. 117 | 118 | 119 | 120 | 121 | We are going to use `fastapi` with our Deta Micro and deploy a simple `python` webhook server. 122 | 123 | 1. Create a directory `fastapi-webhook` and change the current directory to it. 124 | 125 | ```shell 126 | $ mkdir fastapi-webhook && cd fastapi-webhook 127 | ``` 128 | 129 | 2. Create an empty `main.py` file (we will add the code that handles the logic later). 130 | 131 | 3. Create a `requirements.txt` file and add `fastapi` as a dependency. 132 | 133 | ``` 134 | fastapi 135 | ``` 136 | 137 | 5. Create a new `python` micro with `deta new`. This will create a new `python` micro for you and automatically install `fastapi` as a dependency. 138 | 139 | ```shell 140 | $ deta new 141 | Successfully created a new micro 142 | { 143 | "name": "fastapi-webhook", 144 | "runtime": "python3.7", 145 | "endpoint": "https://{micro_name}.deta.dev", 146 | "visor": "enabled", 147 | "http_auth": "enabled" 148 | } 149 | Adding dependencies... 150 | Collecting fastapi 151 | ... 152 | Successfully installed fastapi-0.61.1 pydantic-1.6.1 starlette-0.13.6 153 | ``` 154 | 155 | Your micro's `endpoint` will be different from the output shown above. This `endpoint` will be the webhook URL when you set up your webhooks. 156 | 157 | 6. You can also see that the `http_auth` is `enabled` by default. We will disable the `http_auth` so that webhook events can be sent to the micro. 158 | 159 | ```shell 160 | $ deta auth disable 161 | Successfully disabled http auth 162 | ``` 163 | 164 | :::note 165 | Usually for security, a secret token is shared between the sender and the receiver and a hmac signature is calculated from the payload and the shared secret. The algorithm to calculate the signature varies based on the sender. You should consult the documentation of how the signature is calculated for the system you are receiving events from. 166 | ::: 167 | 168 | 7. Add a `POST` route to `main.py`. Most webhook callbacks send a `POST` request on the webhook URL with the payload containing information about the event that triggered the webhook. 169 | 170 | Open `main.py` and add the handler to handle webhook events. 171 | 172 | ```python 173 | from fastapi import FastAPI, Request 174 | 175 | app = FastAPI() 176 | 177 | # a POST route for our webhook events 178 | @app.post("/") 179 | def webhook_handler(req: Request): 180 | # verify signature if needed 181 | # add logic to handle the request 182 | return "ok" 183 | ``` 184 | 185 | 8. Deploy your changes with `deta deploy`. 186 | 187 | ```shell 188 | $ deta deploy 189 | Successfully deployed changes 190 | ``` 191 | 192 | Your micro will now trigger on `POST` requests to the micro's endpoint. Use your micro's endpoint as the webhook URL when you set up your webhooks elsewhere. 193 | 194 | In order to see the logs of when the webhook is triggered, you can use `deta visor` to see real-time logs of your application. You can also replay your webhook events from `deta visor` to debug any issues. 195 | 196 | You can open your visor page with the command `deta visor open` from the cli. 197 | 198 | 199 | 200 | -------------------------------------------------------------------------------- /docusaurus.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | title: 'Deta Docs', 3 | tagline: 'Deta Library and HTTP API docs.', 4 | url: 'https://docs.deta.sh', 5 | baseUrl: '/', 6 | favicon: 'img/logo.svg', 7 | organizationName: 'Deta', 8 | projectName: 'deta-docs', 9 | themeConfig: { 10 | navbar: { 11 | title: 'Deta', 12 | logo: { 13 | alt: 'Deta Logo', 14 | src: 'img/logo.svg', 15 | href: 'https://deta.sh', 16 | }, 17 | items: [ 18 | { 19 | to: 'docs/home', 20 | activeBasePath: 'docs', 21 | label: 'Docs', 22 | position: 'left', 23 | }, 24 | { 25 | href: 'https://github.com/deta/docs', 26 | label: 'GitHub', 27 | position: 'right', 28 | }, 29 | ], 30 | }, 31 | algolia: { 32 | apiKey: '4b3aaec0466a855ce8ec420d3baedde3', 33 | indexName: 'deta', 34 | }, 35 | footer: { 36 | style: 'light', 37 | links: [ 38 | { 39 | title: 'Community', 40 | items: [ 41 | { 42 | label: 'Discord', 43 | href: 'https://go.deta.dev/discord', 44 | }, 45 | { 46 | label: 'Twitter', 47 | href: 'https://twitter.com/detahq', 48 | }, 49 | ], 50 | }, 51 | { 52 | title: 'More', 53 | items: [ 54 | { 55 | label: 'Blog', 56 | href: 'https://blog.deta.sh/', 57 | }, 58 | { 59 | label: 'GitHub', 60 | href: 'https://github.com/deta/', 61 | }, 62 | ], 63 | }, 64 | ], 65 | copyright: `Copyright © ${new Date().getFullYear()} Abstract Computing UG (haftungsbeschränkt). `, 66 | }, 67 | announcementBar: { 68 | id: 'announcement', 69 | content: 70 | 'Deta Cloud is now a part of Deta Space. We will support Deta Cloud projects until May 1, 2023. Learn more about migrating here', 71 | backgroundColor: '#F478B3', 72 | textColor: '#fff', 73 | isCloseable: false, 74 | }, 75 | }, 76 | presets: [ 77 | [ 78 | '@docusaurus/preset-classic', 79 | { 80 | docs: { 81 | sidebarPath: require.resolve('./sidebars.js'), 82 | // Please change this to your repo. 83 | editUrl: 84 | 'https://github.com/deta/docs/tree/master/', 85 | }, 86 | theme: { 87 | customCss: require.resolve('./src/css/custom.css'), 88 | }, 89 | }, 90 | ], 91 | ], 92 | stylesheets: [ 93 | 'https://fonts.googleapis.com/css2?family=IBM+Plex+Mono&family=Karla&display=swap', 94 | ], 95 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docs", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "docusaurus start", 7 | "build": "docusaurus build", 8 | "swizzle": "docusaurus swizzle", 9 | "deploy": "docusaurus deploy" 10 | }, 11 | "dependencies": { 12 | "@docusaurus/core": "^2.0.0-alpha.69", 13 | "@docusaurus/preset-classic": "^2.0.0-alpha.69", 14 | "classnames": "^2.2.6", 15 | "react": "^16.14.0", 16 | "react-dom": "^16.14.0" 17 | }, 18 | "browserslist": { 19 | "production": [ 20 | ">0.2%", 21 | "not dead", 22 | "not op_mini all" 23 | ], 24 | "development": [ 25 | "last 1 chrome version", 26 | "last 1 firefox version", 27 | "last 1 safari version" 28 | ] 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /sidebars.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | someSidebar: { 3 | General: ['home', 'faqs', 'common_issues'], 4 | ["Deta Base"]: ['base/about', 'base/sdk', 'base/http', 'base/queries', 'base/base_ui', 'base/expiring_items', 'base/node_tutorial', 'base/py_tutorial'], 5 | ["Deta Drive"]: ['drive/about', 'drive/sdk', 'drive/http', 'drive/drive_ui', 'drive/py_tutorial', 'drive/node_tutorial'], 6 | ["Deta Micros"]: ['micros/about', 'micros/getting_started', 'micros/deploy', 'micros/cron', 7 | 'micros/custom_domains', 'micros/env_vars', 'micros/api_keys', 'micros/visor', 'micros/deploy_to_deta_button', 'micros/faqs_micros'], 8 | ["Deta CLI"]: ['cli/install', 'cli/auth', 'cli/commands', 'cli/releases'], 9 | ["Quick Start"]: ['tutorials/fast-api-guide', 'tutorials/webhooks-guide', 'tutorials/cron-guide', 'tutorials/form-endpoints-guide'], 10 | ["Other"]: ['base/async_sdk'], 11 | }, 12 | }; 13 | -------------------------------------------------------------------------------- /src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/src/.DS_Store -------------------------------------------------------------------------------- /src/css/custom.css: -------------------------------------------------------------------------------- 1 | /* stylelint-disable docusaurus/copyright-header */ 2 | /** 3 | * Any CSS included here will be global. The classic template 4 | * bundles Infima by default. Infima is a CSS framework designed to 5 | * work well for content-centric websites. 6 | */ 7 | 8 | /* You can override the default Infima variables here. */ 9 | 10 | 11 | 12 | 13 | 14 | body { 15 | font-family: 'Karla', -apple-system, BlinkMacSystemFont, 'avenir next', avenir, helvetica, 'helvetica neue', ubuntu, roboto, noto, 'segoe ui', arial, sans-serif; 16 | } 17 | 18 | h2 { 19 | margin-top: 3rem !important; 20 | } 21 | 22 | h3 { 23 | margin-top: 2.5rem !important; 24 | } 25 | 26 | h4 { 27 | margin-top: 1.5rem !important; 28 | } 29 | 30 | :root { 31 | --ifm-color-primary: #3884ff; 32 | --ifm-color-primary-dark: #2c69cc; 33 | --ifm-color-primary-darker: #214f99; 34 | --ifm-color-primary-darkest: #163466; 35 | --ifm-color-primary-light: #5f9cff; 36 | --ifm-color-primary-lighter: #87b5ff; 37 | --ifm-color-primary-lightest: #afcdff; 38 | --ifm-code-font-size: 95%; 39 | --ifm-font-family-monospace: "IBM Plex Mono", SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; 40 | --ifm-global-radius: 0.25rem !important; 41 | } 42 | 43 | .twentypx { 44 | height: 20px; 45 | } 46 | 47 | 48 | 49 | 50 | .codeBlockLines_node_modules-\@docusaurus-theme-classic-lib-theme-CodeBlock-, .codeBlockLines_b7E3 { 51 | background-color: #163466 !important; 52 | } 53 | 54 | html[data-theme="dark"] { 55 | --ifm-color-emphasis-0: var(--ifm-color-gray-1000); 56 | --ifm-color-emphasis-100: var(--ifm-color-gray-900); 57 | --ifm-color-emphasis-200: var(--ifm-color-gray-800); 58 | --ifm-color-emphasis-300: var(--ifm-color-gray-700); 59 | --ifm-color-emphasis-400: var(--ifm-color-gray-600); 60 | --ifm-color-emphasis-500: var(--ifm-color-gray-500); 61 | --ifm-color-emphasis-600: var(--ifm-color-gray-400); 62 | --ifm-color-emphasis-700: var(--ifm-color-gray-300); 63 | --ifm-color-emphasis-800: var(--ifm-color-gray-200); 64 | --ifm-color-emphasis-900: var(--ifm-color-gray-100); 65 | --ifm-color-emphasis-1000: var(--ifm-color-gray-0); 66 | --ifm-background-color: #1B1B23; 67 | --ifm-background-surface-color: #20232B; 68 | --ifm-hover-overlay: rgba(255, 255, 255, 0.05); 69 | --ifm-menu-link-sublist-icon: url('data:image/svg+xml;utf8,'); 70 | --ifm-color-content-secondary: #D6D6D6; 71 | --ifm-color-emphasis-100: #20232B !important; 72 | } 73 | -------------------------------------------------------------------------------- /src/pages/.index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import classnames from 'classnames'; 3 | import Layout from '@theme/Layout'; 4 | import Link from '@docusaurus/Link'; 5 | import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; 6 | import useBaseUrl from '@docusaurus/useBaseUrl'; 7 | import styles from './styles.module.css'; 8 | 9 | const features = [ 10 | { 11 | title: <>Easy to Use, 12 | imageUrl: 'img/undraw_docusaurus_mountain.svg', 13 | description: ( 14 | <> 15 | Docusaurus was designed from the ground up to be easily installed and 16 | used to get your website up and running quickly. 17 | 18 | ), 19 | }, 20 | { 21 | title: <>Focus on What Matters, 22 | imageUrl: 'img/undraw_docusaurus_tree.svg', 23 | description: ( 24 | <> 25 | Docusaurus lets you focus on your docs, and we'll do the chores. Go 26 | ahead and move your docs into the docs directory. 27 | 28 | ), 29 | }, 30 | { 31 | title: <>Powered by React, 32 | imageUrl: 'img/undraw_docusaurus_react.svg', 33 | description: ( 34 | <> 35 | Extend or customize your website layout by reusing React. Docusaurus can 36 | be extended while reusing the same header and footer. 37 | 38 | ), 39 | }, 40 | ]; 41 | 42 | function Feature({ imageUrl, title, description }) { 43 | const imgUrl = useBaseUrl(imageUrl); 44 | return ( 45 |
46 | {imgUrl && ( 47 |
48 | {title} 49 |
50 | )} 51 |

{title}

52 |

{description}

53 |
54 | ); 55 | } 56 | 57 | function Home() { 58 | const context = useDocusaurusContext(); 59 | const { siteConfig = {} } = context; 60 | return ( 61 | 64 |
65 |
66 |

{siteConfig.title}

67 |

{siteConfig.tagline}

68 |
69 | 75 | Get Started 76 | 77 |
78 |
79 |
80 |
81 | {features && features.length && ( 82 |
83 |
84 |
85 | {features.map((props, idx) => ( 86 | 87 | ))} 88 |
89 |
90 |
91 | )} 92 |
93 |
94 | ); 95 | } 96 | 97 | export default Home; 98 | -------------------------------------------------------------------------------- /src/pages/styles.module.css: -------------------------------------------------------------------------------- 1 | /* stylelint-disable docusaurus/copyright-header */ 2 | /** 3 | * CSS files with the .module.css suffix will be treated as CSS modules 4 | * and scoped locally. 5 | */ 6 | 7 | .heroBanner { 8 | padding: 4rem 0; 9 | text-align: center; 10 | position: relative; 11 | overflow: hidden; 12 | } 13 | 14 | @media screen and (max-width: 966px) { 15 | .heroBanner { 16 | padding: 2rem; 17 | } 18 | } 19 | 20 | .buttons { 21 | display: flex; 22 | align-items: center; 23 | justify-content: center; 24 | } 25 | 26 | .features { 27 | display: flex; 28 | align-items: center; 29 | padding: 2rem 0; 30 | width: 100%; 31 | } 32 | 33 | .featureImage { 34 | height: 200px; 35 | width: 200px; 36 | } 37 | -------------------------------------------------------------------------------- /static/img/base_ui/base_ui_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/base_ui/base_ui_1.png -------------------------------------------------------------------------------- /static/img/base_ui/base_ui_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/base_ui/base_ui_2.png -------------------------------------------------------------------------------- /static/img/base_ui/base_ui_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/base_ui/base_ui_3.png -------------------------------------------------------------------------------- /static/img/base_ui/base_ui_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/base_ui/base_ui_4.png -------------------------------------------------------------------------------- /static/img/base_ui/base_ui_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/base_ui/base_ui_5.png -------------------------------------------------------------------------------- /static/img/base_ui/base_ui_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/base_ui/base_ui_6.png -------------------------------------------------------------------------------- /static/img/base_ui/base_ui_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/base_ui/base_ui_7.png -------------------------------------------------------------------------------- /static/img/base_ui/base_ui_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/base_ui/base_ui_8.png -------------------------------------------------------------------------------- /static/img/deploy_button/button.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /static/img/deploy_button/deta-topic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/deploy_button/deta-topic.png -------------------------------------------------------------------------------- /static/img/domains/custom_domain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/domains/custom_domain.png -------------------------------------------------------------------------------- /static/img/drive/drive-py-tut-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/drive/drive-py-tut-1.png -------------------------------------------------------------------------------- /static/img/drive/drive-py-tut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/drive/drive-py-tut.png -------------------------------------------------------------------------------- /static/img/drive/drive_ui/drive_ui_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/drive/drive_ui/drive_ui_1.png -------------------------------------------------------------------------------- /static/img/drive/drive_ui/drive_ui_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/drive/drive_ui/drive_ui_2.png -------------------------------------------------------------------------------- /static/img/drive/drive_ui/drive_ui_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/drive/drive_ui/drive_ui_3.png -------------------------------------------------------------------------------- /static/img/drive/drive_ui/drive_ui_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/drive/drive_ui/drive_ui_4.png -------------------------------------------------------------------------------- /static/img/drive/drive_ui/drive_ui_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/drive/drive_ui/drive_ui_5.png -------------------------------------------------------------------------------- /static/img/drive/drive_ui/drive_ui_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/drive/drive_ui/drive_ui_6.png -------------------------------------------------------------------------------- /static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/favicon.ico -------------------------------------------------------------------------------- /static/img/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /static/img/quickstart/contact_form.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/quickstart/contact_form.png -------------------------------------------------------------------------------- /static/img/undraw_docusaurus_tree.svg: -------------------------------------------------------------------------------- 1 | docu_tree -------------------------------------------------------------------------------- /static/img/visor/visor_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/visor/visor_1.png -------------------------------------------------------------------------------- /static/img/visor/visor_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/visor/visor_10.png -------------------------------------------------------------------------------- /static/img/visor/visor_11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/visor/visor_11.png -------------------------------------------------------------------------------- /static/img/visor/visor_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/visor/visor_2.png -------------------------------------------------------------------------------- /static/img/visor/visor_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/visor/visor_3.png -------------------------------------------------------------------------------- /static/img/visor/visor_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/visor/visor_4.png -------------------------------------------------------------------------------- /static/img/visor/visor_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/visor/visor_5.png -------------------------------------------------------------------------------- /static/img/visor/visor_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/visor/visor_6.png -------------------------------------------------------------------------------- /static/img/visor/visor_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/visor/visor_7.png -------------------------------------------------------------------------------- /static/img/visor/visor_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/visor/visor_8.png -------------------------------------------------------------------------------- /static/img/visor/visor_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/deta/cloud-docs/02fb7b73319eb39e2fc8a973c38296f58697e1db/static/img/visor/visor_9.png -------------------------------------------------------------------------------- /static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | Deta Docs 11 | 12 | 13 | 14 | If you are not redirected automatically, follow this 15 | link. 16 | 17 | 18 | --------------------------------------------------------------------------------