@opendaw/studio-core 0.0.44 → 0.0.46

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 (75) hide show
  1. package/dist/AudioOfflineRenderer.d.ts +1 -2
  2. package/dist/AudioOfflineRenderer.d.ts.map +1 -1
  3. package/dist/AudioOfflineRenderer.js +10 -3
  4. package/dist/EffectBox.d.ts +2 -2
  5. package/dist/EffectBox.d.ts.map +1 -1
  6. package/dist/EffectFactories.d.ts +9 -0
  7. package/dist/EffectFactories.d.ts.map +1 -1
  8. package/dist/EffectFactories.js +41 -24
  9. package/dist/EffectFactory.d.ts +1 -1
  10. package/dist/EffectFactory.d.ts.map +1 -1
  11. package/dist/EffectParameterDefaults.d.ts +5 -0
  12. package/dist/EffectParameterDefaults.d.ts.map +1 -0
  13. package/dist/EffectParameterDefaults.js +27 -0
  14. package/dist/Engine.d.ts +1 -1
  15. package/dist/Engine.d.ts.map +1 -1
  16. package/dist/EngineFacade.d.ts +1 -1
  17. package/dist/EngineFacade.d.ts.map +1 -1
  18. package/dist/EngineFacade.js +1 -1
  19. package/dist/EngineWorklet.d.ts +1 -1
  20. package/dist/EngineWorklet.d.ts.map +1 -1
  21. package/dist/EngineWorklet.js +3 -2
  22. package/dist/Preferences.d.ts +20 -0
  23. package/dist/Preferences.d.ts.map +1 -0
  24. package/dist/Preferences.js +46 -0
  25. package/dist/capture/CaptureDevices.d.ts +1 -1
  26. package/dist/capture/CaptureDevices.d.ts.map +1 -1
  27. package/dist/capture/CaptureDevices.js +22 -11
  28. package/dist/capture/CaptureMidi.js +1 -1
  29. package/dist/capture/RecordTrack.d.ts +2 -2
  30. package/dist/capture/RecordTrack.d.ts.map +1 -1
  31. package/dist/capture/Recording.d.ts +1 -1
  32. package/dist/capture/Recording.d.ts.map +1 -1
  33. package/dist/capture/Recording.js +1 -1
  34. package/dist/dawproject/BuiltinDevices.d.ts.map +1 -1
  35. package/dist/dawproject/BuiltinDevices.js +3 -2
  36. package/dist/dawproject/{DawProjectImport.d.ts → DawProjectImporter.d.ts} +1 -1
  37. package/dist/dawproject/DawProjectImporter.d.ts.map +1 -0
  38. package/dist/dawproject/{DawProjectImport.js → DawProjectImporter.js} +17 -5
  39. package/dist/dawproject/DawProjectImporter.test.d.ts +2 -0
  40. package/dist/dawproject/DawProjectImporter.test.d.ts.map +1 -0
  41. package/dist/dawproject/{DawProjectImport.test.js → DawProjectImporter.test.js} +1 -1
  42. package/dist/dawproject/DawProjectService.js +1 -1
  43. package/dist/dawproject/index.d.ts +1 -1
  44. package/dist/dawproject/index.d.ts.map +1 -1
  45. package/dist/dawproject/index.js +1 -1
  46. package/dist/index.d.ts +1 -0
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +1 -0
  49. package/dist/midi/MIDILearning.d.ts +1 -1
  50. package/dist/midi/MIDILearning.d.ts.map +1 -1
  51. package/dist/midi/MIDILearning.js +22 -3
  52. package/dist/processors.js +7 -7
  53. package/dist/processors.js.map +4 -4
  54. package/dist/project/Project.d.ts +12 -7
  55. package/dist/project/Project.d.ts.map +1 -1
  56. package/dist/project/Project.js +60 -33
  57. package/dist/project/ProjectMigration.d.ts.map +1 -1
  58. package/dist/project/ProjectMigration.js +10 -1
  59. package/dist/project/Recovery.d.ts +9 -0
  60. package/dist/project/Recovery.d.ts.map +1 -0
  61. package/dist/project/Recovery.js +49 -0
  62. package/dist/project/index.d.ts +1 -0
  63. package/dist/project/index.d.ts.map +1 -1
  64. package/dist/project/index.js +1 -0
  65. package/dist/workers-main.js +2 -2
  66. package/dist/workers-main.js.map +4 -4
  67. package/dist/ysync/YService.d.ts.map +1 -1
  68. package/dist/ysync/YService.js +19 -8
  69. package/dist/ysync/YSync.d.ts +4 -4
  70. package/dist/ysync/YSync.d.ts.map +1 -1
  71. package/dist/ysync/YSync.js +29 -26
  72. package/package.json +49 -49
  73. package/dist/dawproject/DawProjectImport.d.ts.map +0 -1
  74. package/dist/dawproject/DawProjectImport.test.d.ts +0 -2
  75. package/dist/dawproject/DawProjectImport.test.d.ts.map +0 -1
