@opendaw/studio-core 0.0.44 → 0.0.45

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 (67) 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 +6 -0
  7. package/dist/EffectFactories.d.ts.map +1 -1
  8. package/dist/EffectFactories.js +29 -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.js +2 -2
  26. package/dist/capture/RecordTrack.d.ts +2 -2
  27. package/dist/capture/RecordTrack.d.ts.map +1 -1
  28. package/dist/capture/Recording.d.ts +1 -1
  29. package/dist/capture/Recording.d.ts.map +1 -1
  30. package/dist/capture/Recording.js +1 -1
  31. package/dist/dawproject/BuiltinDevices.d.ts.map +1 -1
  32. package/dist/dawproject/BuiltinDevices.js +3 -2
  33. package/dist/dawproject/{DawProjectImport.d.ts → DawProjectImporter.d.ts} +1 -1
  34. package/dist/dawproject/DawProjectImporter.d.ts.map +1 -0
  35. package/dist/dawproject/{DawProjectImport.js → DawProjectImporter.js} +17 -5
  36. package/dist/dawproject/DawProjectImporter.test.d.ts +2 -0
  37. package/dist/dawproject/DawProjectImporter.test.d.ts.map +1 -0
  38. package/dist/dawproject/{DawProjectImport.test.js → DawProjectImporter.test.js} +1 -1
  39. package/dist/dawproject/DawProjectService.js +1 -1
  40. package/dist/dawproject/index.d.ts +1 -1
  41. package/dist/dawproject/index.d.ts.map +1 -1
  42. package/dist/dawproject/index.js +1 -1
  43. package/dist/index.d.ts +1 -0
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +1 -0
  46. package/dist/midi/MIDILearning.d.ts +1 -1
  47. package/dist/midi/MIDILearning.d.ts.map +1 -1
  48. package/dist/midi/MIDILearning.js +22 -3
  49. package/dist/processors.js +12 -12
  50. package/dist/processors.js.map +4 -4
  51. package/dist/project/Project.d.ts +10 -6
  52. package/dist/project/Project.d.ts.map +1 -1
  53. package/dist/project/Project.js +43 -30
  54. package/dist/project/ProjectMigration.d.ts.map +1 -1
  55. package/dist/project/ProjectMigration.js +10 -1
  56. package/dist/project/Recovery.d.ts +9 -0
  57. package/dist/project/Recovery.d.ts.map +1 -0
  58. package/dist/project/Recovery.js +49 -0
  59. package/dist/project/index.d.ts +1 -0
  60. package/dist/project/index.d.ts.map +1 -1
  61. package/dist/project/index.js +1 -0
  62. package/dist/workers-main.js +2 -2
  63. package/dist/workers-main.js.map +4 -4
  64. package/package.json +49 -49
  65. package/dist/dawproject/DawProjectImport.d.ts.map +0 -1
  66. package/dist/dawproject/DawProjectImport.test.d.ts +0 -2
  67. 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 } 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
24
  static skeleton(env: ProjectEnv, skeleton: ProjectSkeleton): 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;
@@ -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,29 +26,42 @@ 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
+ if (options?.noDefaultUser !== true) {
55
+ const userInterfaceBox = UserInterfaceBox.create(boxGraph, UUID.generate());
56
+ userInterfaceBox.root.refer(rootBox.users);
57
+ userInterfaceBoxes.push(userInterfaceBox);
58
+ }
45
59
  boxGraph.endTransaction();
46
60
  return new Project(env, boxGraph, {
47
61
  rootBox,
48
- userInterfaceBox,
49
- masterBusBox,
50
- masterAudioUnit,
62
+ primaryAudioBus,
63
+ primaryAudioOutputUnit,
64
+ userInterfaceBoxes,
51
65
  timelineBox
52
66
  });
53
67
  }
