npm package diff

Package: @forge/sql

Versions: 2.2.0-next.2 - 2.2.0-next.3

Removed:package/out/utils/response-handler.js

Removed:package/out/utils/__test__/response-handler.test.js

Removed:package/out/utils/response-handler.d.ts.map

Removed:package/out/utils/__test__/response-handler.test.d.ts.map

Removed:package/out/utils/response-handler.d.ts

Removed:package/out/utils/__test__/response-handler.test.d.ts

Added:package/out/utils/error-handling.js

Added:package/out/utils/__test__/error-handling.test.js

Added:package/out/errors.js

Added:package/out/utils/error-handling.d.ts.map

Added:package/out/utils/__test__/error-handling.test.d.ts.map

Added:package/out/errors.d.ts.map

Added:package/out/utils/error-handling.d.ts

Added:package/out/utils/__test__/error-handling.test.d.ts

Added:package/out/errors.d.ts

Modified:package/out/index.js

Index: package/out/index.js
===================================================================
--- package/out/index.js
+++ package/out/index.js
@@ -1,10 +1,13 @@
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
-exports.sql = exports.migrationRunner = exports.errorCodes = void 0;
+exports.ForgeSQLAPIError = exports.ForgeSQLAPIUnknownError = exports.sql = exports.migrationRunner = exports.errorCodes = void 0;
 const sql_1 = require("./sql");
 Object.defineProperty(exports, "sql", { enumerable: true, get: function () { return sql_1.sql; } });
 const errorCodes_1 = require("./errorCodes");
 Object.defineProperty(exports, "errorCodes", { enumerable: true, get: function () { return errorCodes_1.errorCodes; } });
+const errors_1 = require("./errors");
+Object.defineProperty(exports, "ForgeSQLAPIUnknownError", { enumerable: true, get: function () { return errors_1.ForgeSQLAPIUnknownError; } });
+Object.defineProperty(exports, "ForgeSQLAPIError", { enumerable: true, get: function () { return errors_1.ForgeSQLAPIError; } });
 const migration_1 = require("./migration");
 Object.defineProperty(exports, "migrationRunner", { enumerable: true, get: function () { return migration_1.migrationRunner; } });
 exports.default = sql_1.sql;

Modified:package/out/migration.js

Index: package/out/migration.js
===================================================================
--- package/out/migration.js
+++ package/out/migration.js
@@ -1,9 +1,9 @@
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 exports.migrationRunner = exports.MigrationRunner = void 0;
 const sql_1 = require("./sql");
-const response_handler_1 = require("./utils/response-handler");
+const errors_1 = require("./errors");
 const SCHEMA_VERSION_TABLE_CREATE_QUERY = 'CREATE TABLE IF NOT EXISTS __migrations (id BIGINT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255) NOT NULL, migratedAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP);';
 const INSERT_SCHEMA_VERSION_QUERY = 'INSERT INTO __migrations (name) VALUES (?);';
 const LIST_MIGRATIONS_QUERY = 'SELECT id, name, migratedAt FROM __migrations;';
 class MigrationRunner {
@@ -46,15 +46,15 @@
             try {
                 await this.sqlClient.executeRaw(migration.statement);
             }
             catch (error) {
-                throw new response_handler_1.MigrationExecutionError(migration.name, migrationsToRun.map((m) => m.name));
+                throw new errors_1.MigrationExecutionError(migration.name, migrationsToRun.map((m) => m.name));
             }
             try {
                 await this.sqlClient.prepare(INSERT_SCHEMA_VERSION_QUERY).bindParams(migration.name).execute();
             }
             catch (error) {
-                throw new response_handler_1.MigrationCheckPointError(migration.name, migrationsToRun.map((m) => m.name));
+                throw new errors_1.MigrationCheckPointError(migration.name, migrationsToRun.map((m) => m.name));
             }
             migrationsSuccessfullyRun.push(migration.name);
         }
         return migrationsSuccessfullyRun;

Modified:package/out/sql.js

