@lappis/cg-manager 0.0.37 → 0.0.39

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/builder/index.js CHANGED
@@ -41,6 +41,7 @@ async function packageSource(ctx) {
41
41
  console.log('Compiling plugin source...');
42
42
  await node(root, path.join('webpack-cli', 'bin', 'cli'));
43
43
  await fs.rm(path.join(root, 'dist', 'index.js.LICENSE.txt')).catch(() => null);
44
+ await fs.cp(path.join(root, 'package.json'), path.join(root, 'dist', 'package.json'));
44
45
  // Full node_modules copy — externals need their deps at runtime.
45
46
  // TODO: prune to transitive closure of pkg.dependencies once a safe walk is validated.
46
47
  await fs.cp(path.join(root, 'node_modules'), path.join(root, 'dist', 'node_modules'), { recursive: true });
@@ -117,6 +118,12 @@ async function movePlugin(ctx) {
117
118
  console.log(`Plugin installed to ${target}`);
118
119
  }
119
120
 
121
+ // Leave only the archive at root; the assembled dir lives at dest (if any).
122
+ async function cleanup(ctx) {
123
+ const { root, out } = ctx;
124
+ await fs.rm(path.join(root, out), { recursive: true }).catch(() => null);
125
+ }
126
+
120
127
  async function build(options = {}) {
121
128
  const root = options.root || process.cwd();
122
129
  const pkg = JSON.parse(await fs.readFile(path.join(root, 'package.json'), 'utf8'));
@@ -130,7 +137,7 @@ async function build(options = {}) {
130
137
 
131
138
  const ctx = { root, name, out, ui, steps, dest };
132
139
 
133
- const pipeline = [packageSource, packageUI, runSteps, assemble, archive, movePlugin];
140
+ const pipeline = [packageSource, packageUI, runSteps, assemble, archive, movePlugin, cleanup];
134
141
  for (const step of pipeline) {
135
142
  const failed = await step(ctx).then(() => false).catch(e => (console.error(e), true));
136
143
  if (failed) {
@@ -143,4 +150,4 @@ async function build(options = {}) {
143
150
  return true;
144
151
  }
145
152
 
146
- module.exports = { build, packageSource, packageUI, runSteps, assemble, archive, movePlugin };
153
+ module.exports = { build, packageSource, packageUI, runSteps, assemble, archive, movePlugin, cleanup };
package/package.json CHANGED
@@ -3,11 +3,29 @@
3
3
  "repository": "https://github.com/Lapplandsveckan/cg-manager-plugin",
4
4
  "author": "firecraftgaming <eliyah@sundstroem.com>",
5
5
  "license": "MIT",
6
- "version": "0.0.37",
6
+ "version": "0.0.39",
7
7
  "main": "dist/index.js",
8
8
  "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "default": "./dist/index.js"
13
+ },
14
+ "./web-lib": {
15
+ "types": "./web-lib/index.d.ts"
16
+ }
17
+ },
18
+ "peerDependencies": {
19
+ "@types/react": "^18.0.0",
20
+ "react": "^18.0.0"
21
+ },
22
+ "peerDependenciesMeta": {
23
+ "@types/react": { "optional": true },
24
+ "react": { "optional": true }
25
+ },
9
26
  "devDependencies": {
10
27
  "@babel/core": "^7.19.3",
28
+ "@types/react": "^18.2.0",
11
29
  "@babel/preset-env": "^7.19.3",
12
30
  "@babel/preset-typescript": "^7.18.6",
13
31
  "@testdeck/mocha": "^0.3.3",
@@ -32,6 +50,7 @@
32
50
  "dist",
33
51
  "builder",
34
52
  "bin",
53
+ "web-lib",
35
54
  "LICENSE",
36
55
  "package.json"
37
56
  ],
@@ -0,0 +1,292 @@
1
+ /**
2
+ * Type declarations for `@web-lib` — the web component/hook library that
3
+ * cg-manager exposes to plugin UIs at runtime as the global `WebLib`.
4
+ *
5
+ * This is a HAND-AUTHORED, types-only mirror of cg-manager's public web-lib
6
+ * surface (`src/web/src/lib/index.ts`). There is no runtime code here — the
7
+ * host (cg-manager) provides the implementation via the `@web-lib → WebLib`
8
+ * webpack external. Plugins resolve this file through a tsconfig `paths`
9
+ * alias: `"@web-lib": ["node_modules/@lappis/cg-manager/web-lib"]`.
10
+ *
11
+ * A drift guard in cg-manager (`src/web/src/lib/__typecheck__.ts`) fails the
12
+ * build if these declarations diverge from the real exports — keep them in
13
+ * sync there, not by guessing here.
14
+ */
15
+
16
+ import type * as React from 'react';
17
+
18
+ // ---------------------------------------------------------------------------
19
+ // Media
20
+ // ---------------------------------------------------------------------------
21
+
22
+ export interface MediaDoc {
23
+ id: string;
24
+
25
+ mediaPath?: string;
26
+ mediaSize?: number;
27
+ mediaTime?: number;
28
+
29
+ thumbSize?: number;
30
+ thumbTime?: number;
31
+
32
+ cinf?: string;
33
+ tinf?: string;
34
+
35
+ mediainfo?: {
36
+ name: string;
37
+ path: string;
38
+ size: number;
39
+ time: number;
40
+ field_order: string;
41
+
42
+ streams: {
43
+ codec: {
44
+ long_name: string;
45
+ type: string;
46
+ time_base: string;
47
+ tag_string: string;
48
+ is_avc: any;
49
+ };
50
+
51
+ // Video
52
+ width: number;
53
+ height: number;
54
+ sample_aspect_ratio: string;
55
+ display_aspect_ratio: string;
56
+ pix_fmt: string;
57
+ bits_per_raw_sample: string;
58
+
59
+ // Audio
60
+ sample_fmt: string;
61
+ sample_rate: number;
62
+ channels: number;
63
+ channel_layout: string;
64
+ bits_per_sample: number;
65
+
66
+ // Common
67
+ time_base: string;
68
+ start_time: number;
69
+ duration_ts: string;
70
+ duration: string;
71
+
72
+ bit_rate: string;
73
+ max_bit_rate: string;
74
+ nb_frames: string;
75
+ }[];
76
+
77
+ format: {
78
+ name: string;
79
+ long_name: string;
80
+ size: string;
81
+
82
+ start_time: number;
83
+ duration: number;
84
+ bit_rate: number;
85
+ max_bit_rate: number;
86
+ };
87
+ };
88
+
89
+ _attachments?: Record<string, { content_type: string; data: unknown }>;
90
+ }
91
+
92
+ // ---------------------------------------------------------------------------
93
+ // Socket / ManagerApi
94
+ //
95
+ // The real `ManagerApi` (cg-manager `src/web/src/lib/api/api.ts`) is large and
96
+ // pulls in the rest-exchange-protocol client transitively. We declare the
97
+ // members plugins actually reach for; the rest stay broad on purpose. Tighten
98
+ // here as plugin usage grows.
99
+ // ---------------------------------------------------------------------------
100
+
101
+ export interface CasparServerApi {
102
+ on(event: string, listener: (...args: any[]) => void): this;
103
+ off(event: string, listener: (...args: any[]) => void): this;
104
+ getMedia(): Promise<Map<string, MediaDoc>>;
105
+ deleteMedia(id: string): Promise<void>;
106
+ renameMedia(id: string, newName: string): Promise<void>;
107
+ }
108
+
109
+ export interface RoutesApi {
110
+ register(...args: any[]): any;
111
+ unregister(...args: any[]): any;
112
+ }
113
+
114
+ export interface ManagerApi {
115
+ caspar: CasparServerApi;
116
+ routes: RoutesApi;
117
+ videoRoutes: any;
118
+ injects: any;
119
+ plugin: any;
120
+
121
+ rawRequest(path: string, method: string, data: any): Promise<any>;
122
+ connect(): Promise<void>;
123
+ disconnect(): Promise<void>;
124
+ getApiVersion(): Promise<any>;
125
+ }
126
+
127
+ export function useSocket(): ManagerApi | null | undefined;
128
+
129
+ // ---------------------------------------------------------------------------
130
+ // Rundown
131
+ // ---------------------------------------------------------------------------
132
+
133
+ export interface RundownEditorActionBarProps {
134
+ /** Primary action — saves the edit. Always present. */
135
+ onSave: () => void;
136
+ /** Dismiss the editor without saving or deleting. */
137
+ onCancel?: () => void;
138
+ /** Destructive action — usually wired up to a confirmation step. */
139
+ onDelete?: () => void;
140
+ /**
141
+ * @deprecated Legacy contract kept so existing plugins keep working.
142
+ * Prefer omitting `exists` and passing `onCancel` + optional `onDelete`.
143
+ */
144
+ exists?: boolean;
145
+ }
146
+
147
+ export const RundownEditorActionBar: React.FC<RundownEditorActionBarProps>;
148
+
149
+ /** True when the editor is rendered for instant playout. */
150
+ export const InstantPlayoutContext: React.Context<boolean>;
151
+
152
+ export const RundownLiveProvider: React.FC<{
153
+ live: boolean;
154
+ children: React.ReactNode;
155
+ }>;
156
+
157
+ /** `true` when the nearest rundown ancestor is live, `false` otherwise. */
158
+ export function useRundownLive(): boolean;
159
+
160
+ // ---------------------------------------------------------------------------
161
+ // Media views
162
+ // ---------------------------------------------------------------------------
163
+
164
+ export interface MediaViewProps {
165
+ columns?: number;
166
+ onClipSelect?: (clip: MediaDoc) => void;
167
+ prefix?: string;
168
+
169
+ showAsDirectories?: boolean;
170
+ onNavigate?: (path: string) => void;
171
+
172
+ onClipPlay?: (clip: MediaDoc) => void;
173
+ onClipDelete?: (clip: MediaDoc) => void;
174
+ onClipRename?: (clip: MediaDoc) => void;
175
+ onFolderDelete?: (folder: string) => void;
176
+ onFolderRename?: (folder: string) => void;
177
+ onClipMoveToFolder?: (clipId: string, folderFullPath: string) => void;
178
+ }
179
+
180
+ export const MediaView: React.FC<MediaViewProps>;
181
+
182
+ export interface MediaSelectProps {
183
+ clip?: MediaDoc | null;
184
+ onClipSelect: (clip: MediaDoc) => void;
185
+ }
186
+
187
+ export const MediaSelect: React.FC<MediaSelectProps>;
188
+
189
+ export interface MediaCardProps {
190
+ name: string;
191
+ duration: number;
192
+
193
+ backgroundUrl: string;
194
+
195
+ columns?: number;
196
+ onClick?: () => void;
197
+ onPlay?: () => void;
198
+ onDelete?: () => void;
199
+ onRename?: () => void;
200
+ /** Full media id (slash-separated); makes the card draggable. */
201
+ dragId?: string;
202
+ }
203
+
204
+ export const MediaCard: React.FC<MediaCardProps>;
205
+
206
+ export interface MediaDropZoneProps {
207
+ /** Server-side directory prefix uploads land in (trailing slash). */
208
+ destination?: string;
209
+ createUpload?: (file: File) => Promise<string>;
210
+ targetPathFor?: (file: File) => string;
211
+ onComplete?: (results: UploadFileResult[]) => void;
212
+ accept?: string[];
213
+ multiple?: boolean;
214
+ overlayLabel?: string;
215
+ children: React.ReactNode;
216
+ }
217
+
218
+ export const MediaDropZone: React.FC<MediaDropZoneProps>;
219
+
220
+ // ---------------------------------------------------------------------------
221
+ // Upload primitives
222
+ // ---------------------------------------------------------------------------
223
+
224
+ export type UploadPhase =
225
+ | 'idle'
226
+ | 'review'
227
+ | 'starting'
228
+ | 'uploading'
229
+ | 'done'
230
+ | 'error';
231
+
232
+ export interface UploadFileResult {
233
+ file: File;
234
+ error?: string;
235
+ }
236
+
237
+ export interface FileUploadState {
238
+ phase: UploadPhase;
239
+ queue: File[];
240
+ completed: UploadFileResult[];
241
+ currentIndex: number;
242
+ currentProgress: number;
243
+ currentFile: File | null;
244
+ error: string | null;
245
+ }
246
+
247
+ export interface FileUploadController {
248
+ state: FileUploadState;
249
+ start: (files: File[]) => void;
250
+ confirm: () => void;
251
+ cancel: () => void;
252
+ reset: () => void;
253
+ }
254
+
255
+ export function useFileUpload(options: {
256
+ createUpload: (file: File) => Promise<string>;
257
+ }): FileUploadController;
258
+
259
+ export interface DropzoneProps {
260
+ onDrop: (files: File[]) => void;
261
+ children: React.ReactNode;
262
+ accept?: string[];
263
+ multiple?: boolean;
264
+ disabled?: boolean;
265
+ overlayLabel?: string;
266
+ fill?: boolean;
267
+ }
268
+
269
+ export const Dropzone: React.FC<DropzoneProps>;
270
+
271
+ export interface UploadButtonProps {
272
+ types?: { description?: string; accept: Record<string, string[]> }[];
273
+ createUpload?: (file: File) => Promise<string>;
274
+ controller?: FileUploadController;
275
+ multiple?: boolean;
276
+ label?: string;
277
+ targetPathFor?: (file: File) => string;
278
+ }
279
+
280
+ export const UploadButton: React.FC<UploadButtonProps>;
281
+
282
+ export interface UploadModalProps {
283
+ state: FileUploadState;
284
+ onClose: () => void;
285
+ onCancel?: () => void;
286
+ onConfirm?: () => void;
287
+ targetPathFor?: (file: File) => string;
288
+ /** Injection zone key for plugin-injected options; `null` suppresses them. */
289
+ optionsZone?: string | null;
290
+ }
291
+
292
+ export const UploadModal: React.FC<UploadModalProps>;