@@ -1,5 +1,5 @@
1
- import { Procedure, Terminable, TerminableOwner, Terminator } from "@opendaw/lib-std";
2
- import { BoxGraph, Editing } from "@opendaw/lib-box";
1
+ import { Func, Procedure, Terminable, TerminableOwner, Terminator, UUID } from "@opendaw/lib-std";
2
+ import { BoxEditing, BoxGraph } from "@opendaw/lib-box";
3
3
  import { AudioBusBox, AudioUnitBox, BoxIO, RootBox, TimelineBox, UserInterfaceBox } from "@opendaw/studio-boxes";
4
4
  import { BoxAdapters, BoxAdaptersContext, ClipSequencing, ParameterFieldAdapters, ProcessorOptions, ProjectSkeleton, RootBoxAdapter, SampleLoaderManager, SoundfontLoaderManager, TimelineBoxAdapter, UserEditingManager, VertexSelection } from "@opendaw/studio-adapters";
5
5
  import { LiveStreamBroadcaster, LiveStreamReceiver } from "@opendaw/lib-fusion";
@@ -11,23 +11,26 @@ import { EngineFacade } from "../EngineFacade";
11
11
  import { EngineWorklet } from "../EngineWorklet";
12
12
  import { MIDILearning } from "../midi";
13
13
  export type RestartWorklet = {
14
- unload: Procedure<unknown>;
14
+ unload: Func<unknown, Promise<unknown>>;
15
15
  load: Procedure<EngineWorklet>;
16
16
  };