Index: package/out/sql.js
===================================================================
--- package/out/sql.js
+++ package/out/sql.js
@@ -1,10 +1,11 @@
 "use strict";
 Object.defineProperty(exports, "__esModule", { value: true });
 exports.sql = exports.SqlClient = void 0;
 const api_1 = require("@forge/api");
-const response_handler_1 = require("./utils/response-handler");
 const sql_statement_1 = require("./sql-statement");
+const error_handling_1 = require("./utils/error-handling");
+const errors_1 = require("./errors");
 class SqlClient {
     async sendRequest(path, options) {
         const response = await (0, api_1.__fetchProduct)({ provider: 'app', remote: 'sql' })(path, {
             ...options,
@@ -20,9 +21,16 @@
         const response = await this.sendRequest('api/v1/execute', {
             method: 'POST',
             body: JSON.stringify({ query, params, method })
         });
-        return await (0, response_handler_1.getResponseBody)(response);
+        await (0, error_handling_1.checkResponseError)(response);
+        const responseText = await response.text();
+        try {
+            return JSON.parse(responseText);
+        }
+        catch (error) {
+            throw new errors_1.ForgeSQLError(`Unexpected error. Response was not valid JSON: ${responseText}`);
+        }
     }
     prepare(query) {
         return new sql_statement_1.SqlStatement(query, this.storageApi.bind(this));
     }
@@ -32,9 +40,9 @@
     async _provision() {
         const response = await this.sendRequest('/api/v1/provision', {
             method: 'POST'
         });
-        await (0, response_handler_1.getResponseBody)(response);
+        await (0, error_handling_1.checkResponseError)(response, 'Unexpected error in provision request');
     }
 }
 exports.SqlClient = SqlClient;
 exports.sql = new SqlClient();

Modified:package/out/__test__/sql.test.js

Index: package/out/__test__/sql.test.js
===================================================================
--- package/out/__test__/sql.test.js
+++ package/out/__test__/sql.test.js
@@ -3,9 +3,9 @@
 const node_fetch_1 = require("node-fetch");
 const api_1 = require("@forge/api");
 const sql_1 = require("../sql");
 const sql_statement_1 = require("../sql-statement");
-const response_handler_1 = require("../utils/response-handler");
+const errors_1 = require("../errors");
 jest.mock('@forge/api');
 describe('SqlClient', () => {
     let sqlClient;
     let mockFetch;
@@ -82,14 +82,22 @@
                 headers: { 'Content-Type': 'application/json' }
             });
             expect(result).toEqual({ rows: [] });
         });
-        it('should handle errors from getResponseBody', async () => {
+        it('should handle invalid JSON body', async () => {
             const responseText = 'Invalid JSON';
             const response = new node_fetch_1.Response(responseText, { status: 200 });
             mockFetch.mockResolvedValue(response);
-            await expect(sqlClient.storageApi('INVALID SQL QUERY')).rejects.toThrow(`Unexpected error. Response was not valid JSON: ${responseText}`);
+            await expect(sqlClient.storageApi('SELECT * from strange;')).rejects.toThrow(`Unexpected error. Response was not valid JSON: ${responseText}`);
         });
+        it('should throw ForgeSQLAPIError on API error', async () => {
+            const forgeError = { code: 'INVALID_QUERY', message: 'Invalid SQL query' };
+            const mockResponse = new node_fetch_1.Response(JSON.stringify(forgeError), {
+                status: 400
+            });
+            mockFetch.mockResolvedValue(mockResponse);
+            await expect(sqlClient.storageApi('INVALID SQL QUERY')).rejects.toThrow(new errors_1.ForgeSQLAPIError(mockResponse, forgeError));
+        });
     });
     describe('prepare', () => {
         it('should return a SqlStatement instance with query', () => {
             const statement = sqlClient.prepare('INSERT INTO test VALUES (?, ?)');
@@ -111,9 +119,41 @@
                 .execute();
             expect(result).toEqual(mockResult);
         });
         it('should handle API errors', async () => {
-            mockFetch.mockResolvedValue(new node_fetch_1.Response(JSON.stringify({ code: 'INVALID_QUERY', message: 'Invalid SQL query' }), { status: 400 }));
-            await expect(sqlClient.executeRaw('INVALID SQL QUERY')).rejects.toThrow(new response_handler_1.ApiError(400, 'INVALID_QUERY', 'Invalid SQL query'));
+            const forgeError = { code: 'INVALID_QUERY', message: 'Invalid SQL query' };
+            const mockResponse = new node_fetch_1.Response(JSON.stringify(forgeError), {
+                status: 400
+            });
+            mockFetch.mockResolvedValue(mockResponse);
+            await expect(sqlClient.executeRaw('INVALID SQL QUERY')).rejects.toThrow(new errors_1.ForgeSQLAPIError(mockResponse, forgeError));
         });
     });
