@shadowob/sdk 1.1.6 → 1.1.8

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/dist/index.js CHANGED
@@ -1,3 +1,33 @@
1
+ import {
2
+ ShadowBridge
3
+ } from "./chunk-5QQ7ZR6B.js";
4
+ import {
5
+ SHADOW_SERVER_APP_COMMAND_COMPLETED_EVENT,
6
+ SHADOW_SERVER_APP_COMMAND_EVENTS,
7
+ SHADOW_SERVER_APP_COMMAND_FAILED_EVENT,
8
+ SHADOW_SERVER_APP_PROTOCOL,
9
+ ShadowServerAppCommandError,
10
+ ShadowServerAppOutbox,
11
+ ShadowServerAppRuntime,
12
+ buildShadowServerAppInboxDelivery,
13
+ buildShadowServerAppInboxTaskRequest,
14
+ createShadowServerAppManifest,
15
+ defineShadowServerApp,
16
+ extractShadowServerAppBearerToken,
17
+ getShadowServerAppChannelMessageDeliveries,
18
+ getShadowServerAppChannelMessageErrors,
19
+ getShadowServerAppTaskCardId,
20
+ introspectShadowServerAppToken,
21
+ normalizeShadowServerAppCommandInput,
22
+ parseShadowServerAppCommandRequest,
23
+ shadowServerAppActorAvatarUrl,
24
+ shadowServerAppActorDisplayName,
25
+ shadowServerAppActorRef,
26
+ shadowServerAppError,
27
+ shadowServerAppInboxTaskEndpoint,
28
+ validateShadowServerAppJsonSchema
29
+ } from "./chunk-OMTGSMTQ.js";
30
+
1
31
  // src/client.ts
