sg-widgets-core 0.1.0 → 0.3.0

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.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { A as OPERATORS, B as operatorsFor, C as isEmptyFilter, D as walk, E as toFilterArray, F as isFilterable, I as isLinkType, L as isNumericType, M as TIME_UNITS, N as VALUE_SHAPE, O as DATA_TYPES, P as isDataType, R as isOperator, S as isBlankCondition, T as toApi3Hash, V as supportsOperator, a as hierarchyEntity, b as fromWire, c as DISPLAY_NAME_FIELDS, d as fieldSchemaOverride, f as normalizeField, g as undeclaredField, h as statusFieldNameFor, i as eventLogFilters, j as OPERATORS_BY_TYPE, k as NEGATING_OPERATORS, l as FIELD_SCHEMA_OVERRIDES, m as statusFieldFor, n as RestClient, o as normalizeEventLogEntry, p as normalizeFields, r as SgApiError, s as normalizeHierarchyNode, t as EVENT_LOG_FIELDS, u as displayNameOf, v as condition, w as referencedPaths, x as group, y as emptyFilter, z as isTemporalType } from "./client-DwN_-UuF.mjs";
1
+ import { A as NEGATING_OPERATORS, B as isTemporalType, C as isBlankCondition, D as toFilterArray, E as toApi3Hash, F as isDataType, H as supportsOperator, I as isFilterable, L as isLinkType, M as OPERATORS_BY_TYPE, N as TIME_UNITS, O as walk, P as VALUE_SHAPE, R as isNumericType, S as group, T as referencedPaths, V as operatorsFor, _ as undeclaredField, a as eventLogFilters, b as emptyFilter, c as normalizeHierarchyNode, d as displayNameOf, f as fieldSchemaOverride, g as statusFieldNameFor, h as statusFieldFor, i as batchResults, j as OPERATORS, k as DATA_TYPES, l as DISPLAY_NAME_FIELDS, m as normalizeFields, n as RestClient, o as hierarchyEntity, p as normalizeField, r as SgApiError, s as normalizeEventLogEntry, t as EVENT_LOG_FIELDS, u as FIELD_SCHEMA_OVERRIDES, w as isEmptyFilter, x as fromWire, y as condition, z as isOperator } from "./client-izKszX7l.mjs";
2
2
  //#region src/field-icons.ts
