@pipelab/shared 1.0.0-beta.3 → 1.0.0-beta.30

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pipelab/shared",
3
- "version": "1.0.0-beta.3",
3
+ "version": "1.0.0-beta.30",
4
4
  "private": false,
5
5
  "description": "Shared logic and types for the Pipelab ecosystem",
6
6
  "license": "FSL-1.1-MIT",
@@ -37,17 +37,21 @@
37
37
  "tslog": "4.9.3",
38
38
  "type-fest": "4.26.1",
39
39
  "valibot": "0.42.1",
40
- "@pipelab/migration": "1.0.0-beta.3"
40
+ "@pipelab/constants": "1.0.0-beta.31",
41
+ "@pipelab/migration": "1.0.0-beta.29"
41
42
  },
42
43
  "devDependencies": {
43
44
  "esbuild-plugin-wasm": "1.1.0",
44
45
  "tsdown": "0.21.2",
45
46
  "typescript": "5.9.3",
46
- "@pipelab/tsconfig": "1.0.0-beta.3"
47
+ "vitest": "3.1.4",
48
+ "@pipelab/tsconfig": "1.0.0-beta.29"
47
49
  },
48
50
  "scripts": {
49
51
  "build": "tsdown",
50
52
  "format": "oxfmt .",
51
- "lint": "oxlint ."
53
+ "lint": "oxlint .",
54
+ "typecheck": "tsc -b",
55
+ "test": "vitest run"
52
56
  }
53
57
  }
package/src/apis.ts CHANGED
@@ -1,16 +1,11 @@
1
1
  import { RendererPluginDefinition } from "./plugins/definitions";
2
2
  import { User, UserResponse } from "@supabase/supabase-js";
3
3
  import type { Tagged } from "type-fest";
4
- import { PresetResult, Steps } from "./model";
5
- import { AppConfig } from "./config.schema";
4
+ import { PresetResult, Steps, SavedFile } from "./model";
5
+ import { AppConfig, ConnectionsConfig } from "./config.schema";
6
+ import { FileRepo } from "./config/projects-definition";
6
7
  import { Agent } from "./websocket.types";
7
- import {
8
- BuildHistoryEntry,
9
- BuildHistoryQuery,
10
- BuildHistoryResponse,
11
- BuildHistoryConfig,
12
- RetentionPolicy,
13
- } from "./build-history";
8
+ import { BuildHistoryEntry, BuildHistoryQuery, BuildHistoryResponse } from "./build-history";
14
9
 
15
10
  type Event<TYPE extends string, DATA> =
16
11
  | { type: TYPE; data: DATA }
