Share
Explore

The TypeScript Bookstore

This lab creates a TypeScript Application to run the run the Business Domain of a Book store.
By the time you have completed this Lab, you will have:
Learned how to program directly in TypeScript.
Learned how run your TypeScript Program directly at the Command Line.
Your Program Hand In is going to be to send me the URL of your Project on - Here in this Lab you will learn how to do npm -publish to make your project available to the World on NPMjs.com. (You will have a live URL you can put in Resume and LINKEDIN). Next week we will see how to make a README markdown formatted document to present your project and business domain in the polished, visually appealing way.

This Document contains a template document you can replicate to do your own Project.

See also:

megaphone
Here I will create a TypeScript application modeling a bookstore with several classes, demonstrating shared field composition and object interaction via method calls.
I'll provide you with two UML diagrams:
a Class Diagram showing the structure of the classes and their relationships, and
a Sequence Diagram illustrating the object interactions.

1. Class Diagram:

image.png

Explanation: - The Bookstore class has composition relationships (filled diamond) with Book, Customer, and Order. - The Order class has an association with Customer and a composition relationship with Book. - All classes have their respective attributes and methods listed.
2. Sequence Diagram:
image.png
Explanation: (This is your ‘use cases’)
- The sequence starts with creating a Bookstore instance.
- Books and Customers are added to the Bookstore.
- An Order is created for a Customer.
- Books are added to the Order, which updates the Book's stock.
- Finally, displayInfo() methods are called to show the state of various objects.

These diagrams provide a visual representation of the class structure and object interactions in the bookstore application. The Class Diagram shows the static structure and relationships between classes, while the Sequence Diagram illustrates the dynamic interactions between objects over time.

info
I'll include detailed explanatory comments to help students understand the code structure and concepts.
Here's a TypeScript application that models a bookstore:
error
tsconfig.json
{
"compilerOptions": {
"target": "es2015",
"lib": ["es2015", "dom"],
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"outDir": "./dist",
"rootDir": "./",
"declaration": true
},
"include": [
"./**/*.ts"
],
"exclude": [
"node_modules"
]
}


// bookstore.ts : One File into which goes all of my Code

class Book {
constructor(
public id: string,
public title: string,
public author: string,
public price: number,
public stock: number
) {}

displayInfo(): void {
console.log(`${this.title} by ${this.author} - $${this.price} (${this.stock} in stock)`);
}
}

class Customer {
constructor(
public id: string,
public name: string,
public email: string
) {}

displayInfo(): void {
console.log(`Customer: ${this.name} (${this.email})`);
}
}

class Order {
private _books: { book: Book; quantity: number }[] = [];
private _totalPrice: number = 0;

constructor(
public id: string,
public customer: Customer
) {}

addBook(book: Book, quantity: number): void {
if (book.stock >= quantity) {
let existingBookIndex = -1;
for (let i = 0; i < this._books.length; i++) {
if (this._books[i].book.id === book.id) {
existingBookIndex = i;
break;
}
}
if (existingBookIndex !== -1) {
this._books[existingBookIndex].quantity += quantity;
} else {
this._books.push({ book, quantity });
}
this._totalPrice += book.price * quantity;
book.stock -= quantity;
} else {
throw new Error("Not enough stock");
}
}

displayInfo(): void {
console.log(`Order ${this.id} for:`);
this.customer.displayInfo();
console.log("Books ordered:");
this._books.forEach(({ book, quantity }) => {
console.log(` ${quantity}x ${book.title}`);
});
console.log(`Total Price: $${this._totalPrice.toFixed(2)}`);
}
}

class Bookstore {
private _inventory: Book[] = [];
private _customers: Customer[] = [];
private _orders: Order[] = [];

constructor(public name: string) {}

addBook(book: Book): void {
this._inventory.push(book);
}

addCustomer(customer: Customer): void {
this._customers.push(customer);
}

createOrder(customer: Customer): Order {
const order = new Order(`ORD-${this._orders.length + 1}`, customer);
this._orders.push(order);
return order;
}

displayInfo(): void {
console.log(`Welcome to ${this.name}!`);
console.log(`We have ${this._inventory.length} books in stock.`);
console.log(`We have served ${this._customers.length} customers.`);
console.log(`We have processed ${this._orders.length} orders.`);
}
}

