Repository: netlify/build (js)

Issue:
Cannot instantiate Netlify client in JavaScript with Bun
### Describe the bug

When I try to create a client with these lines:

```typescript
// file foo.ts
import { NetlifyAPI } from 'netlify';

try {
    const client = new NetlifyAPI("my-token");
    console.log('Client created successfully');
} catch (error) {
    console.error('Error creating Netlify client:', error);
}
```

I get the following error
```bash
bun run foo.ts 
1 | import omit from 'omit.js';
2 | import { openApiSpec } from './open_api.js';
3 | // Retrieve all OpenAPI operations
4 | export const getOperations = function () {
5 |     return Object.entries(openApiSpec.paths).flatMap(([path, pathItem]) => {
6 |         const operations = omit.default(pathItem, ['parameters']);
                               ^
TypeError: omit.default is not a function. (In 'omit.default(pathItem, ["parameters"])', 'omit.default' is undefined)
      at /[redacted]/node_modules/netlify/lib/operations.js:6:28
      at /[redacted]/node_modules/netlify/lib/index.js:87:24
```

### Steps to reproduce

1. Create new file `foo.ts`
2. Add dependency via bun with `bun add netlify`
3. paste content provided above in the file
4. execute with `bun run foo.ts`

### Configuration

-

### Deploy logs

- 

Pull request:
fix: remove problematic `omit.js` dependency
#### Summary

Something about this module is off. It works with some runtimes/bundlers but not others. It seems to have issues with [webpack](https://github.com/benjycui/omit.js/issues/10) and with [bun](https://github.com/netlify/build/issues/5613).

I just inlined it. It's tiny anyway.

Fixes #5613.

Patch:
diff --git a/package-lock.json b/package-lock.json
index 9a5f0f9d5..efd7153d2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -28861,7 +28861,6 @@
         "lodash-es": "^4.17.21",
         "micro-api-client": "^3.3.0",
         "node-fetch": "^3.0.0",
-        "omit.js": "^2.0.2",
         "p-wait-for": "^5.0.0",
         "qs": "^6.9.6"
       },
diff --git a/packages/js-client/package.json b/packages/js-client/package.json
index 3d76f22d7..128ab082f 100644
--- a/packages/js-client/package.json
+++ b/packages/js-client/package.json
@@ -45,7 +45,6 @@
     "lodash-es": "^4.17.21",
     "micro-api-client": "^3.3.0",
     "node-fetch": "^3.0.0",
-    "omit.js": "^2.0.2",
     "p-wait-for": "^5.0.0",
     "qs": "^6.9.6"
   },
diff --git a/packages/js-client/src/methods/response.js b/packages/js-client/src/methods/response.js
index 548a153b9..5316c46aa 100644
--- a/packages/js-client/src/methods/response.js
+++ b/packages/js-client/src/methods/response.js
@@ -1,5 +1,6 @@
 import { JSONHTTPError, TextHTTPError } from 'micro-api-client'
-import omit from 'omit.js'
+
+import omit from '../omit.js'
 
 // Read and parse the HTTP response
 export const parseResponse = async function (response) {
@@ -44,7 +45,7 @@ const addFallbackErrorMessage = function (error, textResponse) {
 }
 
 export const getFetchError = function (error, url, opts) {
-  const data = omit.default(opts, ['Authorization'])
+  const data = omit(opts, ['Authorization'])
   if (error.name !== 'FetchError') {
     error.name = 'FetchError'
   }
diff --git a/packages/js-client/src/omit.ts b/packages/js-client/src/omit.ts
new file mode 100644
index 000000000..0234afac6
--- /dev/null
+++ b/packages/js-client/src/omit.ts
@@ -0,0 +1,10 @@
+export default function omit<T extends Record<string | number | symbol, unknown>, K extends keyof T>(
+  obj: T,
+  keys: K[],
+): Omit<T, K> {
+  const shallowCopy = { ...obj }
+  for (const key of keys) {
+    delete shallowCopy[key]
+  }
+  return shallowCopy
+}
diff --git a/packages/js-client/src/operations.js b/packages/js-client/src/operations.js
index 2b5bcce69..c6fb8f4e0 100644
--- a/packages/js-client/src/operations.js
+++ b/packages/js-client/src/operations.js
@@ -1,11 +1,10 @@
-import omit from 'omit.js'
-
+import omit from './omit.js'
 import { openApiSpec } from './open_api.js'
 
 // Retrieve all OpenAPI operations
 export const getOperations = function () {
   return Object.entries(openApiSpec.paths).flatMap(([path, pathItem]) => {
-    const operations = omit.default(pathItem, ['parameters'])
+    const operations = omit(pathItem, ['parameters'])
     return Object.entries(operations).map(([method, operation]) => {
       const parameters = getParameters(pathItem.parameters, operation.parameters)
       return { ...operation, verb: method, path, parameters }


Test patch:
diff --git a/packages/js-client/src/omit.test.ts b/packages/js-client/src/omit.test.ts
new file mode 100644
index 000000000..9a13711d3
--- /dev/null
+++ b/packages/js-client/src/omit.test.ts
@@ -0,0 +1,16 @@
+import test from 'ava'
+
+import omit from './omit.js'
+
+test('creates a shallow copy', (t) => {
+  const obj = { name: 'Benjy' }
+  const copy = omit(obj, [])
+  t.not(obj, copy)
+  t.deepEqual(obj, copy)
+})
+
+test('returns an object without the specified fields', (t) => {
+  const obj = { name: 'Benjy', age: 18 }
+  t.deepEqual(omit(obj, ['age']), { name: 'Benjy' })
+  t.deepEqual(omit(obj, ['name', 'age']), {})
+})