@@ -31,6 +26,62 @@ type EndEvent<DATA> = {
31
26
 
32
27
  export type Presets = Record<string, PresetResult>;
33
28
 
29
+ export type StableDataReport = {
30
+ sourceChannel: "Stable" | "Beta" | "Dev";
31
+ targetChannel: "Stable" | "Beta" | "Dev";
32
+
33
+ // Settings
34
+ settingsExists: boolean;
35
+ settingsVersion: string | null;
36
+ settingsVersionTarget: string | null;
37
+ settingsMtimeSource: number;
38
+ settingsMtimeTarget: number;
39
+ settingsImportable: boolean;
40
+
41
+ // Connections
42
+ connectionsExists: boolean;
43
+ connectionsCount: number;
44
+ connectionsVersion: string | null;
45
+ connectionsVersionTarget: string | null;
46
+ connectionsMtimeSource: number;
47
+ connectionsMtimeTarget: number;
48
+ connectionsImportable: boolean;
49
+
50
+ // Projects
51
+ projectsExists: boolean;
52
+ projectsVersion: string | null;
53
+ projectsVersionTarget: string | null;
54
+ projectsMtimeSource: number;
55
+ projectsMtimeTarget: number;
56
+ projectsImportable: boolean;
57
+
58
+ projects: Array<{
59
+ id: string;
60
+ name: string;
61
+ description: string;
62
+ pipelines: Array<{
63
+ id: string;
64
+ name: string;
65
+ description: string;
66
+ type: "internal" | "external" | "pipelab-cloud";
67
+ lastModifiedStable?: string;
68
+ lastModifiedBeta?: string;
69
+ existsInBeta: boolean;
70
+ }>;
71
+ }>;
72
+ };
73
+
74
+ export type ReleaseChannel = "stable" | "beta" | "dev";
75
+ export type MigrationChannel = "stable" | "beta";
76
+
77
+ export type MigrationOptions = {
78
+ migrateSettings: boolean;
79
+ migrateConnections: boolean;
80
+ selectedProjects: string[];
81
+ selectedPipelines: string[];
82
+ sourceChannel?: MigrationChannel;
83
+ };
84
+
34
85
  export type IpcDefinition = {
35
86
  "fs:read": [
36
87
  // input
@@ -72,6 +123,7 @@ export type IpcDefinition = {
72
123
  }[];
73
124
  }>,
74
125
  ];
126
+ "fs:isPathBlacklisted": [{ path: string }, EndEvent<{ isBlacklisted: boolean }>];
75
127
  "fs:getHomeDirectory": [void, EndEvent<{ path: string }>];
76
128
  "dialog:showOpenDialog": [
77
129
  // input
@@ -98,24 +150,27 @@ export type IpcDefinition = {
98
150
  | EndEvent<{ outputs: Record<string, unknown>; tmp: string }>
99
151
  ),
100
152
  ];
101
- "condition:execute": [
102
- {
103
- pluginId: string;
104
- nodeId: string;
105
- params: any;
106
- steps: Steps;
107
- },
108
- (
109
- | Event<"progress", unknown>
110
- | Event<"progress", unknown>
111
- | EndEvent<{ outputs: Record<string, unknown>; value: boolean }>
112
- ),
113
- ];
153
+
114
154
  "constants:get": [void, EndEvent<{ result: { userData: string } }>];
115
155
 
116
- "config:load": [{ config: string }, EndEvent<{ result: any }>];
117
- "config:save": [{ data: any; config: string }, EndEvent<{ result: "ok" }>];
118
- "config:reset": [{ config: string; key: string }, EndEvent<{ result: "ok" }>];
156
+ "settings:load": [void, EndEvent<AppConfig>];
157
+ "settings:save": [{ data: AppConfig }, EndEvent<"ok">];
158
+ "settings:reset": [{ key: string }, EndEvent<"ok">];
159
+
160
+ "connections:load": [void, EndEvent<ConnectionsConfig>];
161
+ "connections:save": [{ data: ConnectionsConfig }, EndEvent<"ok">];
162
+ "connections:reset": [{ key: string }, EndEvent<"ok">];
163
+
164
+ "projects:load": [void, EndEvent<FileRepo>];
165
+ "projects:save": [{ data: FileRepo }, EndEvent<"ok">];
166
+ "projects:reset": [{ key: string }, EndEvent<"ok">];
167
+
168
+ "pipeline:load-by-name": [{ name: string }, EndEvent<SavedFile>];
169
+ "pipeline:load-by-path": [{ path: string }, EndEvent<SavedFile>];
170
+ "pipeline:save-by-name": [{ name: string; data: string }, EndEvent<"ok">];
171
+ "pipeline:save-by-path": [{ path: string; data: string }, EndEvent<"ok">];
172
+ "pipeline:delete-by-name": [{ name: string }, EndEvent<"ok">];
173
+ "pipeline:delete-by-path": [{ path: string }, EndEvent<"ok">];
119
174
  "action:cancel": [void, EndEvent<{ result: "ok" | "ko" }>];
120
175
 
121
176
  // Build History APIs
@@ -141,10 +196,6 @@ export type IpcDefinition = {
141
196
  newestEntry?: number;
142
197
  }>,
143
198
  ];
144
- "build-history:configure": [
145
- { config: Partial<BuildHistoryConfig> },
146
- EndEvent<{ result: "ok" | "ko" }>,
147
- ];
148
199
  "agents:get": [void, EndEvent<{ agents: Agent[] }>];
