@onpeek/nuvio 1.0.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.
Files changed (48) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +83 -0
  3. package/assets/nuvio-wordmark-dark.png +0 -0
  4. package/assets/nuvio-wordmark-light.png +0 -0
  5. package/dist/cli/confirmation.js +45 -0
  6. package/dist/cli/registry.js +14 -0
  7. package/dist/commands/account.js +66 -0
  8. package/dist/commands/addons.js +84 -0
  9. package/dist/commands/collections.js +147 -0
  10. package/dist/commands/helpers.js +186 -0
  11. package/dist/commands/index.js +26 -0
  12. package/dist/commands/library.js +105 -0
  13. package/dist/commands/plugins.js +58 -0
  14. package/dist/commands/profiles.js +126 -0
  15. package/dist/commands/providers.js +57 -0
  16. package/dist/commands/sessions.js +46 -0
  17. package/dist/commands/settings.js +43 -0
  18. package/dist/commands/trackers.js +84 -0
  19. package/dist/commands/undo.js +165 -0
  20. package/dist/config.js +60 -0
  21. package/dist/index.js +195 -0
  22. package/dist/mask.js +33 -0
  23. package/dist/nuvio/auth.js +123 -0
  24. package/dist/nuvio/call-context.js +20 -0
  25. package/dist/nuvio/client.js +149 -0
  26. package/dist/nuvio/errors.js +43 -0
  27. package/dist/nuvio/keys.js +23 -0
  28. package/dist/nuvio/ops/account.js +91 -0
  29. package/dist/nuvio/ops/addons.js +126 -0
  30. package/dist/nuvio/ops/collections.js +158 -0
  31. package/dist/nuvio/ops/library.js +139 -0
  32. package/dist/nuvio/ops/plan.js +728 -0
  33. package/dist/nuvio/ops/plugins.js +127 -0
  34. package/dist/nuvio/ops/profiles.js +383 -0
  35. package/dist/nuvio/ops/providers.js +103 -0
  36. package/dist/nuvio/ops/readers.js +57 -0
  37. package/dist/nuvio/ops/sessions.js +36 -0
  38. package/dist/nuvio/ops/settings.js +143 -0
  39. package/dist/nuvio/ops/trackers.js +80 -0
  40. package/dist/nuvio/ops/transitions.js +100 -0
  41. package/dist/nuvio/paths.js +74 -0
  42. package/dist/nuvio/safe-fetch.js +131 -0
  43. package/dist/nuvio/schemas.js +143 -0
  44. package/dist/nuvio/snapshots.js +664 -0
  45. package/dist/nuvio/types.js +1 -0
  46. package/dist/version.js +12 -0
  47. package/package.json +62 -0
  48. package/skills/nuvio/SKILL.md +19 -0
