{"_id":"@brokenrubik/ns-suitetalk-m2m-rest","_rev":"4-2e56df3e39cdae323d09f026934e8df1","name":"@brokenrubik/ns-suitetalk-m2m-rest","dist-tags":{"latest":"1.1.0"},"versions":{"1.0.0":{"name":"@brokenrubik/ns-suitetalk-m2m-rest","version":"1.0.0","keywords":["netsuite","suitetalk","rest","api","m2m","oauth2"],"author":{"name":"Leandro","email":"leandro@brokenrubik.co"},"license":"ISC","_id":"@brokenrubik/ns-suitetalk-m2m-rest@1.0.0","maintainers":[{"name":"brokenrubik","email":"team@brokenrubik.co"}],"dist":{"shasum":"dbc796a22232e0da925d20b1cce0ccb121feb0b2","tarball":"https://registry.npmjs.org/@brokenrubik/ns-suitetalk-m2m-rest/-/ns-suitetalk-m2m-rest-1.0.0.tgz","fileCount":5,"integrity":"sha512-wPVdUpcVY9CW2YM0EsCZ8JrkB9Qw6b5Jk4reJeUeGP4TEPVV8XszYONdE27fRbYDeD0KZgBaEQ614cVVGyFwEw==","signatures":[{"sig":"MEUCIQCR3CFQ7cykz4blvb/E+UNcF5+xjwlO4SHIzPZHTQG6SwIgIgjaSYzyuyr41wp4Mesx6rQI7S84Lr1QxHFagpG9ueQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":12383},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"779f129b33d562196fb5b168ca9224560fc44c03","scripts":{"build":"tsc","prepare":"npm run build"},"_npmUser":{"name":"brokenrubik","email":"team@brokenrubik.co"},"_npmVersion":"10.9.0","description":"A client for the NetSuite REST API using M2M OAuth 2.0 authentication.","directories":{},"_nodeVersion":"23.3.0","dependencies":{"node-fetch":"^3.3.0","jsonwebtoken":"^9.0.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.0.0","@types/node":"^20.0.0","@types/node-fetch":"^2.6.0","@types/jsonwebtoken":"^9.0.0"},"_npmOperationalInternal":{"tmp":"tmp/ns-suitetalk-m2m-rest_1.0.0_1759434128874_0.5876104259367325","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Package no longer supported. Contact Support at https://www.npmjs.com/support for more info."},"1.0.1":{"name":"@brokenrubik/ns-suitetalk-m2m-rest","version":"1.0.1","keywords":["netsuite","suitetalk","rest","api","m2m","oauth2"],"author":{"name":"Leandro","email":"leandro@brokenrubik.co"},"license":"ISC","_id":"@brokenrubik/ns-suitetalk-m2m-rest@1.0.1","maintainers":[{"name":"brokenrubik","email":"team@brokenrubik.co"}],"dist":{"shasum":"e560379bb4a72ac010679e1752e8819f18ef9ccc","tarball":"https://registry.npmjs.org/@brokenrubik/ns-suitetalk-m2m-rest/-/ns-suitetalk-m2m-rest-1.0.1.tgz","fileCount":6,"integrity":"sha512-5H9peLNJQdO74JFtDgN8BpsZAdgJx5zygxemF3YGZv/LKujm5MXuMhEjX2HP56x/fMrjKqpyakkIPSwWT5+HdQ==","signatures":[{"sig":"MEYCIQC5fTpZjalso/qNRqGvSBWOAznsECeGjZMj0doZzDQxOwIhAJPl69FKTaa2Isx7RZ37evOXH7XPpEHiqRF+foB8/6sZ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":17072},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"3c39a1d53212bb9658836fa9a90cb1dbc8a11e71","scripts":{"build":"tsc","prepare":"npm run build","publish:npm":"npm publish --access public","version:major":"npm version major && npm run publish:npm","version:minor":"npm version minor && npm run publish:npm","version:patch":"npm version patch && npm run publish:npm"},"_npmUser":{"name":"brokenrubik","email":"team@brokenrubik.co"},"_npmVersion":"10.9.3","description":"A client for the NetSuite REST API using M2M OAuth 2.0 authentication.","directories":{},"_nodeVersion":"22.20.0","dependencies":{"node-fetch":"^3.3.0","jsonwebtoken":"^9.0.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.0.0","@types/node":"^20.0.0","@types/node-fetch":"^2.6.0","@types/jsonwebtoken":"^9.0.0"},"_npmOperationalInternal":{"tmp":"tmp/ns-suitetalk-m2m-rest_1.0.1_1760127583324_0.23253224496817393","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Package no longer supported. Contact Support at https://www.npmjs.com/support for more info."},"1.1.0":{"name":"@brokenrubik/ns-suitetalk-m2m-rest","version":"1.1.0","keywords":["netsuite","suitetalk","rest","api","m2m","oauth2"],"author":{"name":"Leandro","email":"leandro@brokenrubik.co"},"license":"ISC","_id":"@brokenrubik/ns-suitetalk-m2m-rest@1.1.0","maintainers":[{"name":"brokenrubik","email":"team@brokenrubik.co"}],"dist":{"shasum":"635338dcc8079e788fe40ec8789256cae9642145","tarball":"https://registry.npmjs.org/@brokenrubik/ns-suitetalk-m2m-rest/-/ns-suitetalk-m2m-rest-1.1.0.tgz","fileCount":6,"integrity":"sha512-3+bmi/+Ixdjjc9Q766am60GCwcJxgE4UuhP9GmzGcquXYWXoMjtzaLpgv1S3Ttj2gfCnwVDikoxrof9S8RI7ug==","signatures":[{"sig":"MEQCIGuKb3Qc1KkFX7vbFz5ezIQ3Gsxkc4BOGBC1FoAAl0azAiAn9dRiThitbg7//+7Z2WUP4uFJA7bR4h+fz9nXEScieg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":24560},"main":"dist/index.js","types":"dist/index.d.ts","engines":{"node":">=12.20.0"},"gitHead":"e27b1eaf5d6040fb44cee0acc2cb1f84d4a0bd9b","scripts":{"build":"tsc","prepare":"npm run build","publish:major":"npm version major && npm publish --access public","publish:minor":"npm version minor && npm publish --access public","publish:patch":"npm version patch && npm publish --access public"},"_npmUser":{"name":"brokenrubik","email":"team@brokenrubik.co"},"_npmVersion":"10.9.3","description":"A client for the NetSuite REST API using M2M OAuth 2.0 authentication.","directories":{},"_nodeVersion":"22.20.0","dependencies":{"node-fetch":"^3.3.0","jsonwebtoken":"^9.0.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.0.0","@types/node":"^20.0.0","@types/node-fetch":"^2.6.0","@types/jsonwebtoken":"^9.0.0"},"_npmOperationalInternal":{"tmp":"tmp/ns-suitetalk-m2m-rest_1.1.0_1760129304505_0.3642939656330053","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Package no longer supported. Contact Support at https://www.npmjs.com/support for more info."}},"time":{"created":"2025-10-02T19:42:08.761Z","modified":"2026-04-05T19:04:06.987Z","1.0.0":"2025-10-02T19:42:09.059Z","1.0.1":"2025-10-10T20:19:43.499Z","1.1.0":"2025-10-10T20:48:24.700Z"},"author":{"name":"Leandro","email":"leandro@brokenrubik.co"},"license":"ISC","keywords":["netsuite","suitetalk","rest","api","m2m","oauth2"],"description":"A client for the NetSuite REST API using M2M OAuth 2.0 authentication.","maintainers":[{"name":"brokenrubik","email":"team@brokenrubik.co"}],"readme":"# NetSuite SuiteTalk M2M REST Client\n\nA TypeScript/Node.js client for the NetSuite SuiteTalk REST API using OAuth 2.0 Machine-to-Machine (M2M) authentication with certificate-based JWT.\n\n## Features\n\n- 🔐 OAuth 2.0 M2M authentication with certificate-based JWT (PS256)\n- 🔄 Automatic token caching and refresh with manual controls\n- 📦 Full TypeScript support with type definitions and generics\n- 🛠️ Comprehensive CRUD operations for NetSuite records\n- 📊 SuiteQL query execution\n- ⚡ Built-in error handling with custom error class\n- ⏱️ Configurable request timeouts\n- ✅ Input validation for all parameters\n- 🎯 Simple, intuitive API\n\n## Installation\n\n```bash\nnpm install @brokenrubik/ns-suitetalk-m2m-rest\n```\n\n## Prerequisites\n\nBefore using this client, you need to set up OAuth 2.0 M2M authentication in NetSuite:\n\n1. Generate a certificate and private key\n2. Create an Integration Record in NetSuite\n3. Note your Account ID, Integration Client ID, and Certificate ID\n\n## Official Documentation\n\nFor detailed information about NetSuite SuiteTalk REST API and OAuth 2.0 setup, refer to these official resources:\n\n- [SuiteTalk REST Web Services Overview](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/chapter_1540391670.html)\n- [OAuth 2.0 for SuiteTalk REST Web Services](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_1540810951.html)\n- [Setting Up OAuth 2.0](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_1545222128.html)\n- [REST Web Services Record API](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_157909186990.html)\n\n## Usage\n\n### Basic Setup\n\n```typescript\nimport { NetSuiteService } from \"@brokenrubik/ns-suitetalk-m2m-rest\";\n\nconst netsuiteClient = new NetSuiteService({\n  accountId: \"YOUR_ACCOUNT_ID\",\n  integrationClientId: \"YOUR_CLIENT_ID\",\n  certificateId: \"YOUR_CERTIFICATE_ID\",\n  privateKey: `-----BEGIN PRIVATE KEY-----\nYOUR_PRIVATE_KEY_HERE\n-----END PRIVATE KEY-----`,\n  // Optional configuration\n  requestTimeout: 30000, // 30 seconds (default)\n  tokenExpiryMargin: 60000, // 1 minute safety margin (default)\n});\n```\n\n### API Methods\n\n#### SuiteQL Queries\n\nExecute SuiteQL queries to retrieve data:\n\n```typescript\nconst result = await netsuiteClient.executeSuiteQLQuery(\n  \"SELECT id, companyname FROM customer WHERE email = ?\",\n);\n```\n\n#### List Records\n\nRetrieve a list of records with optional filtering and pagination:\n\n```typescript\nconst customers = await netsuiteClient.listRecords(\"customer\", {\n  limit: 10,\n  offset: 0,\n  q: 'companyname CONTAINS \"Acme\"',\n});\n```\n\n#### Get Record\n\nRetrieve a single record by ID:\n\n```typescript\nconst customer = await netsuiteClient.getRecord(\"customer\", \"12345\");\n```\n\n#### Create Record\n\nCreate a new record:\n\n```typescript\nconst newCustomer = await netsuiteClient.createRecord(\"customer\", {\n  companyname: \"Acme Corporation\",\n  email: \"contact@acme.com\",\n});\n```\n\n#### Update Record\n\nUpdate an existing record:\n\n```typescript\nconst updated = await netsuiteClient.updateRecord(\"customer\", \"12345\", {\n  email: \"newemail@acme.com\",\n});\n```\n\n#### Delete Record\n\nDelete a record:\n\n```typescript\nawait netsuiteClient.deleteRecord(\"customer\", \"12345\");\n```\n\n#### Custom SuiteTalk Requests\n\nMake custom requests to any SuiteTalk endpoint:\n\n```typescript\nconst response = await netsuiteClient.suitetalkRequest(\n  \"/services/rest/record/v1/customrecord_myrecord\",\n  \"GET\",\n  null,\n  { \"Custom-Header\": \"value\" },\n);\n```\n\n## Configuration\n\n### NetSuiteServiceOptions\n\n| Property              | Type   | Required | Default | Description                                        |\n| --------------------- | ------ | -------- | ------- | -------------------------------------------------- |\n| `accountId`           | string | Yes      | -       | Your NetSuite account ID (e.g., \"1234567\")         |\n| `integrationClientId` | string | Yes      | -       | Client ID from your Integration Record             |\n| `certificateId`       | string | Yes      | -       | Certificate ID from your Integration Record        |\n| `privateKey`          | string | Yes      | -       | Private key in PEM format                          |\n| `requestTimeout`      | number | No       | 30000   | Request timeout in milliseconds                    |\n| `tokenExpiryMargin`   | number | No       | 60000   | Token expiry safety margin in milliseconds         |\n\n## Error Handling\n\nThe client uses a custom `NetSuiteError` class with enhanced error information:\n\n```typescript\nimport { NetSuiteError } from \"@brokenrubik/ns-suitetalk-m2m-rest\";\n\ntry {\n  const record = await netsuiteClient.getRecord(\"customer\", \"12345\");\n} catch (error) {\n  if (error instanceof NetSuiteError) {\n    console.error(\"Error:\", error.message);\n    console.error(\"Status:\", error.status);\n    console.error(\"Details:\", error.body);\n  } else {\n    console.error(\"Unexpected error:\", error);\n  }\n}\n```\n\n## Token Caching\n\nAccess tokens are automatically cached and refreshed when expired, with a configurable safety margin (default: 1 minute).\n\n### Token Cache Controls\n\n```typescript\n// Clear the cached token (forces new token on next request)\nnetsuiteClient.clearTokenCache();\n\n// Check if a valid token is cached\nconst hasToken = netsuiteClient.hasValidToken();\n\n// Get token expiration timestamp\nconst expiration = netsuiteClient.getTokenExpiration();\nif (expiration) {\n  console.log(\"Token expires at:\", new Date(expiration));\n}\n```\n\n## TypeScript Support\n\nFull TypeScript definitions are included with support for generics:\n\n```typescript\nimport {\n  NetSuiteService,\n  NetSuiteServiceOptions,\n  NetSuiteCredentials,\n  NetSuiteHttpMethod,\n  NetSuiteError,\n  ListRecordsOptions,\n  ListRecordsResponse,\n  SuiteQLResponse,\n} from \"@brokenrubik/ns-suitetalk-m2m-rest\";\n\n// Use generics for type-safe responses\ninterface Customer {\n  id: string;\n  companyname: string;\n  email: string;\n}\n\nconst customer = await netsuiteClient.getRecord<Customer>(\"customer\", \"123\");\n// customer is typed as Customer\n\nconst customers = await netsuiteClient.listRecords<Customer>(\"customer\");\n// customers is typed as ListRecordsResponse<Customer>\n```\n","readmeFilename":"README.md"}