@thegraphitelab/n8n-nodes-servicetitan 0.1.0
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 +46 -0
- package/dist/credentials/ServiceTitanApi.credentials.d.ts +14 -0
- package/dist/credentials/ServiceTitanApi.credentials.js +121 -0
- package/dist/credentials/ServiceTitanApi.credentials.js.map +1 -0
- package/dist/nodes/ServiceTitan/TglServiceTitan.node.d.ts +4 -0
- package/dist/nodes/ServiceTitan/TglServiceTitan.node.js +57 -0
- package/dist/nodes/ServiceTitan/TglServiceTitan.node.js.map +1 -0
- package/dist/nodes/ServiceTitan/TglServiceTitan.node.json +18 -0
- package/dist/nodes/ServiceTitan/resources/customer/get.d.ts +2 -0
- package/dist/nodes/ServiceTitan/resources/customer/get.js +26 -0
- package/dist/nodes/ServiceTitan/resources/customer/get.js.map +1 -0
- package/dist/nodes/ServiceTitan/resources/customer/index.d.ts +3 -0
- package/dist/nodes/ServiceTitan/resources/customer/index.js +28 -0
- package/dist/nodes/ServiceTitan/resources/customer/index.js.map +1 -0
- package/dist/nodes/ServiceTitan/servicetitan.dark.svg +4 -0
- package/dist/nodes/ServiceTitan/servicetitan.svg +4 -0
- package/dist/package.json +59 -0
- package/package.json +59 -0
package/README.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# @thegraphitelab/n8n-nodes-servicetitan
|
|
2
|
+
|
|
3
|
+
n8n custom node for ServiceTitan. Internal use only — published to GitHub Packages under the `@thegraphitelab` scope.
|
|
4
|
+
|
|
5
|
+
## Status
|
|
6
|
+
|
|
7
|
+
Day-one scope:
|
|
8
|
+
- **Credentials**: OAuth 2.0 client_credentials grant + ST-App-Key header, environment switch (Integration sandbox vs Production)
|
|
9
|
+
- **Customer**: Get by ID
|
|
10
|
+
|
|
11
|
+
More resources (Job, Invoice, Estimate, Technician, Booking, etc.) get added per the `CONTRIBUTING.md` recipe in the repo root.
|
|
12
|
+
|
|
13
|
+
## Credentials
|
|
14
|
+
|
|
15
|
+
Required fields:
|
|
16
|
+
- **Environment** — `Integration (Sandbox)` or `Production`
|
|
17
|
+
- **Tenant ID** — found in ServiceTitan → Settings → API Application Access
|
|
18
|
+
- **App Key** — `ST-App-Key`. TGL-owned application identifier. Same across all TGL clients (controlled by TGL's ServiceTitan developer portal app).
|
|
19
|
+
- **Client ID** — OAuth client ID, per-client
|
|
20
|
+
- **Client Secret** — OAuth client secret, per-client
|
|
21
|
+
|
|
22
|
+
The credential's "Test" button hits `/settings/v2/tenant/{tenantId}/user-roles?page=1&pageSize=1` to verify the full auth chain works.
|
|
23
|
+
|
|
24
|
+
## Auth flow
|
|
25
|
+
|
|
26
|
+
1. n8n calls `preAuthentication` which POSTs `grant_type=client_credentials` to the env-correct token URL
|
|
27
|
+
2. The returned `access_token` (TTL 15min) is cached in the credential data
|
|
28
|
+
3. Each request injects `Authorization: Bearer <token>` AND `ST-App-Key: <appKey>` headers
|
|
29
|
+
4. The `requestDefaults.baseURL` on the node switches between integration and production hosts based on `$credentials.environment`
|
|
30
|
+
|
|
31
|
+
## Local dev
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pnpm dev
|
|
35
|
+
# Opens http://localhost:5678 with an embedded n8n and this node pre-loaded
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Reference
|
|
39
|
+
|
|
40
|
+
Endpoints and operation catalog are ported from `The-Graphite-Lab/advanced_servicetitan_zapier_app`.
|
|
41
|
+
|
|
42
|
+
## TODO
|
|
43
|
+
|
|
44
|
+
- [ ] Port additional resources (Job, Invoice, Estimate, Technician, Customer Note, etc.)
|
|
45
|
+
- [ ] Add polling trigger node (`ServiceTitanTrigger`) using `modifiedOnOrAfter` filter
|
|
46
|
+
- [ ] Wire usage metering to `api.thegraphitelab.com/usage` (matches the Zapier app's billing layer)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { IAuthenticateGeneric, ICredentialDataDecryptedObject, ICredentialTestRequest, ICredentialType, IHttpRequestHelper, INodeProperties } from 'n8n-workflow';
|
|
2
|
+
export declare function getApiHost(environment: string): string;
|
|
3
|
+
export declare class ServiceTitanApi implements ICredentialType {
|
|
4
|
+
name: string;
|
|
5
|
+
displayName: string;
|
|
6
|
+
icon: "file:../nodes/ServiceTitan/servicetitan.svg";
|
|
7
|
+
documentationUrl: string;
|
|
8
|
+
properties: INodeProperties[];
|
|
9
|
+
preAuthentication(this: IHttpRequestHelper, credentials: ICredentialDataDecryptedObject): Promise<{
|
|
10
|
+
accessToken: string;
|
|
11
|
+
}>;
|
|
12
|
+
authenticate: IAuthenticateGeneric;
|
|
13
|
+
test: ICredentialTestRequest;
|
|
14
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ServiceTitanApi = void 0;
|
|
4
|
+
exports.getApiHost = getApiHost;
|
|
5
|
+
/**
|
|
6
|
+
* ServiceTitan auth hosts by environment.
|
|
7
|
+
* Integration ("Sandbox") and Production are entirely separate ST environments —
|
|
8
|
+
* different app registrations, different tenant IDs, different credentials.
|
|
9
|
+
*/
|
|
10
|
+
function getAuthHost(environment) {
|
|
11
|
+
return environment === 'production'
|
|
12
|
+
? 'auth.servicetitan.io'
|
|
13
|
+
: 'auth-integration.servicetitan.io';
|
|
14
|
+
}
|
|
15
|
+
function getApiHost(environment) {
|
|
16
|
+
return environment === 'production'
|
|
17
|
+
? 'api.servicetitan.io'
|
|
18
|
+
: 'api-integration.servicetitan.io';
|
|
19
|
+
}
|
|
20
|
+
class ServiceTitanApi {
|
|
21
|
+
name = 'serviceTitanApi';
|
|
22
|
+
displayName = 'ServiceTitan API';
|
|
23
|
+
icon = 'file:../nodes/ServiceTitan/servicetitan.svg';
|
|
24
|
+
documentationUrl = 'https://developer.servicetitan.io/';
|
|
25
|
+
properties = [
|
|
26
|
+
{
|
|
27
|
+
displayName: 'Environment',
|
|
28
|
+
name: 'environment',
|
|
29
|
+
type: 'options',
|
|
30
|
+
options: [
|
|
31
|
+
{ name: 'Integration (Sandbox)', value: 'integration' },
|
|
32
|
+
{ name: 'Production', value: 'production' },
|
|
33
|
+
],
|
|
34
|
+
default: 'integration',
|
|
35
|
+
description: 'Which ServiceTitan environment to connect to. Integration and Production are entirely separate — they need different app registrations and credentials.',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
displayName: 'Tenant ID',
|
|
39
|
+
name: 'tenantId',
|
|
40
|
+
type: 'string',
|
|
41
|
+
default: '',
|
|
42
|
+
required: true,
|
|
43
|
+
description: 'Found in ServiceTitan → Settings → API Application Access. Treated as a string in URL paths.',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
displayName: 'App Key',
|
|
47
|
+
name: 'appKey',
|
|
48
|
+
type: 'string',
|
|
49
|
+
typeOptions: { password: true },
|
|
50
|
+
default: '',
|
|
51
|
+
required: true,
|
|
52
|
+
description: 'The ST-App-Key. TGL-owned application identifier — the same value is used across all TGL clients. Get this from the TGL ServiceTitan developer portal application.',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
displayName: 'Client ID',
|
|
56
|
+
name: 'clientId',
|
|
57
|
+
type: 'string',
|
|
58
|
+
default: '',
|
|
59
|
+
required: true,
|
|
60
|
+
description: "Per-client OAuth client ID from ServiceTitan → Settings → API Application Access.",
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
displayName: 'Client Secret',
|
|
64
|
+
name: 'clientSecret',
|
|
65
|
+
type: 'string',
|
|
66
|
+
typeOptions: { password: true },
|
|
67
|
+
default: '',
|
|
68
|
+
required: true,
|
|
69
|
+
description: "Per-client OAuth client secret from ServiceTitan → Settings → API Application Access.",
|
|
70
|
+
},
|
|
71
|
+
// accessToken is populated by preAuthentication and consumed by authenticate
|
|
72
|
+
{
|
|
73
|
+
displayName: 'Access Token',
|
|
74
|
+
name: 'accessToken',
|
|
75
|
+
type: 'hidden',
|
|
76
|
+
typeOptions: { password: true },
|
|
77
|
+
default: '',
|
|
78
|
+
},
|
|
79
|
+
];
|
|
80
|
+
async preAuthentication(credentials) {
|
|
81
|
+
const environment = credentials.environment ?? 'integration';
|
|
82
|
+
const clientId = credentials.clientId;
|
|
83
|
+
const clientSecret = credentials.clientSecret;
|
|
84
|
+
const body = new URLSearchParams({
|
|
85
|
+
grant_type: 'client_credentials',
|
|
86
|
+
client_id: clientId,
|
|
87
|
+
client_secret: clientSecret,
|
|
88
|
+
}).toString();
|
|
89
|
+
const response = (await this.helpers.httpRequest({
|
|
90
|
+
method: 'POST',
|
|
91
|
+
url: `https://${getAuthHost(environment)}/connect/token`,
|
|
92
|
+
headers: {
|
|
93
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
94
|
+
},
|
|
95
|
+
body,
|
|
96
|
+
}));
|
|
97
|
+
return { accessToken: response.access_token };
|
|
98
|
+
}
|
|
99
|
+
authenticate = {
|
|
100
|
+
type: 'generic',
|
|
101
|
+
properties: {
|
|
102
|
+
headers: {
|
|
103
|
+
Authorization: '=Bearer {{$credentials.accessToken}}',
|
|
104
|
+
'ST-App-Key': '={{$credentials.appKey}}',
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
test = {
|
|
109
|
+
request: {
|
|
110
|
+
baseURL: '=https://{{$credentials.environment === "production" ? "api.servicetitan.io" : "api-integration.servicetitan.io"}}',
|
|
111
|
+
url: '=/settings/v2/tenant/{{$credentials.tenantId}}/user-roles',
|
|
112
|
+
method: 'GET',
|
|
113
|
+
qs: {
|
|
114
|
+
page: 1,
|
|
115
|
+
pageSize: 1,
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
exports.ServiceTitanApi = ServiceTitanApi;
|
|
121
|
+
//# sourceMappingURL=ServiceTitanApi.credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ServiceTitanApi.credentials.js","sourceRoot":"","sources":["../../credentials/ServiceTitanApi.credentials.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TglServiceTitan = void 0;
|
|
4
|
+
const n8n_workflow_1 = require("n8n-workflow");
|
|
5
|
+
const customer_1 = require("./resources/customer");
|
|
6
|
+
class TglServiceTitan {
|
|
7
|
+
description = {
|
|
8
|
+
displayName: 'ServiceTitan',
|
|
9
|
+
name: 'tglServiceTitan',
|
|
10
|
+
icon: {
|
|
11
|
+
light: 'file:servicetitan.svg',
|
|
12
|
+
dark: 'file:servicetitan.dark.svg',
|
|
13
|
+
},
|
|
14
|
+
group: ['transform'],
|
|
15
|
+
version: 1,
|
|
16
|
+
subtitle: '={{$parameter.operation}}: {{$parameter.resource}}',
|
|
17
|
+
description: 'Interact with the ServiceTitan API',
|
|
18
|
+
defaults: {
|
|
19
|
+
name: 'ServiceTitan',
|
|
20
|
+
},
|
|
21
|
+
usableAsTool: true,
|
|
22
|
+
inputs: [n8n_workflow_1.NodeConnectionTypes.Main],
|
|
23
|
+
outputs: [n8n_workflow_1.NodeConnectionTypes.Main],
|
|
24
|
+
credentials: [
|
|
25
|
+
{
|
|
26
|
+
name: 'serviceTitanApi',
|
|
27
|
+
required: true,
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
requestDefaults: {
|
|
31
|
+
baseURL: '=https://{{$credentials.environment === "production" ? "api.servicetitan.io" : "api-integration.servicetitan.io"}}',
|
|
32
|
+
headers: {
|
|
33
|
+
'Content-Type': 'application/json',
|
|
34
|
+
Accept: 'application/json',
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
properties: [
|
|
38
|
+
{
|
|
39
|
+
displayName: 'Resource',
|
|
40
|
+
name: 'resource',
|
|
41
|
+
type: 'options',
|
|
42
|
+
noDataExpression: true,
|
|
43
|
+
options: [
|
|
44
|
+
{
|
|
45
|
+
name: 'Customer',
|
|
46
|
+
value: 'customer',
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
default: 'customer',
|
|
50
|
+
},
|
|
51
|
+
...customer_1.customerOperations,
|
|
52
|
+
...customer_1.customerFields,
|
|
53
|
+
],
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
exports.TglServiceTitan = TglServiceTitan;
|
|
57
|
+
//# sourceMappingURL=TglServiceTitan.node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TglServiceTitan.node.js","sourceRoot":"","sources":["../../../nodes/ServiceTitan/TglServiceTitan.node.ts"],"names":[],"mappings":";;;AAAA,+CAIsB;AAEtB,mDAA0E;AAE1E,MAAa,eAAe;IAC3B,WAAW,GAAyB;QACnC,WAAW,EAAE,cAAc;QAC3B,IAAI,EAAE,iBAAiB;QACvB,IAAI,EAAE;YACL,KAAK,EAAE,uBAAuB;YAC9B,IAAI,EAAE,4BAA4B;SAClC;QACD,KAAK,EAAE,CAAC,WAAW,CAAC;QACpB,OAAO,EAAE,CAAC;QACV,QAAQ,EAAE,oDAAoD;QAC9D,WAAW,EAAE,oCAAoC;QACjD,QAAQ,EAAE;YACT,IAAI,EAAE,cAAc;SACpB;QACD,YAAY,EAAE,IAAI;QAClB,MAAM,EAAE,CAAC,kCAAmB,CAAC,IAAI,CAAC;QAClC,OAAO,EAAE,CAAC,kCAAmB,CAAC,IAAI,CAAC;QACnC,WAAW,EAAE;YACZ;gBACC,IAAI,EAAE,iBAAiB;gBACvB,QAAQ,EAAE,IAAI;aACd;SACD;QACD,eAAe,EAAE;YAChB,OAAO,EACN,oHAAoH;YACrH,OAAO,EAAE;gBACR,cAAc,EAAE,kBAAkB;gBAClC,MAAM,EAAE,kBAAkB;aAC1B;SACD;QACD,UAAU,EAAE;YACX;gBACC,WAAW,EAAE,UAAU;gBACvB,IAAI,EAAE,UAAU;gBAChB,IAAI,EAAE,SAAS;gBACf,gBAAgB,EAAE,IAAI;gBACtB,OAAO,EAAE;oBACR;wBACC,IAAI,EAAE,UAAU;wBAChB,KAAK,EAAE,UAAU;qBACjB;iBACD;gBACD,OAAO,EAAE,UAAU;aACnB;YACD,GAAG,6BAAkB;YACrB,GAAG,yBAAc;SACjB;KACD,CAAC;CACF;AAlDD,0CAkDC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"node": "n8n-nodes-base.tglServiceTitan",
|
|
3
|
+
"nodeVersion": "1.0",
|
|
4
|
+
"codexVersion": "1.0",
|
|
5
|
+
"categories": ["Sales", "Productivity"],
|
|
6
|
+
"resources": {
|
|
7
|
+
"primaryDocumentation": [
|
|
8
|
+
{
|
|
9
|
+
"url": "https://github.com/thegraphitelab/tgl-custom-n8n-nodes/blob/main/packages/n8n-nodes-servicetitan/README.md"
|
|
10
|
+
}
|
|
11
|
+
],
|
|
12
|
+
"credentialDocumentation": [
|
|
13
|
+
{
|
|
14
|
+
"url": "https://developer.servicetitan.io/"
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.customerGetDescription = void 0;
|
|
4
|
+
exports.customerGetDescription = [
|
|
5
|
+
{
|
|
6
|
+
displayName: 'Customer ID',
|
|
7
|
+
name: 'customerId',
|
|
8
|
+
type: 'string',
|
|
9
|
+
required: true,
|
|
10
|
+
default: '',
|
|
11
|
+
displayOptions: {
|
|
12
|
+
show: {
|
|
13
|
+
resource: ['customer'],
|
|
14
|
+
operation: ['get'],
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
description: 'The ID of the customer to retrieve',
|
|
18
|
+
routing: {
|
|
19
|
+
request: {
|
|
20
|
+
method: 'GET',
|
|
21
|
+
url: '=/crm/v2/tenant/{{$credentials.tenantId}}/customers/{{$value}}',
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
];
|
|
26
|
+
//# sourceMappingURL=get.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get.js","sourceRoot":"","sources":["../../../../../nodes/ServiceTitan/resources/customer/get.ts"],"names":[],"mappings":";;;AAEa,QAAA,sBAAsB,GAAsB;IACxD;QACC,WAAW,EAAE,aAAa;QAC1B,IAAI,EAAE,YAAY;QAClB,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,IAAI;QACd,OAAO,EAAE,EAAE;QACX,cAAc,EAAE;YACf,IAAI,EAAE;gBACL,QAAQ,EAAE,CAAC,UAAU,CAAC;gBACtB,SAAS,EAAE,CAAC,KAAK,CAAC;aAClB;SACD;QACD,WAAW,EAAE,oCAAoC;QACjD,OAAO,EAAE;YACR,OAAO,EAAE;gBACR,MAAM,EAAE,KAAK;gBACb,GAAG,EAAE,gEAAgE;aACrE;SACD;KACD;CACD,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.customerFields = exports.customerOperations = void 0;
|
|
4
|
+
const get_1 = require("./get");
|
|
5
|
+
exports.customerOperations = [
|
|
6
|
+
{
|
|
7
|
+
displayName: 'Operation',
|
|
8
|
+
name: 'operation',
|
|
9
|
+
type: 'options',
|
|
10
|
+
noDataExpression: true,
|
|
11
|
+
displayOptions: {
|
|
12
|
+
show: {
|
|
13
|
+
resource: ['customer'],
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
options: [
|
|
17
|
+
{
|
|
18
|
+
name: 'Get',
|
|
19
|
+
value: 'get',
|
|
20
|
+
description: 'Get a customer by ID',
|
|
21
|
+
action: 'Get a customer',
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
default: 'get',
|
|
25
|
+
},
|
|
26
|
+
];
|
|
27
|
+
exports.customerFields = [...get_1.customerGetDescription];
|
|
28
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../nodes/ServiceTitan/resources/customer/index.ts"],"names":[],"mappings":";;;AACA,+BAA+C;AAElC,QAAA,kBAAkB,GAAsB;IACpD;QACC,WAAW,EAAE,WAAW;QACxB,IAAI,EAAE,WAAW;QACjB,IAAI,EAAE,SAAS;QACf,gBAAgB,EAAE,IAAI;QACtB,cAAc,EAAE;YACf,IAAI,EAAE;gBACL,QAAQ,EAAE,CAAC,UAAU,CAAC;aACtB;SACD;QACD,OAAO,EAAE;YACR;gBACC,IAAI,EAAE,KAAK;gBACX,KAAK,EAAE,KAAK;gBACZ,WAAW,EAAE,sBAAsB;gBACnC,MAAM,EAAE,gBAAgB;aACxB;SACD;QACD,OAAO,EAAE,KAAK;KACd;CACD,CAAC;AAEW,QAAA,cAAc,GAAsB,CAAC,GAAG,4BAAsB,CAAC,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" fill="none">
|
|
2
|
+
<rect width="64" height="64" rx="12" fill="#4F8AFF"/>
|
|
3
|
+
<text x="32" y="42" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif" font-weight="700" font-size="28" fill="#0B1220" text-anchor="middle">ST</text>
|
|
4
|
+
</svg>
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" fill="none">
|
|
2
|
+
<rect width="64" height="64" rx="12" fill="#0F62FE"/>
|
|
3
|
+
<text x="32" y="42" font-family="-apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif" font-weight="700" font-size="28" fill="#FFFFFF" text-anchor="middle">ST</text>
|
|
4
|
+
</svg>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@thegraphitelab/n8n-nodes-servicetitan",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "n8n custom node for ServiceTitan — TGL internal use.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"n8n-community-node-package",
|
|
7
|
+
"n8n",
|
|
8
|
+
"servicetitan",
|
|
9
|
+
"tgl"
|
|
10
|
+
],
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"private": false,
|
|
13
|
+
"author": {
|
|
14
|
+
"name": "The Graphite Lab",
|
|
15
|
+
"email": "support@thegraphitelab.com"
|
|
16
|
+
},
|
|
17
|
+
"main": "index.js",
|
|
18
|
+
"files": [
|
|
19
|
+
"dist"
|
|
20
|
+
],
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"registry": "https://registry.npmjs.org",
|
|
23
|
+
"access": "public"
|
|
24
|
+
},
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "git+https://github.com/thegraphitelab/tgl-custom-n8n-nodes.git",
|
|
28
|
+
"directory": "packages/n8n-nodes-servicetitan"
|
|
29
|
+
},
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=22"
|
|
32
|
+
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "n8n-node build",
|
|
35
|
+
"dev": "n8n-node dev",
|
|
36
|
+
"lint": "n8n-node lint",
|
|
37
|
+
"lint:fix": "n8n-node lint --fix",
|
|
38
|
+
"test": "echo \"no tests yet\" && exit 0"
|
|
39
|
+
},
|
|
40
|
+
"n8n": {
|
|
41
|
+
"n8nNodesApiVersion": 1,
|
|
42
|
+
"strict": true,
|
|
43
|
+
"credentials": [
|
|
44
|
+
"dist/credentials/ServiceTitanApi.credentials.js"
|
|
45
|
+
],
|
|
46
|
+
"nodes": [
|
|
47
|
+
"dist/nodes/ServiceTitan/TglServiceTitan.node.js"
|
|
48
|
+
]
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@eslint/js": "^9.29.0",
|
|
52
|
+
"@n8n/node-cli": "^0.23.0",
|
|
53
|
+
"eslint": "^9.29.0",
|
|
54
|
+
"n8n-workflow": "*"
|
|
55
|
+
},
|
|
56
|
+
"peerDependencies": {
|
|
57
|
+
"n8n-workflow": "*"
|
|
58
|
+
}
|
|
59
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@thegraphitelab/n8n-nodes-servicetitan",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "n8n custom node for ServiceTitan — TGL internal use.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"n8n-community-node-package",
|
|
7
|
+
"n8n",
|
|
8
|
+
"servicetitan",
|
|
9
|
+
"tgl"
|
|
10
|
+
],
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"private": false,
|
|
13
|
+
"author": {
|
|
14
|
+
"name": "The Graphite Lab",
|
|
15
|
+
"email": "support@thegraphitelab.com"
|
|
16
|
+
},
|
|
17
|
+
"main": "index.js",
|
|
18
|
+
"files": [
|
|
19
|
+
"dist"
|
|
20
|
+
],
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"registry": "https://registry.npmjs.org",
|
|
23
|
+
"access": "public"
|
|
24
|
+
},
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "git+https://github.com/thegraphitelab/tgl-custom-n8n-nodes.git",
|
|
28
|
+
"directory": "packages/n8n-nodes-servicetitan"
|
|
29
|
+
},
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=22"
|
|
32
|
+
},
|
|
33
|
+
"n8n": {
|
|
34
|
+
"n8nNodesApiVersion": 1,
|
|
35
|
+
"strict": true,
|
|
36
|
+
"credentials": [
|
|
37
|
+
"dist/credentials/ServiceTitanApi.credentials.js"
|
|
38
|
+
],
|
|
39
|
+
"nodes": [
|
|
40
|
+
"dist/nodes/ServiceTitan/TglServiceTitan.node.js"
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@eslint/js": "^9.29.0",
|
|
45
|
+
"@n8n/node-cli": "^0.23.0",
|
|
46
|
+
"eslint": "^9.29.0",
|
|
47
|
+
"n8n-workflow": "*"
|
|
48
|
+
},
|
|
49
|
+
"peerDependencies": {
|
|
50
|
+
"n8n-workflow": "*"
|
|
51
|
+
},
|
|
52
|
+
"scripts": {
|
|
53
|
+
"build": "n8n-node build",
|
|
54
|
+
"dev": "n8n-node dev",
|
|
55
|
+
"lint": "n8n-node lint",
|
|
56
|
+
"lint:fix": "n8n-node lint --fix",
|
|
57
|
+
"test": "echo \"no tests yet\" && exit 0"
|
|
58
|
+
}
|
|
59
|
+
}
|