Skip to main content

typescript

The Project

This guide explains how to create a simple command line application that utilizes the Squid Client SDK with a Squid backend. The application will read input from the command line and perform basic database operations based on user input.

Reading command line input

To begin customizing the client, we first need to read input from the command line. Create a readInput() function, which will have the squid object we initialized in the previous step as a parameter. We will use the readline module in order to read user input. The readInput() function will recursively call itself and read input until the user chooses to exit the program. We will execute the main() function at the bottom of the file:

Client code
import { Squid } from '@squidcloud/client';
import * as readline from 'readline';

const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});

function main() {
const squid = new Squid({
appId: 'YOUR_APP_ID',
region: 'YOUR_REGION', // example: 'us-east-1.aws'
environmentId: 'dev | prod', // choose one of 'dev' or 'prod'
squidDeveloperId: 'YOUR_SQUID_DEVELOPER_ID',
});

readInput(squid);
}

function readInput(squid: Squid) {
rl.question('Usage [exit / insert / read / update / delete]: ', (input) => {
if (input.toLowerCase() === 'exit') {
rl.close();
process.exit(0);
} else if (input.toLowerCase() === 'insert') {
console.log('Insert placeholder');
readInput(squid);
} else {
console.log('Please select a recognized command');
readInput(squid);
}
});
}

main();

Insert

Squid organizes data into collections and documents. Documents are individual records in the database (such as rows in a table), while collections are groups of documents (like tables themselves, but unstructured). To access a Squid collection, use the collection() method with the collection name as the first parameter.

To create a new document in Typescript, use the insert() method on a document reference. Document references can be initialized with a document ID, which you can learn more about in our documentation. Create a new insertUser() function:

Client code
import * as crypto from 'crypto';

...

function insertUser(name: string, squid: Squid) {
type User = { id: string; name: string; age: number };
const userId = crypto.randomUUID();

squid
.collection<User>('users') // users collection
.doc(userId) // docId = userId
.insert({
id: userId,
name,
age: Math.ceil(Math.random() * 100),
})
.then(() => console.log("New user created"))
.catch((err) => console.error("Error creating user: ", err));
}

Read

Squid provides a robust and powerful query system. To simply get a reference to the collection of users from Squid, there are multiple different options which suit different use cases, such as subscribing to changes in the collection or accessing it a single time. In our case, we will use the dereference() method to receive the document data directly. Create a readUsers() function:

Client code
function readUsers(squid: Squid) {
type User = { id: string; name: string; age: number };

squid
.collection<User>('users')
.query()
.dereference()
.snapshot()
.then((user) => {
console.log(user);
});
}

Now that we have the ability to insert into and read the collection, we can begin to test our application. Here is the code example in index.ts up to this point. Note that we will wrap the body of the readInput() function in a timeout so that output is printed in the correct order:

Client code
import { Squid } from '@squidcloud/client';
import * as readline from 'readline';
import * as crypto from 'crypto';

const rl = ...

function main() {
const squid = ...

readInput(squid);
}

function readInput(squid: Squid) {
setTimeout(() => {
rl.question('Usage [exit / insert / read / update / delete]: ', (input) => {
if (input.toLowerCase() === 'exit') {
rl.close();
process.exit(0);
} else if (input.toLowerCase() === 'insert') {
rl.question('Name: ', (name) => {
insertUser(name, squid);
readInput(squid);
})
} else if (input.toLowerCase() === 'read') {
readUsers(squid);
readInput(squid);
} else {
console.log("Please select a recognized command");
readInput(squid);
}
})
}, 1500)
}

function insertUser(name: string, squid: Squid) {
...
}

function readUsers(squid: Squid) {
...
}

And here is example usage of the app:

Update

To update a document in the collection, we call the update() method on a DocumentReference and pass in an object that contains the partial update data as an argument. To do so, we will create an updateUser() function which will update a user's name and/or age:

