@redjay/threads-core 1.1.0 → 1.2.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 +21 -21
- package/README.md +42 -42
- package/dist/domain/agenda.d.ts +31 -0
- package/dist/domain/agenda.d.ts.map +1 -0
- package/dist/domain/agenda.js +60 -0
- package/dist/domain/agenda.js.map +1 -0
- package/dist/domain/batch.d.ts +67 -0
- package/dist/domain/batch.d.ts.map +1 -0
- package/dist/domain/batch.js +151 -0
- package/dist/domain/batch.js.map +1 -0
- package/dist/domain/clone.d.ts +31 -0
- package/dist/domain/clone.d.ts.map +1 -0
- package/dist/domain/clone.js +69 -0
- package/dist/domain/clone.js.map +1 -0
- package/dist/domain/index.d.ts +12 -0
- package/dist/domain/index.d.ts.map +1 -0
- package/dist/domain/index.js +30 -0
- package/dist/domain/index.js.map +1 -0
- package/dist/domain/merge.d.ts +25 -0
- package/dist/domain/merge.d.ts.map +1 -0
- package/dist/domain/merge.js +47 -0
- package/dist/domain/merge.js.map +1 -0
- package/dist/domain/overview.d.ts +41 -0
- package/dist/domain/overview.d.ts.map +1 -0
- package/dist/domain/overview.js +95 -0
- package/dist/domain/overview.js.map +1 -0
- package/dist/domain/progress.d.ts +28 -0
- package/dist/domain/progress.d.ts.map +1 -0
- package/dist/domain/progress.js +45 -0
- package/dist/domain/progress.js.map +1 -0
- package/dist/domain/scoring.d.ts +40 -0
- package/dist/domain/scoring.d.ts.map +1 -0
- package/dist/domain/scoring.js +64 -0
- package/dist/domain/scoring.js.map +1 -0
- package/dist/domain/search.d.ts +31 -0
- package/dist/domain/search.d.ts.map +1 -0
- package/dist/domain/search.js +59 -0
- package/dist/domain/search.js.map +1 -0
- package/dist/domain/sorting.d.ts +17 -0
- package/dist/domain/sorting.d.ts.map +1 -0
- package/dist/domain/sorting.js +32 -0
- package/dist/domain/sorting.js.map +1 -0
- package/dist/domain/time.d.ts +78 -0
- package/dist/domain/time.d.ts.map +1 -0
- package/dist/domain/time.js +146 -0
- package/dist/domain/time.js.map +1 -0
- package/dist/domain/timeline.d.ts +43 -0
- package/dist/domain/timeline.d.ts.map +1 -0
- package/dist/domain/timeline.js +65 -0
- package/dist/domain/timeline.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +62 -54
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Date/time utility functions for thread domain logic.
|
|
4
|
+
*
|
|
5
|
+
* Pure functions — no storage or side-effect dependencies.
|
|
6
|
+
* Deduplicates copies from agenda.ts, overview.ts, next.ts.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.daysSince = daysSince;
|
|
10
|
+
exports.hoursSince = hoursSince;
|
|
11
|
+
exports.isToday = isToday;
|
|
12
|
+
exports.isWithinDays = isWithinDays;
|
|
13
|
+
exports.formatRelativeTime = formatRelativeTime;
|
|
14
|
+
exports.getLastProgressDate = getLastProgressDate;
|
|
15
|
+
exports.getLastProgressNote = getLastProgressNote;
|
|
16
|
+
exports.truncate = truncate;
|
|
17
|
+
exports.parseDate = parseDate;
|
|
18
|
+
exports.parseDateTime = parseDateTime;
|
|
19
|
+
/**
|
|
20
|
+
* Calculate calendar days since a given ISO date string.
|
|
21
|
+
*
|
|
22
|
+
* @param isoDate - ISO 8601 timestamp
|
|
23
|
+
* @param now - Current time (injectable for testing)
|
|
24
|
+
* @returns Integer number of days elapsed
|
|
25
|
+
*/
|
|
26
|
+
function daysSince(isoDate, now = new Date()) {
|
|
27
|
+
const then = new Date(isoDate);
|
|
28
|
+
const diffMs = now.getTime() - then.getTime();
|
|
29
|
+
return Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Calculate hours since a given ISO date string.
|
|
33
|
+
*
|
|
34
|
+
* @param isoDate - ISO 8601 timestamp
|
|
35
|
+
* @param now - Current time (injectable for testing)
|
|
36
|
+
* @returns Fractional hours elapsed
|
|
37
|
+
*/
|
|
38
|
+
function hoursSince(isoDate, now = new Date()) {
|
|
39
|
+
const then = new Date(isoDate);
|
|
40
|
+
const diffMs = now.getTime() - then.getTime();
|
|
41
|
+
return diffMs / (1000 * 60 * 60);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Check if a date is today.
|
|
45
|
+
*
|
|
46
|
+
* @param isoDate - ISO 8601 timestamp
|
|
47
|
+
* @param now - Current time (injectable for testing)
|
|
48
|
+
*/
|
|
49
|
+
function isToday(isoDate, now = new Date()) {
|
|
50
|
+
const date = new Date(isoDate);
|
|
51
|
+
return date.toDateString() === now.toDateString();
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Check if a date is within the last N days (inclusive).
|
|
55
|
+
*
|
|
56
|
+
* @param isoDate - ISO 8601 timestamp
|
|
57
|
+
* @param days - Number of days to look back
|
|
58
|
+
* @param now - Current time (injectable for testing)
|
|
59
|
+
*/
|
|
60
|
+
function isWithinDays(isoDate, days, now = new Date()) {
|
|
61
|
+
return daysSince(isoDate, now) <= days;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Format a relative time string for display.
|
|
65
|
+
*
|
|
66
|
+
* @returns "today", "yesterday", "3d ago", "2w ago", "1mo ago"
|
|
67
|
+
*/
|
|
68
|
+
function formatRelativeTime(isoDate, now = new Date()) {
|
|
69
|
+
const days = daysSince(isoDate, now);
|
|
70
|
+
if (days === 0)
|
|
71
|
+
return 'today';
|
|
72
|
+
if (days === 1)
|
|
73
|
+
return 'yesterday';
|
|
74
|
+
if (days < 7)
|
|
75
|
+
return `${days}d ago`;
|
|
76
|
+
if (days < 30)
|
|
77
|
+
return `${Math.floor(days / 7)}w ago`;
|
|
78
|
+
return `${Math.floor(days / 30)}mo ago`;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Get the most recent progress entry timestamp for a thread.
|
|
82
|
+
*
|
|
83
|
+
* @returns ISO timestamp string or null if no progress
|
|
84
|
+
*/
|
|
85
|
+
function getLastProgressDate(thread) {
|
|
86
|
+
if (thread.progress.length === 0)
|
|
87
|
+
return null;
|
|
88
|
+
return thread.progress[thread.progress.length - 1].timestamp;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Get the most recent progress note text for a thread.
|
|
92
|
+
*
|
|
93
|
+
* @returns Note string or null if no progress
|
|
94
|
+
*/
|
|
95
|
+
function getLastProgressNote(thread) {
|
|
96
|
+
if (thread.progress.length === 0)
|
|
97
|
+
return null;
|
|
98
|
+
return thread.progress[thread.progress.length - 1].note;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Truncate a string to a max length with ellipsis.
|
|
102
|
+
*
|
|
103
|
+
* @param str - Input string
|
|
104
|
+
* @param maxLen - Maximum output length (including ellipsis)
|
|
105
|
+
* @returns Truncated string
|
|
106
|
+
*/
|
|
107
|
+
function truncate(str, maxLen) {
|
|
108
|
+
if (str.length <= maxLen)
|
|
109
|
+
return str;
|
|
110
|
+
return str.slice(0, maxLen - 3) + '...';
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Parse a date string loosely. Supports ISO dates and natural language.
|
|
114
|
+
*
|
|
115
|
+
* @returns Date object or null if unparseable
|
|
116
|
+
*/
|
|
117
|
+
function parseDate(dateStr) {
|
|
118
|
+
const parsed = new Date(dateStr);
|
|
119
|
+
return isNaN(parsed.getTime()) ? null : parsed;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Parse a datetime string with natural language support.
|
|
123
|
+
* Supports: ISO dates, "yesterday", "N days ago".
|
|
124
|
+
*
|
|
125
|
+
* @returns Date object or null if unparseable
|
|
126
|
+
*/
|
|
127
|
+
function parseDateTime(input, now = new Date()) {
|
|
128
|
+
const date = new Date(input);
|
|
129
|
+
if (!isNaN(date.getTime())) {
|
|
130
|
+
return date;
|
|
131
|
+
}
|
|
132
|
+
const lower = input.toLowerCase();
|
|
133
|
+
if (lower === 'yesterday') {
|
|
134
|
+
const d = new Date(now);
|
|
135
|
+
d.setDate(d.getDate() - 1);
|
|
136
|
+
return d;
|
|
137
|
+
}
|
|
138
|
+
const daysAgoMatch = lower.match(/^(\d+)\s*days?\s*ago$/);
|
|
139
|
+
if (daysAgoMatch) {
|
|
140
|
+
const d = new Date(now);
|
|
141
|
+
d.setDate(d.getDate() - parseInt(daysAgoMatch[1]));
|
|
142
|
+
return d;
|
|
143
|
+
}
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=time.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time.js","sourceRoot":"","sources":["../../src/domain/time.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Progress timeline collection, filtering, and sorting.
|
|
3
|
+
*
|
|
4
|
+
* Pure pipeline: collect -> filter -> sort -> limit.
|
|
5
|
+
* All functions take data arrays as input.
|
|
6
|
+
*/
|
|
7
|
+
import { Thread, ProgressEntry } from '../models/types';
|
|
8
|
+
/** A timeline entry linking a progress note back to its thread. */
|
|
9
|
+
export interface TimelineEntry {
|
|
10
|
+
thread: Thread;
|
|
11
|
+
progress: ProgressEntry;
|
|
12
|
+
}
|
|
13
|
+
/** Options for timeline pipeline. */
|
|
14
|
+
export interface TimelineOptions {
|
|
15
|
+
since?: string;
|
|
16
|
+
until?: string;
|
|
17
|
+
limit?: number;
|
|
18
|
+
thread?: string;
|
|
19
|
+
reverse?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Flatten all progress entries across threads into timeline entries.
|
|
23
|
+
*/
|
|
24
|
+
export declare function collectTimelineEntries(threads: Thread[]): TimelineEntry[];
|
|
25
|
+
/**
|
|
26
|
+
* Filter timeline entries by date range.
|
|
27
|
+
*
|
|
28
|
+
* @param entries - Timeline entries to filter
|
|
29
|
+
* @param since - Include entries at or after this date
|
|
30
|
+
* @param until - Include entries at or before this date
|
|
31
|
+
*/
|
|
32
|
+
export declare function filterByDateRange(entries: TimelineEntry[], since?: Date, until?: Date): TimelineEntry[];
|
|
33
|
+
/**
|
|
34
|
+
* Sort timeline entries chronologically.
|
|
35
|
+
*
|
|
36
|
+
* @param reverse - If true, oldest first; otherwise newest first.
|
|
37
|
+
*/
|
|
38
|
+
export declare function sortTimelineEntries(entries: TimelineEntry[], reverse?: boolean): TimelineEntry[];
|
|
39
|
+
/**
|
|
40
|
+
* Slice timeline entries to a maximum count.
|
|
41
|
+
*/
|
|
42
|
+
export declare function applyLimit(entries: TimelineEntry[], limit?: number): TimelineEntry[];
|
|
43
|
+
//# sourceMappingURL=timeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeline.d.ts","sourceRoot":"","sources":["../../src/domain/timeline.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAExD,mEAAmE;AACnE,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,aAAa,CAAC;CACzB;AAED,qCAAqC;AACrC,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,aAAa,EAAE,CAQzE;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,aAAa,EAAE,EACxB,KAAK,CAAC,EAAE,IAAI,EACZ,KAAK,CAAC,EAAE,IAAI,GACX,aAAa,EAAE,CAYjB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,aAAa,EAAE,EACxB,OAAO,GAAE,OAAe,GACvB,aAAa,EAAE,CAQjB;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,aAAa,EAAE,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,aAAa,EAAE,CAKpF"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Progress timeline collection, filtering, and sorting.
|
|
4
|
+
*
|
|
5
|
+
* Pure pipeline: collect -> filter -> sort -> limit.
|
|
6
|
+
* All functions take data arrays as input.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.collectTimelineEntries = collectTimelineEntries;
|
|
10
|
+
exports.filterByDateRange = filterByDateRange;
|
|
11
|
+
exports.sortTimelineEntries = sortTimelineEntries;
|
|
12
|
+
exports.applyLimit = applyLimit;
|
|
13
|
+
/**
|
|
14
|
+
* Flatten all progress entries across threads into timeline entries.
|
|
15
|
+
*/
|
|
16
|
+
function collectTimelineEntries(threads) {
|
|
17
|
+
const entries = [];
|
|
18
|
+
for (const thread of threads) {
|
|
19
|
+
for (const progress of thread.progress) {
|
|
20
|
+
entries.push({ thread, progress });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return entries;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Filter timeline entries by date range.
|
|
27
|
+
*
|
|
28
|
+
* @param entries - Timeline entries to filter
|
|
29
|
+
* @param since - Include entries at or after this date
|
|
30
|
+
* @param until - Include entries at or before this date
|
|
31
|
+
*/
|
|
32
|
+
function filterByDateRange(entries, since, until) {
|
|
33
|
+
let filtered = entries;
|
|
34
|
+
if (since) {
|
|
35
|
+
filtered = filtered.filter(e => new Date(e.progress.timestamp) >= since);
|
|
36
|
+
}
|
|
37
|
+
if (until) {
|
|
38
|
+
filtered = filtered.filter(e => new Date(e.progress.timestamp) <= until);
|
|
39
|
+
}
|
|
40
|
+
return filtered;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Sort timeline entries chronologically.
|
|
44
|
+
*
|
|
45
|
+
* @param reverse - If true, oldest first; otherwise newest first.
|
|
46
|
+
*/
|
|
47
|
+
function sortTimelineEntries(entries, reverse = false) {
|
|
48
|
+
const sorted = [...entries];
|
|
49
|
+
sorted.sort((a, b) => {
|
|
50
|
+
const timeA = new Date(a.progress.timestamp).getTime();
|
|
51
|
+
const timeB = new Date(b.progress.timestamp).getTime();
|
|
52
|
+
return reverse ? timeA - timeB : timeB - timeA;
|
|
53
|
+
});
|
|
54
|
+
return sorted;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Slice timeline entries to a maximum count.
|
|
58
|
+
*/
|
|
59
|
+
function applyLimit(entries, limit) {
|
|
60
|
+
if (limit && limit > 0) {
|
|
61
|
+
return entries.slice(0, limit);
|
|
62
|
+
}
|
|
63
|
+
return entries;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=timeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timeline.js","sourceRoot":"","sources":["../../src/domain/timeline.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAsBH,wDAQC;AASD,8CAgBC;AAOD,kDAWC;AAKD,gCAKC;AAhED;;GAEG;AACH,SAAgB,sBAAsB,CAAC,OAAiB;IACtD,MAAM,OAAO,GAAoB,EAAE,CAAC;IACpC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACvC,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,iBAAiB,CAC/B,OAAwB,EACxB,KAAY,EACZ,KAAY;IAEZ,IAAI,QAAQ,GAAG,OAAO,CAAC;IAEvB,IAAI,KAAK,EAAE,CAAC;QACV,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,CAAC;IAC3E,CAAC;IAED,IAAI,KAAK,EAAE,CAAC;QACV,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC,CAAC;IAC3E,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;GAIG;AACH,SAAgB,mBAAmB,CACjC,OAAwB,EACxB,UAAmB,KAAK;IAExB,MAAM,MAAM,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC;IAC5B,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACnB,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;QACvD,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;QACvD,OAAO,OAAO,CAAC,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC;IACjD,CAAC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,SAAgB,UAAU,CAAC,OAAwB,EAAE,KAAc;IACjE,IAAI,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,UAAU,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,UAAU,CAAC;AAGzB,cAAc,UAAU,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -16,4 +16,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
// Re-export all models
|
|
18
18
|
__exportStar(require("./models"), exports);
|
|
19
|
+
// Re-export domain logic
|
|
20
|
+
__exportStar(require("./domain"), exports);
|
|
19
21
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,uBAAuB;AACvB,2CAAyB"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,uBAAuB;AACvB,2CAAyB;AAEzB,yBAAyB;AACzB,2CAAyB"}
|
package/package.json
CHANGED
|
@@ -1,54 +1,62 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@redjay/threads-core",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Core types and models for Threads platform",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
7
|
-
"exports": {
|
|
8
|
-
".": {
|
|
9
|
-
"types": "./dist/index.d.ts",
|
|
10
|
-
"default": "./dist/index.js"
|
|
11
|
-
},
|
|
12
|
-
"./models": {
|
|
13
|
-
"types": "./dist/models/index.d.ts",
|
|
14
|
-
"default": "./dist/models/index.js"
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
"
|
|
46
|
-
|
|
47
|
-
"
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
"@types/node": "^25.0.3",
|
|
52
|
-
"
|
|
53
|
-
|
|
54
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@redjay/threads-core",
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "Core types and models for Threads platform",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"default": "./dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"./models": {
|
|
13
|
+
"types": "./dist/models/index.d.ts",
|
|
14
|
+
"default": "./dist/models/index.js"
|
|
15
|
+
},
|
|
16
|
+
"./domain": {
|
|
17
|
+
"types": "./dist/domain/index.d.ts",
|
|
18
|
+
"default": "./dist/domain/index.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist",
|
|
23
|
+
"README.md",
|
|
24
|
+
"LICENSE"
|
|
25
|
+
],
|
|
26
|
+
"keywords": [
|
|
27
|
+
"threads",
|
|
28
|
+
"types",
|
|
29
|
+
"models"
|
|
30
|
+
],
|
|
31
|
+
"author": "Joshua Ramirez",
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">=20.0.0"
|
|
35
|
+
},
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "git+https://github.com/JoshuaRamirez/threads-cli.git",
|
|
39
|
+
"directory": "packages/core"
|
|
40
|
+
},
|
|
41
|
+
"bugs": {
|
|
42
|
+
"url": "https://github.com/JoshuaRamirez/threads-cli/issues"
|
|
43
|
+
},
|
|
44
|
+
"homepage": "https://github.com/JoshuaRamirez/threads-cli/tree/master/packages/core#readme",
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public",
|
|
47
|
+
"registry": "https://registry.npmjs.org/"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@types/jest": "^30.0.0",
|
|
51
|
+
"@types/node": "^25.0.3",
|
|
52
|
+
"jest": "^30.2.0",
|
|
53
|
+
"ts-jest": "^29.4.6",
|
|
54
|
+
"typescript": "^5.9.3"
|
|
55
|
+
},
|
|
56
|
+
"scripts": {
|
|
57
|
+
"build": "tsc -b",
|
|
58
|
+
"clean": "rm -rf dist",
|
|
59
|
+
"typecheck": "tsc --noEmit",
|
|
60
|
+
"test": "jest --passWithNoTests"
|
|
61
|
+
}
|
|
62
|
+
}
|