Skip to content

Commit d72e32f

Browse files
authored
New Components - nile_database (#14223)
* wip * execute-query-action * pnpm-lock.yaml * execute-query * user api components * pnpm-lock.yaml * remove console.log * update execute-query
1 parent 20c4e2b commit d72e32f

File tree

8 files changed

+383
-8
lines changed

8 files changed

+383
-8
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import nile from "../../nile_database.app.mjs";
2+
3+
export default {
4+
key: "nile_database-create-user",
5+
name: "Create User",
6+
description: "Create a new database user by providing an email address and password. [See the documentation](https://www.thenile.dev/docs/reference/api-reference/users/create-user)",
7+
version: "0.0.1",
8+
type: "action",
9+
props: {
10+
nile,
11+
workspace: {
12+
propDefinition: [
13+
nile,
14+
"workspace",
15+
],
16+
},
17+
database: {
18+
propDefinition: [
19+
nile,
20+
"database",
21+
],
22+
},
23+
email: {
24+
type: "string",
25+
label: "Email",
26+
description: "Email address of the user",
27+
},
28+
password: {
29+
type: "string",
30+
label: "Password",
31+
description: "Password for the user",
32+
},
33+
preferredName: {
34+
type: "string",
35+
label: "Preferred Name",
36+
description: "The preferred name of the user",
37+
optional: true,
38+
},
39+
},
40+
async run({ $ }) {
41+
const response = await this.nile.createUser({
42+
$,
43+
workspace: this.workspace,
44+
database: this.database,
45+
data: {
46+
email: this.email,
47+
password: this.password,
48+
preferredName: this.preferredName,
49+
},
50+
});
51+
$.export("$summary", `Successfully created user with ID: ${response.id}`);
52+
return response;
53+
},
54+
};
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import nile from "../../nile_database.app.mjs";
2+
3+
export default {
4+
name: "Execute Query",
5+
key: "nile_database-execute-query",
6+
description: "Execute a custom PostgreSQL query.",
7+
version: "0.0.1",
8+
type: "action",
9+
props: {
10+
nile,
11+
workspace: {
12+
propDefinition: [
13+
nile,
14+
"workspace",
15+
],
16+
},
17+
database: {
18+
propDefinition: [
19+
nile,
20+
"database",
21+
],
22+
},
23+
user: {
24+
type: "string",
25+
label: "Username",
26+
description: "The username or userId of the database user. Note: Credentials are generated in the Nile Dashboard under Settings -> Credentials",
27+
},
28+
password: {
29+
type: "string",
30+
label: "Password",
31+
description: "The password of the database user",
32+
},
33+
query: {
34+
type: "string",
35+
label: "Query",
36+
description: "The PostgreSQL query to execute",
37+
},
38+
},
39+
async run({ $ }) {
40+
const config = {
41+
user: this.user,
42+
password: this.password,
43+
host: await this.nile.getHost({
44+
workspace: this.workspace,
45+
database: this.database,
46+
}),
47+
port: "5432",
48+
database: this.database,
49+
};
50+
const data = await this.nile.executeQuery(config, this.query);
51+
$.export("$summary", `Returned ${data.length} ${data.length === 1
52+
? "row"
53+
: "rows"}`);
54+
return data;
55+
},
56+
};
Lines changed: 131 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,137 @@
1+
import { axios } from "@pipedream/platform";
2+
import pg from "pg";
3+
14
export default {
25
type: "app",
36
app: "nile_database",
4-
propDefinitions: {},
7+
propDefinitions: {
8+
workspace: {
9+
type: "string",
10+
label: "Workspace",
11+
description: "Your workspace slug",
12+
async options() {
13+
const { workspaces } = await this.getAuthenticatedUser();
14+
return workspaces?.map(({ slug }) => slug) || [];
15+
},
16+
},
17+
database: {
18+
type: "string",
19+
label: "Database",
20+
description: "The database name",
21+
async options() {
22+
const { databases } = await this.getAuthenticatedUser();
23+
return databases?.map(({ name }) => name) || [];
24+
},
25+
},
26+
},
527
methods: {
6-
// this.$auth contains connected account data
7-
authKeys() {
8-
console.log(Object.keys(this.$auth));
28+
_globalBaseUrl() {
29+
return "https://global.thenile.dev";
30+
},
31+
async _getBaseUrl({
32+
workspace, database, ...opts
33+
}) {
34+
const { apiHost } = await this.getDatabase({
35+
workspace,
36+
database,
37+
...opts,
38+
});
39+
return apiHost;
40+
},
41+
async _makeRequest({
42+
$ = this,
43+
workspace,
44+
database,
45+
url,
46+
path,
47+
...opts
48+
}) {
49+
return axios($, {
50+
url: url || `${await this._getBaseUrl({
51+
workspace,
52+
database,
53+
$,
54+
})}${path}`,
55+
headers: {
56+
Authorization: `Bearer ${this.$auth.oauth_access_token}`,
57+
},
58+
...opts,
59+
});
60+
},
61+
getDatabase({
62+
workspace, database, ...opts
63+
}) {
64+
return this._makeRequest({
65+
url: `${this._globalBaseUrl()}/workspaces/${workspace}/databases/${database}`,
66+
workspace,
67+
database,
68+
...opts,
69+
});
70+
},
71+
getAuthenticatedUser(opts = {}) {
72+
return this._makeRequest({
73+
url: `${this._globalBaseUrl()}/developers/me/full`,
74+
...opts,
75+
});
76+
},
77+
async getHost({
78+
workspace, database, ...opts
79+
}) {
80+
const { dbHost } = await this.getDatabase({
81+
workspace,
82+
database,
83+
...opts,
84+
});
85+
const host = dbHost.match(/postgres:\/\/([^/]+)\//);
86+
return host[1];
87+
},
88+
listUsers({
89+
workspace, database, ...opts
90+
}) {
91+
return this._makeRequest({
92+
path: "/users",
93+
workspace,
94+
database,
95+
...opts,
96+
});
97+
},
98+
listTenants({
99+
workspace, database, ...opts
100+
}) {
101+
return this._makeRequest({
102+
path: "/tenants",
103+
workspace,
104+
database,
105+
...opts,
106+
});
107+
},
108+
createUser({
109+
workspace, database, ...opts
110+
}) {
111+
return this._makeRequest({
112+
method: "POST",
113+
path: "/users",
114+
workspace,
115+
database,
116+
...opts,
117+
});
118+
},
119+
async _getClient(config) {
120+
const pool = new pg.Pool(config);
121+
const client = await pool.connect();
122+
return client;
123+
},
124+
async _endClient(client) {
125+
return client.release();
126+
},
127+
async executeQuery(config, query) {
128+
const client = await this._getClient(config);
129+
try {
130+
const { rows } = await client.query(query);
131+
return rows;
132+
} finally {
133+
await this._endClient(client);
134+
}
9135
},
10136
},
11-
};
137+
};

components/nile_database/package.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@pipedream/nile_database",
3-
"version": "0.0.1",
3+
"version": "0.1.0",
44
"description": "Pipedream Nile Database Components",
55
"main": "nile_database.app.mjs",
66
"keywords": [
@@ -11,5 +11,9 @@
1111
"author": "Pipedream <[email protected]> (https://pipedream.com/)",
1212
"publishConfig": {
1313
"access": "public"
14+
},
15+
"dependencies": {
16+
"@pipedream/platform": "^3.0.3",
17+
"pg": "^8.13.0"
1418
}
15-
}
19+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import nile from "../../nile_database.app.mjs";
2+
import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform";
3+
4+
export default {
5+
props: {
6+
nile,
7+
db: "$.service.db",
8+
timer: {
9+
type: "$.interface.timer",
10+
default: {
11+
intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL,
12+
},
13+
},
14+
workspace: {
15+
propDefinition: [
16+
nile,
17+
"workspace",
18+
],
19+
},
20+
database: {
21+
propDefinition: [
22+
nile,
23+
"database",
24+
],
25+
},
26+
},
27+
methods: {
28+
getResourceFn() {
29+
throw new Error("getResourceFn is not implemented");
30+
},
31+
generateMeta() {
32+
throw new Error("generateMeta is not implemented");
33+
},
34+
},
35+
async run() {
36+
const resourceFn = this.getResourceFn();
37+
38+
const results = await resourceFn({
39+
workspace: this.workspace,
40+
database: this.database,
41+
});
42+
43+
for (const item of results) {
44+
const meta = this.generateMeta(item);
45+
this.$emit(item, meta);
46+
}
47+
},
48+
};
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import common from "../common/base.mjs";
2+
3+
export default {
4+
...common,
5+
key: "nile_database-new-tenant-created",
6+
name: "New Tenant Created",
7+
description: "Emit new event when a new tenant is added to a Nile Database",
8+
version: "0.0.1",
9+
type: "source",
10+
dedupe: "unique",
11+
methods: {
12+
...common.methods,
13+
getResourceFn() {
14+
return this.nile.listTenants;
15+
},
16+
generateMeta(tenant) {
17+
return {
18+
id: tenant.id,
19+
summary: `New Tenant ID: ${tenant.id}`,
20+
ts: Date.now(),
21+
};
22+
},
23+
},
24+
};
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import common from "../common/base.mjs";
2+
3+
export default {
4+
...common,
5+
key: "nile_database-new-user-created",
6+
name: "New User Created",
7+
description: "Emit new event when a new user is added in a Nile Database",
8+
version: "0.0.1",
9+
type: "source",
10+
dedupe: "unique",
11+
methods: {
12+
...common.methods,
13+
getResourceFn() {
14+
return this.nile.listUsers;
15+
},
16+
generateMeta(user) {
17+
return {
18+
id: user.id,
19+
summary: `New User ID: ${user.id}`,
20+
ts: Date.parse(user.created),
21+
};
22+
},
23+
},
24+
};

0 commit comments

Comments
 (0)