sg-widgets-core 0.3.1 → 0.4.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.d.mts +85 -68
- package/dist/index.mjs +181 -5
- package/dist/mock.d.mts +39 -1
- package/dist/mock.mjs +267 -2
- package/dist/{client-CP9sWEVZ.d.mts → proxy-handler-C6XB6gss.d.mts} +311 -65
- package/dist/{client-izKszX7l.mjs → schema-write-D_WfMYW8.mjs} +384 -2
- package/package.json +1 -1
|
@@ -236,6 +236,36 @@ function isTemporalType(dataType) {
|
|
|
236
236
|
return dataType === "date" || dataType === "date_time";
|
|
237
237
|
}
|
|
238
238
|
//#endregion
|
|
239
|
+
//#region src/field-name.ts
|
|
240
|
+
/** The prefix the server puts in front of every custom field it creates. */
|
|
241
|
+
const CUSTOM_FIELD_PREFIX = "sg_";
|
|
242
|
+
/**
|
|
243
|
+
* Whether a display name holds a character outside ASCII. The server discards such a name
|
|
244
|
+
* whole when it derives the programmatic name (findings/117_field_types_and_names).
|
|
245
|
+
*/
|
|
246
|
+
function hasNonAscii(displayName) {
|
|
247
|
+
return /[^\u0000-\u007F]/u.test(displayName);
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* The programmatic name the server derives from a display name, or null when it cannot be
|
|
251
|
+
* predicted: a blank display name, or a non-ASCII one without its data type.
|
|
252
|
+
*
|
|
253
|
+
* An ASCII display name gives the prefix, then the name lowercased with each character
|
|
254
|
+
* outside `[a-z0-9_]` replaced by one underscore. Nothing is trimmed, collapsed or cut, a
|
|
255
|
+
* leading digit stays, and a prefix already there is doubled (findings/019_create_fields,
|
|
256
|
+
* findings/117_field_types_and_names).
|
|
257
|
+
*
|
|
258
|
+
* One non-ASCII character anywhere and the server ignores the display name: the field is
|
|
259
|
+
* `sg_<data_type>`. That is measured on a `currency` field and inferred for the other types.
|
|
260
|
+
* A name already taken comes back suffixed `_1`, `_2`, and a name a retired field holds is
|
|
261
|
+
* refused; neither is predicted here.
|
|
262
|
+
*/
|
|
263
|
+
function predictFieldName(displayName, dataType) {
|
|
264
|
+
if (displayName.trim() === "") return null;
|
|
265
|
+
if (hasNonAscii(displayName)) return dataType ? "sg_" + dataType : null;
|
|
266
|
+
return "sg_" + displayName.toLowerCase().replace(/[^a-z0-9_]/g, "_");
|
|
267
|
+
}
|
|
268
|
+
//#endregion
|
|
239
269
|
//#region src/filter.ts
|
|
240
270
|
/**
|
|
241
271
|
* The filter array `entity_types` wants, `[]` for no filter
|
|
@@ -450,7 +480,7 @@ function normalizeField(name, raw) {
|
|
|
450
480
|
if (hiddenValues) field.hiddenValues = hiddenValues;
|
|
451
481
|
const defaultValue = prop(props, "default_value");
|
|
452
482
|
if (defaultValue !== void 0) field.defaultValue = defaultValue;
|
|
453
|
-
const description =
|
|
483
|
+
const description = raw.description?.value;
|
|
454
484
|
if (description) field.description = description;
|
|
455
485
|
if (raw.visible) field.hideable = raw.visible.editable;
|
|
456
486
|
return {
|
|
@@ -1053,4 +1083,356 @@ function toStatusIcon(a) {
|
|
|
1053
1083
|
}
|
|
1054
1084
|
}
|
|
1055
1085
|
//#endregion
|
|
1056
|
-
|
|
1086
|
+
//#region src/schema-write.ts
|
|
1087
|
+
function toSchemaProperties(properties) {
|
|
1088
|
+
if (!properties) return [];
|
|
1089
|
+
if (Array.isArray(properties)) return properties;
|
|
1090
|
+
return Object.entries(properties).map(([property_name, value]) => ({
|
|
1091
|
+
property_name,
|
|
1092
|
+
value
|
|
1093
|
+
}));
|
|
1094
|
+
}
|
|
1095
|
+
function firstError(body) {
|
|
1096
|
+
if (body === null || typeof body !== "object") return {};
|
|
1097
|
+
const errors = body.errors;
|
|
1098
|
+
const first = Array.isArray(errors) ? errors[0] : null;
|
|
1099
|
+
return first !== null && typeof first === "object" ? first : {};
|
|
1100
|
+
}
|
|
1101
|
+
/** The strings a `source` holds, e.g. `{"revive": ["revive is missing"]}`. */
|
|
1102
|
+
function sourceMessages(source) {
|
|
1103
|
+
if (source === null || typeof source !== "object") return [];
|
|
1104
|
+
return Object.values(source).flat().filter((value) => typeof value === "string");
|
|
1105
|
+
}
|
|
1106
|
+
/**
|
|
1107
|
+
* A refusal from a schema call, as the server sent it: `status` and `body` whole,
|
|
1108
|
+
* and the first error's `code`, `title`, `detail` and `source` lifted out.
|
|
1109
|
+
*
|
|
1110
|
+
* `message` is the `detail` where there is one and the `title` otherwise, followed
|
|
1111
|
+
* by whatever only the `source` says. A 404 is titled `Not Found` and says which
|
|
1112
|
+
* name is wrong in its `detail` (002_schema).
|
|
1113
|
+
*/
|
|
1114
|
+
var SchemaApiError = class extends SgApiError {
|
|
1115
|
+
code;
|
|
1116
|
+
title;
|
|
1117
|
+
detail;
|
|
1118
|
+
source;
|
|
1119
|
+
constructor(status, body, message) {
|
|
1120
|
+
const first = firstError(body);
|
|
1121
|
+
const title = typeof first.title === "string" ? first.title : null;
|
|
1122
|
+
const detail = typeof first.detail === "string" ? first.detail : null;
|
|
1123
|
+
const said = detail ?? title;
|
|
1124
|
+
const composed = [said, ...sourceMessages(first.source).filter((text) => !said?.includes(text))].filter((text) => text).join(" ");
|
|
1125
|
+
super(status, body, message ?? (composed || `Flow PT API error ${status}`));
|
|
1126
|
+
this.name = "SchemaApiError";
|
|
1127
|
+
this.code = typeof first.code === "number" ? first.code : null;
|
|
1128
|
+
this.title = title;
|
|
1129
|
+
this.detail = detail;
|
|
1130
|
+
this.source = first.source ?? null;
|
|
1131
|
+
}
|
|
1132
|
+
};
|
|
1133
|
+
/** The one 404 that means the field is absent; an unknown type's 404 says `Entity type` (get_schema_type_fields_field). */
|
|
1134
|
+
const FIELD_MISSING = /^Field '.*' does not exist/;
|
|
1135
|
+
function isMissingField(error) {
|
|
1136
|
+
return error.status === 404 && FIELD_MISSING.test(error.detail ?? error.title ?? error.message);
|
|
1137
|
+
}
|
|
1138
|
+
function isRecord(value) {
|
|
1139
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1140
|
+
}
|
|
1141
|
+
/**
|
|
1142
|
+
* A wrapped record as a `FieldSchema`. The record is left as it came; a key the
|
|
1143
|
+
* response leaves out is read as its default, with the type taken from the path.
|
|
1144
|
+
*/
|
|
1145
|
+
function fieldFromRaw(entityType, name, raw) {
|
|
1146
|
+
const fixed = (value) => ({
|
|
1147
|
+
value,
|
|
1148
|
+
editable: false
|
|
1149
|
+
});
|
|
1150
|
+
const loose = raw;
|
|
1151
|
+
return normalizeField(name, {
|
|
1152
|
+
...raw,
|
|
1153
|
+
name: loose.name ?? fixed(name),
|
|
1154
|
+
entity_type: loose.entity_type ?? fixed(entityType),
|
|
1155
|
+
data_type: loose.data_type ?? fixed(""),
|
|
1156
|
+
editable: loose.editable ?? fixed(false),
|
|
1157
|
+
mandatory: loose.mandatory ?? fixed(false),
|
|
1158
|
+
unique: loose.unique ?? fixed(false),
|
|
1159
|
+
properties: loose.properties ?? {}
|
|
1160
|
+
});
|
|
1161
|
+
}
|
|
1162
|
+
function fieldPath(entityType, field) {
|
|
1163
|
+
const base = `/schema/${encodeURIComponent(entityType)}/fields`;
|
|
1164
|
+
return field === void 0 ? base : `${base}/${encodeURIComponent(field)}`;
|
|
1165
|
+
}
|
|
1166
|
+
var RestSchemaClient = class {
|
|
1167
|
+
options;
|
|
1168
|
+
base;
|
|
1169
|
+
fetchFn;
|
|
1170
|
+
constructor(options) {
|
|
1171
|
+
this.options = options;
|
|
1172
|
+
this.base = options.siteUrl.replace(/\/+$/, "") + "/api/v1";
|
|
1173
|
+
this.fetchFn = options.fetch ?? globalThis.fetch.bind(globalThis);
|
|
1174
|
+
}
|
|
1175
|
+
async request(method, path, body, projectId) {
|
|
1176
|
+
const url = new URL(this.base + path);
|
|
1177
|
+
if (projectId !== void 0) url.searchParams.set("project_id", String(projectId));
|
|
1178
|
+
const headers = {
|
|
1179
|
+
Accept: "application/json",
|
|
1180
|
+
Authorization: `Bearer ${await this.options.token()}`
|
|
1181
|
+
};
|
|
1182
|
+
const init = {
|
|
1183
|
+
method,
|
|
1184
|
+
headers
|
|
1185
|
+
};
|
|
1186
|
+
if (body !== void 0) {
|
|
1187
|
+
headers["Content-Type"] = "application/json";
|
|
1188
|
+
init.body = JSON.stringify(body);
|
|
1189
|
+
}
|
|
1190
|
+
const res = await this.fetchFn(url, init);
|
|
1191
|
+
const text = await res.text();
|
|
1192
|
+
let parsed = null;
|
|
1193
|
+
try {
|
|
1194
|
+
parsed = text ? JSON.parse(text) : null;
|
|
1195
|
+
} catch {
|
|
1196
|
+
parsed = text;
|
|
1197
|
+
}
|
|
1198
|
+
if (!res.ok) throw new SchemaApiError(res.status, parsed);
|
|
1199
|
+
return {
|
|
1200
|
+
status: res.status,
|
|
1201
|
+
body: parsed
|
|
1202
|
+
};
|
|
1203
|
+
}
|
|
1204
|
+
async readField(entityType, field, projectId) {
|
|
1205
|
+
let reply;
|
|
1206
|
+
try {
|
|
1207
|
+
reply = await this.request("GET", fieldPath(entityType, field), void 0, projectId);
|
|
1208
|
+
} catch (error) {
|
|
1209
|
+
if (error instanceof SchemaApiError && isMissingField(error)) return {
|
|
1210
|
+
status: "missing",
|
|
1211
|
+
message: error.message
|
|
1212
|
+
};
|
|
1213
|
+
throw error;
|
|
1214
|
+
}
|
|
1215
|
+
const raw = isRecord(reply.body) ? reply.body["data"] : null;
|
|
1216
|
+
if (!isRecord(raw)) return { status: "undeclared" };
|
|
1217
|
+
const record = raw;
|
|
1218
|
+
return {
|
|
1219
|
+
status: "found",
|
|
1220
|
+
field: fieldFromRaw(entityType, field, record),
|
|
1221
|
+
raw: record
|
|
1222
|
+
};
|
|
1223
|
+
}
|
|
1224
|
+
async readRawFields(entityType, projectId) {
|
|
1225
|
+
const reply = await this.request("GET", fieldPath(entityType), void 0, projectId);
|
|
1226
|
+
const data = isRecord(reply.body) ? reply.body["data"] : null;
|
|
1227
|
+
return isRecord(data) ? data : {};
|
|
1228
|
+
}
|
|
1229
|
+
async createField(entityType, input) {
|
|
1230
|
+
const body = {
|
|
1231
|
+
data_type: input.dataType,
|
|
1232
|
+
properties: [{
|
|
1233
|
+
property_name: "name",
|
|
1234
|
+
value: input.displayName
|
|
1235
|
+
}, ...toSchemaProperties(input.properties)]
|
|
1236
|
+
};
|
|
1237
|
+
const reply = await this.request("POST", fieldPath(entityType), body);
|
|
1238
|
+
const envelope = isRecord(reply.body) ? reply.body : {};
|
|
1239
|
+
const links = envelope["links"];
|
|
1240
|
+
const self = isRecord(links) && typeof links["self"] === "string" ? links["self"] : "";
|
|
1241
|
+
const name = decodeURIComponent(self.split("?")[0]?.split("/").filter(Boolean).pop() ?? "");
|
|
1242
|
+
if (!name) throw new SchemaApiError(reply.status, reply.body, "The create answered no links.self, so the name of the field is unknown");
|
|
1243
|
+
const data = envelope["data"];
|
|
1244
|
+
return {
|
|
1245
|
+
name,
|
|
1246
|
+
self,
|
|
1247
|
+
raw: isRecord(data) ? data : null
|
|
1248
|
+
};
|
|
1249
|
+
}
|
|
1250
|
+
async updateField(entityType, field, properties, projectId) {
|
|
1251
|
+
const body = { properties: toSchemaProperties(properties) };
|
|
1252
|
+
if (projectId !== void 0) body["project_id"] = projectId;
|
|
1253
|
+
const reply = await this.request("PUT", fieldPath(entityType, field), body);
|
|
1254
|
+
const data = isRecord(reply.body) ? reply.body["data"] : null;
|
|
1255
|
+
return isRecord(data) ? data : null;
|
|
1256
|
+
}
|
|
1257
|
+
async retireField(entityType, field) {
|
|
1258
|
+
await this.request("DELETE", fieldPath(entityType, field));
|
|
1259
|
+
}
|
|
1260
|
+
async reviveField(entityType, field) {
|
|
1261
|
+
try {
|
|
1262
|
+
await this.request("POST", fieldPath(entityType, field), { revive: true });
|
|
1263
|
+
return { revived: true };
|
|
1264
|
+
} catch (error) {
|
|
1265
|
+
if (error instanceof SchemaApiError && isDeclined(error.status)) return {
|
|
1266
|
+
revived: false,
|
|
1267
|
+
status: error.status,
|
|
1268
|
+
message: error.message
|
|
1269
|
+
};
|
|
1270
|
+
throw error;
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
};
|
|
1274
|
+
/** A refusal of the revive itself, as against a refused sign-in, a missing right or a fault. */
|
|
1275
|
+
function isDeclined(status) {
|
|
1276
|
+
return status >= 400 && status < 500 && status !== 401 && status !== 403;
|
|
1277
|
+
}
|
|
1278
|
+
/** The schema methods the proxy protocol carries, one POST each, beside `PROXY_METHODS`. */
|
|
1279
|
+
const SCHEMA_PROXY_METHODS = [
|
|
1280
|
+
"readField",
|
|
1281
|
+
"readRawFields",
|
|
1282
|
+
"createField",
|
|
1283
|
+
"updateField",
|
|
1284
|
+
"retireField",
|
|
1285
|
+
"reviveField"
|
|
1286
|
+
];
|
|
1287
|
+
function isSchemaProxyMethod(value) {
|
|
1288
|
+
return SCHEMA_PROXY_METHODS.includes(value);
|
|
1289
|
+
}
|
|
1290
|
+
var BadRequest = class extends Error {};
|
|
1291
|
+
function str(value, name) {
|
|
1292
|
+
if (typeof value !== "string" || value.length === 0) throw new BadRequest(`'${name}' must be a non-empty string`);
|
|
1293
|
+
return value;
|
|
1294
|
+
}
|
|
1295
|
+
function optionalNum(value, name) {
|
|
1296
|
+
if (value === void 0 || value === null) return void 0;
|
|
1297
|
+
if (typeof value !== "number" || !Number.isFinite(value)) throw new BadRequest(`'${name}' must be a number`);
|
|
1298
|
+
return value;
|
|
1299
|
+
}
|
|
1300
|
+
/** A list of `{property_name, value}` or a record; the API names what is wrong inside one. */
|
|
1301
|
+
function properties(value, name) {
|
|
1302
|
+
if (Array.isArray(value)) {
|
|
1303
|
+
for (const [i, item] of value.entries()) if (!isRecord(item) || typeof item["property_name"] !== "string") throw new BadRequest(`'${name}[${i}]' must be a {property_name, value} object`);
|
|
1304
|
+
return value;
|
|
1305
|
+
}
|
|
1306
|
+
if (!isRecord(value)) throw new BadRequest(`'${name}' must be a list or a JSON object`);
|
|
1307
|
+
return value;
|
|
1308
|
+
}
|
|
1309
|
+
function createInput(value) {
|
|
1310
|
+
if (!isRecord(value)) throw new BadRequest("'input' must be a JSON object");
|
|
1311
|
+
const input = {
|
|
1312
|
+
dataType: str(value["dataType"], "input.dataType"),
|
|
1313
|
+
displayName: str(value["displayName"], "input.displayName")
|
|
1314
|
+
};
|
|
1315
|
+
if (value["properties"] !== void 0 && value["properties"] !== null) input.properties = properties(value["properties"], "input.properties");
|
|
1316
|
+
return input;
|
|
1317
|
+
}
|
|
1318
|
+
function fail(status, message, body = null) {
|
|
1319
|
+
return {
|
|
1320
|
+
status,
|
|
1321
|
+
body: { error: {
|
|
1322
|
+
status,
|
|
1323
|
+
message,
|
|
1324
|
+
body
|
|
1325
|
+
} }
|
|
1326
|
+
};
|
|
1327
|
+
}
|
|
1328
|
+
function call(client, method, p) {
|
|
1329
|
+
const entityType = str(p["entityType"], "entityType");
|
|
1330
|
+
switch (method) {
|
|
1331
|
+
case "readField": return client.readField(entityType, str(p["field"], "field"), optionalNum(p["projectId"], "projectId"));
|
|
1332
|
+
case "readRawFields": return client.readRawFields(entityType, optionalNum(p["projectId"], "projectId"));
|
|
1333
|
+
case "createField": return client.createField(entityType, createInput(p["input"]));
|
|
1334
|
+
case "updateField": return client.updateField(entityType, str(p["field"], "field"), properties(p["properties"], "properties"), optionalNum(p["projectId"], "projectId"));
|
|
1335
|
+
case "retireField": return client.retireField(entityType, str(p["field"], "field")).then(() => null);
|
|
1336
|
+
case "reviveField": return client.reviveField(entityType, str(p["field"], "field"));
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
/**
|
|
1340
|
+
* The server half of `ProxySchemaClient`, in the protocol of `createProxyHandler`.
|
|
1341
|
+
* It answers 404 to a method that is not a schema one, so a host routes on
|
|
1342
|
+
* `isSchemaProxyMethod`, or hands the schema client to `createProxyHandler`.
|
|
1343
|
+
*
|
|
1344
|
+
* These calls change the site's schema for everyone: expose them only to the
|
|
1345
|
+
* people who may.
|
|
1346
|
+
*/
|
|
1347
|
+
function createSchemaProxyHandler(client) {
|
|
1348
|
+
return async function handle(method, body) {
|
|
1349
|
+
if (!isSchemaProxyMethod(method)) return fail(404, `Unknown method '${method}'`);
|
|
1350
|
+
if (body !== void 0 && body !== null && !isRecord(body)) return fail(400, "Body must be a JSON object");
|
|
1351
|
+
try {
|
|
1352
|
+
return {
|
|
1353
|
+
status: 200,
|
|
1354
|
+
body: { data: await call(client, method, body ?? {}) }
|
|
1355
|
+
};
|
|
1356
|
+
} catch (error) {
|
|
1357
|
+
if (error instanceof BadRequest) return fail(400, error.message);
|
|
1358
|
+
if (error instanceof SgApiError) return fail(error.status, error.message, error.body);
|
|
1359
|
+
return fail(500, error instanceof Error ? error.message : String(error));
|
|
1360
|
+
}
|
|
1361
|
+
};
|
|
1362
|
+
}
|
|
1363
|
+
/** A `SchemaClient` over the host app's own endpoints: one POST per method under `basePath`. */
|
|
1364
|
+
var ProxySchemaClient = class {
|
|
1365
|
+
options;
|
|
1366
|
+
base;
|
|
1367
|
+
fetchFn;
|
|
1368
|
+
constructor(options) {
|
|
1369
|
+
this.options = options;
|
|
1370
|
+
this.base = options.basePath.replace(/\/+$/, "");
|
|
1371
|
+
this.fetchFn = options.fetch ?? globalThis.fetch.bind(globalThis);
|
|
1372
|
+
}
|
|
1373
|
+
async post(method, body) {
|
|
1374
|
+
const supplied = typeof this.options.headers === "function" ? await this.options.headers() : this.options.headers ?? {};
|
|
1375
|
+
const res = await this.fetchFn(`${this.base}/${method}`, {
|
|
1376
|
+
method: "POST",
|
|
1377
|
+
headers: {
|
|
1378
|
+
Accept: "application/json",
|
|
1379
|
+
"Content-Type": "application/json",
|
|
1380
|
+
...supplied
|
|
1381
|
+
},
|
|
1382
|
+
body: JSON.stringify(body)
|
|
1383
|
+
});
|
|
1384
|
+
const text = await res.text();
|
|
1385
|
+
let payload = null;
|
|
1386
|
+
try {
|
|
1387
|
+
payload = text ? JSON.parse(text) : null;
|
|
1388
|
+
} catch {
|
|
1389
|
+
throw new SchemaApiError(res.status, text, `Proxy returned a non-JSON body for '${method}'`);
|
|
1390
|
+
}
|
|
1391
|
+
const envelope = isRecord(payload) ? payload : {};
|
|
1392
|
+
const error = envelope["error"];
|
|
1393
|
+
if (isRecord(error) && typeof error["status"] === "number" && typeof error["message"] === "string") throw new SchemaApiError(error["status"], error["body"] ?? null, error["message"]);
|
|
1394
|
+
if (!res.ok) throw new SchemaApiError(res.status, payload, `Proxy error ${res.status} for '${method}'`);
|
|
1395
|
+
return envelope["data"] ?? null;
|
|
1396
|
+
}
|
|
1397
|
+
readField(entityType, field, projectId) {
|
|
1398
|
+
return this.post("readField", {
|
|
1399
|
+
entityType,
|
|
1400
|
+
field,
|
|
1401
|
+
projectId: projectId ?? null
|
|
1402
|
+
});
|
|
1403
|
+
}
|
|
1404
|
+
readRawFields(entityType, projectId) {
|
|
1405
|
+
return this.post("readRawFields", {
|
|
1406
|
+
entityType,
|
|
1407
|
+
projectId: projectId ?? null
|
|
1408
|
+
});
|
|
1409
|
+
}
|
|
1410
|
+
createField(entityType, input) {
|
|
1411
|
+
return this.post("createField", {
|
|
1412
|
+
entityType,
|
|
1413
|
+
input
|
|
1414
|
+
});
|
|
1415
|
+
}
|
|
1416
|
+
updateField(entityType, field, properties, projectId) {
|
|
1417
|
+
return this.post("updateField", {
|
|
1418
|
+
entityType,
|
|
1419
|
+
field,
|
|
1420
|
+
properties,
|
|
1421
|
+
projectId: projectId ?? null
|
|
1422
|
+
});
|
|
1423
|
+
}
|
|
1424
|
+
async retireField(entityType, field) {
|
|
1425
|
+
await this.post("retireField", {
|
|
1426
|
+
entityType,
|
|
1427
|
+
field
|
|
1428
|
+
});
|
|
1429
|
+
}
|
|
1430
|
+
reviveField(entityType, field) {
|
|
1431
|
+
return this.post("reviveField", {
|
|
1432
|
+
entityType,
|
|
1433
|
+
field
|
|
1434
|
+
});
|
|
1435
|
+
}
|
|
1436
|
+
};
|
|
1437
|
+
//#endregion
|
|
1438
|
+
export { supportsOperator as $, group as A, DATA_TYPES as B, statusFieldFor as C, condition as D, pluralPath as E, toFilterArray as F, VALUE_SHAPE as G, OPERATORS as H, walk as I, isLinkType as J, isDataType as K, CUSTOM_FIELD_PREFIX as L, isEmptyFilter as M, referencedPaths as N, emptyFilter as O, toApi3Hash as P, operatorsFor as Q, hasNonAscii as R, normalizeFields as S, undeclaredField as T, OPERATORS_BY_TYPE as U, NEGATING_OPERATORS as V, TIME_UNITS as W, isOperator as X, isNumericType as Y, isTemporalType as Z, DISPLAY_NAME_FIELDS as _, createSchemaProxyHandler as a, fieldSchemaOverride as b, toSchemaProperties as c, SgApiError as d, batchResults as f, normalizeHierarchyNode as g, normalizeEventLogEntry as h, SchemaApiError as i, isBlankCondition as j, fromWire as k, EVENT_LOG_FIELDS as l, hierarchyEntity as m, RestSchemaClient as n, fieldFromRaw as o, eventLogFilters as p, isFilterable as q, SCHEMA_PROXY_METHODS as r, isSchemaProxyMethod as s, ProxySchemaClient as t, RestClient as u, FIELD_SCHEMA_OVERRIDES as v, statusFieldNameFor as w, normalizeField as x, displayNameOf as y, predictFieldName as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sg-widgets-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Headless, framework-agnostic model of Flow Production Tracking (ShotGrid) fields, filters, statuses and a client adapter, for building widgets.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"shotgrid",
|