@dbos-inc/create 1.30.13 → 1.31.4-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/hello-nextjs/README.md +91 -0
- package/templates/hello-nextjs/dbos-config.yaml +18 -0
- package/templates/hello-nextjs/eslint.config.mjs +16 -0
- package/templates/hello-nextjs/gitignore.template +41 -0
- package/templates/hello-nextjs/knexfile.js +20 -0
- package/templates/hello-nextjs/migrations/20240212161006_create_dbos_hello_tables.js +18 -0
- package/templates/hello-nextjs/next.config.ts +18 -0
- package/templates/hello-nextjs/package.json +32 -0
- package/templates/hello-nextjs/postcss.config.mjs +8 -0
- package/templates/hello-nextjs/public/file.svg +1 -0
- package/templates/hello-nextjs/public/globe.svg +1 -0
- package/templates/hello-nextjs/public/next.svg +1 -0
- package/templates/hello-nextjs/public/vercel.svg +1 -0
- package/templates/hello-nextjs/public/window.svg +1 -0
- package/templates/hello-nextjs/src/actions/dbosWorkflow.tsx +37 -0
- package/templates/hello-nextjs/src/app/favicon.ico +0 -0
- package/templates/hello-nextjs/src/app/globals.css +21 -0
- package/templates/hello-nextjs/src/app/greetings/route.ts +11 -0
- package/templates/hello-nextjs/src/app/layout.tsx +34 -0
- package/templates/hello-nextjs/src/app/page.tsx +61 -0
- package/templates/hello-nextjs/src/components/client/callDBOSWorkflow.tsx +31 -0
- package/templates/hello-nextjs/start_postgres_docker.js +40 -0
- package/templates/hello-nextjs/tailwind.config.ts +18 -0
- package/templates/hello-nextjs/tsconfig.json +29 -0
package/package.json
CHANGED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# DBOS Hello
|
|
2
|
+
|
|
3
|
+
This is a [DBOS app](https://docs.dbos.dev/) bootstrapped with `npx @dbos-inc/create`, using [Express.js](https://expressjs.com/) and [Knex](https://docs.dbos.dev/tutorials/using-knex) to interact with postgres.
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
Before you can launch your app, you need a database.
|
|
8
|
+
DBOS works with any Postgres database, but to make things easier, we've provided a script that starts a Docker Postgres container and creates a database.
|
|
9
|
+
Run:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
node start_postgres_docker.js
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
If successful, the script should print `Database started successfully!`.
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Production build
|
|
20
|
+
|
|
21
|
+
In production, instead of using `nodemon`, the following separate steps should be used to build, run database setup, and start the app.
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm run build
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Then, run a schema migration to create some tables:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npx dbos migrate
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
If successful, the migration should print `Migration successful!`.
|
|
34
|
+
|
|
35
|
+
Finally, run the app:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npm run start
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
To see that it's working, visit this URL in your browser: [`http://localhost:3000/`](http://localhost:3000/).
|
|
42
|
+
|
|
43
|
+
Click on the "Run DBOS Workflow" button.
|
|
44
|
+
|
|
45
|
+
You should get this message: `Hello, dbos! You have been greeted 1 times.`
|
|
46
|
+
Each time you refresh the page, the counter should go up by one!
|
|
47
|
+
|
|
48
|
+
Congratulations! You just launched a DBOS application.
|
|
49
|
+
|
|
50
|
+
## The application
|
|
51
|
+
|
|
52
|
+
- In `src/action/dbosWorkflow.tsx`, the DBOS workflow is created. When called, it increments a counter in the database and returns a greeting.
|
|
53
|
+
|
|
54
|
+
- The code below in the same file, launches the dbos runtime. This is required for DBOS runtime to start. Do not remove the code
|
|
55
|
+
```
|
|
56
|
+
if (process.env.NEXT_PHASE !== "phase-production-build") {
|
|
57
|
+
await DBOS.launch();
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
- The workflow is called by the POST method in app/greetings/route.ts.
|
|
61
|
+
|
|
62
|
+
- The POST is called by the component in src/components/callDBOSWorkflow.tsx. It calls the route /greetings.
|
|
63
|
+
|
|
64
|
+
- The component is called from the main UI page.tsx.
|
|
65
|
+
|
|
66
|
+
- This is how the DBOS workflow is wired to the NextJs application.
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
DBOS will wrap all routes with an [OpenTelemetry](https://opentelemetry.io/) tracing middleware and tie HTTP traces to DBOS workflow traces.
|
|
70
|
+
|
|
71
|
+
To add more functionality to this application, modify `src/operations.ts`. If you used `npm run dev`, it will automatically rebuild and restart.
|
|
72
|
+
|
|
73
|
+
## Running in DBOS Cloud
|
|
74
|
+
|
|
75
|
+
To deploy this app to DBOS Cloud, first install the DBOS Cloud CLI (example with [npm](https://www.npmjs.com/)):
|
|
76
|
+
|
|
77
|
+
```shell
|
|
78
|
+
npm i -g @dbos-inc/dbos-cloud
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Then, run this command to deploy your app:
|
|
82
|
+
|
|
83
|
+
```shell
|
|
84
|
+
dbos-cloud app deploy
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Next Steps
|
|
88
|
+
|
|
89
|
+
- For a detailed tutorial, check out our [programming quickstart](https://docs.dbos.dev/getting-started/quickstart-programming).
|
|
90
|
+
- To learn more about DBOS, take a look at [our documentation](https://docs.dbos.dev/) or our [source code](https://github.com/dbos-inc/dbos-transact).
|
|
91
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# To enable auto-completion and validation for this file in VSCode, install the RedHat YAML extension
|
|
2
|
+
# https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml
|
|
3
|
+
|
|
4
|
+
# yaml-language-server: $schema=https://raw.githubusercontent.com/dbos-inc/dbos-transact/main/dbos-config.schema.json
|
|
5
|
+
|
|
6
|
+
language: node
|
|
7
|
+
database:
|
|
8
|
+
hostname: localhost
|
|
9
|
+
port: 5432
|
|
10
|
+
username: postgres
|
|
11
|
+
password: ${PGPASSWORD}
|
|
12
|
+
connectionTimeoutMillis: 3000
|
|
13
|
+
app_db_client: knex
|
|
14
|
+
migrate:
|
|
15
|
+
- npx knex migrate:latest
|
|
16
|
+
runtimeConfig:
|
|
17
|
+
start:
|
|
18
|
+
- "npm run start"
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { dirname } from "path";
|
|
2
|
+
import { fileURLToPath } from "url";
|
|
3
|
+
import { FlatCompat } from "@eslint/eslintrc";
|
|
4
|
+
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = dirname(__filename);
|
|
7
|
+
|
|
8
|
+
const compat = new FlatCompat({
|
|
9
|
+
baseDirectory: __dirname,
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const eslintConfig = [
|
|
13
|
+
...compat.extends("next/core-web-vitals", "next/typescript"),
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
export default eslintConfig;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
|
2
|
+
|
|
3
|
+
# dependencies
|
|
4
|
+
/node_modules
|
|
5
|
+
/.pnp
|
|
6
|
+
.pnp.*
|
|
7
|
+
.yarn/*
|
|
8
|
+
!.yarn/patches
|
|
9
|
+
!.yarn/plugins
|
|
10
|
+
!.yarn/releases
|
|
11
|
+
!.yarn/versions
|
|
12
|
+
|
|
13
|
+
# testing
|
|
14
|
+
/coverage
|
|
15
|
+
|
|
16
|
+
# next.js
|
|
17
|
+
/.next/
|
|
18
|
+
/out/
|
|
19
|
+
|
|
20
|
+
# production
|
|
21
|
+
/build
|
|
22
|
+
|
|
23
|
+
# misc
|
|
24
|
+
.DS_Store
|
|
25
|
+
*.pem
|
|
26
|
+
|
|
27
|
+
# debug
|
|
28
|
+
npm-debug.log*
|
|
29
|
+
yarn-debug.log*
|
|
30
|
+
yarn-error.log*
|
|
31
|
+
.pnpm-debug.log*
|
|
32
|
+
|
|
33
|
+
# env files (can opt-in for committing if needed)
|
|
34
|
+
.env*
|
|
35
|
+
|
|
36
|
+
# vercel
|
|
37
|
+
.vercel
|
|
38
|
+
|
|
39
|
+
# typescript
|
|
40
|
+
*.tsbuildinfo
|
|
41
|
+
next-env.d.ts
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const { parseConfigFile } = require('@dbos-inc/dbos-sdk');
|
|
2
|
+
|
|
3
|
+
const [dbosConfig, ] = parseConfigFile();
|
|
4
|
+
|
|
5
|
+
const config = {
|
|
6
|
+
client: 'pg',
|
|
7
|
+
connection: {
|
|
8
|
+
host: dbosConfig.poolConfig.host,
|
|
9
|
+
port: dbosConfig.poolConfig.port,
|
|
10
|
+
user: dbosConfig.poolConfig.user,
|
|
11
|
+
password: dbosConfig.poolConfig.password,
|
|
12
|
+
database: dbosConfig.poolConfig.database,
|
|
13
|
+
ssl: dbosConfig.poolConfig.ssl,
|
|
14
|
+
},
|
|
15
|
+
migrations: {
|
|
16
|
+
directory: './migrations'
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
module.exports = config;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const { Knex } = require("knex");
|
|
2
|
+
|
|
3
|
+
exports.up = async function(knex) {
|
|
4
|
+
await knex.schema.createTable('dbos_hello', table => {
|
|
5
|
+
table.text('name').primary();
|
|
6
|
+
table.integer('greet_count').defaultTo(0);
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
return knex.schema.createTable('dbos_greetings', table => {
|
|
10
|
+
table.text('greeting_name');
|
|
11
|
+
table.text('greeting_note_content');
|
|
12
|
+
});
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
exports.down = async function(knex) {
|
|
16
|
+
await knex.schema.dropTable('dbos_greetings');
|
|
17
|
+
return knex.schema.dropTable('dbos_hello');
|
|
18
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { NextConfig } from "next";
|
|
2
|
+
|
|
3
|
+
const nextConfig: NextConfig = {
|
|
4
|
+
/* config options here */
|
|
5
|
+
webpack: (config) => {
|
|
6
|
+
// Treat @dbos-inc/dbos-sdk as an external package for client builds
|
|
7
|
+
config.externals = [
|
|
8
|
+
...config.externals,
|
|
9
|
+
{
|
|
10
|
+
"@dbos-inc/dbos-sdk": "commonjs @dbos-inc/dbos-sdk",
|
|
11
|
+
},
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
return config;
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export default nextConfig;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "hello-nextjs",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "next dev",
|
|
7
|
+
"build": "next build",
|
|
8
|
+
"start": "next start",
|
|
9
|
+
"lint": "next lint"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@dbos-inc/dbos-sdk": "^1.29.15",
|
|
13
|
+
"next": "15.0.3",
|
|
14
|
+
"react": "19.0.0-rc-66855b96-20241106",
|
|
15
|
+
"react-dom": "19.0.0-rc-66855b96-20241106",
|
|
16
|
+
"typeorm": "^0.3.20",
|
|
17
|
+
"webpack": "^5.96.1"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@babel/cli": "^7.25.9",
|
|
21
|
+
"@babel/core": "^7.26.0",
|
|
22
|
+
"@babel/preset-env": "^7.26.0",
|
|
23
|
+
"@types/node": "^20",
|
|
24
|
+
"@types/react": "^18",
|
|
25
|
+
"@types/react-dom": "^18",
|
|
26
|
+
"eslint": "^8",
|
|
27
|
+
"eslint-config-next": "15.0.3",
|
|
28
|
+
"postcss": "^8",
|
|
29
|
+
"typescript": "^5",
|
|
30
|
+
"tailwindcss": "^3.4.1"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1155 1000"><path d="m577.3 0 577.4 1000H0z" fill="#fff"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
|
|
3
|
+
import { DBOS } from "@dbos-inc/dbos-sdk";
|
|
4
|
+
|
|
5
|
+
// The schema of the database table used in this example.
|
|
6
|
+
export interface dbos_hello {
|
|
7
|
+
name: string;
|
|
8
|
+
greet_count: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Order matters: DBOS decorators must be declared before being used
|
|
12
|
+
class dbosWorkflowClass {
|
|
13
|
+
@DBOS.transaction()
|
|
14
|
+
static async helloDBOS(userName: string) {
|
|
15
|
+
DBOS.logger.info("Hello from DBOS Transaction!");
|
|
16
|
+
// Retrieve and increment the number of times this user has been greeted.
|
|
17
|
+
const query = "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;";
|
|
18
|
+
const { rows } = await DBOS.sqlClient.client.raw(query, [userName]) as { rows: dbos_hello[] };
|
|
19
|
+
const greet_count = rows[0].greet_count;
|
|
20
|
+
const greeting = `Hello! You have been greeted ${greet_count} times.`;
|
|
21
|
+
return greeting;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Launch the DBOS runtime
|
|
26
|
+
// This code needs to execute at least once to launch the DBOS runtime
|
|
27
|
+
// Do not delete this code
|
|
28
|
+
if (process.env.NEXT_PHASE !== "phase-production-build") {
|
|
29
|
+
await DBOS.launch();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// The exported function is the entry point for the workflow
|
|
33
|
+
// The function is exported and not the class because Next does not support exporting classes
|
|
34
|
+
export async function dbosWorkflow(userName: string) {
|
|
35
|
+
DBOS.logger.info("Hello from DBOS!");
|
|
36
|
+
return await dbosWorkflowClass.helloDBOS(userName);
|
|
37
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
@tailwind base;
|
|
2
|
+
@tailwind components;
|
|
3
|
+
@tailwind utilities;
|
|
4
|
+
|
|
5
|
+
:root {
|
|
6
|
+
--background: #ffffff;
|
|
7
|
+
--foreground: #171717;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
@media (prefers-color-scheme: dark) {
|
|
11
|
+
:root {
|
|
12
|
+
--background: #0a0a0a;
|
|
13
|
+
--foreground: #ededed;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
body {
|
|
18
|
+
color: var(--foreground);
|
|
19
|
+
background: var(--background);
|
|
20
|
+
font-family: Arial, Helvetica, sans-serif;
|
|
21
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
import { dbosWorkflow } from "../../actions/dbosWorkflow";
|
|
3
|
+
import { DBOS } from "@dbos-inc/dbos-sdk";
|
|
4
|
+
|
|
5
|
+
export async function POST(request: Request) {
|
|
6
|
+
const body = await request.json();
|
|
7
|
+
const { userName } = body;
|
|
8
|
+
DBOS.logger.info(`Received request with name: ${userName}`);
|
|
9
|
+
const response = await dbosWorkflow(userName);
|
|
10
|
+
return NextResponse.json(response);
|
|
11
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Metadata } from "next";
|
|
2
|
+
import { Geist, Geist_Mono } from "next/font/google";
|
|
3
|
+
import "./globals.css";
|
|
4
|
+
|
|
5
|
+
const geistSans = Geist({
|
|
6
|
+
variable: "--font-geist-sans",
|
|
7
|
+
subsets: ["latin"],
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
const geistMono = Geist_Mono({
|
|
11
|
+
variable: "--font-geist-mono",
|
|
12
|
+
subsets: ["latin"],
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
export const metadata: Metadata = {
|
|
16
|
+
title: "Create Next App with DBOS",
|
|
17
|
+
description: "Generated by DBOS",
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default function RootLayout({
|
|
21
|
+
children,
|
|
22
|
+
}: Readonly<{
|
|
23
|
+
children: React.ReactNode;
|
|
24
|
+
}>) {
|
|
25
|
+
return (
|
|
26
|
+
<html lang="en">
|
|
27
|
+
<body
|
|
28
|
+
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
|
29
|
+
>
|
|
30
|
+
{children}
|
|
31
|
+
</body>
|
|
32
|
+
</html>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import Image from "next/image";
|
|
2
|
+
import CallDBOSWorkflow from "../components/client/callDBOSWorkflow";
|
|
3
|
+
|
|
4
|
+
export default function Home() {
|
|
5
|
+
return (
|
|
6
|
+
<div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]">
|
|
7
|
+
<main className="flex flex-col gap-8 row-start-2 items-center sm:items-start">
|
|
8
|
+
<div>
|
|
9
|
+
<CallDBOSWorkflow wfResult=""/>
|
|
10
|
+
</div>
|
|
11
|
+
</main>
|
|
12
|
+
<footer className="row-start-3 flex gap-6 flex-wrap items-center justify-center">
|
|
13
|
+
<a
|
|
14
|
+
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
|
|
15
|
+
href="https://docs.dbos.dev/"
|
|
16
|
+
target="_blank"
|
|
17
|
+
rel="noopener noreferrer"
|
|
18
|
+
>
|
|
19
|
+
<Image
|
|
20
|
+
aria-hidden
|
|
21
|
+
src="/file.svg"
|
|
22
|
+
alt="File icon"
|
|
23
|
+
width={16}
|
|
24
|
+
height={16}
|
|
25
|
+
/>
|
|
26
|
+
Learn
|
|
27
|
+
</a>
|
|
28
|
+
<a
|
|
29
|
+
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
|
|
30
|
+
href="https://docs.dbos.dev/#example-applications"
|
|
31
|
+
target="_blank"
|
|
32
|
+
rel="noopener noreferrer"
|
|
33
|
+
>
|
|
34
|
+
<Image
|
|
35
|
+
aria-hidden
|
|
36
|
+
src="/window.svg"
|
|
37
|
+
alt="Window icon"
|
|
38
|
+
width={16}
|
|
39
|
+
height={16}
|
|
40
|
+
/>
|
|
41
|
+
Examples
|
|
42
|
+
</a>
|
|
43
|
+
<a
|
|
44
|
+
className="flex items-center gap-2 hover:underline hover:underline-offset-4"
|
|
45
|
+
href="https://www.dbos.dev/"
|
|
46
|
+
target="_blank"
|
|
47
|
+
rel="noopener noreferrer"
|
|
48
|
+
>
|
|
49
|
+
<Image
|
|
50
|
+
aria-hidden
|
|
51
|
+
src="/globe.svg"
|
|
52
|
+
alt="Globe icon"
|
|
53
|
+
width={16}
|
|
54
|
+
height={16}
|
|
55
|
+
/>
|
|
56
|
+
Go to dbos.dev →
|
|
57
|
+
</a>
|
|
58
|
+
</footer>
|
|
59
|
+
</div>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
|
|
5
|
+
export default function CallDBOSWorkflow( { wfResult }: { wfResult: string }) {
|
|
6
|
+
const [greetingsWfResult, setGreetingsWfResult] = useState<string>(wfResult);
|
|
7
|
+
const [loading, setLoading] = useState<boolean>(false);
|
|
8
|
+
|
|
9
|
+
const greetUser = async () => {
|
|
10
|
+
setLoading(true);
|
|
11
|
+
try {
|
|
12
|
+
const response = await fetch("/greetings", { method: "POST", body: JSON.stringify({ userName: "dbosuser" }) });
|
|
13
|
+
const data = await response.json();
|
|
14
|
+
setGreetingsWfResult(data);
|
|
15
|
+
} catch (error) {
|
|
16
|
+
console.error("Error calling greetings workflow", error);
|
|
17
|
+
setGreetingsWfResult("Error calling greetings workflow: " + error);
|
|
18
|
+
} finally {
|
|
19
|
+
setLoading(false);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return(
|
|
24
|
+
<div>
|
|
25
|
+
<button onClick={greetUser} disabled={loading} className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">
|
|
26
|
+
{loading ? "" : "Run DBOS Workflow"}
|
|
27
|
+
</button>
|
|
28
|
+
<p>{greetingsWfResult}</p>
|
|
29
|
+
</div>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const { execSync } = require('child_process');
|
|
2
|
+
|
|
3
|
+
// Default PostgreSQL port
|
|
4
|
+
let port = '5432';
|
|
5
|
+
|
|
6
|
+
// Set the host PostgreSQL port with the -p/--port flag.
|
|
7
|
+
process.argv.forEach((val, index) => {
|
|
8
|
+
if (val === '-p' || val === '--port') {
|
|
9
|
+
if (process.argv[index + 1]) {
|
|
10
|
+
port = process.argv[index + 1];
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
if (!process.env.PGPASSWORD) {
|
|
16
|
+
console.error("Error: PGPASSWORD is not set.");
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
try {
|
|
21
|
+
execSync(`docker run --rm --name=dbos-db --env=POSTGRES_PASSWORD="${process.env.PGPASSWORD}" --env=PGDATA=/var/lib/postgresql/data --volume=/var/lib/postgresql/data -p ${port}:5432 -d sibedge/postgres-plv8`);
|
|
22
|
+
console.log("Waiting for PostgreSQL to start...");
|
|
23
|
+
|
|
24
|
+
let attempts = 30;
|
|
25
|
+
const checkDatabase = setInterval(() => {
|
|
26
|
+
try {
|
|
27
|
+
execSync('docker exec dbos-db psql -U postgres -c "SELECT 1;"', { stdio: 'ignore' });
|
|
28
|
+
console.log("PostgreSQL started!");
|
|
29
|
+
clearInterval(checkDatabase);
|
|
30
|
+
console.log("Database started successfully!");
|
|
31
|
+
} catch (error) {
|
|
32
|
+
if (--attempts === 0) {
|
|
33
|
+
clearInterval(checkDatabase);
|
|
34
|
+
console.error("Failed to start PostgreSQL.");
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}, 1000);
|
|
38
|
+
} catch (error) {
|
|
39
|
+
console.error("Error starting PostgreSQL in Docker:", error.message);
|
|
40
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Config } from "tailwindcss";
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
content: [
|
|
5
|
+
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
|
|
6
|
+
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
|
|
7
|
+
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
|
|
8
|
+
],
|
|
9
|
+
theme: {
|
|
10
|
+
extend: {
|
|
11
|
+
colors: {
|
|
12
|
+
background: "var(--background)",
|
|
13
|
+
foreground: "var(--foreground)",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
plugins: [],
|
|
18
|
+
} satisfies Config;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"experimentalDecorators": true,
|
|
4
|
+
"emitDecoratorMetadata": true,
|
|
5
|
+
"target": "ES2017",
|
|
6
|
+
"lib": ["dom", "dom.iterable", "esnext"],
|
|
7
|
+
"allowJs": true,
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
"strict": true,
|
|
10
|
+
"noEmit": true,
|
|
11
|
+
"esModuleInterop": true,
|
|
12
|
+
"module": "esnext",
|
|
13
|
+
"moduleResolution": "bundler",
|
|
14
|
+
"resolveJsonModule": true,
|
|
15
|
+
"isolatedModules": true,
|
|
16
|
+
"jsx": "preserve",
|
|
17
|
+
"incremental": true,
|
|
18
|
+
"plugins": [
|
|
19
|
+
{
|
|
20
|
+
"name": "next"
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"paths": {
|
|
24
|
+
"@/*": ["./src/*"]
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
|
28
|
+
"exclude": ["node_modules"]
|
|
29
|
+
}
|