@forge/sql 0.0.1-experimental-9332276

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/README.md ADDED
@@ -0,0 +1,8 @@
1
+ Library for Forge environment.
2
+
3
+ Usage example:
4
+ ```typescript
5
+ import sql from "@forge/sql";
6
+
7
+ await sql.execute(`SELECT * FROM example`);
8
+ ```
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=fetch-wrapper.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-wrapper.test.d.ts","sourceRoot":"","sources":["../../src/__test__/fetch-wrapper.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const node_fetch_1 = tslib_1.__importDefault(require("node-fetch"));
5
+ const fetch_wrapper_1 = require("../utils/fetch-wrapper");
6
+ jest.mock('node-fetch');
7
+ const fetchMock = node_fetch_1.default;
8
+ describe('v2', () => {
9
+ it('chooses the v2 fetch based on runtime', async () => {
10
+ const fetch = (0, fetch_wrapper_1.runtimeV2FetchWrapper)();
11
+ fetchMock.mockResolvedValueOnce({
12
+ headers: {
13
+ has: jest.isMockFunction
14
+ },
15
+ ok: true,
16
+ json: async () => ({
17
+ values: []
18
+ })
19
+ });
20
+ await fetch('asdf');
21
+ expect(fetchMock).toHaveBeenCalled();
22
+ });
23
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=sql.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sql.test.d.ts","sourceRoot":"","sources":["../../src/__test__/sql.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const node_fetch_1 = tslib_1.__importDefault(require("node-fetch"));
5
+ const sql_1 = require("../sql");
6
+ const reponse_handler_1 = require("../utils/reponse-handler");
7
+ jest.mock('node-fetch');
8
+ const fetchMock = node_fetch_1.default;
9
+ describe('sql', () => {
10
+ it('should pass', async () => {
11
+ fetchMock.mockResolvedValueOnce({
12
+ headers: {
13
+ has: jest.isMockFunction
14
+ },
15
+ ok: true,
16
+ text: async () => JSON.stringify({
17
+ values: []
18
+ })
19
+ });
20
+ await sql_1.sql.execute('asdf');
21
+ expect(fetchMock).toHaveBeenCalled();
22
+ });
23
+ });
24
+ describe('SqlClient', () => {
25
+ function buildSqlClient() {
26
+ const fetch = jest.fn();
27
+ const client = new sql_1.SqlClient(fetch);
28
+ return { client, fetch };
29
+ }
30
+ it('handles success', async () => {
31
+ const { client, fetch } = buildSqlClient();
32
+ fetch.mockResolvedValueOnce({
33
+ ok: true,
34
+ text: async () => JSON.stringify({ response: 'asdfasdf' }),
35
+ status: 200
36
+ });
37
+ const result = await client.execute('SELECT * FROM example');
38
+ expect(result).toEqual('asdfasdf');
39
+ expect(fetch.mock.lastCall).toMatchSnapshot();
40
+ });
41
+ it('handles success when no value is returned', async () => {
42
+ const { client, fetch } = buildSqlClient();
43
+ fetch.mockResolvedValueOnce({ ok: true, text: async () => JSON.stringify({ response: null }), status: 200 });
44
+ const result = await client.execute(`INSERT INTO x SET y='z'`);
45
+ expect(result).toBeNull();
46
+ expect(fetch.mock.lastCall).toMatchSnapshot();
47
+ });
48
+ it('handles failure', async () => {
49
+ const { client, fetch } = buildSqlClient();
50
+ fetch.mockResolvedValueOnce({
51
+ ok: false,
52
+ text: async () => JSON.stringify({ error: { code: 'SQL_SYNTAX_ERROR', title: 'SQL syntax error' } }),
53
+ status: 400
54
+ });
55
+ await expect(client.execute('DELECT * from example')).rejects.toThrow(new reponse_handler_1.ApiError(400, 'SQL_SYNTAX_ERROR', 'SQL syntax error'));
56
+ expect(fetch.mock.lastCall).toMatchSnapshot();
57
+ });
58
+ });
package/out/index.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import { sql } from './sql';
2
+ export default sql;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAC5B,eAAe,GAAG,CAAC"}
package/out/index.js ADDED
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const sql_1 = require("./sql");
4
+ exports.default = sql_1.sql;
package/out/sql.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ import { RequestInit } from 'node-fetch';
2
+ import { Result, Response } from './utils/types';
3
+ export declare class SqlClient {
4
+ private client;
5
+ constructor(client: (path: string, options?: RequestInit) => Promise<Response>);
6
+ private buildRequest;
7
+ execute(query: string): Promise<Result>;
8
+ }
9
+ export declare const sql: SqlClient;
10
+ //# sourceMappingURL=sql.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sql.d.ts","sourceRoot":"","sources":["../src/sql.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAGzC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGjD,qBAAa,SAAS;IACR,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC;IAEtF,OAAO,CAAC,YAAY;IAUP,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAKrD;AAED,eAAO,MAAM,GAAG,WAAyC,CAAC"}
package/out/sql.js ADDED
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sql = exports.SqlClient = void 0;
4
+ const fetch_wrapper_1 = require("./utils/fetch-wrapper");
5
+ const reponse_handler_1 = require("./utils/reponse-handler");
6
+ class SqlClient {
7
+ client;
8
+ constructor(client) {
9
+ this.client = client;
10
+ }
11
+ buildRequest(requestBody) {
12
+ return {
13
+ method: 'POST',
14
+ body: JSON.stringify(requestBody),
15
+ headers: {
16
+ 'Content-Type': 'application/json'
17
+ }
18
+ };
19
+ }
20
+ async execute(query) {
21
+ const response = await this.client('sql/execute', this.buildRequest({ query }));
22
+ return await (0, reponse_handler_1.getResponseBody)(response);
23
+ }
24
+ }
25
+ exports.SqlClient = SqlClient;
26
+ exports.sql = new SqlClient((0, fetch_wrapper_1.runtimeV2FetchWrapper)());
@@ -0,0 +1,3 @@
1
+ import { FetchMethod } from '@forge/api';
2
+ export declare function runtimeV2FetchWrapper(): FetchMethod;
3
+ //# sourceMappingURL=fetch-wrapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-wrapper.d.ts","sourceRoot":"","sources":["../../src/utils/fetch-wrapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAqB,MAAM,YAAY,CAAC;AAI5D,wBAAgB,qBAAqB,IAAI,WAAW,CAoBnD"}
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runtimeV2FetchWrapper = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const api_1 = require("@forge/api");
6
+ const node_fetch_1 = tslib_1.__importDefault(require("node-fetch"));
7
+ const fetch_1 = require("@forge/api/out/api/fetch");
8
+ function runtimeV2FetchWrapper() {
9
+ return async (path, init) => {
10
+ const url = `https://sql/${path}`;
11
+ init = (0, fetch_1.addMagicAgent)(init);
12
+ init.redirect = 'follow';
13
+ init.headers = {
14
+ ...init.headers,
15
+ redirect: 'follow',
16
+ 'Content-Type': 'application/json'
17
+ };
18
+ const response = await (0, node_fetch_1.default)(url, init);
19
+ if (response.headers.has('forge-proxy-error')) {
20
+ throw new api_1.ProxyRequestError(response.status, response.headers.get('forge-proxy-error'));
21
+ }
22
+ return response;
23
+ };
24
+ }
25
+ exports.runtimeV2FetchWrapper = runtimeV2FetchWrapper;
@@ -0,0 +1,9 @@
1
+ import { Response } from './types';
2
+ export declare class ApiError extends Error {
3
+ readonly status: number;
4
+ readonly code: string;
5
+ readonly data?: any;
6
+ constructor(status: number, code: string, message: string, data?: any);
7
+ }
8
+ export declare function getResponseBody(response: Response): Promise<any>;
9
+ //# sourceMappingURL=reponse-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reponse-handler.d.ts","sourceRoot":"","sources":["../../src/utils/reponse-handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,qBAAa,QAAS,SAAQ,KAAK;IAE/B,QAAQ,CAAC,MAAM,EAAE,MAAM;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM;IAErB,QAAQ,CAAC,IAAI,CAAC;gBAHL,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACN,IAAI,CAAC,KAAK;CAItB;AAED,wBAAsB,eAAe,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CA0BtE"}
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getResponseBody = exports.ApiError = void 0;
4
+ class ApiError extends Error {
5
+ status;
6
+ code;
7
+ data;
8
+ constructor(status, code, message, data) {
9
+ super(message);
10
+ this.status = status;
11
+ this.code = code;
12
+ this.data = data;
13
+ }
14
+ }
15
+ exports.ApiError = ApiError;
16
+ async function getResponseBody(response) {
17
+ const responseText = await response.text();
18
+ if (!response.ok) {
19
+ try {
20
+ const parsedError = JSON.parse(responseText);
21
+ throw new ApiError(response.status, parsedError?.error?.code, parsedError?.error?.title, parsedError?.error?.data);
22
+ }
23
+ catch (e) {
24
+ if (!(e instanceof ApiError)) {
25
+ throw new ApiError(response.status, 'UNKNOWN_ERROR', `${responseText}`);
26
+ }
27
+ else {
28
+ throw e;
29
+ }
30
+ }
31
+ }
32
+ try {
33
+ return JSON.parse(responseText).response;
34
+ }
35
+ catch (error) {
36
+ throw new Error(`Unexpected error. Response was not valid JSON: ${responseText}`);
37
+ }
38
+ }
39
+ exports.getResponseBody = getResponseBody;
@@ -0,0 +1,4 @@
1
+ import { Response as nodeFetchResponse } from 'node-fetch';
2
+ export declare type Response = Pick<nodeFetchResponse, 'text' | 'ok' | 'status'>;
3
+ export declare type Result = any;
4
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/utils/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC3D,oBAAY,QAAQ,GAAG,IAAI,CAAC,iBAAiB,EAAE,MAAM,GAAG,IAAI,GAAG,QAAQ,CAAC,CAAC;AAEzE,oBAAY,MAAM,GAAG,GAAG,CAAC"}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "@forge/sql",
3
+ "version": "0.0.1-experimental-9332276",
4
+ "description": "Forge SQL package",
5
+ "author": "Atlassian",
6
+ "license": "UNLICENSED",
7
+ "main": "out/index.js",
8
+ "types": "out/index.d.ts",
9
+ "files": [
10
+ "out"
11
+ ],
12
+ "scripts": {
13
+ "build": "yarn run clean && yarn run compile",
14
+ "clean": "rm -rf ./out && rm -f tsconfig.tsbuildinfo",
15
+ "compile": "tsc -b -v"
16
+ },
17
+ "devDependencies": {
18
+ "@types/node": "14.18.63",
19
+ "@types/node-fetch": "^2.6.11",
20
+ "expect-type": "^0.17.3",
21
+ "node-fetch": "2.7.0"
22
+ },
23
+ "dependencies": {
24
+ "@forge/api": "^3.9.0"
25
+ }
26
+ }