@timesheet/plugin-xero 1.0.1
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 +41 -0
- package/dist/handlers/handleWebhook.d.ts +5 -0
- package/dist/handlers/handleWebhook.js +16 -0
- package/dist/handlers/listExternalProjects.d.ts +2 -0
- package/dist/handlers/listExternalProjects.js +15 -0
- package/dist/handlers/runFullSync.d.ts +5 -0
- package/dist/handlers/runFullSync.js +17 -0
- package/dist/handlers/syncTaskFromExternal.d.ts +5 -0
- package/dist/handlers/syncTaskFromExternal.js +16 -0
- package/dist/handlers/syncTaskToExternal.d.ts +6 -0
- package/dist/handlers/syncTaskToExternal.js +17 -0
- package/dist/handlers/testConnection.d.ts +5 -0
- package/dist/handlers/testConnection.js +16 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +17 -0
- package/manifest.json +150 -0
- package/package.json +22 -0
package/README.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Xero Sync
|
|
2
|
+
|
|
3
|
+
> Intended integration between Timesheet and Xero. Early scaffold, not yet functional.
|
|
4
|
+
|
|
5
|
+
This package is an early scaffold. The handlers are wired into the plugin runtime and return placeholder results (for example, `testConnection` reports OK and `syncTaskToExternal` echoes the task id), but no calls are made to the Xero API yet. The manifest below describes the intended shape of the integration rather than working behavior.
|
|
6
|
+
|
|
7
|
+
- Package: `@timesheet/plugin-xero`
|
|
8
|
+
- Manifest id: `xero-sync`
|
|
9
|
+
- Category: accounting
|
|
10
|
+
- Status: scaffold (no Xero API integration implemented)
|
|
11
|
+
|
|
12
|
+
## Authentication
|
|
13
|
+
|
|
14
|
+
OAuth 2.0. Scopes are placeholders (`read`, `write`) and will be replaced with the real Xero scopes when the integration is implemented.
|
|
15
|
+
|
|
16
|
+
## Configuration
|
|
17
|
+
|
|
18
|
+
| Option | Required | Default | Description |
|
|
19
|
+
| --- | --- | --- | --- |
|
|
20
|
+
| `syncDirection` | yes | `bidirectional` | One of `bidirectional`, `timesheet-to-external`, `external-to-timesheet`. |
|
|
21
|
+
|
|
22
|
+
## Mappings
|
|
23
|
+
|
|
24
|
+
- **Project mapping**: Timesheet project to Xero (placeholder, not yet wired to real Xero entities).
|
|
25
|
+
|
|
26
|
+
## Triggers
|
|
27
|
+
|
|
28
|
+
- **Task Created** (event): scaffolded handler for new Timesheet tasks.
|
|
29
|
+
- **Xero Webhook** (webhook): scaffolded inbound endpoint.
|
|
30
|
+
- **Scheduled Full Sync** (daily at 02:00 UTC): scaffolded background sync.
|
|
31
|
+
- **Manual Sync** (user action): scaffolded sync from the integration settings page.
|
|
32
|
+
|
|
33
|
+
## Development
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm install # or: npm ci
|
|
37
|
+
npm run build # compile TypeScript into dist/
|
|
38
|
+
npm run typecheck
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The package ships `dist/` and `manifest.json`; the sandboxed plugin runtime loads it by package name, version, and integrity. Shared tests live in `integrations/tests/` and run from the `integrations/` root with `npm test`.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleWebhook = void 0;
|
|
4
|
+
const integration_sdk_1 = require("@timesheet/integration-sdk");
|
|
5
|
+
const SYSTEM = 'xero';
|
|
6
|
+
exports.handleWebhook = (0, integration_sdk_1.defineHandler)(async (input, context) => {
|
|
7
|
+
context.logger.info('Handling webhook', {
|
|
8
|
+
system: SYSTEM,
|
|
9
|
+
method: input.method,
|
|
10
|
+
installationId: context.installationId
|
|
11
|
+
});
|
|
12
|
+
return {
|
|
13
|
+
system: SYSTEM,
|
|
14
|
+
handled: true
|
|
15
|
+
};
|
|
16
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.listExternalProjects = void 0;
|
|
4
|
+
const integration_sdk_1 = require("@timesheet/integration-sdk");
|
|
5
|
+
const SYSTEM = 'xero';
|
|
6
|
+
exports.listExternalProjects = (0, integration_sdk_1.defineHandler)(async (_input, context) => {
|
|
7
|
+
context.logger.info('Listing external projects', {
|
|
8
|
+
system: SYSTEM,
|
|
9
|
+
installationId: context.installationId
|
|
10
|
+
});
|
|
11
|
+
return [
|
|
12
|
+
{ id: 'xero-project-1', name: 'Xero Sync Project 1' },
|
|
13
|
+
{ id: 'xero-project-2', name: 'Xero Sync Project 2' }
|
|
14
|
+
];
|
|
15
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runFullSync = void 0;
|
|
4
|
+
const integration_sdk_1 = require("@timesheet/integration-sdk");
|
|
5
|
+
const SYSTEM = 'xero';
|
|
6
|
+
exports.runFullSync = (0, integration_sdk_1.defineHandler)(async (_input, context) => {
|
|
7
|
+
context.logger.info('Running full sync', {
|
|
8
|
+
system: SYSTEM,
|
|
9
|
+
installationId: context.installationId,
|
|
10
|
+
syncDirection: context.config?.syncDirection ?? 'bidirectional'
|
|
11
|
+
});
|
|
12
|
+
return {
|
|
13
|
+
system: SYSTEM,
|
|
14
|
+
status: 'completed',
|
|
15
|
+
syncedCount: 0
|
|
16
|
+
};
|
|
17
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.syncTaskFromExternal = void 0;
|
|
4
|
+
const integration_sdk_1 = require("@timesheet/integration-sdk");
|
|
5
|
+
const SYSTEM = 'xero';
|
|
6
|
+
exports.syncTaskFromExternal = (0, integration_sdk_1.defineHandler)(async (input, context) => {
|
|
7
|
+
context.logger.info('Syncing task from external payload', {
|
|
8
|
+
system: SYSTEM,
|
|
9
|
+
method: input.method,
|
|
10
|
+
installationId: context.installationId
|
|
11
|
+
});
|
|
12
|
+
return {
|
|
13
|
+
system: SYSTEM,
|
|
14
|
+
accepted: true
|
|
15
|
+
};
|
|
16
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.syncTaskToExternal = void 0;
|
|
4
|
+
const integration_sdk_1 = require("@timesheet/integration-sdk");
|
|
5
|
+
const SYSTEM = 'xero';
|
|
6
|
+
exports.syncTaskToExternal = (0, integration_sdk_1.defineHandler)(async (input, context) => {
|
|
7
|
+
context.logger.info('Syncing task to external system', {
|
|
8
|
+
system: SYSTEM,
|
|
9
|
+
taskId: input.taskId,
|
|
10
|
+
installationId: context.installationId
|
|
11
|
+
});
|
|
12
|
+
return {
|
|
13
|
+
system: SYSTEM,
|
|
14
|
+
taskId: input.taskId,
|
|
15
|
+
direction: 'timesheet-to-external'
|
|
16
|
+
};
|
|
17
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.testConnection = void 0;
|
|
4
|
+
const integration_sdk_1 = require("@timesheet/integration-sdk");
|
|
5
|
+
const SYSTEM = 'xero';
|
|
6
|
+
exports.testConnection = (0, integration_sdk_1.defineHandler)(async (_input, context) => {
|
|
7
|
+
context.logger.info('Testing integration connection', {
|
|
8
|
+
system: SYSTEM,
|
|
9
|
+
installationId: context.installationId
|
|
10
|
+
});
|
|
11
|
+
return {
|
|
12
|
+
system: SYSTEM,
|
|
13
|
+
ok: true,
|
|
14
|
+
installationId: context.installationId
|
|
15
|
+
};
|
|
16
|
+
});
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { syncTaskToExternal } from './handlers/syncTaskToExternal';
|
|
2
|
+
export { syncTaskFromExternal } from './handlers/syncTaskFromExternal';
|
|
3
|
+
export { handleWebhook } from './handlers/handleWebhook';
|
|
4
|
+
export { runFullSync } from './handlers/runFullSync';
|
|
5
|
+
export { testConnection } from './handlers/testConnection';
|
|
6
|
+
export { listExternalProjects } from './handlers/listExternalProjects';
|
|
7
|
+
export declare const PLUGIN_SYSTEM = "xero";
|
|
8
|
+
export declare const PLUGIN_NAME = "Xero Sync";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PLUGIN_NAME = exports.PLUGIN_SYSTEM = exports.listExternalProjects = exports.testConnection = exports.runFullSync = exports.handleWebhook = exports.syncTaskFromExternal = exports.syncTaskToExternal = void 0;
|
|
4
|
+
var syncTaskToExternal_1 = require("./handlers/syncTaskToExternal");
|
|
5
|
+
Object.defineProperty(exports, "syncTaskToExternal", { enumerable: true, get: function () { return syncTaskToExternal_1.syncTaskToExternal; } });
|
|
6
|
+
var syncTaskFromExternal_1 = require("./handlers/syncTaskFromExternal");
|
|
7
|
+
Object.defineProperty(exports, "syncTaskFromExternal", { enumerable: true, get: function () { return syncTaskFromExternal_1.syncTaskFromExternal; } });
|
|
8
|
+
var handleWebhook_1 = require("./handlers/handleWebhook");
|
|
9
|
+
Object.defineProperty(exports, "handleWebhook", { enumerable: true, get: function () { return handleWebhook_1.handleWebhook; } });
|
|
10
|
+
var runFullSync_1 = require("./handlers/runFullSync");
|
|
11
|
+
Object.defineProperty(exports, "runFullSync", { enumerable: true, get: function () { return runFullSync_1.runFullSync; } });
|
|
12
|
+
var testConnection_1 = require("./handlers/testConnection");
|
|
13
|
+
Object.defineProperty(exports, "testConnection", { enumerable: true, get: function () { return testConnection_1.testConnection; } });
|
|
14
|
+
var listExternalProjects_1 = require("./handlers/listExternalProjects");
|
|
15
|
+
Object.defineProperty(exports, "listExternalProjects", { enumerable: true, get: function () { return listExternalProjects_1.listExternalProjects; } });
|
|
16
|
+
exports.PLUGIN_SYSTEM = 'xero';
|
|
17
|
+
exports.PLUGIN_NAME = 'Xero Sync';
|
package/manifest.json
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "xero-sync",
|
|
3
|
+
"name": "Xero Sync",
|
|
4
|
+
"version": "1.0.1",
|
|
5
|
+
"description": "Timesheet Xero Sync plugin integration",
|
|
6
|
+
"category": "accounting",
|
|
7
|
+
"tags": ["sync", "timesheet", "xero"],
|
|
8
|
+
"dataAccess": ["projects", "tasks", "colleagues", "settings"],
|
|
9
|
+
"externalAuth": [
|
|
10
|
+
{
|
|
11
|
+
"id": "xero",
|
|
12
|
+
"type": "oauth2",
|
|
13
|
+
"oauth": {
|
|
14
|
+
"authorizeUrl": "https://example.com/oauth/authorize",
|
|
15
|
+
"tokenUrl": "https://example.com/oauth/token",
|
|
16
|
+
"scopes": ["read", "write"]
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
],
|
|
20
|
+
"configSchema": {
|
|
21
|
+
"type": "object",
|
|
22
|
+
"properties": {
|
|
23
|
+
"syncDirection": {
|
|
24
|
+
"type": "string",
|
|
25
|
+
"title": "Sync Direction",
|
|
26
|
+
"enum": ["bidirectional", "timesheet-to-external", "external-to-timesheet"],
|
|
27
|
+
"default": "bidirectional",
|
|
28
|
+
"x-ui-widget": "radio"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"required": ["syncDirection"]
|
|
32
|
+
},
|
|
33
|
+
"mappingSchema": {
|
|
34
|
+
"system": "xero",
|
|
35
|
+
"mappings": [
|
|
36
|
+
{
|
|
37
|
+
"id": "projects",
|
|
38
|
+
"title": "Project Mapping",
|
|
39
|
+
"description": "Map Timesheet projects to Xero Sync projects",
|
|
40
|
+
"localEntity": {
|
|
41
|
+
"type": "project",
|
|
42
|
+
"label": "Timesheet Project",
|
|
43
|
+
"display": "{{title}}"
|
|
44
|
+
},
|
|
45
|
+
"externalEntity": {
|
|
46
|
+
"type": "project",
|
|
47
|
+
"label": "Xero Sync Project",
|
|
48
|
+
"fetchAction": "list-external-projects"
|
|
49
|
+
},
|
|
50
|
+
"required": true,
|
|
51
|
+
"minMappings": 1
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
},
|
|
55
|
+
"triggers": [
|
|
56
|
+
{
|
|
57
|
+
"id": "task-created",
|
|
58
|
+
"type": "event",
|
|
59
|
+
"name": "Task Created",
|
|
60
|
+
"description": "Sync when a new task is created",
|
|
61
|
+
"events": ["task.create"],
|
|
62
|
+
"configurable": true
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"id": "integration-webhook",
|
|
66
|
+
"type": "webhook",
|
|
67
|
+
"name": "Xero Sync Webhook",
|
|
68
|
+
"description": "Receive inbound changes from Xero Sync",
|
|
69
|
+
"configurable": false,
|
|
70
|
+
"webhook": {
|
|
71
|
+
"signature": {
|
|
72
|
+
"header": "x-timesheet-signature",
|
|
73
|
+
"algorithm": "hmac-sha256",
|
|
74
|
+
"secretConfigKey": "webhookSecret"
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"id": "full-sync",
|
|
80
|
+
"type": "schedule",
|
|
81
|
+
"name": "Scheduled Full Sync",
|
|
82
|
+
"description": "Run background synchronization",
|
|
83
|
+
"schedule": "0 2 * * *",
|
|
84
|
+
"timezone": "UTC",
|
|
85
|
+
"configurable": true
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"id": "manual-sync",
|
|
89
|
+
"type": "user_action",
|
|
90
|
+
"name": "Manual Sync",
|
|
91
|
+
"description": "Trigger a sync from settings",
|
|
92
|
+
"userAction": {
|
|
93
|
+
"label": "Sync Now",
|
|
94
|
+
"placement": "settings"
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
],
|
|
98
|
+
"actions": [
|
|
99
|
+
{
|
|
100
|
+
"id": "sync-task-to-external",
|
|
101
|
+
"name": "Sync task to Xero Sync",
|
|
102
|
+
"handler": "syncTaskToExternal"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"id": "sync-task-from-external",
|
|
106
|
+
"name": "Sync task from Xero Sync",
|
|
107
|
+
"handler": "syncTaskFromExternal"
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"id": "handle-webhook",
|
|
111
|
+
"handler": "handleWebhook",
|
|
112
|
+
"internal": true
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"id": "run-full-sync",
|
|
116
|
+
"name": "Run full sync",
|
|
117
|
+
"handler": "runFullSync"
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"id": "test-connection",
|
|
121
|
+
"name": "Test connection",
|
|
122
|
+
"handler": "testConnection"
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"id": "list-external-projects",
|
|
126
|
+
"handler": "listExternalProjects",
|
|
127
|
+
"internal": true
|
|
128
|
+
}
|
|
129
|
+
],
|
|
130
|
+
"pages": [
|
|
131
|
+
{
|
|
132
|
+
"id": "dashboard",
|
|
133
|
+
"title": "Sync Dashboard",
|
|
134
|
+
"icon": "chart-bar",
|
|
135
|
+
"layout": "dashboard",
|
|
136
|
+
"widgets": [
|
|
137
|
+
{
|
|
138
|
+
"id": "manual-sync-btn",
|
|
139
|
+
"type": "action_button",
|
|
140
|
+
"title": "Manual Sync",
|
|
141
|
+
"config": {
|
|
142
|
+
"actionId": "run-full-sync",
|
|
143
|
+
"label": "Run Full Sync",
|
|
144
|
+
"variant": "primary"
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
]
|
|
148
|
+
}
|
|
149
|
+
]
|
|
150
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@timesheet/plugin-xero",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"types": "dist/index.d.ts",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist",
|
|
8
|
+
"manifest.json"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "rm -rf dist && tsc -p tsconfig.json",
|
|
12
|
+
"typecheck": "tsc --noEmit",
|
|
13
|
+
"prepublishOnly": "npm run build"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@timesheet/integration-sdk": "^0.5.0"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@types/node": "^20.19.43",
|
|
20
|
+
"typescript": "^5.9.3"
|
|
21
|
+
}
|
|
22
|
+
}
|