@granular-software/sdk 0.4.43 → 0.4.44

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.
@@ -11471,6 +11471,164 @@ async function invokeRegisteredEffect(effectMap, request) {
11471
11471
  return resolved.handler(request.input, context);
11472
11472
  }
11473
11473
 
11474
+ // src/client-normalizers.ts
11475
+ function createEmptyHeapSnapshot(now = Date.now()) {
11476
+ return {
11477
+ entriesByPath: {},
11478
+ listsByName: {},
11479
+ variablesByName: {},
11480
+ updatedAt: now
11481
+ };
11482
+ }
11483
+ function normalizeHeapSnapshot(raw) {
11484
+ if (!raw || typeof raw !== "object") {
11485
+ return createEmptyHeapSnapshot();
11486
+ }
11487
+ const heap = raw;
11488
+ return {
11489
+ entriesByPath: heap.entriesByPath && typeof heap.entriesByPath === "object" ? JSON.parse(JSON.stringify(heap.entriesByPath)) : {},
11490
+ listsByName: heap.listsByName && typeof heap.listsByName === "object" ? JSON.parse(JSON.stringify(heap.listsByName)) : {},
11491
+ variablesByName: heap.variablesByName && typeof heap.variablesByName === "object" ? JSON.parse(JSON.stringify(heap.variablesByName)) : {},
11492
+ updatedAt: typeof heap.updatedAt === "number" ? heap.updatedAt : Date.now()
11493
+ };
11494
+ }
11495
+ function normalizeGraphPathSegment(value) {
11496
+ return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
11497
+ }
11498
+ function extractRecordIdFromGraphPath(path2, className) {
11499
+ const normalizedPrefix = `${normalizeGraphPathSegment(className)}_`;
11500
+ if (path2.startsWith(normalizedPrefix)) {
11501
+ return path2.slice(normalizedPrefix.length);
11502
+ }
11503
+ const legacyPrefix = `${className}_`;
11504
+ if (path2.startsWith(legacyPrefix)) {
11505
+ return path2.slice(legacyPrefix.length);
11506
+ }
11507
+ return path2;
11508
+ }
11509
+ function toRecordSearchResult(className, node) {
11510
+ const path2 = typeof node.path === "string" ? node.path : "";
11511
+ if (!path2) return null;
11512
+ const fields = Array.isArray(node.submodels) ? node.submodels.flatMap(
11513
+ (submodel) => {
11514
+ const name = typeof submodel?.label === "string" && submodel.label.trim() ? submodel.label : typeof submodel?.path === "string" ? submodel.path.split(":").pop() || submodel.path : "";
11515
+ if (!name) return [];
11516
+ if (typeof submodel.string_value === "string") {
11517
+ return [{ name, type: "string", value: submodel.string_value }];
11518
+ }
11519
+ if (typeof submodel.number_value === "number") {
11520
+ return [{ name, type: "number", value: submodel.number_value }];
11521
+ }
11522
+ if (typeof submodel.boolean_value === "boolean") {
11523
+ return [
11524
+ {
11525
+ name,
11526
+ type: "boolean",
11527
+ value: submodel.boolean_value
11528
+ }
11529
+ ];
11530
+ }
11531
+ return [];
11532
+ }
11533
+ ) : [];
11534
+ return {
11535
+ path: path2,
11536
+ className,
11537
+ id: extractRecordIdFromGraphPath(path2, className),
11538
+ label: typeof node.label === "string" && node.label.trim() ? node.label : extractRecordIdFromGraphPath(path2, className),
11539
+ description: typeof node.description === "string" && node.description.trim() ? node.description : null,
11540
+ fields
11541
+ };
11542
+ }
11543
+ function normalizeRecordSearchText(value) {
11544
+ return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, " ").replace(/\s+/g, " ").trim();
11545
+ }
11546
+ function rankRecordSearchResult(result, query, index) {
11547
+ const normalizedQuery = normalizeRecordSearchText(query);
11548
+ if (!normalizedQuery) {
11549
+ return index;
11550
+ }
11551
+ const label = normalizeRecordSearchText(result.label || "");
11552
+ const id = normalizeRecordSearchText(result.id || "");
11553
+ const path2 = normalizeRecordSearchText(result.path || "");
11554
+ const className = normalizeRecordSearchText(result.className || "");
11555
+ const searchable = [label, id, path2, className].filter(Boolean);
11556
+ if (label === normalizedQuery) return index;
11557
+ if (id === normalizedQuery || path2 === normalizedQuery) return 100 + index;
11558
+ if (label.startsWith(normalizedQuery)) return 200 + index;
11559
+ if (searchable.some((value) => value.startsWith(normalizedQuery))) {
11560
+ return 300 + index;
11561
+ }
11562
+ if (label.includes(normalizedQuery)) return 400 + index;
11563
+ if (searchable.some((value) => value.includes(normalizedQuery))) {
11564
+ return 500 + index;
11565
+ }
11566
+ return 900 + index;
11567
+ }
11568
+ function deriveRuntimeBaseUrl(apiEndpoint) {
11569
+ try {
11570
+ const endpoint = new URL(apiEndpoint);
11571
+ const graphqlSuffix = "/orchestrator/graphql";
11572
+ if (endpoint.pathname.endsWith(graphqlSuffix)) {
11573
+ endpoint.pathname = endpoint.pathname.slice(0, -graphqlSuffix.length);
11574
+ } else if (endpoint.pathname.endsWith("/graphql")) {
11575
+ endpoint.pathname = endpoint.pathname.slice(0, -"/graphql".length);
11576
+ }
11577
+ endpoint.search = "";
11578
+ endpoint.hash = "";
11579
+ return endpoint.toString().replace(/\/$/, "");
11580
+ } catch {
11581
+ return apiEndpoint.replace(/\/orchestrator\/graphql$/, "").replace(/\/$/, "");
11582
+ }
11583
+ }
11584
+
11585
+ // src/client-transport.ts
11586
+ function sleep(ms) {
11587
+ return new Promise((resolve) => setTimeout(resolve, ms));
11588
+ }
11589
+ function withTimeout(promise, timeoutMs, label) {
11590
+ let timer = null;
11591
+ const timeout = new Promise((_, reject) => {
11592
+ timer = setTimeout(() => {
11593
+ reject(new Error(`${label} timed out after ${timeoutMs}ms`));
11594
+ }, timeoutMs);
11595
+ });
11596
+ return Promise.race([promise, timeout]).finally(() => {
11597
+ if (timer) {
11598
+ clearTimeout(timer);
11599
+ }
11600
+ });
11601
+ }
11602
+ function isLocalControlUrl(url) {
11603
+ try {
11604
+ const parsed = new URL(url);
11605
+ return parsed.hostname === "127.0.0.1" || parsed.hostname === "localhost" || parsed.hostname === "::1";
11606
+ } catch {
11607
+ return false;
11608
+ }
11609
+ }
11610
+ function isRetryableLocalWorkerRestart(status, body, url) {
11611
+ return isLocalControlUrl(url) && (status === 503 && body.includes("Your worker restarted mid-request") || status === 500 && body.includes("Network connection lost"));
11612
+ }
11613
+ function isRetryableRecordObjectsError(error) {
11614
+ const message = error instanceof Error ? error.message : String(error);
11615
+ return /worker restarted mid-request|econnreset|network|socket connection was closed unexpectedly|timed out|bad gateway|too many requests|gateway timeout|control plane api error \((?:429|500|502|503|504)\)|graphql api error \((?:429|500|502|503|504)\)|failed to record batch/i.test(
11616
+ message
11617
+ );
11618
+ }
11619
+ function isRetryableEffectRegistrationError(error) {
11620
+ const message = error instanceof Error ? error.message : String(error);
11621
+ return /timed out|websocket disconnected|websocket not connected|rpc timeout|worker restarted mid-request|network connection lost|bad gateway|gateway timeout|too many requests|(?:control plane|granular|graphql) api error \((?:429|500|502|503|504)\)/i.test(
11622
+ message
11623
+ );
11624
+ }
11625
+ function isRetryableSessionDataError(error) {
11626
+ const message = error instanceof Error ? error.message : String(error);
11627
+ return /network connection lost|worker restarted mid-request|econnreset|socket connection was closed unexpectedly|bad gateway|gateway timeout|service unavailable|session data api error \((?:429|500|502|503|504)\)/i.test(
11628
+ message
11629
+ );
11630
+ }
11631
+
11474
11632
  // src/spend.ts