+    describe('_provision', () => {
+        it('should work if the response is a 201', async () => {
+            const mockResponse = new node_fetch_1.Response(JSON.stringify({ success: true }), {
+                status: 201,
+                statusText: 'OK'
+            });
+            mockFetch.mockResolvedValue(mockResponse);
+            await sqlClient._provision();
+            expect(mockFetch).toHaveBeenCalledWith('/api/v1/provision', expect.objectContaining({ method: 'POST' }));
+        });
+        it('should work if the response is a 204', async () => {
+            const mockResponse = new node_fetch_1.Response(undefined, {
+                status: 204,
+                statusText: 'OK'
+            });
+            mockFetch.mockResolvedValue(mockResponse);
+            await sqlClient._provision();
+            expect(mockFetch).toHaveBeenCalledWith('/api/v1/provision', expect.objectContaining({ method: 'POST' }));
+        });
+        it('should throw an error if the response is not 201 or 204', async () => {
+            const mockResponse = new node_fetch_1.Response('Server Error', {
+                status: 500,
+                statusText: 'Bad Request'
+            });
+            mockFetch.mockResolvedValue(mockResponse);
+            await expect(sqlClient._provision()).rejects.toThrow('Unexpected error in provision request');
+        });
+    });
 });

Modified:package/package.json