@@ -63,7 +77,7 @@ export class Project {
63
77
  #env;
64
78
  boxGraph;
65
79
  rootBox;
66
- userInterfaceBox;
80
+ userInterfaceBoxes;
67
81
  masterBusBox;
68
82
  masterAudioUnit;
69
83
  timelineBox;
@@ -78,26 +92,28 @@ export class Project {
78
92
  midiLearning;
79
93
  mixer;
80
94
  engine = new EngineFacade();
81
- constructor(env, boxGraph, { rootBox, userInterfaceBox, masterBusBox, masterAudioUnit, timelineBox }) {
95
+ constructor(env, boxGraph, { rootBox, userInterfaceBoxes, primaryAudioBus, primaryAudioOutputUnit, timelineBox }) {
82
96
  this.#env = env;
83
97
  this.boxGraph = boxGraph;
84
98
  this.rootBox = rootBox;
85
- this.userInterfaceBox = userInterfaceBox;
86
- this.masterBusBox = masterBusBox;
87
- this.masterAudioUnit = masterAudioUnit;
99
+ this.userInterfaceBoxes = userInterfaceBoxes;
100
+ this.masterBusBox = primaryAudioBus;
101
+ this.masterAudioUnit = primaryAudioOutputUnit;
88
102
  this.timelineBox = timelineBox;
89
103
  this.api = new ProjectApi(this);
90
- this.editing = new Editing(this.boxGraph);
104
+ this.editing = new BoxEditing(this.boxGraph);
91
105
  this.selection = new VertexSelection(this.editing, this.boxGraph);
92
106
  this.parameterFieldAdapters = new ParameterFieldAdapters();
93
107
  this.boxAdapters = this.#terminator.own(new BoxAdapters(this));
94
108
  this.userEditingManager = new UserEditingManager(this.editing);
95
- this.userEditingManager.follow(this.userInterfaceBox);
96
- this.selection.switch(this.userInterfaceBox.selection);
97
109
  this.liveStreamReceiver = this.#terminator.own(new LiveStreamReceiver());
98
110
  this.midiLearning = this.#terminator.own(new MIDILearning(this));
99
111
  this.captureDevices = this.#terminator.own(new CaptureDevices(this));
100
112
  this.mixer = new Mixer(this.rootBoxAdapter.audioUnits);
113
+ // TODO We are probably doing that from the outside
114
+ if (this.userInterfaceBoxes.length > 0) {
115
+ this.follow(this.userInterfaceBoxes[0]);
116
+ }
101
117
  console.debug(`Project was created on ${this.rootBoxAdapter.created.toString()}`);
102
118
  }
103
119
  startAudioWorklet(restart, options) {
@@ -109,8 +125,8 @@ export class Project {
109
125
  // we will only accept the first error
110
126
  engine.removeEventListener("error", handler);
111
127
  engine.removeEventListener("processorerror", handler);
112
- safeExecute(restart?.unload, event);
113
128
  lifecycle.terminate();
129
+ await safeExecute(restart?.unload, event);
114
130
  safeExecute(restart?.load, this.startAudioWorklet(restart));
115
131
  };
116
132
  engine.addEventListener("error", handler);
@@ -126,6 +142,10 @@ export class Project {
126
142
  }
127
143
  Recording.start(this, countIn).finally();
128
144
  }
145
+ follow(box) {
146
+ this.userEditingManager.follow(box);
147
+ this.selection.switch(box.selection);
148
+ }
129
149
  own(terminable) { return this.#terminator.own(terminable); }
130
150
  ownAll(...terminables) { return this.#terminator.ownAll(...terminables); }
131
151
  spawn() { return this.#terminator.spawn(); }
@@ -145,9 +165,9 @@ export class Project {
145
165
  mandatoryBoxes: {
146
166
  rootBox: this.rootBox,
147
167
  timelineBox: this.timelineBox,
148
- masterBusBox: this.masterBusBox,
149
- masterAudioUnit: this.masterAudioUnit,
150
- userInterfaceBox: this.userInterfaceBox
168
+ primaryAudioBus: this.masterBusBox,
169
+ primaryAudioOutputUnit: this.masterAudioUnit,
170
+ userInterfaceBoxes: this.userInterfaceBoxes
151
171
  }
152
172
  };
153
173
  }
@@ -155,16 +175,9 @@ export class Project {
155
175
  const output = ByteArrayOutput.create();
156
176
  output.writeInt(ProjectDecoder.MAGIC_HEADER_OPEN);
157
177
  output.writeInt(ProjectDecoder.FORMAT_VERSION);
158
- // store all boxes
159
178
  const boxGraphChunk = this.boxGraph.toArrayBuffer();
160
179
  output.writeInt(boxGraphChunk.byteLength);
161
180
  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
181
  return output.toArrayBuffer();
169
182
  }
170
183
  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";