@orgloop/transform-dedup 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/LICENSE.md +21 -0
- package/README.md +71 -0
- package/dist/dedup.d.ts +20 -0
- package/dist/dedup.d.ts.map +1 -0
- package/dist/dedup.js +82 -0
- package/dist/dedup.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/package.json +28 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 OrgLoop contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# @orgloop/transform-dedup
|
|
2
|
+
|
|
3
|
+
Deduplicates events within a configurable time window. Events with the same key hash seen within the window are dropped; the first occurrence passes through.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @orgloop/transform-dedup
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Configuration
|
|
12
|
+
|
|
13
|
+
```yaml
|
|
14
|
+
transforms:
|
|
15
|
+
- name: dedup-5m
|
|
16
|
+
type: package
|
|
17
|
+
package: "@orgloop/transform-dedup"
|
|
18
|
+
config:
|
|
19
|
+
key: # fields used to build the dedup hash
|
|
20
|
+
- source
|
|
21
|
+
- type
|
|
22
|
+
- provenance.platform_event
|
|
23
|
+
- payload.pr_number
|
|
24
|
+
window: "5m" # time window for dedup (default: 5m)
|
|
25
|
+
store: "memory" # storage backend (only "memory" for now)
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Config options
|
|
29
|
+
|
|
30
|
+
| Field | Type | Required | Default | Description |
|
|
31
|
+
|-------|------|----------|---------|-------------|
|
|
32
|
+
| `key` | `string[]` | yes | `["source", "type", "id"]` | Dot-path fields used to build the dedup hash. Values are concatenated and SHA-256 hashed |
|
|
33
|
+
| `window` | `string` | yes | `"5m"` | Duration window. Supported units: `ms`, `s`, `m`, `h`, `d` |
|
|
34
|
+
| `store` | `string` | no | `"memory"` | Storage backend. Only `"memory"` is supported in the current version |
|
|
35
|
+
|
|
36
|
+
### How it works
|
|
37
|
+
|
|
38
|
+
1. For each incoming event, the transform extracts values at the configured `key` field paths.
|
|
39
|
+
2. The values are concatenated (null-separated) and hashed with SHA-256.
|
|
40
|
+
3. If the hash has been seen within the `window` duration, the event is dropped (returns `null`).
|
|
41
|
+
4. If the hash is new or expired, the event passes through and the hash is recorded with the current timestamp.
|
|
42
|
+
|
|
43
|
+
A periodic cleanup timer evicts expired entries from the in-memory store.
|
|
44
|
+
|
|
45
|
+
## Example route
|
|
46
|
+
|
|
47
|
+
```yaml
|
|
48
|
+
routes:
|
|
49
|
+
- name: deduped-pr-reviews
|
|
50
|
+
when:
|
|
51
|
+
source: github-eng
|
|
52
|
+
events:
|
|
53
|
+
- resource.changed
|
|
54
|
+
transforms:
|
|
55
|
+
- ref: dedup-5m
|
|
56
|
+
- ref: humans-only
|
|
57
|
+
then:
|
|
58
|
+
actor: openclaw-agent
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Auth / prerequisites
|
|
62
|
+
|
|
63
|
+
None.
|
|
64
|
+
|
|
65
|
+
## Limitations / known issues
|
|
66
|
+
|
|
67
|
+
- **Memory-only store** -- Dedup state is held entirely in memory and is lost on engine restart. After a restart, previously seen events may be processed again until the window catches up.
|
|
68
|
+
- **No distributed dedup** -- The in-memory store does not support multiple engine instances. Running multiple instances results in each instance maintaining its own independent dedup state.
|
|
69
|
+
- **Hash collisions** -- SHA-256 collisions are theoretically possible but practically negligible.
|
|
70
|
+
- **Cleanup interval** -- Expired entries are cleaned up on a timer interval equal to the dedup window (minimum 10 seconds). Between cleanups, the memory footprint grows proportionally to event throughput.
|
|
71
|
+
- **Key field ordering matters** -- The hash is built from key fields in the order specified. Changing the `key` array order produces different hashes.
|
package/dist/dedup.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dedup transform — deduplicates events within a configurable time window.
|
|
3
|
+
*
|
|
4
|
+
* Builds a hash from specified key fields and drops events that have
|
|
5
|
+
* been seen within the configured window.
|
|
6
|
+
*/
|
|
7
|
+
import type { OrgLoopEvent, Transform, TransformContext } from '@orgloop/sdk';
|
|
8
|
+
export declare class DedupTransform implements Transform {
|
|
9
|
+
readonly id = "dedup";
|
|
10
|
+
private config;
|
|
11
|
+
private windowMs;
|
|
12
|
+
private seen;
|
|
13
|
+
private cleanupTimer;
|
|
14
|
+
init(config: Record<string, unknown>): Promise<void>;
|
|
15
|
+
execute(event: OrgLoopEvent, _context: TransformContext): Promise<OrgLoopEvent | null>;
|
|
16
|
+
shutdown(): Promise<void>;
|
|
17
|
+
private buildHash;
|
|
18
|
+
private cleanup;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=dedup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dedup.d.ts","sourceRoot":"","sources":["../src/dedup.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAwB9E,qBAAa,cAAe,YAAW,SAAS;IAC/C,QAAQ,CAAC,EAAE,WAAW;IACtB,OAAO,CAAC,MAAM,CAA0C;IACxD,OAAO,CAAC,QAAQ,CAAiB;IACjC,OAAO,CAAC,IAAI,CAA6B;IACzC,OAAO,CAAC,YAAY,CAA+C;IAE7D,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBpD,OAAO,CAAC,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAetF,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ/B,OAAO,CAAC,SAAS;IAajB,OAAO,CAAC,OAAO;CAQf"}
|
package/dist/dedup.js
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dedup transform — deduplicates events within a configurable time window.
|
|
3
|
+
*
|
|
4
|
+
* Builds a hash from specified key fields and drops events that have
|
|
5
|
+
* been seen within the configured window.
|
|
6
|
+
*/
|
|
7
|
+
import { createHash } from 'node:crypto';
|
|
8
|
+
import { parseDuration } from '@orgloop/sdk';
|
|
9
|
+
/**
|
|
10
|
+
* Get a value from a nested object using a dot-separated path.
|
|
11
|
+
*/
|
|
12
|
+
function getByPath(obj, path) {
|
|
13
|
+
const segments = path.split('.');
|
|
14
|
+
let current = obj;
|
|
15
|
+
for (const segment of segments) {
|
|
16
|
+
if (current === null || current === undefined || typeof current !== 'object') {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
current = current[segment];
|
|
20
|
+
}
|
|
21
|
+
return current;
|
|
22
|
+
}
|
|
23
|
+
export class DedupTransform {
|
|
24
|
+
id = 'dedup';
|
|
25
|
+
config = { key: [], window: '5m' };
|
|
26
|
+
windowMs = 5 * 60 * 1000;
|
|
27
|
+
seen = new Map();
|
|
28
|
+
cleanupTimer = null;
|
|
29
|
+
async init(config) {
|
|
30
|
+
const c = config;
|
|
31
|
+
this.config = {
|
|
32
|
+
key: c.key ?? ['source', 'type', 'id'],
|
|
33
|
+
window: c.window ?? '5m',
|
|
34
|
+
};
|
|
35
|
+
this.windowMs = parseDuration(this.config.window);
|
|
36
|
+
// Clean up expired entries every window period (minimum 10s)
|
|
37
|
+
const cleanupInterval = Math.max(this.windowMs, 10_000);
|
|
38
|
+
this.cleanupTimer = setInterval(() => this.cleanup(), cleanupInterval);
|
|
39
|
+
// Allow the process to exit even if cleanup timer is pending
|
|
40
|
+
if (this.cleanupTimer.unref) {
|
|
41
|
+
this.cleanupTimer.unref();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async execute(event, _context) {
|
|
45
|
+
const hash = this.buildHash(event);
|
|
46
|
+
const now = Date.now();
|
|
47
|
+
const lastSeen = this.seen.get(hash);
|
|
48
|
+
if (lastSeen !== undefined && now - lastSeen < this.windowMs) {
|
|
49
|
+
// Duplicate within window — drop
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
// New or expired — pass and record
|
|
53
|
+
this.seen.set(hash, now);
|
|
54
|
+
return event;
|
|
55
|
+
}
|
|
56
|
+
async shutdown() {
|
|
57
|
+
if (this.cleanupTimer) {
|
|
58
|
+
clearInterval(this.cleanupTimer);
|
|
59
|
+
this.cleanupTimer = null;
|
|
60
|
+
}
|
|
61
|
+
this.seen.clear();
|
|
62
|
+
}
|
|
63
|
+
buildHash(event) {
|
|
64
|
+
const eventObj = event;
|
|
65
|
+
const parts = [];
|
|
66
|
+
for (const keyPath of this.config.key) {
|
|
67
|
+
const value = getByPath(eventObj, keyPath);
|
|
68
|
+
parts.push(String(value ?? ''));
|
|
69
|
+
}
|
|
70
|
+
const joined = parts.join('\0');
|
|
71
|
+
return createHash('sha256').update(joined).digest('hex');
|
|
72
|
+
}
|
|
73
|
+
cleanup() {
|
|
74
|
+
const now = Date.now();
|
|
75
|
+
for (const [hash, timestamp] of this.seen) {
|
|
76
|
+
if (now - timestamp >= this.windowMs) {
|
|
77
|
+
this.seen.delete(hash);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=dedup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dedup.js","sourceRoot":"","sources":["../src/dedup.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAQ7C;;GAEG;AACH,SAAS,SAAS,CAAC,GAAY,EAAE,IAAY;IAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,OAAO,GAAY,GAAG,CAAC;IAC3B,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAChC,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9E,OAAO,SAAS,CAAC;QAClB,CAAC;QACD,OAAO,GAAI,OAAmC,CAAC,OAAO,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,OAAO,CAAC;AAChB,CAAC;AAED,MAAM,OAAO,cAAc;IACjB,EAAE,GAAG,OAAO,CAAC;IACd,MAAM,GAAgB,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAChD,QAAQ,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;IACzB,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAC;IACjC,YAAY,GAA0C,IAAI,CAAC;IAEnE,KAAK,CAAC,IAAI,CAAC,MAA+B;QACzC,MAAM,CAAC,GAAG,MAAyC,CAAC;QACpD,IAAI,CAAC,MAAM,GAAG;YACb,GAAG,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC;YACtC,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,IAAI;SACxB,CAAC;QACF,IAAI,CAAC,QAAQ,GAAG,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAElD,6DAA6D;QAC7D,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACxD,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,eAAe,CAAC,CAAC;QACvE,6DAA6D;QAC7D,IAAI,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;YAC7B,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;QAC3B,CAAC;IACF,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,KAAmB,EAAE,QAA0B;QAC5D,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAErC,IAAI,QAAQ,KAAK,SAAS,IAAI,GAAG,GAAG,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC9D,iCAAiC;YACjC,OAAO,IAAI,CAAC;QACb,CAAC;QAED,mCAAmC;QACnC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACzB,OAAO,KAAK,CAAC;IACd,CAAC;IAED,KAAK,CAAC,QAAQ;QACb,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACvB,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACjC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QAC1B,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;IACnB,CAAC;IAEO,SAAS,CAAC,KAAmB;QACpC,MAAM,QAAQ,GAAG,KAA2C,CAAC;QAC7D,MAAM,KAAK,GAAa,EAAE,CAAC;QAE3B,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;YACvC,MAAM,KAAK,GAAG,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAC3C,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC;QACjC,CAAC;QAED,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC1D,CAAC;IAEO,OAAO;QACd,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,KAAK,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YAC3C,IAAI,GAAG,GAAG,SAAS,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACtC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACxB,CAAC;QACF,CAAC;IACF,CAAC;CACD"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @orgloop/transform-dedup — registration entry point.
|
|
3
|
+
*/
|
|
4
|
+
import type { TransformRegistration } from '@orgloop/sdk';
|
|
5
|
+
export declare function register(): TransformRegistration;
|
|
6
|
+
export { DedupTransform } from './dedup.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAG1D,wBAAgB,QAAQ,IAAI,qBAAqB,CA4BhD;AAED,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @orgloop/transform-dedup — registration entry point.
|
|
3
|
+
*/
|
|
4
|
+
import { DedupTransform } from './dedup.js';
|
|
5
|
+
export function register() {
|
|
6
|
+
return {
|
|
7
|
+
id: 'dedup',
|
|
8
|
+
transform: DedupTransform,
|
|
9
|
+
configSchema: {
|
|
10
|
+
type: 'object',
|
|
11
|
+
properties: {
|
|
12
|
+
key: {
|
|
13
|
+
type: 'array',
|
|
14
|
+
items: { type: 'string' },
|
|
15
|
+
description: 'Event field paths to use as dedup key.',
|
|
16
|
+
},
|
|
17
|
+
window: {
|
|
18
|
+
type: 'string',
|
|
19
|
+
description: 'Duration window for deduplication (e.g., "5m").',
|
|
20
|
+
default: '5m',
|
|
21
|
+
},
|
|
22
|
+
store: {
|
|
23
|
+
type: 'string',
|
|
24
|
+
enum: ['memory'],
|
|
25
|
+
description: 'Storage backend (only "memory" for MVP).',
|
|
26
|
+
default: 'memory',
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
required: ['key', 'window'],
|
|
30
|
+
additionalProperties: false,
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export { DedupTransform } from './dedup.js';
|
|
35
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,MAAM,UAAU,QAAQ;IACvB,OAAO;QACN,EAAE,EAAE,OAAO;QACX,SAAS,EAAE,cAAc;QACzB,YAAY,EAAE;YACb,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACX,GAAG,EAAE;oBACJ,IAAI,EAAE,OAAO;oBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;oBACzB,WAAW,EAAE,wCAAwC;iBACrD;gBACD,MAAM,EAAE;oBACP,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,iDAAiD;oBAC9D,OAAO,EAAE,IAAI;iBACb;gBACD,KAAK,EAAE;oBACN,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,CAAC,QAAQ,CAAC;oBAChB,WAAW,EAAE,0CAA0C;oBACvD,OAAO,EAAE,QAAQ;iBACjB;aACD;YACD,QAAQ,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC;YAC3B,oBAAoB,EAAE,KAAK;SAC3B;KACD,CAAC;AACH,CAAC;AAED,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@orgloop/transform-dedup",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "OrgLoop dedup transform — deduplicate events within a time window",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"dependencies": {
|
|
9
|
+
"@orgloop/sdk": "0.1.0"
|
|
10
|
+
},
|
|
11
|
+
"orgloop": {
|
|
12
|
+
"type": "transform",
|
|
13
|
+
"id": "dedup"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public"
|
|
20
|
+
},
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsc",
|
|
24
|
+
"clean": "rm -rf dist",
|
|
25
|
+
"typecheck": "tsc --noEmit",
|
|
26
|
+
"test": "vitest run"
|
|
27
|
+
}
|
|
28
|
+
}
|