17
+ export type ProjectCreateOptions = {
18
+ noDefaultUser?: boolean;
19
+ };
17
20
  export declare class Project implements BoxAdaptersContext, Terminable, TerminableOwner {
18
21
  #private;
19
- static new(env: ProjectEnv): Project;
22
+ static new(env: ProjectEnv, options?: ProjectCreateOptions): Project;
20
23
  static load(env: ProjectEnv, arrayBuffer: ArrayBuffer): Project;
21
- static skeleton(env: ProjectEnv, skeleton: ProjectSkeleton): Project;
24
+ static skeleton(env: ProjectEnv, skeleton: ProjectSkeleton, followFirstUser?: boolean): Project;
22
25
  readonly boxGraph: BoxGraph<BoxIO.TypeMap>;
23
26
  readonly rootBox: RootBox;
24
- readonly userInterfaceBox: UserInterfaceBox;
27
+ readonly userInterfaceBoxes: ReadonlyArray<UserInterfaceBox>;
25
28
  readonly masterBusBox: AudioBusBox;
26
29
  readonly masterAudioUnit: AudioUnitBox;
27
30
  readonly timelineBox: TimelineBox;
28
31
  readonly api: ProjectApi;
29
32
  readonly captureDevices: CaptureDevices;
30
- readonly editing: Editing;
33
+ readonly editing: BoxEditing;
31
34
  readonly selection: VertexSelection;
32
35
  readonly boxAdapters: BoxAdapters;
33
36
  readonly userEditingManager: UserEditingManager;
@@ -39,6 +42,7 @@ export declare class Project implements BoxAdaptersContext, Terminable, Terminab
39
42
  private constructor();
40
43
  startAudioWorklet(restart?: RestartWorklet, options?: ProcessorOptions): EngineWorklet;
41
44
  startRecording(countIn?: boolean): void;
45
+ follow(box: UserInterfaceBox): void;
42
46
  own<T extends Terminable>(terminable: T): T;
43
47
  ownAll<T extends Terminable>(...terminables: Array<T>): void;
44
48
  spawn(): Terminator;
@@ -53,6 +57,7 @@ export declare class Project implements BoxAdaptersContext, Terminable, Terminab
53
57
  get isMainThread(): boolean;
54
58
  get liveStreamBroadcaster(): LiveStreamBroadcaster;
55
59
  get skeleton(): ProjectSkeleton;
60
+ collectSampleUUIDs(): ReadonlyArray<UUID.Bytes>;
56
61
  toArrayBuffer(): ArrayBufferLike;
57
62
  copy(env?: Partial<ProjectEnv>): Project;
58
63
  invalid(): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"Project.d.ts","sourceRoot":"","sources":["../../src/project/Project.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Project.d.ts","sourceRoot":"","sources":["../../src/project/Project.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { Arrays, ByteArrayOutput, Option, panic, safeExecute, Terminator, UUID } from "@opendaw/lib-std";
2
- import { BoxGraph, Editing } from "@opendaw/lib-box";
3
- import { AudioBusBox, AudioUnitBox, BoxIO, GrooveShuffleBox, RootBox, TimelineBox, UserInterfaceBox } from "@opendaw/studio-boxes";
2
+ import { BoxEditing, BoxGraph } from "@opendaw/lib-box";
3
+ import { AudioBusBox, AudioUnitBox, BoxIO, CompressorDeviceBox, GrooveShuffleBox, RootBox, TimelineBox, UserInterfaceBox } from "@opendaw/studio-boxes";
4
4
  import { BoxAdapters, IconSymbol, ParameterFieldAdapters, ProjectDecoder, RootBoxAdapter, TimelineBoxAdapter, UnionBoxTypes, UserEditingManager, VertexSelection } from "@opendaw/studio-adapters";
5
5
  import { LiveStreamReceiver } from "@opendaw/lib-fusion";
6
6
  import { AudioUnitType } from "@opendaw/studio-enums";
@@ -11,9 +11,10 @@ import { CaptureDevices, Recording } from "../capture";
11
11
  import { EngineFacade } from "../EngineFacade";
12
12
  import { MIDILearning } from "../midi";
13
13
  import { ProjectValidation } from "./ProjectValidation";
14
+ import { Preferences } from "../Preferences";
14
15
  // Main Entry Point for a Project
15
16
  export class Project {
16
- static new(env) {
17
+ static new(env, options) {
17
18
  const boxGraph = new BoxGraph(Option.wrap(BoxIO.create));
18
19
  const isoString = new Date().toISOString();
19
20
  console.debug(`New Project created on ${isoString}`);
@@ -25,45 +26,67 @@ export class Project {
25
26
  box.groove.refer(grooveShuffleBox);
26
27
  box.created.setValue(isoString);
27
28
  });
28
- const userInterfaceBox = UserInterfaceBox.create(boxGraph, UUID.generate());
29
- const masterBusBox = AudioBusBox.create(boxGraph, UUID.generate(), box => {
29
+ const primaryAudioBus = AudioBusBox.create(boxGraph, UUID.generate(), box => {
30
30
  box.collection.refer(rootBox.audioBusses);
31
31
  box.label.setValue("Output");
32
32
  box.icon.setValue(IconSymbol.toName(IconSymbol.SpeakerHeadphone));
33
33
  box.color.setValue(/*Colors.blue*/ "hsl(189, 100%, 65%)"); // TODO
34
34
  });
35
- const masterAudioUnit = AudioUnitBox.create(boxGraph, UUID.generate(), box => {
35
+ const primaryAudioOutputUnit = AudioUnitBox.create(boxGraph, UUID.generate(), box => {
36
36
  box.type.setValue(AudioUnitType.Output);
37
37
  box.collection.refer(rootBox.audioUnits);
38
38
  box.output.refer(rootBox.outputDevice);
39
39
  box.index.setValue(0);
40
40
  });
41
+ if (Preferences.values["auto-create-output-compressor"]) {
42
+ CompressorDeviceBox.create(boxGraph, UUID.generate(), box => {
43
+ box.label.setValue("Compressor");
44
+ box.index.setValue(0);
45
+ box.host.refer(primaryAudioOutputUnit.audioEffects);
46
+ box.threshold.setValue(0);
47
+ box.ratio.setValue(24);
48
+ });
49
+ }
41
50
  const timelineBox = TimelineBox.create(boxGraph, UUID.generate());
42
51
  rootBox.timeline.refer(timelineBox.root);
43
- userInterfaceBox.root.refer(rootBox.users);
44
- masterBusBox.output.refer(masterAudioUnit.input);
52
+ primaryAudioBus.output.refer(primaryAudioOutputUnit.input);
53
+ const userInterfaceBoxes = [];
54
+ const createDefaultUser = options?.noDefaultUser !== true;
55
+ if (createDefaultUser) {
56
+ const userInterfaceBox = UserInterfaceBox.create(boxGraph, UUID.generate());
57
+ userInterfaceBox.root.refer(rootBox.users);
58
+ userInterfaceBoxes.push(userInterfaceBox);
59
+ }
45
60
  boxGraph.endTransaction();
46
- return new Project(env, boxGraph, {
61
+ const project = new Project(env, boxGraph, {
47
62
  rootBox,
48
- userInterfaceBox,
49
- masterBusBox,
50
- masterAudioUnit,
63
+ primaryAudioBus,
64
+ primaryAudioOutputUnit,
65
+ userInterfaceBoxes,
51
66
  timelineBox
52
67
  });
68
+ if (createDefaultUser) {
69
+ project.follow(userInterfaceBoxes[0]);
70
+ }
71
+ return project;
53
72
  }
54
73
  static load(env, arrayBuffer) {
55
74
  return this.skeleton(env, ProjectDecoder.decode(arrayBuffer));
56
75
  }
57
- static skeleton(env, skeleton) {
76
+ static skeleton(env, skeleton, followFirstUser = true) {
58
77
  ProjectMigration.migrate(skeleton);
59
78
  ProjectValidation.validate(skeleton);
60
- return new Project(env, skeleton.boxGraph, skeleton.mandatoryBoxes);
79
+ const project = new Project(env, skeleton.boxGraph, skeleton.mandatoryBoxes);
80
+ if (followFirstUser) {
81
+ project.follow(project.userInterfaceBoxes[0]);
82
+ }
83
+ return project;
61
84
  }
62
85
  #terminator = new Terminator();
63
86
  #env;
64
87
  boxGraph;
65
88
  rootBox;
66
- userInterfaceBox;
89
+ userInterfaceBoxes;
67
90
  masterBusBox;
68
91
  masterAudioUnit;
69
92
  timelineBox;
@@ -78,26 +101,28 @@ export class Project {
78
101
  midiLearning;
79
102
  mixer;
80
103
  engine = new EngineFacade();
81
- constructor(env, boxGraph, { rootBox, userInterfaceBox, masterBusBox, masterAudioUnit, timelineBox }) {
104
+ constructor(env, boxGraph, { rootBox, userInterfaceBoxes, primaryAudioBus, primaryAudioOutputUnit, timelineBox }) {
82
105
  this.#env = env;
83
106
  this.boxGraph = boxGraph;
84
107
  this.rootBox = rootBox;
85
- this.userInterfaceBox = userInterfaceBox;
86
- this.masterBusBox = masterBusBox;
87
- this.masterAudioUnit = masterAudioUnit;
108
+ this.userInterfaceBoxes = userInterfaceBoxes;
109
+ this.masterBusBox = primaryAudioBus;
110
+ this.masterAudioUnit = primaryAudioOutputUnit;
88
111
  this.timelineBox = timelineBox;
89
112
  this.api = new ProjectApi(this);
90
- this.editing = new Editing(this.boxGraph);
113
+ this.editing = new BoxEditing(this.boxGraph);
91
114
  this.selection = new VertexSelection(this.editing, this.boxGraph);
92
115
  this.parameterFieldAdapters = new ParameterFieldAdapters();
93
116
  this.boxAdapters = this.#terminator.own(new BoxAdapters(this));
94
117
  this.userEditingManager = new UserEditingManager(this.editing);
95
- this.userEditingManager.follow(this.userInterfaceBox);
96
- this.selection.switch(this.userInterfaceBox.selection);
97
118
  this.liveStreamReceiver = this.#terminator.own(new LiveStreamReceiver());
98
119
  this.midiLearning = this.#terminator.own(new MIDILearning(this));
99
120
  this.captureDevices = this.#terminator.own(new CaptureDevices(this));
100
121
  this.mixer = new Mixer(this.rootBoxAdapter.audioUnits);
122
+ // TODO We are probably doing that from the outside
123
+ if (this.userInterfaceBoxes.length === 1) {
124
+ this.follow(this.userInterfaceBoxes[0]);
125
+ }
101
126
  console.debug(`Project was created on ${this.rootBoxAdapter.created.toString()}`);
102
127
  }
103
128
  startAudioWorklet(restart, options) {
@@ -109,8 +134,8 @@ export class Project {
109
134
  // we will only accept the first error
110
135
  engine.removeEventListener("error", handler);
111
136
  engine.removeEventListener("processorerror", handler);
112
- safeExecute(restart?.unload, event);
113
137
  lifecycle.terminate();
138
+ await safeExecute(restart?.unload, event);
114
139
  safeExecute(restart?.load, this.startAudioWorklet(restart));
115
140
  };
116
141
  engine.addEventListener("error", handler);
@@ -126,6 +151,10 @@ export class Project {
126
151
  }
127
152
  Recording.start(this, countIn).finally();
128
153
  }
154
+ follow(box) {
155
+ this.userEditingManager.follow(box);
156
+ this.selection.switch(box.selection);
157
+ }
129
158
  own(terminable) { return this.#terminator.own(terminable); }
130
159
  ownAll(...terminables) { return this.#terminator.ownAll(...terminables); }
131
160
  spawn() { return this.#terminator.spawn(); }
@@ -145,26 +174,24 @@ export class Project {
145
174
  mandatoryBoxes: {
146
175
  rootBox: this.rootBox,
147
176
  timelineBox: this.timelineBox,
148
- masterBusBox: this.masterBusBox,
149
- masterAudioUnit: this.masterAudioUnit,
150
- userInterfaceBox: this.userInterfaceBox
177
+ primaryAudioBus: this.masterBusBox,
178
+ primaryAudioOutputUnit: this.masterAudioUnit,
179
+ userInterfaceBoxes: this.userInterfaceBoxes
151
180
  }
152
181
  };
153
182
  }
183
+ collectSampleUUIDs() {
184
+ return this.boxGraph.boxes()
185
+ .filter(box => box.accept({ visitAudioFileBox: (_box) => true }))
186
+ .map(box => box.address.uuid);
187
+ }
154
188
  toArrayBuffer() {
155
189
  const output = ByteArrayOutput.create();
156
190
  output.writeInt(ProjectDecoder.MAGIC_HEADER_OPEN);
157
191
  output.writeInt(ProjectDecoder.FORMAT_VERSION);
158
- // store all boxes
159
192
  const boxGraphChunk = this.boxGraph.toArrayBuffer();
160
193
  output.writeInt(boxGraphChunk.byteLength);
161
194
  output.writeBytes(new Int8Array(boxGraphChunk));
162
- // store mandatory boxes' addresses
163
- UUID.toDataOutput(output, this.rootBox.address.uuid);
164
- UUID.toDataOutput(output, this.userInterfaceBox.address.uuid);
165
- UUID.toDataOutput(output, this.masterBusBox.address.uuid);
166
- UUID.toDataOutput(output, this.masterAudioUnit.address.uuid);
167
- UUID.toDataOutput(output, this.timelineBox.address.uuid);
168
195
  return output.toArrayBuffer();
169
196
  }
170
197
  copy(env) {
@@ -1 +1 @@
1
- {"version":3,"file":"ProjectMigration.d.ts","sourceRoot":"","sources":["../../src/project/ProjectMigration.ts"],"names":[],"mappings":"AAYA,OAAO,EAAC,eAAe,EAAC,MAAM,0BAA0B,CAAA;AAExD,qBAAa,gBAAgB;IACzB,MAAM,CAAC,OAAO,CAAC,EAAC,QAAQ,EAAE,cAAc,EAAC,EAAE,eAAe,GAAG,IAAI;CAmEpE"}
1
+ {"version":3,"file":"ProjectMigration.d.ts","sourceRoot":"","sources":["../../src/project/ProjectMigration.ts"],"names":[],"mappings":"AAaA,OAAO,EAAC,eAAe,EAAC,MAAM,0BAA0B,CAAA;AAExD,qBAAa,gBAAgB;IACzB,MAAM,CAAC,OAAO,CAAC,EAAC,QAAQ,EAAE,cAAc,EAAC,EAAE,eAAe,GAAG,IAAI;CA4EpE"}
@@ -1,5 +1,5 @@
1
1
  import { CaptureAudioBox, CaptureMidiBox, GrooveShuffleBox, ValueEventCurveBox } from "@opendaw/studio-boxes";
2
- import { asDefined, asInstanceOf, UUID } from "@opendaw/lib-std";
2
+ import { asDefined, asInstanceOf, clamp, UUID } from "@opendaw/lib-std";
3
3
  import { AudioUnitType } from "@opendaw/studio-enums";
4
4
  export class ProjectMigration {
5
5
  static migrate({ boxGraph, mandatoryBoxes }) {
@@ -70,6 +70,15 @@ export class ProjectMigration {
70
70
  }));
71
71
  box.capture.refer(captureBox);
72
72
  boxGraph.endTransaction();
73
+ },
74
+ visitRevampDeviceBox: (box) => {
75
+ // Clamp order in RevampDeviceBox to 0-3
76
+ // The older version stored the actual order,
77
+ // but the new version only stores indices, so 4 is not valid anymore
78
+ boxGraph.beginTransaction();
79
+ box.lowPass.order.setValue(clamp(box.lowPass.order.getValue(), 0, 3));
80
+ box.highPass.order.setValue(clamp(box.highPass.order.getValue(), 0, 3));
81
+ boxGraph.endTransaction();
73
82
  }
74
83
  }));
75
84
  }
@@ -0,0 +1,9 @@
1
+ import { Option, Provider } from "@opendaw/lib-std";
2
+ import { ProjectEnv, ProjectProfile } from "../";
3
+ export declare class Recovery {
4
+ #private;
5
+ constructor(projectProfileService: Provider<Option<ProjectProfile>>, env: ProjectEnv);
6
+ restoreProfile(): Promise<Option<ProjectProfile>>;
7
+ createBackupCommand(): Option<Provider<Promise<void>>>;
8
+ }
9
+ //# sourceMappingURL=Recovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Recovery.d.ts","sourceRoot":"","sources":["../../src/project/Recovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAE,QAAQ,EAAO,MAAM,kBAAkB,CAAA;AAEvD,OAAO,EAAU,UAAU,EAAe,cAAc,EAAU,MAAM,KAAK,CAAA;AAE7E,qBAAa,QAAQ;;gBAML,qBAAqB,EAAE,QAAQ,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU;IAK9E,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;IAsBvD,mBAAmB,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;CAgBzD"}
@@ -0,0 +1,49 @@
1
+ import { Option, UUID } from "@opendaw/lib-std";
2
+ import { Promises } from "@opendaw/lib-runtime";
3
+ import { Project, ProjectProfile, Workers } from "../";
4
+ export class Recovery {
5
+ static #RESTORE_FILE_PATH = ".backup";
6
+ #projectProfileProvider;
7
+ #env;
8
+ constructor(projectProfileService, env) {
9
+ this.#projectProfileProvider = projectProfileService;
10
+ this.#env = env;
11
+ }
12
+ async restoreProfile() {
13
+ const backupResult = await Promises.tryCatch(Workers.Opfs.list(Recovery.#RESTORE_FILE_PATH));
14
+ if (backupResult.status === "rejected" || backupResult.value.length === 0) {
15
+ return Option.None;
16
+ }
17
+ const readResult = await Promises.tryCatch(Promise.all([
18
+ Workers.Opfs.read(`${Recovery.#RESTORE_FILE_PATH}/uuid`)
19
+ .then(x => UUID.validateBytes(x)),
20
+ Workers.Opfs.read(`${Recovery.#RESTORE_FILE_PATH}/project.od`)
21
+ .then(x => Project.load(this.#env, x.buffer)),
22
+ Workers.Opfs.read(`${Recovery.#RESTORE_FILE_PATH}/meta.json`)
23
+ .then(x => JSON.parse(new TextDecoder().decode(x.buffer))),
24
+ Workers.Opfs.read(`${Recovery.#RESTORE_FILE_PATH}/saved`)
25
+ .then(x => x.at(0) === 1)
26
+ ]));
27
+ const deleteResult = await Promises.tryCatch(Workers.Opfs.delete(Recovery.#RESTORE_FILE_PATH));
28
+ console.debug(`delete backup: "${deleteResult.status}"`);
29
+ if (readResult.status === "rejected") {
30
+ return Option.None;
31
+ }
32
+ const [uuid, project, meta, saved] = readResult.value;
33
+ const profile = new ProjectProfile(uuid, project, meta, Option.None, saved);
34
+ console.debug(`restore ${profile}, saved: ${saved}`);
35
+ return Option.wrap(profile);
36
+ }
37
+ createBackupCommand() {
38
+ return this.#projectProfileProvider().map((profile) => async () => {
39
+ console.debug("backup project");
40
+ const { project, meta, uuid } = profile;
41
+ return Promises.tryCatch(Promise.all([
42
+ Workers.Opfs.write(`${Recovery.#RESTORE_FILE_PATH}/uuid`, uuid),
43
+ Workers.Opfs.write(`${Recovery.#RESTORE_FILE_PATH}/project.od`, new Uint8Array(project.toArrayBuffer())),
44
+ Workers.Opfs.write(`${Recovery.#RESTORE_FILE_PATH}/meta.json`, new TextEncoder().encode(JSON.stringify(meta))),
45
+ Workers.Opfs.write(`${Recovery.#RESTORE_FILE_PATH}/saved`, new Uint8Array([profile.saved() ? 1 : 0]))
46
+ ])).then(result => console.debug(`backup result: ${result.status}`));
47
+ });
48
+ }
49
+ }
@@ -7,4 +7,5 @@ export * from "./ProjectPaths";
7
7
  export * from "./ProjectProfile";
8
8
  export * from "./ProjectSignals";
9
9
  export * from "./ProjectStorage";
10
+ export * from "./Recovery";
10
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/project/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,eAAe,CAAA;AAC7B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/project/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,eAAe,CAAA;AAC7B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,YAAY,CAAA"}
@@ -7,3 +7,4 @@ export * from "./ProjectPaths";
7
7
  export * from "./ProjectProfile";
8
8
  export * from "./ProjectSignals";
9
9
  export * from "./ProjectStorage";
10
+ export * from "./Recovery";