11475
11633
  function toGranularHttpBase(apiUrl) {
11476
11634
  const url = new URL(apiUrl);
@@ -12956,51 +13114,6 @@ function planRecordObjectsChunks(records, batchSize) {
12956
13114
  }
12957
13115
  return plans;
12958
13116
  }
12959
- function sleep(ms) {
12960
- return new Promise((resolve) => setTimeout(resolve, ms));
12961
- }
12962
- function withTimeout(promise, timeoutMs, label) {
12963
- let timer = null;
12964
- const timeout = new Promise((_, reject) => {
12965
- timer = setTimeout(() => {
12966
- reject(new Error(`${label} timed out after ${timeoutMs}ms`));
12967
- }, timeoutMs);
12968
- });
12969
- return Promise.race([promise, timeout]).finally(() => {
12970
- if (timer) {
12971
- clearTimeout(timer);
12972
- }
12973
- });
12974
- }
12975
- function isLocalControlUrl(url) {
12976
- try {
12977
- const parsed = new URL(url);
12978
- return parsed.hostname === "127.0.0.1" || parsed.hostname === "localhost" || parsed.hostname === "::1";
12979
- } catch {
12980
- return false;
12981
- }
12982
- }
12983
- function isRetryableLocalWorkerRestart(status, body, url) {
12984
- return isLocalControlUrl(url) && (status === 503 && body.includes("Your worker restarted mid-request") || status === 500 && body.includes("Network connection lost"));
12985
- }
12986
- function isRetryableRecordObjectsError(error) {
12987
- const message = error instanceof Error ? error.message : String(error);
12988
- return /worker restarted mid-request|econnreset|network|socket connection was closed unexpectedly|timed out|bad gateway|too many requests|gateway timeout|control plane api error \((?:429|500|502|503|504)\)|graphql api error \((?:429|500|502|503|504)\)|failed to record batch/i.test(
12989
- message
12990
- );
12991
- }
12992
- function isRetryableEffectRegistrationError(error) {
12993
- const message = error instanceof Error ? error.message : String(error);
12994
- return /timed out|websocket disconnected|websocket not connected|rpc timeout|worker restarted mid-request|network connection lost|bad gateway|gateway timeout|too many requests|(?:control plane|granular|graphql) api error \((?:429|500|502|503|504)\)/i.test(
12995
- message
12996
- );
12997
- }
12998
- function isRetryableSessionDataError(error) {
12999
- const message = error instanceof Error ? error.message : String(error);
13000
- return /network connection lost|worker restarted mid-request|econnreset|socket connection was closed unexpectedly|bad gateway|gateway timeout|service unavailable|session data api error \((?:429|500|502|503|504)\)/i.test(
13001
- message
13002
- );
13003
- }
13004
13117
  function computeEffectKey2(effect) {
13005
13118
  const attachedClass = effect.className?.trim();
13006
13119
  if (!attachedClass) {
@@ -13055,115 +13168,6 @@ function buildEffectHostUrl(apiUrl, sandboxId, effectClientId, clientId, effectH
13055
13168
  url.searchParams.set("clientId", clientId);
13056
13169
  return url.toString();
13057
13170
  }
13058
- function createEmptyHeapSnapshot(now = Date.now()) {
13059
- return {
13060
- entriesByPath: {},
13061
- listsByName: {},
13062
- variablesByName: {},
13063
- updatedAt: now
13064
- };
13065
- }
13066
- function normalizeHeapSnapshot(raw) {
13067
- if (!raw || typeof raw !== "object") {
13068
- return createEmptyHeapSnapshot();
13069
- }
13070
- const heap = raw;
13071
- return {
13072
- entriesByPath: heap.entriesByPath && typeof heap.entriesByPath === "object" ? JSON.parse(JSON.stringify(heap.entriesByPath)) : {},
13073
- listsByName: heap.listsByName && typeof heap.listsByName === "object" ? JSON.parse(JSON.stringify(heap.listsByName)) : {},
13074
- variablesByName: heap.variablesByName && typeof heap.variablesByName === "object" ? JSON.parse(JSON.stringify(heap.variablesByName)) : {},
13075
- updatedAt: typeof heap.updatedAt === "number" ? heap.updatedAt : Date.now()
13076
- };
13077
- }
13078
- function normalizeGraphPathSegment(value) {
13079
- return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
13080
- }
13081
- function extractRecordIdFromGraphPath(path2, className) {
13082
- const normalizedPrefix = `${normalizeGraphPathSegment(className)}_`;
13083
- if (path2.startsWith(normalizedPrefix)) {
13084
- return path2.slice(normalizedPrefix.length);
13085
- }
13086
- const legacyPrefix = `${className}_`;
13087
- if (path2.startsWith(legacyPrefix)) {
13088
- return path2.slice(legacyPrefix.length);
13089
- }
13090
- return path2;
13091
- }
13092
- function toRecordSearchResult(className, node) {
13093
- const path2 = typeof node.path === "string" ? node.path : "";
13094
- if (!path2) return null;
13095
- const fields = Array.isArray(node.submodels) ? node.submodels.flatMap(
13096
- (submodel) => {
13097
- const name = typeof submodel?.label === "string" && submodel.label.trim() ? submodel.label : typeof submodel?.path === "string" ? submodel.path.split(":").pop() || submodel.path : "";
13098
- if (!name) return [];
13099
- if (typeof submodel.string_value === "string") {
13100
- return [{ name, type: "string", value: submodel.string_value }];
13101
- }
13102
- if (typeof submodel.number_value === "number") {
13103
- return [{ name, type: "number", value: submodel.number_value }];
13104
- }
13105
- if (typeof submodel.boolean_value === "boolean") {
13106
- return [
13107
- {
13108
- name,
13109
- type: "boolean",
13110
- value: submodel.boolean_value
13111
- }
13112
- ];
13113
- }
13114
- return [];
13115
- }
13116
- ) : [];
13117
- return {
13118
- path: path2,
13119
- className,
13120
- id: extractRecordIdFromGraphPath(path2, className),
13121
- label: typeof node.label === "string" && node.label.trim() ? node.label : extractRecordIdFromGraphPath(path2, className),
13122
- description: typeof node.description === "string" && node.description.trim() ? node.description : null,
13123
- fields
13124
- };
13125
- }
13126
- function normalizeRecordSearchText(value) {
13127
- return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, " ").replace(/\s+/g, " ").trim();
13128
- }
13129
- function rankRecordSearchResult(result, query, index) {
13130
- const normalizedQuery = normalizeRecordSearchText(query);
13131
- if (!normalizedQuery) {
13132
- return index;
13133
- }
13134
- const label = normalizeRecordSearchText(result.label || "");
13135
- const id = normalizeRecordSearchText(result.id || "");
13136
- const path2 = normalizeRecordSearchText(result.path || "");
13137
- const className = normalizeRecordSearchText(result.className || "");
13138
- const searchable = [label, id, path2, className].filter(Boolean);
13139
- if (label === normalizedQuery) return index;
13140
- if (id === normalizedQuery || path2 === normalizedQuery) return 100 + index;
13141
- if (label.startsWith(normalizedQuery)) return 200 + index;
13142
- if (searchable.some((value) => value.startsWith(normalizedQuery))) {
13143
- return 300 + index;
13144
- }
13145
- if (label.includes(normalizedQuery)) return 400 + index;
13146
- if (searchable.some((value) => value.includes(normalizedQuery))) {
13147
- return 500 + index;
13148
- }
13149
- return 900 + index;
13150
- }
13151
- function deriveRuntimeBaseUrl(apiEndpoint) {
13152
- try {
13153
- const endpoint = new URL(apiEndpoint);
13154
- const graphqlSuffix = "/orchestrator/graphql";
13155
- if (endpoint.pathname.endsWith(graphqlSuffix)) {
13156
- endpoint.pathname = endpoint.pathname.slice(0, -graphqlSuffix.length);
13157
- } else if (endpoint.pathname.endsWith("/graphql")) {
13158
- endpoint.pathname = endpoint.pathname.slice(0, -"/graphql".length);
13159
- }
13160
- endpoint.search = "";
13161
- endpoint.hash = "";
13162
- return endpoint.toString().replace(/\/$/, "");
13163
- } catch {
13164
- return apiEndpoint.replace(/\/orchestrator\/graphql$/, "").replace(/\/$/, "");
13165
- }
13166
- }
13167
13171
  function normalizeSubject(subject) {
13168
13172
  const granularId = subject.granularId || subject.subjectId;
13169
13173
  const userId = subject.userId || subject.identityId || granularId;