@dbos-inc/create 3.0.38-preview.g835773f00f → 3.0.42-preview
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/templates/dbos-drizzle/dbos-config.yaml +2 -3
- package/templates/dbos-drizzle/drizzle/0000_dbos.sql +10 -0
- package/templates/dbos-drizzle/package.json +4 -2
- package/templates/dbos-drizzle/src/{operations.test.ts → main.test.ts} +2 -3
- package/templates/dbos-drizzle/src/main.ts +111 -0
- package/templates/dbos-knex/dbos-config.yaml +0 -1
- package/templates/dbos-knex/migrations/000_dbos_schema.js +9 -0
- package/templates/dbos-knex/package.json +1 -0
- package/templates/dbos-knex/src/main.test.ts +4 -2
- package/templates/dbos-knex/src/main.ts +27 -3
- package/templates/dbos-prisma/dbos-config.yaml +2 -3
- package/templates/dbos-prisma/package.json +3 -1
- package/templates/dbos-prisma/prisma/migrations/000_transaction_completions/migration.sql +10 -0
- package/templates/dbos-prisma/src/{operations.test.ts → main.test.ts} +2 -3
- package/templates/dbos-prisma/src/main.ts +109 -0
- package/templates/dbos-typeorm/dbos-config.yaml +2 -3
- package/templates/dbos-typeorm/migrations/1714934318135-DBOSTransactionCompletions.ts +16 -0
- package/templates/dbos-typeorm/package.json +3 -1
- package/templates/dbos-typeorm/src/{operations.test.ts → main.test.ts} +2 -3
- package/templates/dbos-typeorm/src/main.ts +109 -0
- package/templates/dbos-drizzle/src/operations.ts +0 -57
- package/templates/dbos-prisma/src/operations.ts +0 -58
- package/templates/dbos-typeorm/src/operations.ts +0 -56
package/package.json
CHANGED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
CREATE SCHEMA IF NOT EXISTS dbos;
|
|
2
|
+
|
|
3
|
+
CREATE TABLE IF NOT EXISTS dbos.transaction_completion (
|
|
4
|
+
workflow_id TEXT NOT NULL,
|
|
5
|
+
function_num INT NOT NULL,
|
|
6
|
+
output TEXT,
|
|
7
|
+
error TEXT,
|
|
8
|
+
created_at BIGINT NOT NULL DEFAULT (EXTRACT(EPOCH FROM now())*1000)::bigint,
|
|
9
|
+
PRIMARY KEY (workflow_id, function_num)
|
|
10
|
+
);
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"@dbos-inc/eslint-plugin": "^3.3.4",
|
|
14
14
|
"@types/jest": "^29.5.12",
|
|
15
15
|
"@types/supertest": "^2.0.16",
|
|
16
|
-
"drizzle-kit": "^0.
|
|
16
|
+
"drizzle-kit": "^0.31.4",
|
|
17
17
|
"eslint": "^8.57.0",
|
|
18
18
|
"jest": "^29.7.0",
|
|
19
19
|
"nodemon": "^3.1.0",
|
|
@@ -23,6 +23,8 @@
|
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@dbos-inc/dbos-sdk": "file:../../../..",
|
|
26
|
-
"drizzle-
|
|
26
|
+
"@dbos-inc/drizzle-datasource": "file:../../../drizzle-datasource",
|
|
27
|
+
"drizzle-orm": "^0.44.3",
|
|
28
|
+
"express": "^4.21.2"
|
|
27
29
|
}
|
|
28
30
|
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { DBOS } from '@dbos-inc/dbos-sdk';
|
|
2
|
-
import { Hello } from './
|
|
2
|
+
import { app, Hello } from './main';
|
|
3
3
|
import request from 'supertest';
|
|
4
4
|
|
|
5
5
|
describe('operations-test', () => {
|
|
6
6
|
beforeAll(async () => {
|
|
7
7
|
await DBOS.launch();
|
|
8
|
-
await DBOS.launchAppHTTPServer();
|
|
9
8
|
});
|
|
10
9
|
|
|
11
10
|
afterAll(async () => {
|
|
@@ -28,7 +27,7 @@ describe('operations-test', () => {
|
|
|
28
27
|
* Test the HTTP endpoint.
|
|
29
28
|
*/
|
|
30
29
|
test('test-endpoint', async () => {
|
|
31
|
-
const res = await request(
|
|
30
|
+
const res = await request(app).get('/greeting/dbos');
|
|
32
31
|
expect(res.statusCode).toBe(200);
|
|
33
32
|
expect(res.text).toMatch('Hello, dbos! We have made');
|
|
34
33
|
});
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// Welcome to DBOS!
|
|
2
|
+
|
|
3
|
+
// This is the Quickstart Drizzle template app. It greets visitors, counting how many total greetings were made.
|
|
4
|
+
// To learn how to run this app, visit the Drizzle tutorial: https://docs.dbos.dev/tutorials/using-drizzle
|
|
5
|
+
|
|
6
|
+
import express, { Request, Response } from 'express';
|
|
7
|
+
import { DBOS } from '@dbos-inc/dbos-sdk';
|
|
8
|
+
import { dbosHello } from './schema';
|
|
9
|
+
|
|
10
|
+
import { DrizzleDataSource } from '@dbos-inc/drizzle-datasource';
|
|
11
|
+
import { NodePgDatabase } from 'drizzle-orm/node-postgres';
|
|
12
|
+
|
|
13
|
+
const config = {
|
|
14
|
+
host: process.env.PGHOST || 'localhost',
|
|
15
|
+
port: parseInt(process.env.PGPORT || '5432'),
|
|
16
|
+
database: process.env.PGDATABASE || 'dbos_drizzle',
|
|
17
|
+
user: process.env.PGUSER || 'postgres',
|
|
18
|
+
password: process.env.PGPASSWORD || 'dbos',
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const drizzleds = new DrizzleDataSource<NodePgDatabase>('app-db', config);
|
|
22
|
+
|
|
23
|
+
export class Hello {
|
|
24
|
+
// This transaction uses DBOS and drizzle to perform database operations.
|
|
25
|
+
@drizzleds.transaction()
|
|
26
|
+
static async helloTransaction(user: string) {
|
|
27
|
+
const greeting = `Hello, ${user}!`;
|
|
28
|
+
const greetings_output = await drizzleds.client
|
|
29
|
+
.insert(dbosHello)
|
|
30
|
+
.values({ greeting })
|
|
31
|
+
.returning({ greet_count: dbosHello.greet_count });
|
|
32
|
+
const greeting_message = `${greeting} We have made ${greetings_output[0].greet_count} greetings.`;
|
|
33
|
+
return makeHTML(greeting_message);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Let's create an HTML + CSS Readme for our app.
|
|
38
|
+
function readme() {
|
|
39
|
+
return makeHTML(
|
|
40
|
+
`Visit the route <code class="bg-gray-100 px-1 rounded">/greeting/{name}</code> to be greeted!<br>
|
|
41
|
+
For example, visit <code class="bg-gray-100 px-1 rounded"><a href="/greeting/Mike" class="text-blue-600 hover:underline">/greeting/Mike</a></code><br>
|
|
42
|
+
The counter increments with each page visit.`,
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function makeHTML(message: string) {
|
|
47
|
+
const page =
|
|
48
|
+
`
|
|
49
|
+
<!DOCTYPE html>
|
|
50
|
+
<html lang="en">
|
|
51
|
+
<head>
|
|
52
|
+
<title>DBOS Template App</title>
|
|
53
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
54
|
+
</head>
|
|
55
|
+
<body class="font-sans text-gray-800 p-6 max-w-2xl mx-auto">
|
|
56
|
+
<h1 class="text-3xl font-semibold mb-4">Welcome to DBOS!</h1>
|
|
57
|
+
<p class="mt-8 mb-8">` +
|
|
58
|
+
message +
|
|
59
|
+
`</p>
|
|
60
|
+
<p class="mb-2">
|
|
61
|
+
To learn how to run this app yourself, visit our
|
|
62
|
+
<a href="https://docs.dbos.dev/quickstart?language=typescript" class="text-blue-600 hover:underline">Quickstart</a>.
|
|
63
|
+
</p><p class="mb-2">
|
|
64
|
+
Then, to learn how to build crashproof apps, continue to our
|
|
65
|
+
<a href="https://docs.dbos.dev/typescript/programming-guide" class="text-blue-600 hover:underline">Programming Guide</a>.<br>
|
|
66
|
+
</p>
|
|
67
|
+
</body>
|
|
68
|
+
</html>`;
|
|
69
|
+
return page;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Let's create an HTTP server using Express.js
|
|
73
|
+
export const app = express();
|
|
74
|
+
app.use(express.json());
|
|
75
|
+
|
|
76
|
+
// Serve the Readme from the root path
|
|
77
|
+
app.get('/', (req: Request, res: Response) => {
|
|
78
|
+
res.send(readme());
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// Serve the transaction from the /greeting/:name path
|
|
82
|
+
app.get('/greeting/:name', (req: Request, res: Response) => {
|
|
83
|
+
const { name } = req.params;
|
|
84
|
+
Hello.helloTransaction(name)
|
|
85
|
+
.then((result) => res.send(result))
|
|
86
|
+
.catch((error) => {
|
|
87
|
+
console.error(error);
|
|
88
|
+
res.status(500).send('Internal Server Error');
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Finally, launch DBOS and start the server
|
|
93
|
+
async function main() {
|
|
94
|
+
DBOS.setConfig({
|
|
95
|
+
name: 'dbos-drizzle',
|
|
96
|
+
databaseUrl: process.env.DBOS_DATABASE_URL,
|
|
97
|
+
});
|
|
98
|
+
await DBOS.launch({ expressApp: app });
|
|
99
|
+
const PORT = parseInt(process.env.NODE_PORT || '3000');
|
|
100
|
+
const ENV = process.env.NODE_ENV || 'development';
|
|
101
|
+
|
|
102
|
+
app.listen(PORT, () => {
|
|
103
|
+
console.log(`🚀 Server is running on http://localhost:${PORT}`);
|
|
104
|
+
console.log(`🌟 Environment: ${ENV}`);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Only start the server when this file is run directly from Node
|
|
109
|
+
if (require.main === module) {
|
|
110
|
+
main().catch(console.log);
|
|
111
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DBOS } from '@dbos-inc/dbos-sdk';
|
|
2
|
-
import { app,
|
|
2
|
+
import { app, Hello } from './main';
|
|
3
3
|
import request from 'supertest';
|
|
4
4
|
|
|
5
5
|
describe('operations-test', () => {
|
|
@@ -15,11 +15,13 @@ describe('operations-test', () => {
|
|
|
15
15
|
* Test the transaction.
|
|
16
16
|
*/
|
|
17
17
|
test('test-transaction', async () => {
|
|
18
|
+
await Hello.deleteUser('dbos');
|
|
19
|
+
|
|
18
20
|
const res = await Hello.helloTransaction('dbos');
|
|
19
21
|
expect(res).toMatch('Hello, dbos! You have been greeted');
|
|
20
22
|
|
|
21
23
|
// Check the greet count.
|
|
22
|
-
const rows =
|
|
24
|
+
const rows = await Hello.getCount('dbos');
|
|
23
25
|
expect(rows[0].greet_count).toBe(1);
|
|
24
26
|
});
|
|
25
27
|
|
|
@@ -5,6 +5,20 @@
|
|
|
5
5
|
|
|
6
6
|
import express, { Request, Response } from 'express';
|
|
7
7
|
import { DBOS } from '@dbos-inc/dbos-sdk';
|
|
8
|
+
import { KnexDataSource } from '@dbos-inc/knex-datasource';
|
|
9
|
+
|
|
10
|
+
const config = {
|
|
11
|
+
client: 'pg',
|
|
12
|
+
connection: {
|
|
13
|
+
host: process.env.PGHOST || 'localhost',
|
|
14
|
+
port: parseInt(process.env.PGPORT || '5432'),
|
|
15
|
+
database: process.env.PGDATABASE || 'dbos_knex',
|
|
16
|
+
user: process.env.PGUSER || 'postgres',
|
|
17
|
+
password: process.env.PGPASSWORD || 'dbos',
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const knexds = new KnexDataSource('app-db', config);
|
|
8
22
|
|
|
9
23
|
export interface dbos_hello {
|
|
10
24
|
name: string;
|
|
@@ -14,15 +28,25 @@ export interface dbos_hello {
|
|
|
14
28
|
export class Hello {
|
|
15
29
|
// This transaction uses DBOS and Knex to perform database operations.
|
|
16
30
|
// It retrieves and increments the number of times a user has been greeted.
|
|
17
|
-
@
|
|
31
|
+
@knexds.transaction()
|
|
18
32
|
static async helloTransaction(user: string) {
|
|
19
33
|
const query =
|
|
20
34
|
'INSERT INTO dbos_hello (name, greet_count) VALUES (?, 1) ON CONFLICT (name) DO UPDATE SET greet_count = dbos_hello.greet_count + 1 RETURNING greet_count;';
|
|
21
|
-
const { rows } = (await
|
|
35
|
+
const { rows } = (await knexds.client.raw(query, [user])) as { rows: dbos_hello[] };
|
|
22
36
|
const greet_count = rows[0].greet_count;
|
|
23
37
|
const greeting = `Hello, ${user}! You have been greeted ${greet_count} times.`;
|
|
24
38
|
return makeHTML(greeting);
|
|
25
39
|
}
|
|
40
|
+
|
|
41
|
+
@knexds.transaction({ readOnly: true })
|
|
42
|
+
static async getCount(user: string) {
|
|
43
|
+
return await knexds.client<dbos_hello>('dbos_hello').where({ name: user }).select('*');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
@knexds.transaction()
|
|
47
|
+
static async deleteUser(user: string) {
|
|
48
|
+
await knexds.client<dbos_hello>('dbos_hello').where({ name: user }).delete();
|
|
49
|
+
}
|
|
26
50
|
}
|
|
27
51
|
|
|
28
52
|
// Let's create an HTML + CSS Readme for our app.
|
|
@@ -87,7 +111,7 @@ async function main() {
|
|
|
87
111
|
databaseUrl: process.env.DBOS_DATABASE_URL,
|
|
88
112
|
});
|
|
89
113
|
await DBOS.launch({ expressApp: app });
|
|
90
|
-
const PORT = 3000;
|
|
114
|
+
const PORT = parseInt(process.env.NODE_PORT || '3000');
|
|
91
115
|
const ENV = process.env.NODE_ENV || 'development';
|
|
92
116
|
|
|
93
117
|
app.listen(PORT, () => {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
CREATE SCHEMA IF NOT EXISTS dbos;
|
|
2
|
+
|
|
3
|
+
CREATE TABLE IF NOT EXISTS dbos.transaction_completion (
|
|
4
|
+
workflow_id TEXT NOT NULL,
|
|
5
|
+
function_num INT NOT NULL,
|
|
6
|
+
output TEXT,
|
|
7
|
+
error TEXT,
|
|
8
|
+
created_at BIGINT NOT NULL DEFAULT (EXTRACT(EPOCH FROM now())*1000)::bigint,
|
|
9
|
+
PRIMARY KEY (workflow_id, function_num)
|
|
10
|
+
);
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { DBOS } from '@dbos-inc/dbos-sdk';
|
|
2
|
-
import { Hello } from './
|
|
2
|
+
import { app, Hello } from './main';
|
|
3
3
|
import request from 'supertest';
|
|
4
4
|
|
|
5
5
|
describe('operations-test', () => {
|
|
6
6
|
beforeAll(async () => {
|
|
7
7
|
await DBOS.launch();
|
|
8
|
-
await DBOS.launchAppHTTPServer();
|
|
9
8
|
});
|
|
10
9
|
|
|
11
10
|
afterAll(async () => {
|
|
@@ -16,7 +15,7 @@ describe('operations-test', () => {
|
|
|
16
15
|
* Test the HTTP endpoint.
|
|
17
16
|
*/
|
|
18
17
|
test('test-greet', async () => {
|
|
19
|
-
const res = await request(
|
|
18
|
+
const res = await request(app).get('/greeting/dbos');
|
|
20
19
|
expect(res.statusCode).toBe(200);
|
|
21
20
|
expect(res.text).toMatch('Greeting 1: Hello, dbos!');
|
|
22
21
|
expect(await Hello.helloTransaction('bob')).toMatch('Greeting 2: Hello, bob!');
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// Welcome to DBOS!
|
|
2
|
+
|
|
3
|
+
// This is the Quickstart Prisma template app. It greets visitors, counting how many total greetings were made.
|
|
4
|
+
// To learn how to run this app, visit the Prisma tutorial: https://docs.dbos.dev/tutorials/using-prisma
|
|
5
|
+
|
|
6
|
+
import express, { Request, Response } from 'express';
|
|
7
|
+
import { DBOS } from '@dbos-inc/dbos-sdk';
|
|
8
|
+
|
|
9
|
+
import { PrismaClient } from '@prisma/client';
|
|
10
|
+
import { PrismaDataSource } from '@dbos-inc/prisma-datasource';
|
|
11
|
+
|
|
12
|
+
process.env['DATABASE_URL'] =
|
|
13
|
+
process.env['DATABASE_URL'] ||
|
|
14
|
+
`postgresql://${process.env.PGUSER || 'postgres'}:${process.env.PGPASSWORD || 'dbos'}@${process.env.PGHOST || 'localhost'}:${process.env.PGPORT || '5432'}/${process.env.PGDATABASE || 'dbos_prisma'}`;
|
|
15
|
+
|
|
16
|
+
const prismaClient = new PrismaClient();
|
|
17
|
+
|
|
18
|
+
const dataSource = new PrismaDataSource<PrismaClient>('app-db', prismaClient);
|
|
19
|
+
|
|
20
|
+
export class Hello {
|
|
21
|
+
// This transaction uses DBOS and prisma to perform database operations.
|
|
22
|
+
@dataSource.transaction()
|
|
23
|
+
static async helloTransaction(name: string) {
|
|
24
|
+
const greeting = `Hello, ${name}!`;
|
|
25
|
+
const res = await dataSource.client.dbosHello.create({
|
|
26
|
+
data: {
|
|
27
|
+
greeting: greeting,
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
const greeting_note = `Greeting ${res.greeting_id}: ${greeting}`;
|
|
31
|
+
return makeHTML(greeting_note);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Let's create an HTML + CSS Readme for our app.
|
|
36
|
+
function readme() {
|
|
37
|
+
return makeHTML(
|
|
38
|
+
`Visit the route <code class="bg-gray-100 px-1 rounded">/greeting/{name}</code> to be greeted!<br>
|
|
39
|
+
For example, visit <code class="bg-gray-100 px-1 rounded"><a href="/greeting/Mike" class="text-blue-600 hover:underline">/greeting/Mike</a></code><br>
|
|
40
|
+
The counter increments with each page visit.`,
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function makeHTML(message: string) {
|
|
45
|
+
const page =
|
|
46
|
+
`
|
|
47
|
+
<!DOCTYPE html>
|
|
48
|
+
<html lang="en">
|
|
49
|
+
<head>
|
|
50
|
+
<title>DBOS Template App</title>
|
|
51
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
52
|
+
</head>
|
|
53
|
+
<body class="font-sans text-gray-800 p-6 max-w-2xl mx-auto">
|
|
54
|
+
<h1 class="text-3xl font-semibold mb-4">Welcome to DBOS!</h1>
|
|
55
|
+
<p class="mt-8 mb-8">` +
|
|
56
|
+
message +
|
|
57
|
+
`</p>
|
|
58
|
+
<p class="mb-2">
|
|
59
|
+
To learn how to run this app yourself, visit our
|
|
60
|
+
<a href="https://docs.dbos.dev/quickstart?language=typescript" class="text-blue-600 hover:underline">Quickstart</a>.
|
|
61
|
+
</p><p class="mb-2">
|
|
62
|
+
Then, to learn how to build crashproof apps, continue to our
|
|
63
|
+
<a href="https://docs.dbos.dev/typescript/programming-guide" class="text-blue-600 hover:underline">Programming Guide</a>.<br>
|
|
64
|
+
</p>
|
|
65
|
+
</body>
|
|
66
|
+
</html>`;
|
|
67
|
+
return page;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Let's create an HTTP server using Express.js
|
|
71
|
+
export const app = express();
|
|
72
|
+
app.use(express.json());
|
|
73
|
+
|
|
74
|
+
// Serve the Readme from the root path
|
|
75
|
+
app.get('/', (req: Request, res: Response) => {
|
|
76
|
+
res.send(readme());
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Serve the transaction from the /greeting/:name path
|
|
80
|
+
app.get('/greeting/:name', (req: Request, res: Response) => {
|
|
81
|
+
const { name } = req.params;
|
|
82
|
+
Hello.helloTransaction(name)
|
|
83
|
+
.then((result) => res.send(result))
|
|
84
|
+
.catch((error) => {
|
|
85
|
+
console.error(error);
|
|
86
|
+
res.status(500).send('Internal Server Error');
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// Finally, launch DBOS and start the server
|
|
91
|
+
async function main() {
|
|
92
|
+
DBOS.setConfig({
|
|
93
|
+
name: 'dbos-prisma',
|
|
94
|
+
databaseUrl: process.env.DBOS_DATABASE_URL,
|
|
95
|
+
});
|
|
96
|
+
await DBOS.launch({ expressApp: app });
|
|
97
|
+
const PORT = parseInt(process.env.NODE_PORT || '3000');
|
|
98
|
+
const ENV = process.env.NODE_ENV || 'development';
|
|
99
|
+
|
|
100
|
+
app.listen(PORT, () => {
|
|
101
|
+
console.log(`🚀 Server is running on http://localhost:${PORT}`);
|
|
102
|
+
console.log(`🌟 Environment: ${ENV}`);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Only start the server when this file is run directly from Node
|
|
107
|
+
if (require.main === module) {
|
|
108
|
+
main().catch(console.log);
|
|
109
|
+
}
|
|
@@ -7,11 +7,10 @@ name: dbos-typeorm
|
|
|
7
7
|
language: node
|
|
8
8
|
database_url: ${DBOS_DATABASE_URL}
|
|
9
9
|
database:
|
|
10
|
-
app_db_client: typeorm
|
|
11
10
|
migrate:
|
|
12
11
|
- npx typeorm migration:run -d dist/datasource.js
|
|
13
12
|
rollback:
|
|
14
13
|
- npx typeorm migration:revert -d dist/datasource.js
|
|
15
14
|
runtimeConfig:
|
|
16
|
-
|
|
17
|
-
- dist/src/
|
|
15
|
+
start:
|
|
16
|
+
- node dist/src/main.js
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from 'typeorm';
|
|
2
|
+
|
|
3
|
+
import { createTransactionCompletionSchemaPG, createTransactionCompletionTablePG } from '@dbos-inc/dbos-sdk/datasource';
|
|
4
|
+
|
|
5
|
+
export class DBOSTransactionCompletions1714934318135 implements MigrationInterface {
|
|
6
|
+
name = 'DBOSTransactionCompletions1714934318135';
|
|
7
|
+
|
|
8
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
9
|
+
await queryRunner.query(createTransactionCompletionSchemaPG);
|
|
10
|
+
await queryRunner.query(createTransactionCompletionTablePG);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
14
|
+
await queryRunner.query('DROP SCHEMA IF EXISTS dbos CASCADE');
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { DBOS } from '@dbos-inc/dbos-sdk';
|
|
2
|
-
import { Hello } from './
|
|
2
|
+
import { app, Hello } from './main';
|
|
3
3
|
import request from 'supertest';
|
|
4
4
|
|
|
5
5
|
describe('operations-test', () => {
|
|
6
6
|
beforeAll(async () => {
|
|
7
7
|
await DBOS.launch();
|
|
8
|
-
await DBOS.launchAppHTTPServer();
|
|
9
8
|
});
|
|
10
9
|
|
|
11
10
|
afterAll(async () => {
|
|
@@ -16,7 +15,7 @@ describe('operations-test', () => {
|
|
|
16
15
|
* Test the HTTP endpoint.
|
|
17
16
|
*/
|
|
18
17
|
test('test-greet', async () => {
|
|
19
|
-
const res = await request(
|
|
18
|
+
const res = await request(app).get('/greeting/dbos');
|
|
20
19
|
expect(res.statusCode).toBe(200);
|
|
21
20
|
expect(res.text).toMatch('Greeting 1: Hello, dbos!');
|
|
22
21
|
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// Welcome to DBOS!
|
|
2
|
+
|
|
3
|
+
// This is the Quickstart TypeORM template app. It greets visitors, counting how many total greetings were made.
|
|
4
|
+
// To learn how to run this app, visit the TypeORM tutorial: https://docs.dbos.dev/tutorials/using-typeorm
|
|
5
|
+
|
|
6
|
+
import express, { Request, Response } from 'express';
|
|
7
|
+
import { DBOS } from '@dbos-inc/dbos-sdk';
|
|
8
|
+
import { DBOSHello } from '../entities/DBOSHello';
|
|
9
|
+
|
|
10
|
+
import { TypeOrmDataSource } from '@dbos-inc/typeorm-datasource';
|
|
11
|
+
|
|
12
|
+
const config = {
|
|
13
|
+
host: process.env.PGHOST || 'localhost',
|
|
14
|
+
port: parseInt(process.env.PGPORT || '5432'),
|
|
15
|
+
database: process.env.PGDATABASE || 'dbos_typeorm',
|
|
16
|
+
user: process.env.PGUSER || 'postgres',
|
|
17
|
+
password: process.env.PGPASSWORD || 'dbos',
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const dataSource = new TypeOrmDataSource('app-db', config, [DBOSHello]);
|
|
21
|
+
|
|
22
|
+
export class Hello {
|
|
23
|
+
// This transaction uses DBOS and TypeORM to perform database operations.
|
|
24
|
+
@dataSource.transaction()
|
|
25
|
+
static async helloTransaction(name: string) {
|
|
26
|
+
const greeting = `Hello, ${name}!`;
|
|
27
|
+
let entity = new DBOSHello();
|
|
28
|
+
entity.greeting = greeting;
|
|
29
|
+
entity = await dataSource.entityManager.save(entity);
|
|
30
|
+
const greeting_note = `Greeting ${entity.greeting_id}: ${greeting}`;
|
|
31
|
+
return makeHTML(greeting_note);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Let's create an HTML + CSS Readme for our app.
|
|
36
|
+
function readme() {
|
|
37
|
+
return makeHTML(
|
|
38
|
+
`Visit the route <code class="bg-gray-100 px-1 rounded">/greeting/{name}</code> to be greeted!<br>
|
|
39
|
+
For example, visit <code class="bg-gray-100 px-1 rounded"><a href="/greeting/Mike" class="text-blue-600 hover:underline">/greeting/Mike</a></code><br>
|
|
40
|
+
The counter increments with each page visit.`,
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function makeHTML(message: string) {
|
|
45
|
+
const page =
|
|
46
|
+
`
|
|
47
|
+
<!DOCTYPE html>
|
|
48
|
+
<html lang="en">
|
|
49
|
+
<head>
|
|
50
|
+
<title>DBOS Template App</title>
|
|
51
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
52
|
+
</head>
|
|
53
|
+
<body class="font-sans text-gray-800 p-6 max-w-2xl mx-auto">
|
|
54
|
+
<h1 class="text-3xl font-semibold mb-4">Welcome to DBOS!</h1>
|
|
55
|
+
<p class="mt-8 mb-8">` +
|
|
56
|
+
message +
|
|
57
|
+
`</p>
|
|
58
|
+
<p class="mb-2">
|
|
59
|
+
To learn how to run this app yourself, visit our
|
|
60
|
+
<a href="https://docs.dbos.dev/quickstart?language=typescript" class="text-blue-600 hover:underline">Quickstart</a>.
|
|
61
|
+
</p><p class="mb-2">
|
|
62
|
+
Then, to learn how to build crashproof apps, continue to our
|
|
63
|
+
<a href="https://docs.dbos.dev/typescript/programming-guide" class="text-blue-600 hover:underline">Programming Guide</a>.<br>
|
|
64
|
+
</p>
|
|
65
|
+
</body>
|
|
66
|
+
</html>`;
|
|
67
|
+
return page;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Let's create an HTTP server using Express.js
|
|
71
|
+
export const app = express();
|
|
72
|
+
app.use(express.json());
|
|
73
|
+
|
|
74
|
+
// Serve the Readme from the root path
|
|
75
|
+
app.get('/', (req: Request, res: Response) => {
|
|
76
|
+
res.send(readme());
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Serve the transaction from the /greeting/:name path
|
|
80
|
+
app.get('/greeting/:name', (req: Request, res: Response) => {
|
|
81
|
+
const { name } = req.params;
|
|
82
|
+
Hello.helloTransaction(name)
|
|
83
|
+
.then((result) => res.send(result))
|
|
84
|
+
.catch((error) => {
|
|
85
|
+
console.error(error);
|
|
86
|
+
res.status(500).send('Internal Server Error');
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// Finally, launch DBOS and start the server
|
|
91
|
+
async function main() {
|
|
92
|
+
DBOS.setConfig({
|
|
93
|
+
name: 'dbos-typeorm',
|
|
94
|
+
databaseUrl: process.env.DBOS_DATABASE_URL,
|
|
95
|
+
});
|
|
96
|
+
await DBOS.launch({ expressApp: app });
|
|
97
|
+
const PORT = parseInt(process.env.NODE_PORT || '3000');
|
|
98
|
+
const ENV = process.env.NODE_ENV || 'development';
|
|
99
|
+
|
|
100
|
+
app.listen(PORT, () => {
|
|
101
|
+
console.log(`🚀 Server is running on http://localhost:${PORT}`);
|
|
102
|
+
console.log(`🌟 Environment: ${ENV}`);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Only start the server when this file is run directly from Node
|
|
107
|
+
if (require.main === module) {
|
|
108
|
+
main().catch(console.log);
|
|
109
|
+
}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
// Welcome to DBOS!
|
|
2
|
-
|
|
3
|
-
// This is the Quickstart Drizzle template app. It greets visitors, counting how many total greetings were made.
|
|
4
|
-
// To learn how to run this app, visit the Drizzle tutorial: https://docs.dbos.dev/tutorials/using-drizzle
|
|
5
|
-
|
|
6
|
-
import { DBOS } from '@dbos-inc/dbos-sdk';
|
|
7
|
-
import { dbosHello } from './schema';
|
|
8
|
-
import { NodePgDatabase } from 'drizzle-orm/node-postgres';
|
|
9
|
-
|
|
10
|
-
export class Hello {
|
|
11
|
-
// Serve this function from HTTP GET requests at the /greeting endpoint with 'user' as a path parameter
|
|
12
|
-
@DBOS.getApi('/greeting/:user')
|
|
13
|
-
@DBOS.transaction()
|
|
14
|
-
static async helloTransaction(user: string) {
|
|
15
|
-
const greeting = `Hello, ${user}!`;
|
|
16
|
-
const greetings_output = await (DBOS.drizzleClient as NodePgDatabase)
|
|
17
|
-
.insert(dbosHello)
|
|
18
|
-
.values({ greeting })
|
|
19
|
-
.returning({ greet_count: dbosHello.greet_count });
|
|
20
|
-
const greeting_message = `${greeting} We have made ${greetings_output[0].greet_count} greetings.`;
|
|
21
|
-
return Hello.makeHTML(greeting_message);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Serve a quick readme for the app at the / endpoint
|
|
25
|
-
@DBOS.getApi('/')
|
|
26
|
-
static async readme() {
|
|
27
|
-
const message = Hello.makeHTML(
|
|
28
|
-
`Visit the route <code class="bg-gray-100 px-1 rounded">/greeting/{name}</code> to be greeted!<br>
|
|
29
|
-
For example, visit <code class="bg-gray-100 px-1 rounded"><a href="/greeting/Mike" class="text-blue-600 hover:underline">/greeting/Mike</a></code><br>
|
|
30
|
-
The counter increments with each page visit.`,
|
|
31
|
-
);
|
|
32
|
-
return Promise.resolve(message);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// A helper function to create HTML pages with some styling
|
|
36
|
-
static makeHTML(message: string) {
|
|
37
|
-
const page =
|
|
38
|
-
`
|
|
39
|
-
<!DOCTYPE html>
|
|
40
|
-
<html lang="en">
|
|
41
|
-
<head>
|
|
42
|
-
<title>DBOS Template App</title>
|
|
43
|
-
<script src="https://cdn.tailwindcss.com"></script>
|
|
44
|
-
</head>
|
|
45
|
-
<body class="font-sans text-gray-800 p-6 max-w-2xl mx-auto">
|
|
46
|
-
<h1 class="text-3xl font-semibold mb-4">Welcome to DBOS!</h1>
|
|
47
|
-
<p class="mt-8 mb-8">` +
|
|
48
|
-
message +
|
|
49
|
-
`</p>
|
|
50
|
-
<p class="mb-2">
|
|
51
|
-
This is the Drizzle quickstart template app. Read the documentation for it <a href="https://docs.dbos.dev/typescript/tutorials/using-drizzle" class="text-blue-600 hover:underline">here</a>.
|
|
52
|
-
</p>
|
|
53
|
-
</body>
|
|
54
|
-
</html>`;
|
|
55
|
-
return page;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
// Welcome to DBOS!
|
|
2
|
-
|
|
3
|
-
// This is the Quickstart Prisma template app. It greets visitors, counting how many total greetings were made.
|
|
4
|
-
// To learn how to run this app, visit the Prisma tutorial: https://docs.dbos.dev/tutorials/using-prisma
|
|
5
|
-
|
|
6
|
-
import { DBOS } from '@dbos-inc/dbos-sdk';
|
|
7
|
-
|
|
8
|
-
import { PrismaClient } from '@prisma/client';
|
|
9
|
-
|
|
10
|
-
export class Hello {
|
|
11
|
-
// Serve this function from HTTP GET requests at the /greeting endpoint with 'name' as a path parameter
|
|
12
|
-
@DBOS.getApi('/greeting/:name')
|
|
13
|
-
@DBOS.transaction()
|
|
14
|
-
static async helloTransaction(name: string) {
|
|
15
|
-
const greeting = `Hello, ${name}!`;
|
|
16
|
-
const res = await (DBOS.prismaClient as PrismaClient).dbosHello.create({
|
|
17
|
-
data: {
|
|
18
|
-
greeting: greeting,
|
|
19
|
-
},
|
|
20
|
-
});
|
|
21
|
-
const greeting_note = `Greeting ${res.greeting_id}: ${greeting}`;
|
|
22
|
-
return Hello.makeHTML(greeting_note);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// Serve a quick readme for the app at the / endpoint
|
|
26
|
-
@DBOS.getApi('/')
|
|
27
|
-
static async readme() {
|
|
28
|
-
const message = Hello.makeHTML(
|
|
29
|
-
`Visit the route <code class="bg-gray-100 px-1 rounded">/greeting/{name}</code> to be greeted!<br>
|
|
30
|
-
For example, visit <code class="bg-gray-100 px-1 rounded"><a href="/greeting/Mike" class="text-blue-600 hover:underline">/greeting/Mike</a></code><br>
|
|
31
|
-
The counter increments with each page visit.`,
|
|
32
|
-
);
|
|
33
|
-
return Promise.resolve(message);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// A helper function to create HTML pages with some styling
|
|
37
|
-
static makeHTML(message: string) {
|
|
38
|
-
const page =
|
|
39
|
-
`
|
|
40
|
-
<!DOCTYPE html>
|
|
41
|
-
<html lang="en">
|
|
42
|
-
<head>
|
|
43
|
-
<title>DBOS Template App</title>
|
|
44
|
-
<script src="https://cdn.tailwindcss.com"></script>
|
|
45
|
-
</head>
|
|
46
|
-
<body class="font-sans text-gray-800 p-6 max-w-2xl mx-auto">
|
|
47
|
-
<h1 class="text-3xl font-semibold mb-4">Welcome to DBOS!</h1>
|
|
48
|
-
<p class="mt-8 mb-8">` +
|
|
49
|
-
message +
|
|
50
|
-
`</p>
|
|
51
|
-
<p class="mb-2">
|
|
52
|
-
This is the Prisma quickstart template app. Read the documentation for it <a href="https://docs.dbos.dev/typescript/tutorials/using-prisma" class="text-blue-600 hover:underline">here</a>.
|
|
53
|
-
</p>
|
|
54
|
-
</body>
|
|
55
|
-
</html>`;
|
|
56
|
-
return page;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
// Welcome to DBOS!
|
|
2
|
-
|
|
3
|
-
// This is the Quickstart TypeORM template app. It greets visitors, counting how many total greetings were made.
|
|
4
|
-
// To learn how to run this app, visit the TypeORM tutorial: https://docs.dbos.dev/tutorials/using-typeorm
|
|
5
|
-
|
|
6
|
-
import { DBOS, OrmEntities } from '@dbos-inc/dbos-sdk';
|
|
7
|
-
import { EntityManager } from 'typeorm';
|
|
8
|
-
import { DBOSHello } from '../entities/DBOSHello';
|
|
9
|
-
|
|
10
|
-
@OrmEntities([DBOSHello])
|
|
11
|
-
export class Hello {
|
|
12
|
-
@DBOS.getApi('/greeting/:name')
|
|
13
|
-
@DBOS.transaction()
|
|
14
|
-
static async helloTransaction(name: string) {
|
|
15
|
-
const greeting = `Hello, ${name}!`;
|
|
16
|
-
let entity = new DBOSHello();
|
|
17
|
-
entity.greeting = greeting;
|
|
18
|
-
entity = await (DBOS.typeORMClient as EntityManager).save(entity);
|
|
19
|
-
const greeting_note = `Greeting ${entity.greeting_id}: ${greeting}`;
|
|
20
|
-
return Hello.makeHTML(greeting_note);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// Serve a quick readme for the app at the / endpoint
|
|
24
|
-
@DBOS.getApi('/')
|
|
25
|
-
static async readme() {
|
|
26
|
-
const message = Hello.makeHTML(
|
|
27
|
-
`Visit the route <code class="bg-gray-100 px-1 rounded">/greeting/{name}</code> to be greeted!<br>
|
|
28
|
-
For example, visit <code class="bg-gray-100 px-1 rounded"><a href="/greeting/Mike" class="text-blue-600 hover:underline">/greeting/Mike</a></code><br>
|
|
29
|
-
The counter increments with each page visit.`,
|
|
30
|
-
);
|
|
31
|
-
return Promise.resolve(message);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// A helper function to create HTML pages with some styling
|
|
35
|
-
static makeHTML(message: string) {
|
|
36
|
-
const page =
|
|
37
|
-
`
|
|
38
|
-
<!DOCTYPE html>
|
|
39
|
-
<html lang="en">
|
|
40
|
-
<head>
|
|
41
|
-
<title>DBOS Template App</title>
|
|
42
|
-
<script src="https://cdn.tailwindcss.com"></script>
|
|
43
|
-
</head>
|
|
44
|
-
<body class="font-sans text-gray-800 p-6 max-w-2xl mx-auto">
|
|
45
|
-
<h1 class="text-3xl font-semibold mb-4">Welcome to DBOS!</h1>
|
|
46
|
-
<p class="mt-8 mb-8">` +
|
|
47
|
-
message +
|
|
48
|
-
`</p>
|
|
49
|
-
<p class="mb-2">
|
|
50
|
-
This is the TypeORM quickstart template app. Read the documentation for it <a href="https://docs.dbos.dev/typescript/tutorials/using-typeorm" class="text-blue-600 hover:underline">here</a>.
|
|
51
|
-
</p>
|
|
52
|
-
</body>
|
|
53
|
-
</html>`;
|
|
54
|
-
return page;
|
|
55
|
-
}
|
|
56
|
-
}
|