// Main application logic
const myBookstore = new Bookstore("TypeScript Bookstore");

const book1 = new Book("B001", "TypeScript in Action", "John Doe", 29.99, 50);
const book2 = new Book("B002", "Node.js Essentials", "Jane Smith", 24.99, 30);
myBookstore.addBook(book1);
myBookstore.addBook(book2);

const customer1 = new Customer("C001", "Alice Johnson", "alice@example.com");
const customer2 = new Customer("C002", "Bob Williams", "bob@example.com");
myBookstore.addCustomer(customer1);
myBookstore.addCustomer(customer2);

const order1 = myBookstore.createOrder(customer1);
order1.addBook(book1, 2);
order1.addBook(book2, 1);

const order2 = myBookstore.createOrder(customer2);
order2.addBook(book2, 3);

console.log("Bookstore Information:");
myBookstore.displayInfo();

console.log("\nOrder Information:");
order1.displayInfo();
console.log();
order2.displayInfo();

console.log("\nUpdated Book Stock:");
book1.displayInfo();
book2.displayInfo();

This TypeScript application models a bookstore with the following classes:
1. `Book`: Represents a book in the inventory.
2. `Customer`: Represents a customer of the bookstore.
3. `Order`: Represents an order placed by a customer.
4. `Bookstore`: Manages the overall bookstore operations.

The application demonstrates:
- Shared field composition:
The `Bookstore` class contains arrays of `Book`, `Customer`, and `Order` objects.
- Object interaction via method calls:
Methods like `addBook`, `createOrder`, and `displayInfo` show how objects interact.
- Encapsulation: Private fields with getter and setter methods.
- Type safety: TypeScript's static typing helps prevent errors.

To use this code in Visual Studio Code:

1. Create a new directory for your project.
2. Open the directory in Visual Studio Code.
3. Create a new file named `bookstore.ts`.
4. Paste the entire code into `bookstore.ts`.
5. Install TypeScript if you haven't already: `npm install -g typescript`
6. Compile the TypeScript code: `tsc bookstore.ts`
7. Run the compiled JavaScript: `node bookstore.js`
This example provides a comprehensive demonstration of object-oriented programming concepts in TypeScript, suitable for teaching students about class composition, interaction, and TypeScript's features in the context of a real-world scenario.

info

The tsconfig.json file: You need a tsconfig.json file to configure the TypeScript compiler settings, especially when using features like Map that require ES2015 or later.


error

Going to the Metal: TypeScript Application


Now I will provide instructions on how to use the typescript npmjs.com package to compile this typescript to sandalone execution typescript

Learning Outcomes:

Guide the process of using TypeScript with npm to compile and run your bookstore application as a standalone executable.