149
200
  "graph:execute": [
150
201
  {
@@ -171,8 +222,52 @@ export type IpcDefinition = {
171
222
  { name: string; options?: any },
172
223
  EndEvent<{ data: any | null; error: any | null }>,
173
224
  ];
174
- "agent:version:get": [void, EndEvent<{ version: string }>];
175
- "startup:progress": [void, { type: "progress"; data: { message: string } } | { type: "ready" }];
225
+ "agent:version:get": [void, EndEvent<{ version: string; channel: ReleaseChannel }>];
226
+ "system:packages:cleanup": [void, EndEvent<boolean>];
227
+ "startup:progress": [
228
+ void,
229
+ { type: "progress"; data: { message: string } } | { type: "ready" } | { type: "done" },
230
+ ];
231
+ "plugin:loaded": [void, { plugin: RendererPluginDefinition }];
232
+ "plugin:search": [
233
+ { query: string },
234
+ EndEvent<{
235
+ results: Array<{
236
+ name: string;
237
+ version: string;
238
+ description?: string;
239
+ keywords?: string[];
240
+ date?: string;
241
+ }>;
242
+ }>,
243
+ ];
244
+ "plugin:get-details": [
245
+ { packageName: string },
246
+ EndEvent<{
247
+ name: string;
248
+ latestVersion: string;
249
+ versions: string[];
250
+ description?: string;
251
+ }>,
252
+ ];
253
+ "plugin:install": [{ packageName: string; version: string }, EndEvent<{ result: "ok" }>];
254
+ "plugin:uninstall": [{ packageName: string }, EndEvent<{ result: "ok" }>];
255
+ "plugin:list-installed": [
256
+ void,
257
+ EndEvent<{
258
+ installed: Array<{
259
+ name: string;
260
+ version: string;
261
+ description?: string;
262
+ }>;
263
+ }>,
264
+ ];
265
+ "plugin:ensure-loaded": [
266
+ { plugins: Record<string, string> },
267
+ EndEvent<{ loaded: string[]; failed: string[] }>,
268
+ ];
269
+ "migration:scan-stable": [{ sourceChannel?: MigrationChannel }, EndEvent<StableDataReport>];
270
+ "migration:perform": [MigrationOptions, EndEvent<{ result: "ok" }>];
176
271
  };
177
272
 
178
273
  export type Channels = keyof IpcDefinition;
@@ -1,4 +1,5 @@
1
1
  // Build History Storage Types and Interfaces
2
+ import { SandboxFolder } from "@pipelab/constants";
2
3
 
3
4
  export interface ExecutionStep {
4
5
  id: string;
@@ -33,6 +34,7 @@ export interface BuildHistoryEntry {
33
34
  pipelineId: string;
34
35
  projectName: string;
35
36
  projectPath: string;
37
+ cachePath?: string;
36
38
  status: "running" | "completed" | "failed" | "cancelled";
37
39
  startTime: number;
38
40
  endTime?: number;
@@ -77,37 +79,15 @@ export interface IBuildHistoryStorage {
77
79
  newestEntry?: number;
78
80
  numberOfPipelines: number;
79
81
  userDataPath: string;
80
- retentionPolicy: {
81
- enabled: boolean;
82
- maxEntries: number;
83
- maxAge: number;
84
- };
85
82
  disk: {
86
83
  total: number;
87
84
  free: number;
88
85
  pipelab: number;
86
+ folders: Array<{ name: SandboxFolder; label: string; size: number }>;
89
87
  };
90
88
  }>;
91
89
  }
92
90
 
93
- // Retention policy configuration
94
- export interface RetentionPolicy {
95
- enabled: boolean;
96
- maxEntries: number;
97
- maxAge: number; // in milliseconds
98
- maxSize: number; // in bytes
99
- keepFailedBuilds: boolean;
100
- keepSuccessfulBuilds: boolean;
101
- }
102
-
103
- // Storage configuration
104
- export interface BuildHistoryConfig {
105
- storagePath: string;
106
- indexFileName: string;
107
- entryFilePrefix: string;
108
- retentionPolicy: RetentionPolicy;
109
- }
110
-
111
91
  // Authorization and subscription types
112
92
  export interface SubscriptionBenefit {
113
93
  id: string;
@@ -0,0 +1,3 @@
1
+ import type { ConnectionsConfig, ConnectionsConfigV1, Connection } from "../config.schema";
2
+
3
+ export type { ConnectionsConfig, ConnectionsConfigV1, Connection };
@@ -16,17 +16,48 @@ import {
16
16
  AppConfigV5,
17
17
  AppConfigV6,
18
18
  AppConfigV7,
19
+ ConnectionsConfig,
20
+ ConnectionsConfigV1,
19
21
  } from "../config.schema";
20
- import { FileRepoV1, FileRepoV2, FileRepo } from "./projects-types";
21
- import { SavedFileV1, SavedFileV2, SavedFileV3, SavedFileV4, SavedFile } from "../model";
22
+
23
+ const DEFAULT_PLUGINS: AppConfig["plugins"] = [
24
+ {
25
+ name: "@pipelab/plugin-construct",
26
+ enabled: true,
27
+ description: "Construct 3 export & packaging",
28
+ },
29
+ { name: "@pipelab/plugin-filesystem", enabled: true, description: "Filesystem utilities" },
30
+ { name: "@pipelab/plugin-system", enabled: true, description: "System & shell commands" },
31
+ { name: "@pipelab/plugin-steam", enabled: true, description: "Steam publishing" },
32
+ { name: "@pipelab/plugin-itch", enabled: true, description: "Itch.io publishing" },
33
+ { name: "@pipelab/plugin-electron", enabled: true, description: "Electron packaging" },
34
+ { name: "@pipelab/plugin-discord", enabled: true, description: "Discord Rich Presence" },
35
+ { name: "@pipelab/plugin-poki", enabled: true, description: "Poki publishing" },
36
+ { name: "@pipelab/plugin-nvpatch", enabled: true, description: "NW.js patching" },
37
+ { name: "@pipelab/plugin-tauri", enabled: true, description: "Tauri packaging" },
38
+ { name: "@pipelab/plugin-minify", enabled: true, description: "Asset minification" },
39
+ { name: "@pipelab/plugin-netlify", enabled: true, description: "Netlify deployment" },
40
+ ];
41
+ import { FileRepoV1, FileRepoV2, FileRepoV3, FileRepo } from "./projects-types";
42
+ import {
43
+ SavedFileV1,
44
+ SavedFileV2,
45
+ SavedFileV3,
46
+ SavedFileV4,
47
+ SavedFileV5,
48
+ SavedFile,
49
+ } from "../model";
22
50
 
23
51
  // --- Types ---
24
52
 
25
53
  export type Additive<T, P> = OmitVersion<T> & OmitVersion<P>;
26
54
 
55
+ type DistributiveOmit<T, K extends keyof any> = T extends any ? Omit<T, K> : never;
56
+ type DistributiveOmitVersion<T> = DistributiveOmit<T, keyof MigrationSchema>;
57
+
27
58
  const createMigration = <From extends MigrationSchema, To extends MigrationSchema>(config: {
28
59
  version: SemVer;
29
- up: (state: OmitVersion<From>, targetVersion: string) => Awaitable<Additive<To, From>>;
60
+ up: (state: OmitVersion<From>, targetVersion: string) => Awaitable<OmitVersion<To>>;
30
61
  }) => createMigrationBase<From, To>(config);
31
62
 
32
63
  export interface Migrator<T> {
@@ -54,13 +85,7 @@ export const defaultAppSettings = settingsMigratorInternal.createDefault({
54
85
  completed: false,
55
86
  },
56
87
  },
57
- buildHistory: {
58
- retentionPolicy: {
59
- enabled: false,
60
- maxEntries: 50,
61
- maxAge: 30,
62
- },
63
- },
88
+ plugins: DEFAULT_PLUGINS,
64
89
  });
65
90
 
66
91
  export const appSettingsMigrator = settingsMigratorInternal.createMigrations({
@@ -112,18 +137,12 @@ export const appSettingsMigrator = settingsMigratorInternal.createMigrations({
112
137
  createMigration<AppConfigV6, AppConfigV7>({
113
138
  version: "6.0.0" as SemVer,
114
139
  up: (state) => {
115
- // Upgrades V6 to V7: Add agents, add buildHistory.
116
- // (Additive only - keeping cacheFolder and clearTemporaryFoldersOnPipelineEnd)
140
+ const { cacheFolder, clearTemporaryFoldersOnPipelineEnd: __, ...rest } = state;
117
141
  return {
118
- ...state,
142
+ ...rest,
143
+ cacheFolder,
119
144
  agents: [],
120
- buildHistory: {
121
- retentionPolicy: {
122
- enabled: false,
123
- maxEntries: 50,
124
- maxAge: 30,
125
- },
126
- },
145
+ plugins: DEFAULT_PLUGINS,
127
146
  };
128
147
  },
129
148
  }),
@@ -134,12 +153,31 @@ export const appSettingsMigrator = settingsMigratorInternal.createMigrations({
134
153
  ],
135
154
  });
136
155
 
156
+ // --- Connections Migrator ---
157
+
158
+ const connectionsMigratorInternal = createMigrator<ConnectionsConfigV1, ConnectionsConfig>();
159
+
160
+ export const defaultConnections = connectionsMigratorInternal.createDefault({
161
+ version: "1.0.0",
162
+ connections: [],
163
+ });
164
+
165
+ export const connectionsMigrator = connectionsMigratorInternal.createMigrations({
166
+ defaultValue: defaultConnections,
167
+ migrations: [
168
+ createMigration<ConnectionsConfigV1, never>({
169
+ version: "1.0.0" as SemVer,
170
+ up: finalVersion,
171
+ }),
172
+ ],
173
+ });
174
+
137
175
  // --- Projects Migrator ---
138
176
 
139
177
  const fileRepoMigratorInternal = createMigrator<FileRepoV1, FileRepo>();
140
178
 
141
179
  export const defaultFileRepo = fileRepoMigratorInternal.createDefault({
142
- version: "2.0.0",
180
+ version: "3.0.0",
143
181
  projects: [
144
182
  {
145
183
  id: "main",
@@ -178,8 +216,16 @@ export const fileRepoMigrations = fileRepoMigratorInternal.createMigrations({
178
216
  };
179
217
  },
180
218
  }),
181
- createMigration<FileRepoV2, never>({
219
+ createMigration<FileRepoV2, FileRepoV3>({
182
220
  version: "2.0.0",
221
+ up: (state) => {
222
+ return {
223
+ ...state,
224
+ };
225
+ },
226
+ }),
227
+ createMigration<FileRepoV3, never>({
228
+ version: "3.0.0",
183
229
  up: finalVersion,
184
230
  }),
185
231
  ],
@@ -196,8 +242,7 @@ const savedFileDefaultValue = savedFileMigratorInternal.createDefault({
196
242
  description: "",
197
243
  name: "",
198
244
  variables: [],
199
- type: "default",
200
- version: "4.0.0",
245
+ version: "5.0.0",
201
246
  });
202
247
 
203
248
  export const savedFileMigrator = savedFileMigratorInternal.createMigrations({
@@ -275,17 +320,123 @@ export const savedFileMigrator = savedFileMigratorInternal.createMigrations({
275
320
  type: "default",
276
321
  }),
277
322
  }),
278
- createMigration<SavedFileV4, never>({
323
+ createMigration<SavedFileV4, SavedFileV5>({
279
324
  version: "4.0.0" as SemVer,
325
+ up: (_state) => {
326
+ const state = _state as DistributiveOmitVersion<SavedFileV4>;
327
+ if (state.type === "simple") {
328
+ return {
329
+ name: state.name,
330
+ description: state.description,
331
+ canvas: {
332
+ blocks: [],
333
+ triggers: [],
334
+ },
335
+ variables: [],
336
+ };
337
+ }
338
+
339
+ const migrateBlock = (block: any, pluginsMap: Record<string, string>) => {
340
+ if (!block) return;
341
+ if (block.origin?.pluginId) {
342
+ block.origin.pluginId = getStrictPluginId(block.origin.pluginId);
343
+ // Stamp the version from the old top-level plugins map, falling back to "latest"
344
+ block.origin.version = pluginsMap[block.origin.pluginId] ?? "latest";
345
+ }
346
+ };
347
+
348
+ // Normalise the old plugins map's keys first so lookups are consistent
349
+ const normalizedPlugins: Record<string, string> = {};
350
+ if (state.plugins) {
351
+ for (const [key, val] of Object.entries(state.plugins)) {
352
+ normalizedPlugins[getStrictPluginId(key)] = val;
353
+ }
354
+ }
355
+
356
+ // Stamp origin.version on every block and trigger
357
+ if (state.canvas) {
358
+ for (const block of state.canvas.blocks ?? []) {
359
+ migrateBlock(block, normalizedPlugins);
360
+ }
361
+ for (const trigger of state.canvas.triggers ?? []) {
362
+ migrateBlock(trigger, normalizedPlugins);
363
+ }
364
+ }
365
+
366
+ // Drop the top-level plugins map — version is now per-block. Omit type.
367
+ const { plugins: _dropped, type: _type, ...rest } = state;
368
+ return rest;
369
+ },
370
+ }),
371
+ createMigration<SavedFileV5, never>({
372
+ version: "5.0.0" as SemVer,
280
373
  up: finalVersion,
281
374
  }),
282
375
  ],
283
376
  });
284
377
 
378
+ const LEGACY_ID_MAP: Record<string, string> = {
379
+ construct: "@pipelab/plugin-construct",
380
+ filesystem: "@pipelab/plugin-filesystem",
381
+ system: "@pipelab/plugin-system",
382
+ steam: "@pipelab/plugin-steam",
383
+ itch: "@pipelab/plugin-itch",
384
+ electron: "@pipelab/plugin-electron",
385
+ discord: "@pipelab/plugin-discord",
386
+ dicord: "@pipelab/plugin-discord",
387
+ "@pipelab/plugin-dicord": "@pipelab/plugin-discord",
388
+ poki: "@pipelab/plugin-poki",
389
+ nvpatch: "@pipelab/plugin-nvpatch",
390
+ tauri: "@pipelab/plugin-tauri",
391
+ minify: "@pipelab/plugin-minify",
392
+ netlify: "@pipelab/plugin-netlify",
393
+ };
394
+
395
+ export const getStrictPluginId = (pluginId: string): string => {
396
+ if (!pluginId) return pluginId;
397
+ return LEGACY_ID_MAP[pluginId] || pluginId;
398
+ };
399
+
400
+ const normalizeBlockPluginId = (block: any): boolean => {
401
+ if (!block) return false;
402
+ let changed = false;
403
+ if (block.origin?.pluginId) {
404
+ const strictId = getStrictPluginId(block.origin.pluginId);
405
+ if (block.origin.pluginId !== strictId) {
406
+ block.origin.pluginId = strictId;
407
+ changed = true;
408
+ }
409
+ }
410
+ return changed;
411
+ };
412
+
413
+ export const normalizePipelineConfig = (state: any): boolean => {
414
+ if (!state) return false;
415
+ let changed = false;
416
+
417
+ // Normalise plugin IDs in block and trigger origins (pluginId field only;
418
+ // version strings don't need normalisation)
419
+ if (state.canvas) {
420
+ if (Array.isArray(state.canvas.blocks)) {
421
+ for (const block of state.canvas.blocks) {
422
+ if (normalizeBlockPluginId(block)) changed = true;
423
+ }
424
+ }
425
+ if (Array.isArray(state.canvas.triggers)) {
426
+ for (const trigger of state.canvas.triggers) {
427
+ if (normalizeBlockPluginId(trigger)) changed = true;
428
+ }
429
+ }
430
+ }
431
+
432
+ return changed;
433
+ };
434
+
285
435
  // --- Registry ---
286
436
 
287
437
  export const configRegistry: Record<string, Migrator<any>> = {
288
438
  settings: appSettingsMigrator,
289
439
  projects: fileRepoMigrations,
290
440
  pipeline: savedFileMigrator,
441
+ connections: connectionsMigrator,
291
442
  };
@@ -18,8 +18,15 @@ export const FileRepoValidatorV2 = object({
18
18
  pipelines: optional(array(SaveLocationValidator), []),
19
19
  });
20
20
 
21
+ export const FileRepoValidatorV3 = object({
22
+ version: literal("3.0.0"),
23
+ projects: array(FileRepoProjectValidatorV2),
24
+ pipelines: optional(array(SaveLocationValidator), []),
25
+ });
26
+
21
27
  export type FileRepoV1 = InferInput<typeof FileRepoValidatorV1>;
22
28
  export type FileRepoV2 = InferInput<typeof FileRepoValidatorV2>;
29
+ export type FileRepoV3 = InferInput<typeof FileRepoValidatorV3>;
23
30
 
24
- export const FileRepoValidator = FileRepoValidatorV2;
31
+ export const FileRepoValidator = FileRepoValidatorV3;
25
32
  export type FileRepo = InferInput<typeof FileRepoValidator>;
@@ -1,25 +1 @@
1
- import { SaveLocationValidator } from "../save-location";
2
- import { object, string, optional, record, InferInput, literal, array } from "valibot";
3
-
4
- export const FileRepoValidatorV1 = object({
5
- version: literal("1.0.0"),
6
- data: optional(record(string(), SaveLocationValidator), {}),
7
- });
8
-
9
- export const FileRepoProjectValidatorV2 = object({
10
- id: string(),
11
- name: string(),
12
- description: string(),
13
- });
14
-
15
- export const FileRepoValidatorV2 = object({
16
- version: literal("2.0.0"),
17
- projects: array(FileRepoProjectValidatorV2),
18
- pipelines: optional(array(SaveLocationValidator), []),
19
- });
20
-
21
- export type FileRepoV1 = InferInput<typeof FileRepoValidatorV1>;
22
- export type FileRepoV2 = InferInput<typeof FileRepoValidatorV2>;
23
-
24
- export const FileRepoValidator = FileRepoValidatorV2;
25
- export type FileRepo = InferInput<typeof FileRepoValidator>;
1
+ export * from "./projects-definition";
@@ -8,6 +8,8 @@ import {
8
8
  number,
9
9
  array,
10
10
  GenericSchema,
11
+ optional,
12
+ looseObject,
11
13
  } from "valibot";
12
14
 
13
15
  export const createVersionSchema = <T extends GenericSchema<any, any>>(schema: T) => schema;
@@ -126,15 +128,37 @@ export const AppSettingsValidatorV7 = object({
126
128
  url: string(),
127
129
  }),
128
130
  ),
129
- buildHistory: object({
130
- retentionPolicy: object({
131
+ // Metadata list of plugins the user has enabled (official + community).
132
+ // No binaries are stored here — versions are resolved JIT at node-add time.
133
+ plugins: array(
134
+ object({
135
+ name: string(),
131
136
  enabled: boolean(),
132
- maxEntries: number(), // Maximum number of entries per pipeline
133
- maxAge: number(), // Maximum age of entries in days
137
+ description: string(),
134
138
  }),
135
- }),
139
+ ),
140
+ cacheFolder: optional(string()),
141
+ tempFolder: optional(string()),
142
+ });
143
+
144
+ export const ConnectionValidator = looseObject({
145
+ id: string(),
146
+ pluginName: string(),
147
+ name: string(),
148
+ createdAt: string(),
149
+ isDefault: boolean(),
136
150
  });
137
151
 
152
+ export const ConnectionsValidatorV1 = object({
153
+ version: literal("1.0.0"),
154
+ connections: array(ConnectionValidator),
155
+ });
156
+
157
+ export type Connection = InferInput<typeof ConnectionValidator>;
158
+ export type ConnectionsConfigV1 = InferInput<typeof ConnectionsValidatorV1>;
159
+ export type ConnectionsConfig = ConnectionsConfigV1;
160
+ export const ConnectionsValidator = ConnectionsValidatorV1;
161
+
138
162
  export type AppConfigV1 = InferInput<typeof AppSettingsValidatorV1>;
139
163
  export type AppConfigV2 = InferInput<typeof AppSettingsValidatorV2>;
140
164
  export type AppConfigV3 = InferInput<typeof AppSettingsValidatorV3>;
package/src/evaluator.ts CHANGED
@@ -22,7 +22,6 @@ export const makeResolvedParams = async (
22
22
  for (const [paramName, param] of Object.entries(data.params)) {
23
23
  try {
24
24
  const parameterCodeValue = (param.value ?? "").toString();
25
-
26
25
  // Bypass QuickJS for simple static values
27
26
  try {
28
27
  result[paramName] = JSON.parse(parameterCodeValue);