2
32
  function sanitizeErrorBody(body) {
3
33
  if (!body) return "(empty response)";
@@ -28,6 +58,9 @@ var ShadowClient = class {
28
58
  this.baseUrl = baseUrl.replace(/\/api\/?$/, "");
29
59
  }
30
60
  baseUrl;
61
+ serverAppEventStreamUrl(eventStreamPath) {
62
+ return new URL(eventStreamPath, `${this.baseUrl}/`).toString();
63
+ }
31
64
  isShadowPrivateMediaUrl(value) {
32
65
  if (value.startsWith("/shadow/uploads/") || value.startsWith("/api/media/signed/")) {
33
66
  return true;
@@ -118,6 +151,18 @@ var ShadowClient = class {
118
151
  body: JSON.stringify(data)
119
152
  });
120
153
  }
154
+ async startPasswordReset(data) {
155
+ return this.request("/api/auth/password-reset/start", {
156
+ method: "POST",
157
+ body: JSON.stringify(data)
158
+ });
159
+ }
160
+ async completePasswordReset(data) {
161
+ return this.request("/api/auth/password-reset/complete", {
162
+ method: "POST",
163
+ body: JSON.stringify(data)
164
+ });
165
+ }
121
166
  async refreshToken(refreshToken) {
122
167
  return this.request("/api/auth/refresh", {
123
168
  method: "POST",
@@ -203,6 +248,27 @@ var ShadowClient = class {
203
248
  async generateAgentToken(agentId) {
204
249
  return this.request(`/api/agents/${agentId}/token`, { method: "POST" });
205
250
  }
251
+ async listConnectorComputers() {
252
+ return this.request("/api/connector/computers");
253
+ }
254
+ async createConnectorBootstrap(data) {
255
+ return this.request("/api/connector/computers/bootstrap", {
256
+ method: "POST",
257
+ body: JSON.stringify(data)
258
+ });
259
+ }
260
+ async createAgentOnConnectorComputer(computerId, data) {
261
+ return this.request(`/api/connector/computers/${computerId}/buddies`, {
262
+ method: "POST",
263
+ body: JSON.stringify(data)
264
+ });
265
+ }
266
+ async configureAgentOnConnectorComputer(computerId, agentId, data) {
267
+ return this.request(`/api/connector/computers/${computerId}/buddies/${agentId}/configure`, {
268
+ method: "POST",
269
+ body: JSON.stringify(data)
270
+ });
271
+ }
206
272
  async startAgent(agentId) {
207
273
  return this.request(`/api/agents/${agentId}/start`, { method: "POST" });
208
274
  }
@@ -248,6 +314,7 @@ var ShadowClient = class {
248
314
  const policy = {
249
315
  serverId,
250
316
  ...data.channelId !== void 0 ? { channelId: data.channelId } : {},
317
+ ...data.listen !== void 0 ? { listen: data.listen } : {},
251
318
  ...data.mentionOnly !== void 0 ? { mentionOnly: data.mentionOnly } : {},
252
319
  ...data.reply !== void 0 ? { reply: data.reply } : {},
253
320
  ...data.config !== void 0 ? { config: data.config } : {}
@@ -341,6 +408,24 @@ var ShadowClient = class {
341
408
  }
342
409
  );
343
410
  }
411
+ async updateServerAppAccessPolicy(serverIdOrSlug, appKey, data) {
412
+ return this.request(
413
+ `/api/servers/${serverIdOrSlug}/apps/${encodeURIComponent(appKey)}/access-policy`,
414
+ {
415
+ method: "PATCH",
416
+ body: JSON.stringify(data)
417
+ }
418
+ );
419
+ }
420
+ async approveServerAppCommand(serverIdOrSlug, appKey, data) {
421
+ return this.request(
422
+ `/api/servers/${serverIdOrSlug}/apps/${encodeURIComponent(appKey)}/approvals`,
423
+ {
424
+ method: "POST",
425
+ body: JSON.stringify(data)
426
+ }
427
+ );
428
+ }
344
429
  async getServerAppSkills(serverIdOrSlug, appKey) {
345
430
  return this.request(`/api/servers/${serverIdOrSlug}/apps/${encodeURIComponent(appKey)}/skills`);
346
431
  }
@@ -386,6 +471,7 @@ var ShadowClient = class {
386
471
  const form = new FormData();
387
472
  form.set("input", JSON.stringify(data.input ?? {}));
388
473
  if (data.channelId) form.set("channelId", data.channelId);
474
+ if (data.task) form.set("task", JSON.stringify(data.task));
389
475
  form.set(data.field ?? "file", data.file, data.filename);
390
476
  return this.request(
391
477
  `/api/servers/${serverIdOrSlug}/apps/${encodeURIComponent(appKey)}/commands/${encodeURIComponent(
@@ -608,6 +694,83 @@ var ShadowClient = class {
608
694
  async getMessage(messageId) {
609
695
  return this.request(`/api/messages/${messageId}`);
610
696
  }
697
+ async listBuddyInboxes() {
698
+ return this.request("/api/buddy-inboxes");
699
+ }
700
+ async listServerBuddyInboxes(serverIdOrSlug) {
701
+ return this.request(`/api/servers/${serverIdOrSlug}/inboxes`);
702
+ }
703
+ async ensureBuddyInbox(serverIdOrSlug, agentId) {
704
+ return this.request(`/api/servers/${serverIdOrSlug}/inboxes/${agentId}`, {
705
+ method: "POST"
706
+ });
707
+ }
708
+ async getBuddyInboxAdmissionPolicy(serverIdOrSlug, agentId) {
709
+ return this.request(`/api/servers/${serverIdOrSlug}/inboxes/${agentId}/admission-policy`);
710
+ }
711
+ async updateBuddyInboxAdmissionPolicy(serverIdOrSlug, agentId, policy) {
712
+ return this.request(`/api/servers/${serverIdOrSlug}/inboxes/${agentId}/admission-policy`, {
713
+ method: "PUT",
714
+ body: JSON.stringify(policy)
715
+ });
716
+ }
717
+ async listBuddyInboxAdmissionPending(serverIdOrSlug, agentId) {
718
+ return this.request(`/api/servers/${serverIdOrSlug}/inboxes/${agentId}/admission-pending`);
719
+ }
720
+ async approveBuddyInboxAdmissionPending(serverIdOrSlug, agentId, pendingId) {
721
+ return this.request(
722
+ `/api/servers/${serverIdOrSlug}/inboxes/${agentId}/admission-pending/${pendingId}/approve`,
723
+ { method: "POST" }
724
+ );
725
+ }
726
+ async rejectBuddyInboxAdmissionPending(serverIdOrSlug, agentId, pendingId) {
727
+ return this.request(
728
+ `/api/servers/${serverIdOrSlug}/inboxes/${agentId}/admission-pending/${pendingId}/reject`,
729
+ { method: "POST" }
730
+ );
731
+ }
732
+ async enqueueInboxTaskForAgent(serverIdOrSlug, agentId, task) {
733
+ return this.request(`/api/servers/${serverIdOrSlug}/inboxes/${agentId}/tasks`, {
734
+ method: "POST",
735
+ body: JSON.stringify(task)
736
+ });
737
+ }
738
+ async enqueueInboxTask(channelId, task) {
739
+ return this.request(`/api/channels/${channelId}/inbox/tasks`, {
740
+ method: "POST",
741
+ body: JSON.stringify(task)
742
+ });
743
+ }
744
+ async claimTaskCard(messageId, cardId, data = {}) {
745
+ return this.request(`/api/messages/${messageId}/cards/${cardId}/claim`, {
746
+ method: "POST",
747
+ body: JSON.stringify(data)
748
+ });
749
+ }
750
+ async updateTaskCard(messageId, cardId, data) {
751
+ return this.request(`/api/messages/${messageId}/cards/${cardId}`, {
752
+ method: "PATCH",
753
+ body: JSON.stringify(data)
754
+ });
755
+ }
756
+ async retryTaskCard(messageId, cardId, data = {}) {
757
+ return this.request(`/api/messages/${messageId}/cards/${cardId}/retry`, {
758
+ method: "POST",
759
+ body: JSON.stringify(data)
760
+ });
761
+ }
762
+ async claimNextInboxTask(serverIdOrSlug, agentId, data = {}) {
763
+ return this.request(`/api/servers/${serverIdOrSlug}/inboxes/${agentId}/claim-next`, {
764
+ method: "POST",
765
+ body: JSON.stringify(data)
766
+ });
767
+ }
768
+ async promoteMessageToInboxTask(messageId, data) {
769
+ return this.request(`/api/messages/${messageId}/inbox/tasks`, {
770
+ method: "POST",
771
+ body: JSON.stringify(data)
772
+ });
773
+ }
611
774
  async submitInteractiveAction(messageId, input) {
612
775
  return this.request(`/api/messages/${messageId}/interactive`, {
613
776
  method: "POST",
@@ -759,6 +922,19 @@ var ShadowClient = class {
759
922
  formData.append("messageId", messageId);
760
923
  } else if (messageId) {
761
924
  if (messageId.messageId) formData.append("messageId", messageId.messageId);
925
+ if (messageId.kind) formData.append("kind", messageId.kind);
926
+ if (typeof messageId.durationMs === "number") {
927
+ formData.append("durationMs", String(messageId.durationMs));
928
+ }
929
+ if (messageId.waveformPeaks) {
930
+ formData.append("waveformPeaks", JSON.stringify(messageId.waveformPeaks));
931
+ }
932
+ if (messageId.transcriptText) formData.append("transcriptText", messageId.transcriptText);
933
+ if (messageId.transcriptLanguage) {
934
+ formData.append("transcriptLanguage", messageId.transcriptLanguage);
935
+ }
936
+ if (messageId.transcriptSource)
937
+ formData.append("transcriptSource", messageId.transcriptSource);
762
938
  }
763
939
  const url = `${this.baseUrl}/api/media/upload`;
764
940
  const res = await fetch(url, {
@@ -774,6 +950,43 @@ var ShadowClient = class {
774
950
  }
775
951
  return res.json();
776
952
  }
953
+ async sendVoiceMessage(channelId, file, filename, contentType, opts) {
954
+ const message = await this.sendMessage(channelId, "\u200B", {
955
+ threadId: opts.threadId,
956
+ replyToId: opts.replyToId
957
+ });
958
+ await this.uploadMedia(file, filename, contentType, {
959
+ messageId: message.id,
960
+ kind: "voice",
961
+ durationMs: opts.durationMs,
962
+ waveformPeaks: opts.waveformPeaks,
963
+ transcriptText: opts.transcriptText,
964
+ transcriptLanguage: opts.transcriptLanguage,
965
+ transcriptSource: opts.transcriptSource
966
+ });
967
+ return this.getMessage(message.id);
968
+ }
969
+ async markVoicePlayed(attachmentId, input) {
970
+ return this.request(`/api/attachments/${attachmentId}/voice-playback`, {
971
+ method: "PUT",
972
+ body: JSON.stringify(input ?? {})
973
+ });
974
+ }
975
+ async requestVoiceTranscript(attachmentId, input) {
976
+ return this.request(`/api/attachments/${attachmentId}/transcript`, {
977
+ method: "POST",
978
+ body: JSON.stringify({
979
+ mode: "server",
980
+ ...input?.language ? { language: input.language } : {}
981
+ })
982
+ });
983
+ }
984
+ async updateVoiceTranscript(attachmentId, input) {
985
+ return this.request(`/api/attachments/${attachmentId}/transcript`, {
986
+ method: "PUT",
987
+ body: JSON.stringify(input)
988
+ });
989
+ }
777
990
  async resolveAttachmentMediaUrl(attachmentId, options) {
778
991
  const params = new URLSearchParams();
779
992
  params.set("disposition", options?.disposition ?? "inline");
@@ -1029,9 +1242,14 @@ var ShadowClient = class {
1029
1242
  return this.request(`/api/auth/sessions/${sessionId}`, { method: "DELETE" });
1030
1243
  }
1031
1244
  async changePassword(data) {
1245
+ const oldPassword = data.oldPassword ?? data.currentPassword;
1032
1246
  return this.request("/api/auth/password", {
1033
1247
  method: "PUT",
1034
- body: JSON.stringify(data)
1248
+ body: JSON.stringify({
1249
+ oldPassword,
1250
+ newPassword: data.newPassword,
1251
+ confirmPassword: data.confirmPassword ?? data.newPassword
1252
+ })
1035
1253
  });
1036
1254
  }
1037
1255
  async getDashboard() {
@@ -1040,7 +1258,13 @@ var ShadowClient = class {
1040
1258
  async loginWithGoogleIdToken(idToken) {
1041
1259
  return this.request("/api/auth/google/id-token", {
1042
1260
  method: "POST",
1043
- body: JSON.stringify({ idToken })
1261
+ body: JSON.stringify({ credential: idToken })
1262
+ });
1263
+ }
1264
+ async loginWithAppleIdentityToken(data) {
1265
+ return this.request("/api/auth/oauth/apple/mobile", {
1266
+ method: "POST",
1267
+ body: JSON.stringify(data)
1044
1268
  });
1045
1269
  }
1046
1270
  // ── Friendships ───────────────────────────────────────────────────────
@@ -1789,6 +2013,24 @@ var ShadowClient = class {
1789
2013
  const suffix = qs.toString();
1790
2014
  return this.request(`/api/discover/business${suffix ? `?${suffix}` : ""}`);
1791
2015
  }
2016
+ async discoverMarketplaceProducts(params) {
2017
+ const qs = new URLSearchParams();
2018
+ if (params?.q) qs.set("q", params.q);
2019
+ if (params?.tag) qs.set("tag", params.tag);
2020
+ if (params?.category) qs.set("category", params.category);
2021
+ if (params?.scope) qs.set("scope", params.scope);
2022
+ if (params?.limit) qs.set("limit", String(params.limit));
2023
+ if (params?.offset) qs.set("offset", String(params.offset));
2024
+ const suffix = qs.toString();
2025
+ return this.request(`/api/discover/marketplace/products${suffix ? `?${suffix}` : ""}`);
2026
+ }
2027
+ async discoverMarketplaceCategories(params) {
2028
+ const qs = new URLSearchParams();
2029
+ if (params?.q) qs.set("q", params.q);
2030
+ if (params?.limit) qs.set("limit", String(params.limit));
2031
+ const suffix = qs.toString();
2032
+ return this.request(`/api/discover/marketplace/categories${suffix ? `?${suffix}` : ""}`);
2033
+ }
1792
2034
  async discoverBusinessHub(params) {
1793
2035
  return this.discoverCommerce(params);
1794
2036
  }
@@ -2255,10 +2497,35 @@ var ShadowVoiceConsumer = class {
2255
2497
  export {
2256
2498
  CLIENT_EVENTS,
2257
2499
  SERVER_EVENTS,
2500
+ SHADOW_SERVER_APP_COMMAND_COMPLETED_EVENT,
2501
+ SHADOW_SERVER_APP_COMMAND_EVENTS,
2502
+ SHADOW_SERVER_APP_COMMAND_FAILED_EVENT,
2503
+ SHADOW_SERVER_APP_PROTOCOL,
2504
+ ShadowBridge,
2258
2505
  ShadowClient,
2506
+ ShadowServerAppCommandError,
2507
+ ShadowServerAppOutbox,
2508
+ ShadowServerAppRuntime,
2259
2509
  ShadowSocket,
2260
2510
  ShadowVoiceConsumer,
2511
+ buildShadowServerAppInboxDelivery,
2512
+ buildShadowServerAppInboxTaskRequest,
2261
2513
  channelRoom,
2514
+ createShadowServerAppManifest,
2515
+ defineShadowServerApp,
2516
+ extractShadowServerAppBearerToken,
2517
+ getShadowServerAppChannelMessageDeliveries,
2518
+ getShadowServerAppChannelMessageErrors,
2519
+ getShadowServerAppTaskCardId,
2520
+ introspectShadowServerAppToken,
2521
+ normalizeShadowServerAppCommandInput,
2522
+ parseShadowServerAppCommandRequest,
2523
+ shadowServerAppActorAvatarUrl,
2524
+ shadowServerAppActorDisplayName,
2525
+ shadowServerAppActorRef,
2526
+ shadowServerAppError,
2527
+ shadowServerAppInboxTaskEndpoint,
2262
2528
  threadRoom,
2263
- userRoom
2529
+ userRoom,
2530
+ validateShadowServerAppJsonSchema
2264
2531
  };
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/server-app-node.ts
21
+ var server_app_node_exports = {};
22
+ __export(server_app_node_exports, {
23
+ ShadowServerAppJsonStore: () => ShadowServerAppJsonStore,
24
+ createShadowServerAppJsonStore: () => createShadowServerAppJsonStore
25
+ });
26
+ module.exports = __toCommonJS(server_app_node_exports);
27
+ var import_node_fs = require("fs");
28
+ var import_node_path = require("path");
29
+ var ShadowServerAppJsonStore = class {
30
+ constructor(options) {
31
+ this.options = options;
32
+ }
33
+ read() {
34
+ if (!(0, import_node_fs.existsSync)(this.options.filePath)) {
35
+ const value = this.defaultValue();
36
+ if (this.options.persistDefault !== false) this.write(value);
37
+ return value;
38
+ }
39
+ try {
40
+ const parsed = JSON.parse((0, import_node_fs.readFileSync)(this.options.filePath, "utf8"));
41
+ if (this.options.validate && !this.options.validate(parsed)) return this.defaultValue();
42
+ return this.normalize(parsed);
43
+ } catch {
44
+ return this.defaultValue();
45
+ }
46
+ }
47
+ write(value) {
48
+ const normalized = this.normalize(value);
49
+ (0, import_node_fs.mkdirSync)((0, import_node_path.dirname)(this.options.filePath), { recursive: true });
50
+ const tempPath = `${this.options.filePath}.${process.pid}.${Date.now()}.tmp`;
51
+ (0, import_node_fs.writeFileSync)(tempPath, `${JSON.stringify(normalized, null, 2)}
52
+ `);
53
+ (0, import_node_fs.renameSync)(tempPath, this.options.filePath);
54
+ return normalized;
55
+ }
56
+ update(mutator) {
57
+ const current = this.clone(this.read());
58
+ const next = mutator(current) ?? current;
59
+ return this.write(next);
60
+ }
61
+ reset(nextValue) {
62
+ return this.write(nextValue ?? this.defaultValue());
63
+ }
64
+ defaultValue() {
65
+ const value = typeof this.options.defaultValue === "function" ? this.options.defaultValue() : this.options.defaultValue;
66
+ return this.normalize(this.clone(value));
67
+ }
68
+ normalize(value) {
69
+ return this.options.normalize ? this.options.normalize(value) : value;
70
+ }
71
+ clone(value) {
72
+ return structuredClone(value);
73
+ }
74
+ };
75
+ function createShadowServerAppJsonStore(options) {
76
+ return new ShadowServerAppJsonStore(options);
77
+ }
78
+ // Annotate the CommonJS export names for ESM import in node:
79
+ 0 && (module.exports = {
80
+ ShadowServerAppJsonStore,
81
+ createShadowServerAppJsonStore
82
+ });
@@ -0,0 +1,21 @@
1
+ interface ShadowServerAppJsonStoreOptions<T> {
2
+ filePath: string;
3
+ defaultValue: T | (() => T);
4
+ validate?: (value: unknown) => value is T;
5
+ normalize?: (value: T) => T;
6
+ persistDefault?: boolean;
7
+ }
8
+ declare class ShadowServerAppJsonStore<T> {
9
+ private readonly options;
10
+ constructor(options: ShadowServerAppJsonStoreOptions<T>);
11
+ read(): T;
12
+ write(value: T): T;
13
+ update(mutator: (value: T) => T | void): T;
14
+ reset(nextValue?: T): T;
15
+ private defaultValue;
16
+ private normalize;
17
+ private clone;
18
+ }
19
+ declare function createShadowServerAppJsonStore<T>(options: ShadowServerAppJsonStoreOptions<T>): ShadowServerAppJsonStore<T>;
20
+
21
+ export { ShadowServerAppJsonStore, type ShadowServerAppJsonStoreOptions, createShadowServerAppJsonStore };
@@ -0,0 +1,21 @@
1
+ interface ShadowServerAppJsonStoreOptions<T> {
2
+ filePath: string;
3
+ defaultValue: T | (() => T);
4
+ validate?: (value: unknown) => value is T;
5
+ normalize?: (value: T) => T;
6
+ persistDefault?: boolean;
7
+ }
8
+ declare class ShadowServerAppJsonStore<T> {
9
+ private readonly options;
10
+ constructor(options: ShadowServerAppJsonStoreOptions<T>);
11
+ read(): T;
12
+ write(value: T): T;
13
+ update(mutator: (value: T) => T | void): T;
14
+ reset(nextValue?: T): T;
15
+ private defaultValue;
16
+ private normalize;
17
+ private clone;
18
+ }
19
+ declare function createShadowServerAppJsonStore<T>(options: ShadowServerAppJsonStoreOptions<T>): ShadowServerAppJsonStore<T>;
20
+
21
+ export { ShadowServerAppJsonStore, type ShadowServerAppJsonStoreOptions, createShadowServerAppJsonStore };
@@ -0,0 +1,56 @@
1
+ // src/server-app-node.ts
2
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "fs";
3
+ import { dirname } from "path";
4
+ var ShadowServerAppJsonStore = class {
5
+ constructor(options) {
6
+ this.options = options;
7
+ }
8
+ read() {
9
+ if (!existsSync(this.options.filePath)) {
10
+ const value = this.defaultValue();
11
+ if (this.options.persistDefault !== false) this.write(value);
12
+ return value;
13
+ }
14
+ try {
15
+ const parsed = JSON.parse(readFileSync(this.options.filePath, "utf8"));
16
+ if (this.options.validate && !this.options.validate(parsed)) return this.defaultValue();
17
+ return this.normalize(parsed);
18
+ } catch {
19
+ return this.defaultValue();
20
+ }
21
+ }
22
+ write(value) {
23
+ const normalized = this.normalize(value);
24
+ mkdirSync(dirname(this.options.filePath), { recursive: true });
25
+ const tempPath = `${this.options.filePath}.${process.pid}.${Date.now()}.tmp`;
26
+ writeFileSync(tempPath, `${JSON.stringify(normalized, null, 2)}
27
+ `);
28
+ renameSync(tempPath, this.options.filePath);
29
+ return normalized;
30
+ }
31
+ update(mutator) {
32
+ const current = this.clone(this.read());
33
+ const next = mutator(current) ?? current;
34
+ return this.write(next);
35
+ }
36
+ reset(nextValue) {
37
+ return this.write(nextValue ?? this.defaultValue());
38
+ }
39
+ defaultValue() {
40
+ const value = typeof this.options.defaultValue === "function" ? this.options.defaultValue() : this.options.defaultValue;
41
+ return this.normalize(this.clone(value));
42
+ }
43
+ normalize(value) {
44
+ return this.options.normalize ? this.options.normalize(value) : value;
45
+ }
46
+ clone(value) {
47
+ return structuredClone(value);
48
+ }
49
+ };
50
+ function createShadowServerAppJsonStore(options) {
51
+ return new ShadowServerAppJsonStore(options);
52
+ }
53
+ export {
54
+ ShadowServerAppJsonStore,
55
+ createShadowServerAppJsonStore
56
+ };