Here's a step-by-step guide:
Initialize a new npm project: Open your terminal, navigate to your project directory, and run:
npm init -y
This creates a package.json file.
Install TypeScript and ts-node:
npm install --save-dev typescript ts-node
TypeScript is the compiler, and ts-node allows you to run TypeScript files directly.
Install @types/node for TypeScript declarations:
npm install --save-dev @types/node
Create a TypeScript configuration file:
Create a file named tsconfig.json in your project root:
{
"compilerOptions": {
"target": "ES2018",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src/**/*"]
}
Organize your project:
**—- Create a src folder and move your bookstore.ts file into it.
Update your package.json: Add these scripts to your package.json:
"scripts": {
"start": "ts-node src/bookstore.ts",
"build": "tsc",
"exec": "node dist/bookstore.js"
}
Run your TypeScript application: You can now run your application directly with:
npm start

image.png

Compile to JavaScript: To compile your TypeScript to JavaScript, run:
npm run build
This will create a dist folder with the compiled JavaScript.
Run the compiled JavaScript: After building, you can run the compiled JavaScript with:
npm run exec


(Optional) Create a standalone executable: If you want to create a standalone executable, you can use a tool like pkg. First, install it:

npm install --save-dev pkg
Then add this script to your package.json:
"scripts": {
...
"package": "pkg ."
}
Update your package.json to include:
"bin": "dist/bookstore.js",
"pkg": {
"targets": [
"node14-win-x64",
"node14-macos-x64",
"node14-linux-x64"
],
"outputPath": "executable"
}
Now you can create executables with:
npm run package
This will create executables for Windows, macOS, and Linux in an executable folder.

With these steps, you've set up a TypeScript project that can be:
- run directly
compiled to JavaScript,
packaged as a standalone executable.

This approach demonstrates how to use npm packages to enhance the development workflow for TypeScript applications.

Remember to explain to your students the benefits of going TypeScript:
Type checking during development
Easy execution of TypeScript files
Compilation to JavaScript for broader compatibility
Option to create standalone executables for distribution
This process showcases a professional development workflow that students might encounter in real-world TypeScript projects.

megaphone

The Last Mile:

Now let's do the last mile: present instructions on how to publish this project on npmjs.com


Publishing your project on npmjs.com is indeed the last mile in sharing your work with the wider JavaScript community.
Here's a step-by-step guide on how to publish your TypeScript bookstore project on npmjs.com:
Ensure your package.json is properly configured:
Open your package.json and make sure it includes:
{
"name": "your-unique-package-name",
"version": "1.0.0",
"description": "A TypeScript bookstore management system",
"main": "dist/bookstore.js",
"types": "dist/bookstore.d.ts",
"files": [
"dist"
],
"scripts": {
"build": "tsc",
"prepublishOnly": "npm run build"
},
"keywords": ["bookstore", "typescript", "management"],
"author": "Your Name",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/yourusername/your-repo.git"
}
}
Replace placeholders with your actual information.
Create a README.md file: This file should explain what your package does, how to install it, and how to use it.
Update your tsconfig.json: Ensure it includes:
{
"compilerOptions": {
// ... other options ...
"declaration": true
}
}
This generates .d.ts files for TypeScript users of your package.
Create a .npmignore file: This file specifies which files should not be included in your npm package:

tsconfig.json
.gitignore
Build your project:
npm run build

Create an npm account: If you don't have one, go to npmjs.com and sign up.
Log in to npm via terminal:
npm login
Enter your npm username, password, and email when prompted.
Publish your package:
npm publish
image.png
finding your repos on npmjscom.gif

If your package name is already taken, you'll need to choose a different name in your package.json.
Verify your package: Go to npmjs.com/package/your-package-name to see your published package.
Update your package (for future versions): When you make changes:
Update the version in package.json (e.g., "1.0.1")
Run npm run build
Run npm publish
(Optional) Set up two-factor authentication: For added security, enable 2FA on your npm account.
Additional best practices to explain to students:
Semantic Versioning: Explain the importance of following semantic versioning (MAJOR.MINOR.PATCH).
Testing: Implement unit tests (e.g., with Jest) and add a "test" script to package.json.
Continuous Integration: Set up CI/CD pipelines (e.g., with GitHub Actions) to automate testing and publishing.
Documentation: Maintain comprehensive documentation, including JSDoc comments in your code.
Licensing: Choose and include an appropriate open-source license.
Code of Conduct: Include a CODE_OF_CONDUCT.md file to set community guidelines.
Contributing Guidelines: Add a CONTRIBUTING.md file to guide potential contributors.
Changelog: Maintain a CHANGELOG.md to track version changes.
Publishing to npm teaches valuable lessons about package management, versioning, and sharing code with the community. It's a great way to introduce students to real-world JavaScript/TypeScript development practices.
Remember to emphasize the responsibility that comes with publishing packages, including maintaining the package, addressing issues, and following npm's best practices and policies.
Want to print your doc?
This is not the way.
Try clicking the ⋯ next to your doc name or using a keyboard shortcut (
CtrlP
) instead.