├── slides.pdf ├── .config └── httpie │ └── config.json ├── README.md ├── .vscode └── settings.json ├── .gitpod.yml ├── .tours ├── setup.tour ├── api-rest.tour └── api-document.tour └── Dockerfile /slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datastaxdevs/apiworld-stargate-tour/main/slides.pdf -------------------------------------------------------------------------------- /.config/httpie/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "default_options": [ 3 | "--style=fruity", 4 | "--auth-type=astra", 5 | "--auth=default:" 6 | ] 7 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # API World Stargate Tour 2 | 3 | Just open the course in Gitpod to get started: 4 | 5 | [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/synedra/apiworld-stargate-tour) 6 | 7 | [View the slides](https://github.com/synedra/apiworld-stargate-tour/blob/main/slides.pdf) 8 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "workbench.editor.enablePreviewFromCodeNavigation": true, 3 | "workbench.editor.enablePreviewFromQuickOpen": true, 4 | "workbench.editor.enablePreview": true, 5 | "workbench.editorAssociations": { 6 | "*.md": "vscode.markdown.preview.editor" 7 | }, 8 | "auto-run-command.rules": [ 9 | { 10 | "command": "codetour.startTour" 11 | } 12 | ] 13 | } 14 | 15 | -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | image: 2 | file: Dockerfile 3 | 4 | vscode: 5 | extensions: 6 | - vsls-contrib.codetour 7 | - auchenberg.vscode-browser-preview 8 | - synedra.auto-run-command 9 | 10 | checkoutLocation: "." 11 | 12 | github: 13 | prebuilds: 14 | master: true 15 | branches: true 16 | pullRequests: true 17 | pullRequestsFromForks: false 18 | addCheck: true 19 | addComment: false 20 | addBadge: true 21 | addLabel: false 22 | ports: 23 | - port: 8888 24 | onOpen: open-preview 25 | visibility: public 26 | - port: 3000 27 | onOpen: ignore 28 | visibility: public 29 | - port: 8443 30 | onOpen: ignore 31 | visibility: public 32 | -------------------------------------------------------------------------------- /.tours/setup.tour: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://aka.ms/codetour-schema", 3 | "title": "1. Setup Astra", 4 | "nextTour": "2. REST API", 5 | "steps": [ 6 | { 7 | "title": "Authentication", 8 | "description": "## Initial Setup\n\n*Note: `astra-setup` requires an authentication token, and will guide you on how to generate this in your Astra DB dashboard.*\n\n**RUN**\n>> astra-setup workshops stargate\n\n[Visit Astra](https://dtsx.io/3nmAYf4) and follow the instructions in the console to get your token for the astra-setup step. Note that on October 28 during API World you will receive a $25 gift card for signing up!\n\n![Image of Yaktocat](https://github.com/datastaxdevs/workshop-spring-stargate/raw/main/images/tutorials/astra-create-db.gif?raw=true)\n" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gitpod/workspace-full 2 | 3 | USER root 4 | 5 | RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo gpg --dearmor -o /usr/share/keyrings/githubcli-archive-keyring.gpg 6 | RUN echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null 7 | 8 | RUN set -ex; \ 9 | apt-get update; \ 10 | apt-get upgrade -y && \ 11 | apt-get install -y --no-install-recommends \ 12 | chromium-chromedriver \ 13 | vim \ 14 | python3 \ 15 | gh 16 | 17 | RUN apt-get clean 18 | RUN curl -L https://deb.nodesource.com/setup_16.x | bash \ 19 | && apt-get update -yq \ 20 | && apt-get install nodejs 21 | RUN npm install -g astra-setup netlify-cli axios 22 | 23 | RUN sed -i.bkp -e 's/%sudo\s\+ALL=(ALL\(:ALL\)\?)\s\+ALL/%sudo ALL=NOPASSWD:ALL/g' /etc/sudoers 24 | RUN chmod 777 /usr/lib/node_modules/astra-setup/node_modules/node-jq/bin/jq 25 | RUN chown -R gitpod:gitpod /workspace 26 | 27 | # COPY --chown=gitpod:gitpod /root/config/.bashrc /home/gitpod/.bashrc.d/999-datastax 28 | USER gitpod 29 | RUN mkdir -p /home/gitpod/.config/httpie 30 | COPY .config/httpie/config.json /home/gitpod/.config/httpie 31 | RUN pip3 install httpie-astra 32 | 33 | EXPOSE 8888 34 | EXPOSE 8443 35 | EXPOSE 3000 36 | -------------------------------------------------------------------------------- /.tours/api-rest.tour: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://aka.ms/codetour-schema", 3 | "title": "2. REST API", 4 | "nextTour": "3. Document API", 5 | "steps": [ 6 | { 7 | "title": "REST API", 8 | "description": "## REST API\n\nThe REST API accesses resources by endpoint, with additional instructions through POST body where needed\n\nThis feels very similar to CQL access, but can be accessed via any HTTP client code\n\nFront end developers are most familiar with this type of interface.\n" 9 | }, 10 | { 11 | "title": "REST API - Create table", 12 | "description": "## REST API - Create Table\n\nWe'll work through the process of creating a table, adding some rows, editing and deleting them and then deleting the table, to see what the calls look like using HTTP.\n\nThe table will be called \"cavemen\" and it will have three fields:\n* Firstname\n* Lastname\n* Occupation\n\nThe partitioning (primary) key will be lastname and the clustering (ordering) key will be firstname.\n\nThe whole call looks like this:\n\n``` json\nhttp POST :/rest/v2/schemas/keyspaces/stargate/tables json:='{\n \"name\": \"cavemen\",\n \"ifNotExists\": false,\n \"columnDefinitions\": [\n {\n \"name\": \"firstname\",\n \"typeDefinition\": \"text\",\n \"static\": false\n },\n {\n \"name\": \"lastname\",\n \"typeDefinition\": \"text\",\n \"static\": false\n },\n {\n \"name\": \"occupation\",\n \"typeDefinition\": \"text\"\n }\n ],\n \"primaryKey\": {\n \"partitionKey\": [\n \"lastname\"\n ],\n \"clusteringKey\": [\n \"firstname\"\n ]\n }\n}'\n```\n\n>> http POST :/rest/v2/schemas/keyspaces/stargate/tables json:='{\"name\": \"cavemen\", \"ifNotExists\": false, \"columnDefinitions\": [{ \"name\": \"firstname\",\"typeDefinition\": \"text\", \"static\": false},{\"name\": \"lastname\",\"typeDefinition\": \"text\",\"static\": false},{\"name\": \"occupation\",\"typeDefinition\": \"text\"}],\"primaryKey\": {\"partitionKey\": [\"lastname\"],\"clusteringKey\": [\"firstname\"]}}'\n\nTo make sure it was created, let's check the list of tables we have:\n\n>> http :/rest/v2/schemas/keyspaces/stargate/tables\n\n" 13 | }, 14 | { 15 | "title": "REST API - Add Some Rows", 16 | "description": "## REST API - Add Some Rows\n\nWe've got a table but it's empty - let's put some cavemen in our cavemen table.\n\n>> http POST :/rest/v2/keyspaces/stargate/cavemen json:='{\"firstname\" : \"Fred\", \"lastname\": \"Flintstone\"}'\n\n>> http POST :/rest/v2/keyspaces/stargate/cavemen json:='{\"firstname\" : \"Barney\", \"lastname\": \"Rubble\"}'\n\nTo make sure they made it in, we can do a simple search on the database:\n\n>> http :/rest/v2/keyspaces/stargate/cavemen where=='{\"lastname\":{\"$in\":[\"Rubble\",\"Flintstone\"]}}'" 17 | }, 18 | { 19 | "title": "REST API - Update Rows", 20 | "description": "## REST API - Update Rows\n\nFred is driving Wilma crazy, so she needs him to get a job. Give him one by updating the row.\n\n>> http PUT :/rest/v2/keyspaces/stargate/cavemen/Flintstone/Fred json:='{ \"occupation\": \"Quarry Screamer\"}'\n\nCheck our work: \n\n>> http :/rest/v2/keyspaces/stargate/cavemen where=='{\"lastname\":{\"$in\":[\"Rubble\",\"Flintstone\"]}}' " 21 | }, 22 | { 23 | "title": "REST API - Delete Rows", 24 | "description": "## REST API - Delete Rows\n\nNow Fred has a job but Barney's kind of useless. Let's delete him from the database. Notice that here we're addressing Barney by the partition key (lastname) and the clustering key (firstname).\n\n>> http DELETE :/rest/v2/keyspaces/stargate/cavemen/Rubble/Barney\n\nSo wait, is he gone?\n\n>> http :/rest/v2/keyspaces/stargate/cavemen/Rubble/Barney" 25 | }, 26 | { 27 | "title": "REST API - Delete Table", 28 | "description": "## REST API - Delete Table\n\nLet's clear out this table so we can use it again for the other APIs.\n\n>> http DELETE :/rest/v2/schemas/keyspaces/stargate/tables/cavemen\n\nDouble checking - what tables are in my keyspace?\n\n>> http :/rest/v2/schemas/keyspaces/stargate/tables" 29 | }, 30 | { 31 | "title": "Back to the slides", 32 | "description": "Time to get back to the slides to move on to the Document API." 33 | } 34 | ], 35 | "ref": "main" 36 | } -------------------------------------------------------------------------------- /.tours/api-document.tour: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://aka.ms/codetour-schema", 3 | "title": "3. Document API", 4 | "steps": [ 5 | { 6 | "title": "Document API", 7 | "description": "## Document API\n\n* Similar to MongoDB\n* No schema required\n* Upload structured JSON objects to collections\n* Access data based on values within the objects\n" 8 | }, 9 | { 10 | "title": "Document API - Create table", 11 | "file": ".env", 12 | "description": "## Document API - Create Table\n\nWe'll work through the process of creating a table, adding some rows, editing and deleting them and then deleting the table, to see what the calls look like using HTTP.\n\nCheck to see what keyspaces we have available:\n\n>> http :/rest/v2/schemas/namespaces | jq \".data[].name\"\n\nHey, look! There's our friend 'stargate'. A namespace is just a different way to organize data, and your keyspace is right there. In fact, your keyspace should be in your environment variables, but just to check, look in the open file to see what ASTRA_DB_KEYSPACE is set to.\n\nIf that says \"stargate\" you're good to go, you'll get that for free as the KS placeholder in the queries. If not, go ahead and change it to 'stargate.'" 13 | }, 14 | { 15 | "title": "Document API - Add Some Rows", 16 | "description": "## Document API - Add Some Rows\n\nOK, let's get some cavemen in there! The collection name will be auto-created when you add the document, so it doesn't have to exist ahead of time. We'll use the KS shortcut to grab the keyspace from our credentials resource file.\n\n>> http POST :/rest/v2/namespaces/KS/collections/cavemen json:='{\"firstname\": \"Fred\", \"lastname\": \"Flintstone\"}'\n\nHmm, that document ID isn't easy to use, let's go ahead and specify one explicitly for Barney.\n\n>> http PUT :/rest/v2/namespaces/KS/collections/cavemen/BarneyRubble json:='{\"firstname\": \"Barney\", \"lastname\": \"Rubble\"}'\n\nLet's make sure our documents were written correctly:\n\n>> http :/rest/v2/namespaces/KS/collections/cavemen page-size==5\n\nIF you know the ID of your document, it's easy to see what's there:\n\n>> http :/rest/v2/namespaces/KS/collections/cavemen/BarneyRubble\n\nBut where is Fred? I didn't write down his document ID! You can get the Document ID for anything by querying the values in the document.\n\n>> http GET :/rest/v2/namespaces/KS/collections/cavemen where=='{\"firstname\": { \"$eq\": \"Fred\"}}'\n\nThe \"where\" clause is really powerful, and allows you to combine different elements to really zero in on the document you want.\n\nYou can even get just a subset of the document by specifying a particular section in the path. Let's just get Barney's first name.\n\n>> http :/rest/v2/namespaces/KS/collections/cavemen/BarneyRubble/firstname\n\nand you can use \"where\" to specify a range of documents:\n\n>> http GET :/rest/v2/namespaces/KS/collections/cavemen/BarneyRubble where:='{\"lastname\": {\"$gt\": \"Flintstone\"}}'" 17 | }, 18 | { 19 | "title": "Document API - Update Rows", 20 | "description": "## Document API - Update Rows\n\nSo now we have Fred and Barney, but once again we haven't given Fred a job. He just annoys Wilma when he hangs out at home, so that won't do at all.\n\nHere's how you give Fred a job and get him out of Wilma's hair. Remember, we just got his ID a few commands ago. Let's grab it again and set it in the environment so we can use it as we like.\n\nFirst, get your documentId.\n\n>> export DOCUMENT_ID=`http :/rest/v2/namespaces/KS/collections/cavemen where=='{\"firstname\": { \"$eq\": \"Fred\"}}'`\n\nAgain, giving Fred a job. Wilma thanks you.\n\n>> http PATCH :/rest/v2/namespaces/KS/collections/cavemen/$DOCUMENT_ID json:='{\"firstname\":\"Fred\",\"lastname\":\"flintstone\",\"occupation\":\"Quarry Screamer\"}'\n\nSo, how's Fred looking now?\n\n>> http GET :/rest/v2/namespaces/KS/collections/cavemen/$DOCUMENT_ID" 21 | }, 22 | { 23 | "title": "Document API - Delete Rows", 24 | "description": "## Document API - Delete Table\n\nNow Fred has a job but Barney's kind of useless. Let's delete him from the database. Notice that here we're addressing Barney by the partition key (lastname) and the clustering key (firstname).\n\nhttp DELETE :/rest/v2/namespaces/KS/collections/cavemen/BarneyRubble\n\nBut what if you're done with all the cavemen and want to clear out your documents? This one is also really easy:\n\nhttp DELETE :/rest/v2/namespaces/KS/collections/cavemen" 25 | }, 26 | { 27 | "title": "Back to the slides", 28 | "description": "Time to get back to the slides to move on to the GraphQL API." 29 | } 30 | ], 31 | "ref": "main" 32 | } --------------------------------------------------------------------------------