Index: package/package.json
===================================================================
--- package/package.json
+++ package/package.json
@@ -1,7 +1,7 @@
 {
   "name": "@forge/sql",
-  "version": "2.2.0-next.2",
+  "version": "2.2.0-next.3",
   "description": "Forge SQL sdk",
   "author": "Atlassian",
   "license": "UNLICENSED",
   "main": "out/index.js",

Modified:package/out/errorCodes.d.ts.map

Index: package/out/errorCodes.d.ts.map
===================================================================
--- package/out/errorCodes.d.ts.map
+++ package/out/errorCodes.d.ts.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"errorCodes.d.ts","sourceRoot":"","sources":["../src/errorCodes.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU;;;;;CAKtB,CAAC"}
\ No newline at end of file
+{"version":3,"file":"errorCodes.d.ts","sourceRoot":"","sources":["../src/errorCodes.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU;;;;;CAUb,CAAC"}
\ No newline at end of file

Modified:package/out/index.d.ts.map

Index: package/out/index.d.ts.map
===================================================================
--- package/out/index.d.ts.map
+++ package/out/index.d.ts.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEjE,YAAY,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;AAE5C,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,GAAG,EAAE,CAAC;AAC5C,eAAe,GAAG,CAAC"}
\ No newline at end of file
+{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AACjF,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,OAAO,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEjE,YAAY,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;AAE5C,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,GAAG,EAAE,UAAU,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,CAAC;AAEnG,eAAe,GAAG,CAAC"}
\ No newline at end of file

Modified:package/out/sql.d.ts.map

Index: package/out/sql.d.ts.map
===================================================================
--- package/out/sql.d.ts.map
+++ package/out/sql.d.ts.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"sql.d.ts","sourceRoot":"","sources":["../src/sql.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAY,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE9D,qBAAa,SAAS;YACN,WAAW;IAYnB,UAAU,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAE,aAAkB,EAAE,MAAM,SAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAQhH,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAI1D,UAAU,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAI9D,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;CAMlC;AAED,eAAO,MAAM,GAAG,WAAkB,CAAC"}
\ No newline at end of file
+{"version":3,"file":"sql.d.ts","sourceRoot":"","sources":["../src/sql.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAI9D,qBAAa,SAAS;YACN,WAAW;IAYnB,UAAU,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAE,aAAkB,EAAE,MAAM,SAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAiBhH,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAI1D,UAAU,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAK9D,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;CASlC;AAED,eAAO,MAAM,GAAG,WAAkB,CAAC"}
\ No newline at end of file

Modified:package/out/utils/types.d.ts.map

Index: package/out/utils/types.d.ts.map
===================================================================
--- package/out/utils/types.d.ts.map
+++ package/out/utils/types.d.ts.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/utils/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,oBAAY,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,QAAQ,CAAC,CAAC;AAGnE,MAAM,WAAW,mBAAmB;IAElC,YAAY,EAAE,MAAM,CAAC;IAErB,UAAU,EAAE,MAAM,CAAC;IAEnB,IAAI,EAAE,MAAM,CAAC;IAEb,QAAQ,EAAE,MAAM,CAAC;IAEjB,YAAY,EAAE,MAAM,CAAC;IAErB,aAAa,EAAE,MAAM,CAAC;CACvB;AAWD,MAAM,WAAW,MAAM,CAAC,QAAQ,GAAG,GAAG;IAKpC,IAAI,EAAE,QAAQ,SAAS,mBAAmB,GAAG,mBAAmB,GAAG,QAAQ,EAAE,CAAC;IAM9E,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAChC"}
\ No newline at end of file
+{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/utils/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC,oBAAY,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,QAAQ,CAAC,CAAC;AAGnE,MAAM,WAAW,mBAAmB;IAElC,YAAY,EAAE,MAAM,CAAC;IAErB,UAAU,EAAE,MAAM,CAAC;IAEnB,IAAI,EAAE,MAAM,CAAC;IAEb,QAAQ,EAAE,MAAM,CAAC;IAEjB,YAAY,EAAE,MAAM,CAAC;IAErB,aAAa,EAAE,MAAM,CAAC;CACvB;AAWD,MAAM,WAAW,MAAM,CAAC,QAAQ,GAAG,GAAG;IAKpC,IAAI,EAAE,QAAQ,SAAS,mBAAmB,GAAG,mBAAmB,GAAG,QAAQ,EAAE,CAAC;IAO9E,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAChC"}
\ No newline at end of file

Modified:package/out/errorCodes.d.ts

Index: package/out/errorCodes.d.ts
===================================================================
--- package/out/errorCodes.d.ts
+++ package/out/errorCodes.d.ts
@@ -1,7 +1,7 @@
 export declare const errorCodes: {
-    SQL_EXECUTION_ERROR: string;
-    INVALID_SQL_QUERY: string;
-    QUERY_TIMED_OUT: string;
-    APP_NOT_ENABLED: string;
+    readonly SQL_EXECUTION_ERROR: "SQL_EXECUTION_ERROR";
+    readonly INVALID_SQL_QUERY: "INVALID_SQL_QUERY";
+    readonly QUERY_TIMED_OUT: "QUERY_TIMED_OUT";
+    readonly APP_NOT_ENABLED: "APP_NOT_ENABLED";
 };
 //# sourceMappingURL=errorCodes.d.ts.map
\ No newline at end of file

Modified:package/out/index.d.ts

Index: package/out/index.d.ts
===================================================================
--- package/out/index.d.ts
+++ package/out/index.d.ts
@@ -1,8 +1,9 @@
 import { sql } from './sql';
 import { errorCodes } from './errorCodes';
+import { ForgeError, ForgeSQLAPIUnknownError, ForgeSQLAPIError } from './errors';
 import { migrationRunner } from './migration';
 import type { Result, UpdateQueryResponse } from './utils/types';
 export type { Result, UpdateQueryResponse };
-export { errorCodes, migrationRunner, sql };
+export { errorCodes, migrationRunner, sql, ForgeError, ForgeSQLAPIUnknownError, ForgeSQLAPIError };
 export default sql;
 //# sourceMappingURL=index.d.ts.map
\ No newline at end of file