@@ -0,0 +1,139 @@
1
+ import { NuvioError } from '../errors.js';
2
+ import { historyKeyOf, libraryKeyOf, progressKeyOf, storedProgressKey, } from '../keys.js';
3
+ import { readAllLibrary, readAllWatchHistory, readAllWatchProgress } from './readers.js';
4
+ import { planHistoryAdd, planHistoryDelete, planLibraryAdd, planLibraryRemove, planProgressDelete, planProgressSet, } from './transitions.js';
5
+ export { progressKeyOf, historyKeyOf };
6
+ export const historyKeyFrom = historyKeyOf;
7
+ function nowSeconds() {
8
+ return Math.floor(Date.now() / 1000);
9
+ }
10
+ // ---------------------------------------------------------------------------
11
+ // Reads (public list tools keep their own pagination shape)
12
+ // ---------------------------------------------------------------------------
13
+ export async function getLibrary(client, profileId, limit = 100, offset = 0) {
14
+ return client.readRpc('sync_pull_library', { p_profile_id: profileId, p_limit: limit, p_offset: offset });
15
+ }
16
+ export async function getWatchProgress(client, profileId, limit = 100) {
17
+ return client.readRpc('sync_pull_watch_progress', { p_profile_id: profileId, p_limit: limit });
18
+ }
19
+ export async function getWatchHistory(client, profileId, page = 1, pageSize = 100) {
20
+ return client.readRpc('sync_pull_watched_items', {
21
+ p_profile_id: profileId,
22
+ p_page: page,
23
+ p_page_size: pageSize,
24
+ });
25
+ }
26
+ // ---------------------------------------------------------------------------
27
+ // Mutations (complete readers; deletes are not gated on a first page)
28
+ // ---------------------------------------------------------------------------
29
+ export async function addToLibrary(client, profileId, items, originId, apply, now = nowSeconds()) {
30
+ if (items.length === 0)
31
+ throw new NuvioError('At least one item is required');
32
+ const before = (await readAllLibrary(client, profileId));
33
+ const { after, diff } = planLibraryAdd(before, items, now);
34
+ if (apply && diff.length > 0) {
35
+ const pushes = after.filter((row) => {
36
+ const key = libraryKeyOf(row);
37
+ const prev = before.find((b) => libraryKeyOf(b) === key);
38
+ return !prev || JSON.stringify(prev) !== JSON.stringify(row);
39
+ });
40
+ await client.rpc('sync_push_library_items', {
41
+ p_profile_id: profileId,
42
+ p_items: pushes,
43
+ p_origin_client_id: originId,
44
+ });
45
+ }
46
+ return { applied: apply && diff.length > 0, changed: diff.length > 0, before, after, diff };
47
+ }
48
+ export async function removeFromLibrary(client, profileId, keys, originId, apply) {
49
+ if (keys.length === 0)
50
+ throw new NuvioError('At least one key is required');
51
+ const before = (await readAllLibrary(client, profileId));
52
+ const { after, diff } = planLibraryRemove(before, keys);
53
+ // Always send the delete for the provided keys — the backend is the source of
54
+ // truth, not the read page.
55
+ if (apply) {
56
+ await client.rpc('sync_delete_library_items', {
57
+ p_profile_id: profileId,
58
+ p_keys: keys,
59
+ p_origin_client_id: originId,
60
+ });
61
+ }
62
+ return { applied: apply, changed: keys.length > 0, before, after, diff };
63
+ }
64
+ export async function setWatchProgress(client, profileId, entries, originId, apply, now = nowSeconds()) {
65
+ if (entries.length === 0)
66
+ throw new NuvioError('At least one entry is required');
67
+ const before = (await readAllWatchProgress(client, profileId, { requireComplete: true }));
68
+ const { after, diff } = planProgressSet(before, entries, now);
69
+ if (apply && diff.length > 0) {
70
+ const pushes = after.filter((row) => {
71
+ const prev = before.find((b) => storedProgressKey(b) === storedProgressKey(row));
72
+ return !prev || JSON.stringify(prev) !== JSON.stringify(row);
73
+ });
74
+ await client.rpc('sync_push_watch_progress', {
75
+ p_profile_id: profileId,
76
+ p_entries: pushes,
77
+ p_origin_client_id: originId,
78
+ });
79
+ }
80
+ return { applied: apply && diff.length > 0, changed: diff.length > 0, before, after, diff };
81
+ }
82
+ export async function addToWatchHistory(client, profileId, items, originId, apply, now = nowSeconds()) {
83
+ if (items.length === 0)
84
+ throw new NuvioError('At least one item is required');
85
+ const before = (await readAllWatchHistory(client, profileId));
86
+ const { after, diff } = planHistoryAdd(before, items, now);
87
+ if (apply && diff.length > 0) {
88
+ const pushes = after.filter((row) => {
89
+ const prev = before.find((b) => historyKeyOf(b) === historyKeyOf(row));
90
+ return !prev || JSON.stringify(prev) !== JSON.stringify(row);
91
+ });
92
+ await client.rpc('sync_push_watched_items', {
93
+ p_profile_id: profileId,
94
+ p_items: pushes,
95
+ p_origin_client_id: originId,
96
+ });
97
+ }
98
+ return { applied: apply && diff.length > 0, changed: diff.length > 0, before, after, diff };
99
+ }
100
+ export async function deleteWatchProgress(client, profileId, keys, originId, apply) {
101
+ if (keys.length === 0)
102
+ throw new NuvioError('At least one key is required');
103
+ const before = (await readAllWatchProgress(client, profileId, { requireComplete: true }));
104
+ const { after, diff } = planProgressDelete(before, keys);
105
+ const wanted = new Set(keys.map((k) => progressKeyOf(k)));
106
+ const internalKeys = new Set();
107
+ for (const key of keys)
108
+ internalKeys.add(progressKeyOf(key));
109
+ for (const row of before) {
110
+ if (wanted.has(progressKeyOf(row)))
111
+ internalKeys.add(storedProgressKey(row));
112
+ }
113
+ if (apply) {
114
+ await client.rpc('sync_delete_watch_progress', {
115
+ p_profile_id: profileId,
116
+ p_keys: [...internalKeys],
117
+ p_origin_client_id: originId,
118
+ });
119
+ }
120
+ return { applied: apply, changed: keys.length > 0, before, after, diff };
121
+ }
122
+ export async function deleteWatchHistory(client, profileId, keys, originId, apply) {
123
+ if (keys.length === 0)
124
+ throw new NuvioError('At least one key is required');
125
+ const before = (await readAllWatchHistory(client, profileId));
126
+ const { after, diff } = planHistoryDelete(before, keys);
127
+ if (apply) {
128
+ await client.rpc('sync_delete_watched_items', {
129
+ p_profile_id: profileId,
130
+ p_keys: keys.map((k) => ({
131
+ content_id: k.content_id,
132
+ season: k.season ?? null,
133
+ episode: k.episode ?? null,
134
+ })),
135
+ p_origin_client_id: originId,
136
+ });
137
+ }
138
+ return { applied: apply, changed: keys.length > 0, before, after, diff };
139
+ }