Skip to content

Commit e99c665

Browse files
committed
Add PostgreSQL plugin template for .NET
Signed-off-by: Itai Nathaniel <itainathaniel@gmail.com>
1 parent 21825d1 commit e99c665

File tree

12 files changed

+287
-0
lines changed

12 files changed

+287
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules/

plugin-templates/dotnet/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules/

plugin-templates/dotnet/.keep

Whitespace-only changes.

plugin-templates/dotnet/README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# @amplication/dotnet-plugin-db-postgres
2+
3+
[![NPM Downloads](https://img.shields.io/npm/dt/@amplication/dotnet-plugin-db-postgres)](https://www.npmjs.com/package/@amplication/dotnet-plugin-db-postgres)
4+
5+
Use a PostgreSQL database in the service generated by Amplication.
6+
7+
## Purpose
8+
9+
This plugin adds the required code to use MS SQL Server database in the service generated by Amplication.
10+
It updates the following parts:
11+
12+
- Adds the required services and variables to `docker-compose.yml`
13+
- Add the required environment variables to `appsettings.json`
14+
- Configure Entity Framework Core to work with Microsoft SQL Server
15+
16+
## Configuration
17+
18+
The plugin uses the parameters configured on the plugin settings page.
19+
These settings include: `host`, `port`, `user`, `password`, `dbName`
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"name": "@amplication/plugin-dotnet-db-postgres",
3+
"version": "0.1.0",
4+
"description": "Use a PostgreSQL database in a service generated by Amplication",
5+
"main": "dist/index.js",
6+
"nx": {},
7+
"scripts": {
8+
"dev": "webpack --watch",
9+
"build": "webpack",
10+
"prebuild": "rimraf dist"
11+
},
12+
"author": "Daniele Iasella",
13+
"license": "Apache-2.0",
14+
"devDependencies": {
15+
"@amplication/csharp-ast": "^0.0.4",
16+
"@amplication/code-gen-types": "2.0.37",
17+
"@amplication/code-gen-utils": "^0.0.9",
18+
"@babel/parser": "^7.18.11",
19+
"@babel/types": "^7.18.10",
20+
"@types/lodash": "^4.14.182",
21+
"@types/normalize-path": "^3.0.0",
22+
"@typescript-eslint/eslint-plugin": "^5.33.0",
23+
"@typescript-eslint/parser": "^5.33.0",
24+
"copy-webpack-plugin": "^12.0.2",
25+
"eslint": "^8.21.0",
26+
"jest-mock-extended": "^2.0.7",
27+
"lodash": "^4.17.21",
28+
"pascal-case": "^3.1.2",
29+
"prettier": "^2.6.2",
30+
"rimraf": "^4.4.1",
31+
"ts-loader": "^9.4.2",
32+
"typescript": "^4.9.3",
33+
"webpack": "^5.75.0",
34+
"webpack-cli": "^5.0.1"
35+
}
36+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { CreateServerDockerComposeParams } from "@amplication/code-gen-types";
2+
import { Settings } from "./types";
3+
4+
export const updateDockerComposeProperties = (
5+
settings: Settings
6+
): CreateServerDockerComposeParams["updateProperties"] => {
7+
const { port, password, user, dbName } = settings;
8+
return [
9+
{
10+
services: {
11+
server: {
12+
environment: {
13+
ConnectionStrings__DbContext: `Host=db:5432;Username=${user};Password=${password};Database=${dbName}`,
14+
},
15+
},
16+
migrate: {
17+
environment: {
18+
MIGRATION_CONNECTION: `Host=db:5432;Username=${user};Password=${password};Database=${dbName}`,
19+
},
20+
},
21+
db: {
22+
image: "postgres:15",
23+
restart: "unless-stopped",
24+
ports: [`${port}:5432`],
25+
environment: {
26+
POSTGRES_DB: dbName,
27+
POSTGRES_USER: user,
28+
POSTGRES_PASSWORD: password,
29+
},
30+
healthcheck: {
31+
test: [
32+
"CMD-SHELL",
33+
"pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}",
34+
],
35+
timeout: "5s",
36+
interval: "10s",
37+
retries: 10,
38+
start_period: "10s",
39+
},
40+
},
41+
},
42+
volumes: {
43+
postgres: null,
44+
},
45+
},
46+
];
47+
};
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import {
2+
dotnetPluginEventsTypes,
3+
dotnetPluginEventsParams as dotnet,
4+
dotnetTypes,
5+
FileMap,
6+
} from "@amplication/code-gen-types";
7+
import { ClassReference, CodeBlock, ProgramClass } from "@amplication/csharp-ast";
8+
import { updateDockerComposeProperties } from "./constants";
9+
import { getPluginSettings } from "./utils";
10+
import { pascalCase } from "pascal-case";
11+
import { join } from "path";
12+
13+
const CONNECTION_STRING = "DefaultConnection";
14+
15+
class PostgreSQLPlugin implements dotnetTypes.AmplicationPlugin {
16+
register(): dotnetPluginEventsTypes.DotnetEvents {
17+
return {
18+
CreateServerDockerCompose: {
19+
before: this.beforeCreateServerDockerCompose,
20+
},
21+
CreateServerCsproj: {
22+
before: this.beforeCreateServerCsproj,
23+
},
24+
CreateServerAppsettings: {
25+
before: this.beforeCreateServerAppsettings,
26+
},
27+
CreateProgramFile: {
28+
after: this.afterCreateProgramFile,
29+
},
30+
};
31+
}
32+
33+
beforeCreateServerDockerCompose(
34+
context: dotnetTypes.DsgContext,
35+
eventParams: dotnet.CreateServerDockerComposeParams
36+
) {
37+
const settings = getPluginSettings(context.pluginInstallations);
38+
39+
eventParams.updateProperties.push(
40+
...updateDockerComposeProperties(settings)
41+
);
42+
return eventParams;
43+
}
44+
45+
beforeCreateServerCsproj(
46+
_: dotnetTypes.DsgContext,
47+
eventParams: dotnet.CreateServerCsprojParams
48+
) {
49+
eventParams.packageReferences.push({
50+
include: "Npgsql.EntityFrameworkCore.PostgreSQL",
51+
version: "8.0.4",
52+
});
53+
54+
return eventParams;
55+
}
56+
57+
beforeCreateServerAppsettings(
58+
context: dotnetTypes.DsgContext,
59+
eventParams: dotnet.CreateServerAppsettingsParams
60+
) {
61+
const { port, password, user, host, dbName } = getPluginSettings(
62+
context.pluginInstallations
63+
);
64+
65+
eventParams.updateProperties = {
66+
...eventParams.updateProperties,
67+
ConnectionStrings: {
68+
[CONNECTION_STRING]: `Host=${host}:${port};Username=${user};Password=${password};Database=${dbName}`,
69+
},
70+
};
71+
return eventParams;
72+
}
73+
74+
afterCreateProgramFile(
75+
{ resourceInfo, serverDirectories }: dotnetTypes.DsgContext,
76+
eventParams: dotnet.CreateProgramFileParams,
77+
programClass: FileMap<ProgramClass>
78+
): FileMap<ProgramClass> {
79+
const serviceNamespace = pascalCase(resourceInfo?.name ?? "");
80+
const serviceDbContext = `${pascalCase(resourceInfo?.name ?? "")}DbContext`;
81+
const programCsPath = join(serverDirectories.srcDirectory, "Program.cs");
82+
const programCs = programClass.get(programCsPath);
83+
if (!programCs)
84+
return programClass;
85+
86+
programCs.code.builderServicesBlocks.push(
87+
new CodeBlock({
88+
code: `builder.Services.AddDbContext<${serviceDbContext}>(opt => opt.UseNpgsql(builder.Configuration.GetConnectionString("${CONNECTION_STRING}")));`,
89+
references: [
90+
new ClassReference({
91+
name: "AddDbContext",
92+
namespace: "Microsoft.EntityFrameworkCore",
93+
}),
94+
new ClassReference({
95+
name: serviceDbContext,
96+
namespace: `${serviceNamespace}.Infrastructure`,
97+
}),
98+
],
99+
})
100+
);
101+
102+
return programClass;
103+
}
104+
}
105+
106+
export default PostgreSQLPlugin;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export interface Settings {
2+
host: string;
3+
port: number;
4+
user: string;
5+
password: string;
6+
dbName: string;
7+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { PluginInstallation } from "@amplication/code-gen-types";
2+
import { name as PackageName } from "../package.json";
3+
import { Settings } from "./types";
4+
import defaultSettings from "../.amplicationrc.json";
5+
6+
export const getPluginSettings = (
7+
pluginInstallations: PluginInstallation[]
8+
): Settings => {
9+
const plugin = pluginInstallations.find(
10+
(plugin) => plugin.npm === PackageName
11+
);
12+
13+
const userSettings = plugin?.settings ?? {};
14+
15+
const settings: Settings = {
16+
...defaultSettings.settings,
17+
...userSettings,
18+
};
19+
20+
return settings;
21+
};
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"extends": "../../tsconfig.base.json",
3+
"include": ["src/index.ts"],
4+
"exclude": ["node_modules"]
5+
}

0 commit comments

Comments
 (0)