Client code
function updateUser(squid: Squid, id: string, name?: string, age?: number) {
type User = { id: string; name: string; age: number };

let updateObj;

// updateObj should be partial or complete
if (name && age) {
updateObj = { name, age };
} else if (name) {
updateObj = { name };
} else if (age) {
updateObj = { age };
} else {
console.log('Please update either a name or age');
return;
}

squid
.collection<User>('users')
.doc(id)
.update(updateObj)
.then(() => console.log(`User ${id} updated`))
.catch((err) => console.error(`Error updating user ${id}: `, err));
}

Next, we can update readInput() to execute the update function. To use the update function, you can copy a user's id after executing the read command:

Client code
function readInput(squid: Squid) {
setTimeout(() => {
rl.question('Usage [exit / insert / read / update / delete]: ', (input) => {
if (input.toLowerCase() === 'exit') {
...
} else if (input.toLowerCase() === 'insert') {
...
} else if (input.toLowerCase() === 'read') {
...
} else if (input.toLowerCase() === 'update') {
rl.question('Id: ', (id) => {
rl.question('Name: ', (name) => {
rl.question('Age: ', (age) => {
updateUser(squid, id, name, parseInt(age));
readInput(squid);
})
})
})
} else {
...
}
})
}, 1500)
}

Delete

To delete a document, you can call the delete() method on a DocumentReference. Create a deleteUser() function, which takes in an id as the second parameter:

Client code
function deleteUser(squid: Squid, id: string) {
type User = { id: string; name: string; age: number };

squid
.collection<User>('users')
.doc(id)
.delete()
.then(() => console.log(`User ${id} deleted`))
.catch((err) => console.error(`Error deleting user ${id}: `, err));
}

Next, update readInput() to execute the delete function:

Client code
function readInput(squid: Squid) {
setTimeout(() => {
rl.question('Usage [exit / insert / read / update / delete]: ', (input) => {
if (input.toLowerCase() === 'exit') {
...
} else if (input.toLowerCase() === 'insert') {
...
} else if (input.toLowerCase() === 'read') {
...
} else if (input.toLowerCase() === 'update') {
...
} else if (input.toLowerCase() === 'delete') {
rl.question('Id: ', (id) => {
deleteUser(squid, id);
readInput(squid);
})
} else {
...
}
})
}, 1500)
}

After completing delete, we are now able to use Squid’s built in database service to accomplish all the major functionality that is required in a database. Here is the final index.ts file:

Client code
import { Squid } from '@squidcloud/client';
import * as readline from 'readline';
import * as crypto from 'crypto';

const rl = ...

function main() {
const squid = ...

readInput(squid);
}

function readInput(squid: Squid) {
setTimeout(() => {
rl.question('Usage [exit / insert / read / update / delete]: ', (input) => {
if (input.toLowerCase() === 'exit') {
rl.close();
process.exit(0);
} else if (input.toLowerCase() === 'insert') {
rl.question('Name: ', (name) => {
insertUser(name, squid);
readInput(squid);
})
} else if (input.toLowerCase() === 'read') {
readUsers(squid);
readInput(squid);
} else if (input.toLowerCase() === 'update') {
rl.question('Id: ', (id) => {
rl.question('Name: ', (name) => {
rl.question('Age: ', (age) => {
updateUser(squid, id, name, parseInt(age));
readInput(squid);
})
})
})
} else if (input.toLowerCase() === 'delete') {
rl.question('Id: ', (id) => {
deleteUser(squid, id);
readInput(squid);
})
} else {
console.log("Please select a recognized command");
readInput(squid);
}
})
}, 1500)
}

function insertUser(name: string, squid: Squid) {
...
}

function readUsers(squid: Squid) {
...
}

function updateUser(squid: Squid, id: string, name?: string, age?: number) {
...
}

function deleteUser(squid: Squid, id: string) {
...
}

main();

Next steps

Congratulations on completing the tutorial! To learn about key features of the Squid backend including security functionality, view the Backend SDK documentation. To learn about the functionality of the Squid Client SDK including more complex data queries, managing secrets, and interacting with your storage buckets, view the Client SDK documentation.