3
3
  const ICONS = {
4
4
  text: "type",
@@ -3689,6 +3689,7 @@ function createQueryCache(client, options = {}) {
3689
3689
  }
3690
3690
  function invalidateSearches(entityType) {
3691
3691
  drop(`search:[${JSON.stringify(entityType)}`);
3692
+ drop(`read:[${JSON.stringify(entityType)}`);
3692
3693
  drop("textSearch");
3693
3694
  drop(`summarize:[${JSON.stringify(entityType)}`);
3694
3695
  }
@@ -3700,6 +3701,22 @@ function createQueryCache(client, options = {}) {
3700
3701
  function invalidateThreads() {
3701
3702
  drop("threadContents");
3702
3703
  }
3704
+ /**
3705
+ * A delete retires and unlinks rows of other types, a Shot's Versions (probe 060)
3706
+ * and a Task's dependencies, `Version.sg_task` and `PublishedFile.task`, and a
3707
+ * revive puts them back (089_task_delete_side_effects). Every row read goes.
3708
+ */
3709
+ function invalidateAllRows() {
3710
+ for (const prefix of [
3711
+ "search",
3712
+ "read",
3713
+ "textSearch",
3714
+ "summarize",
3715
+ "threadContents",
3716
+ "hierarchyExpand",
3717
+ "hierarchySearch"
3718
+ ]) drop(prefix);
3719
+ }
3703
3720
  return {
3704
3721
  entityTypes() {
3705
3722
  return run("entityTypes", [], () => client.entityTypes());
@@ -3717,6 +3734,13 @@ function createQueryCache(client, options = {}) {
3717
3734
  search(entityType, searchOptions) {
3718
3735
  return run("search", [entityType, searchOptions], () => client.search(entityType, searchOptions));
3719
3736
  },
3737
+ read(entityType, id, readOptions) {
3738
+ return run("read", [
3739
+ entityType,
3740
+ id,
3741
+ readOptions ?? null
3742
+ ], () => client.read(entityType, id, readOptions));
3743
+ },
3720
3744
  textSearch(text, entityTypes, page) {
3721
3745
  return run("textSearch", [
3722
3746
  text,
@@ -3768,6 +3792,22 @@ function createQueryCache(client, options = {}) {
3768
3792
  invalidateThreads();
3769
3793
  return row;
3770
3794
  },
3795
+ async delete(entityType, id) {
3796
+ await client.delete(entityType, id);
3797
+ invalidateAllRows();
3798
+ },
3799
+ async revive(entityType, id) {
3800
+ const revived = await client.revive(entityType, id);
3801
+ invalidateAllRows();
3802
+ return revived;
3803
+ },
3804
+ async batch(requests) {
3805
+ const results = await client.batch(requests);
3806
+ if (requests.some((r) => r.request_type === "delete")) invalidateAllRows();
3807
+ else for (const type of new Set(requests.map((r) => r.entity))) invalidateSearches(type);
3808
+ invalidateThreads();
3809
+ return results;
3810
+ },
3771
3811
  invalidate(prefix) {
3772
3812
  if (prefix === void 0) {
3773
3813
  entries.clear();
@@ -4679,6 +4719,7 @@ const PROXY_METHODS = [
4679
4719
  "fields",
4680
4720
  "fieldWithProject",
4681
4721
  "search",
4722
+ "read",
4682
4723
  "textSearch",
4683
4724
  "statuses",
4684
4725
  "create",
@@ -4689,7 +4730,10 @@ const PROXY_METHODS = [
4689
4730
  "summarize",
4690
4731
  "threadContents",
4691
4732
  "eventLog",
4692
- "following"
4733
+ "following",
4734
+ "delete",
4735
+ "revive",
4736
+ "batch"
4693
4737
  ];
4694
4738
  function isProxyMethod(value) {
4695
4739
  return PROXY_METHODS.includes(value);
@@ -4739,6 +4783,12 @@ function entityRef(value, name) {
4739
4783
  id: num(ref.id, `${name}.id`)
4740
4784
  };
4741
4785
  }
4786
+ /** The list is passed on as sent; the API names what is wrong with a request (recipes/002). */
4787
+ function requestList(value, name) {
4788
+ if (!Array.isArray(value)) throw new BadRequest(`'${name}' must be a list`);
4789
+ for (const [i, request] of value.entries()) obj(request, `${name}[${i}]`);
4790
+ return value;
4791
+ }
4742
4792
  function str(value, name) {
4743
4793
  if (typeof value !== "string" || value.length === 0) throw new BadRequest(`'${name}' must be a non-empty string`);
4744
4794
  return value;
@@ -4788,6 +4838,7 @@ function call(client, method, p) {
4788
4838
  case "fields": return client.fields(str(p.entityType, "entityType"), optionalNum(p.projectId, "projectId"));
4789
4839
  case "fieldWithProject": return client.fieldWithProject(str(p.entityType, "entityType"), str(p.field, "field"), num(p.projectId, "projectId"));
4790
4840
  case "search": return client.search(str(p.entityType, "entityType"), p.options ?? {});
4841
+ case "read": return client.read(str(p.entityType, "entityType"), num(p.id, "id"), p.options ?? {});
4791
4842
  case "textSearch": return client.textSearch(str(p.text, "text"), p.entityTypes ?? {}, p.page ?? void 0);
4792
4843
  case "statuses": return client.statuses();
4793
4844
  case "create": return client.create(str(p.entityType, "entityType"), obj(p.body, "body"));
@@ -4799,6 +4850,9 @@ function call(client, method, p) {
4799
4850
  case "threadContents": return client.threadContents(num(p.noteId, "noteId"), p.entityFields ?? void 0);
4800
4851
  case "eventLog": return client.eventLog(p.options ?? {});
4801
4852
  case "following": return client.following(num(p.userId, "userId"), p.options ?? {});
4853
+ case "delete": return client.delete(str(p.entityType, "entityType"), num(p.id, "id")).then(() => null);
4854
+ case "revive": return client.revive(str(p.entityType, "entityType"), num(p.id, "id"));
4855
+ case "batch": return client.batch(requestList(p.requests, "requests"));
4802
4856
  }
4803
4857
  }
4804
4858
  //#endregion
@@ -4862,6 +4916,13 @@ var ProxyClient = class {
4862
4916
  options
4863
4917
  });
4864
4918
  }
4919
+ read(entityType, id, options = {}) {
4920
+ return this.post("read", {
4921
+ entityType,
4922
+ id,
4923
+ options
4924
+ });
4925
+ }
4865
4926
  textSearch(text, entityTypes, page) {
4866
4927
  return this.post("textSearch", {
4867
4928
  text,
@@ -4878,6 +4939,21 @@ var ProxyClient = class {
4878
4939
  body
4879
4940
  });
4880
4941
  }
4942
+ async delete(entityType, id) {
4943
+ await this.post("delete", {
4944
+ entityType,
4945
+ id
4946
+ });
4947
+ }
4948
+ revive(entityType, id) {
4949
+ return this.post("revive", {
4950
+ entityType,
4951
+ id
4952
+ });
4953
+ }
4954
+ batch(requests) {
4955
+ return this.post("batch", { requests });
4956
+ }
4881
4957
  /** The bytes cross the protocol base64-encoded; the handler runs the three calls. */
4882
4958
  upload(entityType, id, file) {
4883
4959
  return this.post("upload", {
@@ -6417,7 +6493,7 @@ function asError$1(value) {
6417
6493
  }
6418
6494
  function createEntitySource(options) {
6419
6495
  const { client, entityType } = options;
6420
- const fields = [.../* @__PURE__ */ new Set(["id", ...options.fields])];
6496
+ let fields = [.../* @__PURE__ */ new Set(["id", ...options.fields])];
6421
6497
  let state = {
6422
6498
  rows: [],
6423
6499
  status: "idle",
@@ -6503,7 +6579,9 @@ function createEntitySource(options) {
6503
6579
  }
6504
6580
  const source = {
6505
6581
  entityType,
6506
- fields,
6582
+ get fields() {
6583
+ return fields;
6584
+ },
6507
6585
  get rows() {
6508
6586
  return state.rows;
6509
6587
  },
@@ -6556,6 +6634,15 @@ function createEntitySource(options) {
6556
6634
  set({ total: null });
6557
6635
  return run(() => read(pages, "loading", [], 1));
6558
6636
  },
6637
+ addFields(paths) {
6638
+ const added = paths.filter((path) => path && !fields.includes(path));
6639
+ if (added.length === 0) return Promise.resolve();
6640
+ fields = [...fields, ...new Set(added)];
6641
+ if (state.status === "idle") return Promise.resolve();
6642
+ if (state.mode === "pages") return run(() => read(1, "loading", [], state.page));
6643
+ const pages = Math.max(1, Math.ceil(state.rows.length / state.pageSize));
6644
+ return run(() => read(pages, "loading", [], 1));
6645
+ },
6559
6646
  setFilters(filters) {
6560
6647
  set({ filters: toWireGroup(filters) });
6561
6648
  return source.load();
@@ -6954,6 +7041,175 @@ function sameCollapse(a, b) {
6954
7041
  return a.all === b.all && sameIds(a.except, b.except);
6955
7042
  }
6956
7043
  //#endregion
7044
+ //#region src/selection.ts
7045
+ const refOf = (row) => ({
7046
+ type: row.type,
7047
+ id: row.id
7048
+ });
7049
+ /** Shift ranges; a plain press and Cmd or Ctrl both toggle. */
7050
+ function gestureOf(event) {
7051
+ return event.shiftKey ? "range" : "toggle";
7052
+ }
7053
+ /** Space toggles, Shift+ArrowUp and Shift+ArrowDown extend, Cmd or Ctrl+A takes every loaded row. */
7054
+ function selectionKeyIntent(event) {
7055
+ const command = event.metaKey || event.ctrlKey;
7056
+ if (event.key === " " && !command && !event.altKey) return "toggle";
7057
+ if (event.shiftKey && !command && !event.altKey) {
7058
+ if (event.key === "ArrowDown") return "extend-down";
7059
+ if (event.key === "ArrowUp") return "extend-up";
7060
+ }
7061
+ if (command && !event.shiftKey && !event.altKey && event.key.toLowerCase() === "a") return "all";
7062
+ return null;
7063
+ }
7064
+ /** `selection` with every ref of `refs` added, or every one of them dropped. */
7065
+ function setRefs(selection, refs, on) {
7066
+ const named = new Set(refs.map(rowKey));
7067
+ if (!on) return selection.filter((entry) => !named.has(rowKey(entry)));
7068
+ const held = new Set(selection.map(rowKey));
7069
+ return [...selection, ...refs.filter((entry) => !held.has(rowKey(entry))).map((entry) => ({ ...entry }))];
7070
+ }
7071
+ /** Toggle the row at `index` and anchor on it. A disabled row refuses. */
7072
+ function toggleRow(selection, anchor, rows, index, isRowDisabled) {
7073
+ const row = rows[index];
7074
+ if (!row || rowIsDisabled(row, isRowDisabled)) return {
7075
+ selection: [...selection],
7076
+ anchor
7077
+ };
7078
+ const key = rowKey(row);
7079
+ const on = !selection.some((entry) => rowKey(entry) === key);
7080
+ const next = setRefs(selection, [refOf(row)], on);
7081
+ return {
7082
+ selection: next,
7083
+ anchor: {
7084
+ key,
7085
+ on,
7086
+ base: next,
7087
+ last: next
7088
+ }
7089
+ };
7090
+ }
7091
+ /**
7092
+ * Range from the anchor to the row at `index`, skipping disabled rows.
7093
+ *
7094
+ * With no anchor among the rows, the row pressed is selected and becomes the anchor.
7095
+ */
7096
+ function extendRange(selection, anchor, rows, index, isRowDisabled) {
7097
+ const row = rows[index];
7098
+ if (!row) return {
7099
+ selection: [...selection],
7100
+ anchor
7101
+ };
7102
+ const from = anchor ? rows.findIndex((entry) => rowKey(entry) === anchor.key) : -1;
7103
+ if (!anchor || from < 0) {
7104
+ if (rowIsDisabled(row, isRowDisabled)) return {
7105
+ selection: [...selection],
7106
+ anchor
7107
+ };
7108
+ const next = setRefs(selection, [refOf(row)], true);
7109
+ return {
7110
+ selection: next,
7111
+ anchor: {
7112
+ key: rowKey(row),
7113
+ on: true,
7114
+ base: next,
7115
+ last: next
7116
+ }
7117
+ };
7118
+ }
7119
+ const base = sameRefs(selection, anchor.last) ? anchor.base : [...selection];
7120
+ const [lo, hi] = from <= index ? [from, index] : [index, from];
7121
+ const next = setRefs(base, rows.slice(lo, hi + 1).filter((entry) => !rowIsDisabled(entry, isRowDisabled)).map(refOf), anchor.on);
7122
+ return {
7123
+ selection: next,
7124
+ anchor: {
7125
+ ...anchor,
7126
+ base,
7127
+ last: next
7128
+ }
7129
+ };
7130
+ }
7131
+ /**
7132
+ * Shift+arrow: move the far end of the range from row `from` to row `to`. With no
7133
+ * anchor among the rows, the row the cursor leaves becomes one, selecting.
7134
+ */
7135
+ function extendByStep(selection, anchor, rows, from, to, isRowDisabled) {
7136
+ const start = rows[from];
7137
+ return extendRange(selection, anchor !== null && rows.some((entry) => rowKey(entry) === anchor.key) || !start ? anchor : {
7138
+ key: rowKey(start),
7139
+ on: true,
7140
+ base: [...selection],
7141
+ last: [...selection]
7142
+ }, rows, to, isRowDisabled);
7143
+ }
7144
+ /**
7145
+ * Whether to offer every row the filter matches: once every loaded row is picked and
7146
+ * the set holds more than is loaded, until the selection covers a counted set.
7147
+ */
7148
+ function matchingOffer(state) {
7149
+ const { allLoaded, loaded, selected, hasMore, total } = state;
7150
+ return {
7151
+ show: allLoaded && (hasMore || total !== null && total > loaded) && !(total !== null && selected >= total),
7152
+ total
7153
+ };
7154
+ }
7155
+ //#endregion
7156
+ //#region src/column-choice.ts
7157
+ const PREFIX = "sg-widgets:columns:";
7158
+ /** Where a choice is kept: the caller's key, or one per entity type. */
7159
+ function columnsStorageKey(entityType, key) {
7160
+ return key ? key : `${PREFIX}${entityType}`;
7161
+ }
7162
+ /** A stored choice as paths. Null for nothing, an empty list, or anything that is not a list of paths. */
7163
+ function parseColumnChoice(raw) {
7164
+ if (!raw) return null;
7165
+ let value;
7166
+ try {
7167
+ value = JSON.parse(raw);
7168
+ } catch {
7169
+ return null;
7170
+ }
7171
+ if (!Array.isArray(value) || !value.every((entry) => typeof entry === "string")) return null;
7172
+ const paths = [...new Set(value.map((entry) => entry.trim()).filter(Boolean))];
7173
+ return paths.length > 0 ? paths : null;
7174
+ }
7175
+ /** The string a choice is kept as. */
7176
+ function serializeColumnChoice(paths) {
7177
+ return JSON.stringify(paths);
7178
+ }
7179
+ /** The paths of a column list, in order. */
7180
+ function columnPaths(columns) {
7181
+ return columns.map((column) => column.path);
7182
+ }
7183
+ /** True when two path lists name the same columns in the same order. */
7184
+ function sameColumnPaths(a, b) {
7185
+ return a.length === b.length && a.every((path, at) => path === b[at]);
7186
+ }
7187
+ /** The paths a source with `fields` does not read yet. */
7188
+ function unreadPaths(fields, paths) {
7189
+ const read = new Set(fields);
7190
+ return paths.filter((path) => !read.has(path));
7191
+ }
7192
+ /** The known columns in the order `paths` names them. A path none of them carries is dropped. */
7193
+ function arrangeColumns(paths, known) {
7194
+ const byPath = /* @__PURE__ */ new Map();
7195
+ for (const column of known) if (!byPath.has(column.path)) byPath.set(column.path, column);
7196
+ return paths.flatMap((path) => {
7197
+ const column = byPath.get(path);
7198
+ return column ? [column] : [];
7199
+ });
7200
+ }
7201
+ /**
7202
+ * A choice as columns: the ones already resolved are kept as they are, the rest are
7203
+ * resolved from the schema, and a path the type does not have is skipped, so a
7204
+ * choice kept before a field was removed still opens.
7205
+ */
7206
+ async function resolveColumnChoice(schema, entityType, paths, known) {
7207
+ const have = new Set(known.map((column) => column.path));
7208
+ const missing = paths.filter((path) => !have.has(path));
7209
+ const resolved = await Promise.all(missing.map((path) => resolveColumns(schema, entityType, [path]).then((columns) => columns, () => [])));
7210
+ return arrangeColumns(paths, [...known, ...resolved.flat()]);
7211
+ }
7212
+ //#endregion
6957
7213
  //#region src/entity-card.ts
6958
7214
  const DEFAULT_IMAGE_PATH = "image";
6959
7215
  /**
@@ -7929,4 +8185,4 @@ function watchOverflow(list) {
7929
8185
  };
7930
8186
  }
7931
8187
  //#endregion
7932
- export { AppSessionError, COLOR_SENTINEL, DATA_TYPES, DEFAULT_FIELD_ICON, DISPLAY_NAME_FIELDS, ELLIPSIS_CHIPS, ERROR_LABEL, EVENT_LOG_FIELDS, FIELD_ICON_NAMES, FIELD_SCHEMA_OVERRIDES, FLOAT_PRECISION, HIERARCHY_LEAF_LIMIT, INT32_MAX, INT32_MIN, LOADING_LABEL, NAME_HUES, NATIVE_STATUSES, NEGATING_OPERATORS, NOTHING_CHOSEN_LABEL, NO_MATCH_LABEL, NO_ROWS_LABEL, OPERATORS, OPERATORS_BY_TYPE, OPERATOR_LABELS, OVERFLOW_END_VAR, OVERFLOW_START_VAR, PATH_SEPARATOR, PRESS_WINDOW_MS, PROJECT_PICKER_FIELDS, PROXY_METHODS, ProxyClient, RestClient, SCROLL_THRESHOLD, SEARCHING_LABEL, SEARCH_DEBOUNCE_MS, SEARCH_PAGE_SIZE, SORTABLE_HANDLE_ATTRIBUTE, SORTABLE_ID_ATTRIBUTE, STOCK_ICON_CELLS, STOCK_ICON_DATA_URLS, STOCK_ICON_KEYS, STOCK_SPRITE_PATH, SgApiError, THUMBNAIL_PENDING_PATH, TIME_UNITS, TIME_UNIT_LABELS, TREE_STATUS_FIELDS, UNRESOLVED_PATH_LABEL, USER_PICKER_FIELDS, VALUE_SHAPE, appendAt, applyPreset, asCollapseState, asFilterGroup, base64ToBytes, breadcrumb, bytesToBase64, canLoadNext, cellValue, clearableForField, collapseAll, collapseStateFrom, collapsedKeys, collectionBottom, collectionView, colorToHex, condition, conditionArity, conditionList, conditionParts, conditionValues, contextFromClient, countActiveConditions, countConditions, countLine, createEntitySearch, createEntitySource, createProxyHandler, createQueryCache, createSchemaService, createSessionTokenAuth, createSgContext, createSortable, createSortableController, createStatusService, createTree, currentPlatform, currentType, defaultCondition, defaultValueFor, deriveFieldOptions, describeCondition, describeEntityCard, describePaging, displayNameOf, editorKindFor, editorNeedsContext, editorPlacementFor, emptyFilter, emptyValueFor, entityCardFields, entityCardSlot, entityDetailUrl, entityKey, entityTypeOptions, errorText, eventLogFilters, expandAll, facetCounts, facetLists, facetPresets, facetScopes, facetShape, facetValues, facetValuesFromGroups, fieldOperators, fieldPathOf, fieldSchemaOverride, fieldText, fileHref, fileNameFromUrl, filterEntityTypes, filterableFields, findCondition, findFacet, firstEnabledIndex, fitChips, flattenRow, focusChip, foregroundFor, formatCurrency, formatDate, formatDateTime, formatDuration, formatFloat, formatNumberInput, formatPercent, formatTimecode, friendlyFieldPath, fromApiDateTime, fromSortString, fromWire, group, groupKeyText, groupRows, groupRowsKeyed, hasFailedPage, hasMorePage, hierarchyEntity, hierarchyLoader, hierarchySearcher, hydrate, iconNameFor, idsForRefs, imageState, initialsOf, intersectStatuses, isBareRef, isBlankCondition, isCollapsed, isDataType, isEditableType, isEmptyFilter, isEmptyValue, isFilterable, isGroupingRefusal, isHiddenPath, isLinkType, isNativeStatus, isNumericType, isOperator, isParseError, isPinned, isProxyMethod, isSortable, isTemporalType, isValidListValue, isoDay, isoDayParts, listStatus, loadEntityCard, loadsOnArrowDown, markOverflow, matchRuns, matchesEveryWord, measureSortable, mergeFilters, moveAt, moveFieldPath, nameColorIndex, nameHue, nameSearchFilter, nativeStatus, nextEnabledIndex, nodeAt, normalizeEventLogEntry, normalizeField, normalizeFields, normalizeHierarchyNode, normalizeSiteUrl, numberDigits, numberDraft, numberSteps, numberWire, operatorLabel, operatorMenu, operatorsFor, overflowEdges, parseBgColor, parseColorInput, parseDurationInput, parseFloatInput, parseInteger, parseNumberInput, parseTextInput, parseTimecodeInput, parseUrlInput, pathLabel, pathOf, pathRefs, pathTypes, pickerKeyIntent, placeholderName, playSortableFlip, pollAppSession, preferencesOf, prependRecent, presetById, presetIdOf, presetsFor, pressGate, projectOfPath, projectPickerFilters, pruneFilterToFields, queryPlan, reachedEnd, referencedPaths, refsForIds, relativeFrom, relativeLuminance, relativeOperator, relativeValue, relativeWindow, removeAt, renderKindFor, replaceAt, requestAppSession, requestGate, resolveColumns, resolveFieldPathOptions, resolveRowFields, resolveTreeFields, rgbToCss, rowCode, rowFields, rowIdOf, rowIsDisabled, rowKey, rowSecondary, rowSubLabel, rowThumbnail, sameCollapse, sameFilters, sameIds, sameRefs, sameSort, scopeToProject, scrollHighlightedIntoView, searchFieldOptions, searchFieldPathOptions, searchKeyIntent, searchTypeMap, searchView, searchWords, secondaryType, selectableRefs, selectionState, serializeSort, setFacet, setFacetPreset, settleStep, shouldLoadNext, sortableAnnouncements, sortableDropIndex, sortableFields, sortableScrollStep, sortableStride, sourceModeFor, spriteStyle, stateLine, statusFieldFor, statusFieldNameFor, statusGlyph, statusLabel, statusPaint, stepNumber, stockIconSource, storedNumber, subLabelType, summariseSelection, supportsEmpty, supportsOperator, thumbnailField, timeUnitField, timeUnitLabel, timeZoneName, toApi3Hash, toApiDate, toApiDateTime, toApiFloat, toColumn, toFilterArray, toRef, toSearchHit, toSortKeys, toSortSpecs, toSortString, toWireGroup, toggleCollapsed, toggleFieldPath, toggleId, toggleRef, traversalTargets, undeclaredField, unformatNumberInput, urlLink, usableStatuses, userPickerFilters, userPickerSearchFields, userPickerSubLabel, userPickerTypes, userSearchFields, validateCondition, valueArity, valueEditorFor, walk, watchHighlight, watchOverflow, withAddedListValue, withListValue, withRelativeWindow, withSelectedPinned, withoutListValue, withoutPaths };
8188
+ export { AppSessionError, COLOR_SENTINEL, DATA_TYPES, DEFAULT_FIELD_ICON, DISPLAY_NAME_FIELDS, ELLIPSIS_CHIPS, ERROR_LABEL, EVENT_LOG_FIELDS, FIELD_ICON_NAMES, FIELD_SCHEMA_OVERRIDES, FLOAT_PRECISION, HIERARCHY_LEAF_LIMIT, INT32_MAX, INT32_MIN, LOADING_LABEL, NAME_HUES, NATIVE_STATUSES, NEGATING_OPERATORS, NOTHING_CHOSEN_LABEL, NO_MATCH_LABEL, NO_ROWS_LABEL, OPERATORS, OPERATORS_BY_TYPE, OPERATOR_LABELS, OVERFLOW_END_VAR, OVERFLOW_START_VAR, PATH_SEPARATOR, PRESS_WINDOW_MS, PROJECT_PICKER_FIELDS, PROXY_METHODS, ProxyClient, RestClient, SCROLL_THRESHOLD, SEARCHING_LABEL, SEARCH_DEBOUNCE_MS, SEARCH_PAGE_SIZE, SORTABLE_HANDLE_ATTRIBUTE, SORTABLE_ID_ATTRIBUTE, STOCK_ICON_CELLS, STOCK_ICON_DATA_URLS, STOCK_ICON_KEYS, STOCK_SPRITE_PATH, SgApiError, THUMBNAIL_PENDING_PATH, TIME_UNITS, TIME_UNIT_LABELS, TREE_STATUS_FIELDS, UNRESOLVED_PATH_LABEL, USER_PICKER_FIELDS, VALUE_SHAPE, appendAt, applyPreset, arrangeColumns, asCollapseState, asFilterGroup, base64ToBytes, batchResults, breadcrumb, bytesToBase64, canLoadNext, cellValue, clearableForField, collapseAll, collapseStateFrom, collapsedKeys, collectionBottom, collectionView, colorToHex, columnPaths, columnsStorageKey, condition, conditionArity, conditionList, conditionParts, conditionValues, contextFromClient, countActiveConditions, countConditions, countLine, createEntitySearch, createEntitySource, createProxyHandler, createQueryCache, createSchemaService, createSessionTokenAuth, createSgContext, createSortable, createSortableController, createStatusService, createTree, currentPlatform, currentType, defaultCondition, defaultValueFor, deriveFieldOptions, describeCondition, describeEntityCard, describePaging, displayNameOf, editorKindFor, editorNeedsContext, editorPlacementFor, emptyFilter, emptyValueFor, entityCardFields, entityCardSlot, entityDetailUrl, entityKey, entityTypeOptions, errorText, eventLogFilters, expandAll, extendByStep, extendRange, facetCounts, facetLists, facetPresets, facetScopes, facetShape, facetValues, facetValuesFromGroups, fieldOperators, fieldPathOf, fieldSchemaOverride, fieldText, fileHref, fileNameFromUrl, filterEntityTypes, filterableFields, findCondition, findFacet, firstEnabledIndex, fitChips, flattenRow, focusChip, foregroundFor, formatCurrency, formatDate, formatDateTime, formatDuration, formatFloat, formatNumberInput, formatPercent, formatTimecode, friendlyFieldPath, fromApiDateTime, fromSortString, fromWire, gestureOf, group, groupKeyText, groupRows, groupRowsKeyed, hasFailedPage, hasMorePage, hierarchyEntity, hierarchyLoader, hierarchySearcher, hydrate, iconNameFor, idsForRefs, imageState, initialsOf, intersectStatuses, isBareRef, isBlankCondition, isCollapsed, isDataType, isEditableType, isEmptyFilter, isEmptyValue, isFilterable, isGroupingRefusal, isHiddenPath, isLinkType, isNativeStatus, isNumericType, isOperator, isParseError, isPinned, isProxyMethod, isSortable, isTemporalType, isValidListValue, isoDay, isoDayParts, listStatus, loadEntityCard, loadsOnArrowDown, markOverflow, matchRuns, matchesEveryWord, matchingOffer, measureSortable, mergeFilters, moveAt, moveFieldPath, nameColorIndex, nameHue, nameSearchFilter, nativeStatus, nextEnabledIndex, nodeAt, normalizeEventLogEntry, normalizeField, normalizeFields, normalizeHierarchyNode, normalizeSiteUrl, numberDigits, numberDraft, numberSteps, numberWire, operatorLabel, operatorMenu, operatorsFor, overflowEdges, parseBgColor, parseColorInput, parseColumnChoice, parseDurationInput, parseFloatInput, parseInteger, parseNumberInput, parseTextInput, parseTimecodeInput, parseUrlInput, pathLabel, pathOf, pathRefs, pathTypes, pickerKeyIntent, placeholderName, playSortableFlip, pollAppSession, preferencesOf, prependRecent, presetById, presetIdOf, presetsFor, pressGate, projectOfPath, projectPickerFilters, pruneFilterToFields, queryPlan, reachedEnd, referencedPaths, refsForIds, relativeFrom, relativeLuminance, relativeOperator, relativeValue, relativeWindow, removeAt, renderKindFor, replaceAt, requestAppSession, requestGate, resolveColumnChoice, resolveColumns, resolveFieldPathOptions, resolveRowFields, resolveTreeFields, rgbToCss, rowCode, rowFields, rowIdOf, rowIsDisabled, rowKey, rowSecondary, rowSubLabel, rowThumbnail, sameCollapse, sameColumnPaths, sameFilters, sameIds, sameRefs, sameSort, scopeToProject, scrollHighlightedIntoView, searchFieldOptions, searchFieldPathOptions, searchKeyIntent, searchTypeMap, searchView, searchWords, secondaryType, selectableRefs, selectionKeyIntent, selectionState, serializeColumnChoice, serializeSort, setFacet, setFacetPreset, setRefs, settleStep, shouldLoadNext, sortableAnnouncements, sortableDropIndex, sortableFields, sortableScrollStep, sortableStride, sourceModeFor, spriteStyle, stateLine, statusFieldFor, statusFieldNameFor, statusGlyph, statusLabel, statusPaint, stepNumber, stockIconSource, storedNumber, subLabelType, summariseSelection, supportsEmpty, supportsOperator, thumbnailField, timeUnitField, timeUnitLabel, timeZoneName, toApi3Hash, toApiDate, toApiDateTime, toApiFloat, toColumn, toFilterArray, toRef, toSearchHit, toSortKeys, toSortSpecs, toSortString, toWireGroup, toggleCollapsed, toggleFieldPath, toggleId, toggleRef, toggleRow, traversalTargets, undeclaredField, unformatNumberInput, unreadPaths, urlLink, usableStatuses, userPickerFilters, userPickerSearchFields, userPickerSubLabel, userPickerTypes, userSearchFields, validateCondition, valueArity, valueEditorFor, walk, watchHighlight, watchOverflow, withAddedListValue, withListValue, withRelativeWindow, withSelectedPinned, withoutListValue, withoutPaths };
package/dist/mock.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { D as UploadFile, E as ThreadRow, Et as TextSearchFilter, O as UploadResult, R as StatusRecord, _ as SgClient, a as EventLogOptions, bt as EntityRef, c as HierarchyNode, ct as FieldSchema, h as SearchResult, l as HierarchyPath, m as SearchOptions, n as EntityRow, o as EventLogResult, r as EntityTypeInfo, s as FollowingOptions, v as SummarizeOptions, w as TextSearchRow, y as SummarizeResult } from "./client-BhHppzTV.mjs";
1
+ import { A as ThreadRow, C as SummarizeResult, M as UploadResult, O as TextSearchRow, S as SummarizeOptions, Tt as EntityRef, U as StatusRecord, a as EntityTypeInfo, c as EventLogResult, d as HierarchyPath, h as ReadOptions, i as EntityRow, j as UploadFile, jt as TextSearchFilter, l as FollowingOptions, n as BatchResult, pt as FieldSchema, s as EventLogOptions, t as BatchRequest, u as HierarchyNode, v as SearchOptions, x as SgClient, y as SearchResult } from "./client-CP9sWEVZ.mjs";
2
2
  //#region src/mock.d.ts
3
3
  /** What the next call should throw instead of answering. */
4
4
  export interface MockFailure {
@@ -34,6 +34,15 @@ export declare class MockClient implements SgClient {
34
34
  private readonly latencyMs;
35
35
  private readonly clock;
36
36
  private pendingFailure;
37
+ /** Rows a delete retired, by `Type:id`. Reads skip them and a revive puts them back. */
38
+ private readonly retired;
39
+ /** Rows a batch created with no `project`: no read reaches them, a delete does (report 001). */
40
+ private readonly unreadable;
41
+ /** What a Task delete did to other rows, by `Task:id`, for its revive to undo (089_task_delete_side_effects). */
42
+ private readonly cascades;
43
+ /** The highest id handed out per type, so an erased row's id is never reused. */
44
+ private readonly issued;
45
+ private deletes;
37
46
  constructor(options?: MockClientOptions);
38
47
  /**
39
48
  * Make the next call reject with an `SgApiError`, for demoing an error state.
@@ -48,11 +57,13 @@ export declare class MockClient implements SgClient {
48
57
  fields(entityType: string, projectId?: number): Promise<Record<string, FieldSchema>>;
49
58
  fieldWithProject(entityType: string, field: string, projectId: number): Promise<FieldSchema>;
50
59
  search(entityType: string, options: SearchOptions): Promise<SearchResult>;
60
+ read(entityType: string, id: number, options?: ReadOptions): Promise<EntityRow>;
51
61
  textSearch(text: string, entityTypes: Record<string, TextSearchFilter>, page?: {
52
62
  size?: number;
53
63
  number?: number;
54
64
  }): Promise<TextSearchRow[]>;
55
65
  update(entityType: string, id: number, patch: Record<string, unknown>): Promise<EntityRow>;
66
+ private updateRow;
56
67
  /**
57
68
  * Counts without paging rows.
58
69
  *
@@ -104,6 +115,66 @@ export declare class MockClient implements SgClient {
104
115
  * entity_types/Note). Nothing is unique, so two identical creates make two rows.
105
116
  */
106
117
  create(entityType: string, body: Record<string, unknown>): Promise<EntityRow>;
118
+ /**
119
+ * A create, alone or inside a batch. The batch skips the `project` check and stores
120
+ * the row where no read reaches it (report 001), and it spells an unknown field its
121
+ * own way (recipes/002).
122
+ */
123
+ private createRow;
124
+ /**
125
+ * Retire one row: reads skip it and a second delete is 404 (delete_entity_type_id).
126
+ * A Task takes its TaskDependency rows with it and leaves `Version.sg_task` and
127
+ * `PublishedFile.task` null until its revive (089_task_delete_side_effects), alone or
128
+ * in a batch (103_batch_delete_revive). A TaskTemplate retires its tasks
129
+ * (entity_types/TaskTemplate). What a Shot delete does to its Versions (probe 060)
130
+ * is not modelled.
131
+ */
132
+ delete(entityType: string, id: number): Promise<void>;
133
+ private deleteRow;
134
+ /**
135
+ * Bring a retired row back with its values; `false` for a row that is already live
136
+ * (post_entity_type_id). A Task gets back what its delete took (089_task_delete_side_effects).
137
+ * A TaskDependency whose pair is linked again refuses, the pair being a unique index
138
+ * (095_dependency_remove_undo). A TaskTemplate's tasks stay retired: unmeasured.
139
+ */
140
+ revive(entityType: string, id: number): Promise<boolean>;
141
+ private retire;
142
+ private unretire;
143
+ /** Remove a row for good: no read reaches it and no revive brings it back. */
144
+ private erase;
145
+ private live;
146
+ /** The live TaskDependency rows with this Task at either end. */
147
+ private edgesOf;
148
+ /** Whether a live row already links this row's pair. */
149
+ private pairTaken;
150
+ /** Whether `from` depends on `target`, directly or through other Tasks. */
151
+ private dependsOn;
152
+ /**
153
+ * The checks a TaskDependency create makes: one of four types, one row per pair, and
154
+ * no loop of any length (085_task_dependency_types, 107_dependency_three_task_loop).
155
+ */
156
+ private checkEdge;
157
+ /**
158
+ * A write to `upstream_tasks` or `downstream_tasks`: a new neighbour gets a row of the
159
+ * default type and no offset, a dropped one's row is erased, not retired
160
+ * (086_batch_tasks_with_dependencies, 095_dependency_remove_undo).
161
+ */
162
+ private writeEdges;
163
+ /** Where the written field is one side of a two-sided link, make the other side agree. */
164
+ private mirror;
165
+ /**
166
+ * What the server derives from other rows: a Task's two edge lists from the
167
+ * TaskDependency rows, their ids and name, and a template's task count, a string.
168
+ */
169
+ private derive;
170
+ /**
171
+ * Apply the requests in order, and undo all of them when one fails (recipes/002).
172
+ * A create or update row carries the record under `data`; a delete row is flat.
173
+ */
174
+ batch(requests: BatchRequest[]): Promise<BatchResult[]>;
175
+ private batchOne;
176
+ /** Everything a batch can change, and a function that puts it back. */
177
+ private snapshot;
107
178
  /**
108
179
  * Put a file on a row, as the three-call handshake leaves the site.
109
180
  *
@@ -118,6 +189,13 @@ export declare class MockClient implements SgClient {
118
189
  * missing key (field_types/entity).
119
190
  */
120
191
  private checkLink;
192
+ /**
193
+ * Values the server checks beyond their shape. A status code must be in the site-wide
194
+ * `valid_values`, hidden ones included, and a create or any batch request wraps the
195
+ * refusal (field_types/status_list, recipes/002, 094_permission_preflight). A
196
+ * TaskTemplate's `entity_type` must name a type (entity_types/TaskTemplate).
197
+ */
198
+ private checkValue;
121
199
  /** The next free id of a type, which is what a create takes. */
122
200
  private nextId;
123
201
  /** The reverse view of a link the server fills in: a Reply lands in `Note.replies`. */