@lotics/app-sdk 0.114.0 → 0.115.1
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 +1016 -600
- package/dist/shared_types.d.ts +1 -1
- package/docs/members_and_options.md +3 -3
- package/docs/mutations.md +2 -3
- package/docs/queries.md +13 -6
- package/docs/workflows.md +13 -14
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -21561,6 +21561,180 @@ function validateFieldTypeForOperation(fieldType, operation, subject) {
|
|
|
21561
21561
|
throw new Error(`Operation '${operation}' is not valid for field type '${fieldType}'`);
|
|
21562
21562
|
}
|
|
21563
21563
|
|
|
21564
|
+
// ../shared/src/schemas/iam.ts
|
|
21565
|
+
var jsonSchemaSchema = zod_default.string();
|
|
21566
|
+
var organizationSchema = zod_default.object({
|
|
21567
|
+
id: zod_default.string().describe("Unique identifier for the organization"),
|
|
21568
|
+
name: zod_default.string().describe("Display name of the organization"),
|
|
21569
|
+
slug: zod_default.string().nullable().describe("Slug for the organization")
|
|
21570
|
+
});
|
|
21571
|
+
var memberAccountTypeSchema = zod_default.enum(["self_managed", "admin_managed", "service"]).describe(
|
|
21572
|
+
"How the account is credentialed. admin_managed means an admin chose the sign-in name and set the password; the account has NO email address at all, so nothing can be mailed to it until the member claims one they control. service means no credential exists at all \u2014 the membership is an integration's identity, reached only by an API key bound to it."
|
|
21573
|
+
);
|
|
21574
|
+
var ALL_ACCOUNT_TYPES = memberAccountTypeSchema.options;
|
|
21575
|
+
var memberSchema = zod_default.object({
|
|
21576
|
+
member_id: zod_default.string().describe("Unique identifier for the member"),
|
|
21577
|
+
organization_id: zod_default.string().describe("Organization ID the member belongs to"),
|
|
21578
|
+
name: zod_default.string().describe("Display name of the member"),
|
|
21579
|
+
email_address: zod_default.string().nullable().describe(
|
|
21580
|
+
"What the member types to sign in: an email address for a self-managed member, an administrator-issued name (e.g. giamdoc.sunrise) for an admin-managed one. The latter is NOT an address and cannot receive mail \u2014 the field name predates the split. Null for a service identity, which holds no credential and signs in nowhere."
|
|
21581
|
+
),
|
|
21582
|
+
role: zod_default.enum(["owner", "admin", "member"]).describe("Organization role"),
|
|
21583
|
+
image: zod_default.string().nullable().optional().describe("URL to the member's profile picture"),
|
|
21584
|
+
account_type: memberAccountTypeSchema,
|
|
21585
|
+
archived: zod_default.boolean().optional().describe(
|
|
21586
|
+
"True when this person has been removed from the organization. The membership survives removal so records naming them keep resolving; it grants nothing. Optional because an older server omits it \u2014 absent means active."
|
|
21587
|
+
),
|
|
21588
|
+
joined_at: zod_default.string().optional().describe(
|
|
21589
|
+
"ISO timestamp of when this membership began. Optional because an older server omits it \u2014 absent means not told, never 'joined at the epoch'."
|
|
21590
|
+
)
|
|
21591
|
+
});
|
|
21592
|
+
var pendingInvitationSchema = zod_default.object({
|
|
21593
|
+
invitation_id: zod_default.string().describe("Unique identifier for the pending invitation"),
|
|
21594
|
+
organization_id: zod_default.string().describe("Organization the invitee will join on accept"),
|
|
21595
|
+
email: zod_default.string().describe("Email the invitation was sent to"),
|
|
21596
|
+
name: zod_default.string().nullable().describe("Admin-supplied display name (carried onto member.name on accept; invitee can override at accept time)"),
|
|
21597
|
+
role: zod_default.enum(["owner", "admin", "member"]).describe("Role the invitee will receive on accept"),
|
|
21598
|
+
expires_at: zod_default.string().describe("ISO timestamp when the invitation expires")
|
|
21599
|
+
});
|
|
21600
|
+
var ianaTimezoneSchema = zod_default.string().refine(
|
|
21601
|
+
(tz) => {
|
|
21602
|
+
try {
|
|
21603
|
+
new Intl.DateTimeFormat("en-US", { timeZone: tz });
|
|
21604
|
+
return true;
|
|
21605
|
+
} catch {
|
|
21606
|
+
return false;
|
|
21607
|
+
}
|
|
21608
|
+
},
|
|
21609
|
+
{ message: "must be an IANA timezone name, e.g. Asia/Ho_Chi_Minh or America/New_York" }
|
|
21610
|
+
).describe("IANA timezone name (e.g., 'America/New_York', 'Asia/Ho_Chi_Minh')");
|
|
21611
|
+
var currencyCodeSchema = zod_default.string().trim().toUpperCase().regex(/^[A-Z]{3}$/, "must be an ISO 4217 currency code, e.g. VND, USD, EUR").describe("ISO 4217 currency code (e.g. 'VND', 'USD', 'EUR'). Upper-cased.");
|
|
21612
|
+
var workspaceSchema = zod_default.object({
|
|
21613
|
+
id: zod_default.string().describe("Unique identifier for the workspace"),
|
|
21614
|
+
name: zod_default.string().describe("Display name of the workspace"),
|
|
21615
|
+
default_currency: zod_default.string().describe("Default currency code for the workspace"),
|
|
21616
|
+
// Plain string on the way OUT, deliberately. This is a response schema, so
|
|
21617
|
+
// validating here would make the server reject its own stored rows — and on
|
|
21618
|
+
// the workspace LIST one bad row fails the entire array. The zone is enforced
|
|
21619
|
+
// where it is written; a read is too late to do anything about it anyway.
|
|
21620
|
+
timezone: zod_default.string().describe("IANA timezone name (e.g., 'America/New_York', 'Asia/Ho_Chi_Minh')"),
|
|
21621
|
+
organization_id: zod_default.string().describe("Organization ID this workspace belongs to"),
|
|
21622
|
+
created_at: zod_default.string().describe("Timestamp when workspace was created")
|
|
21623
|
+
});
|
|
21624
|
+
var memberGroupSchema = zod_default.object({
|
|
21625
|
+
id: zod_default.string().describe("Unique identifier for the member group"),
|
|
21626
|
+
name: zod_default.string().describe("Display name of the group"),
|
|
21627
|
+
description: zod_default.string().optional().describe("Optional description of the group's purpose"),
|
|
21628
|
+
member_ids: zod_default.array(zod_default.string()).describe("Array of member IDs in this group"),
|
|
21629
|
+
invitation_ids: zod_default.array(zod_default.string()).describe("Array of pending invitation IDs pre-granted membership; migrated to member_ids on accept"),
|
|
21630
|
+
organization_id: zod_default.string().describe("ID of the organization this group belongs to"),
|
|
21631
|
+
created_at: zod_default.string().describe("Timestamp when group was created"),
|
|
21632
|
+
created_by: zod_default.string().describe("Member ID of the user who created this group")
|
|
21633
|
+
});
|
|
21634
|
+
var principalGroupSchema = zod_default.object({
|
|
21635
|
+
id: zod_default.string().describe("Unique identifier for the member group"),
|
|
21636
|
+
name: zod_default.string().describe("Display name of the group"),
|
|
21637
|
+
description: zod_default.string().optional().describe("Optional description of the group's purpose"),
|
|
21638
|
+
member_count: zod_default.number().int().describe("Number of accepted members in the group"),
|
|
21639
|
+
invitation_count: zod_default.number().int().describe("Number of pending invitations pre-granted membership")
|
|
21640
|
+
});
|
|
21641
|
+
var PUBLIC_PRINCIPAL_ID = "public";
|
|
21642
|
+
var principalSchema = zod_default.discriminatedUnion("type", [
|
|
21643
|
+
zod_default.object({
|
|
21644
|
+
type: zod_default.literal("member").describe("Principal type: individual member"),
|
|
21645
|
+
id: zod_default.string().describe("Member ID")
|
|
21646
|
+
}),
|
|
21647
|
+
zod_default.object({
|
|
21648
|
+
type: zod_default.literal("member_group").describe("Principal type: group of members"),
|
|
21649
|
+
id: zod_default.string().describe("Member group ID")
|
|
21650
|
+
}),
|
|
21651
|
+
zod_default.object({
|
|
21652
|
+
type: zod_default.literal("organization").describe("Principal type: all members in organization"),
|
|
21653
|
+
id: zod_default.string().describe("Organization ID")
|
|
21654
|
+
}),
|
|
21655
|
+
zod_default.object({
|
|
21656
|
+
type: zod_default.literal("public").describe("Principal type: anyone, including unauthenticated visitors"),
|
|
21657
|
+
id: zod_default.literal(PUBLIC_PRINCIPAL_ID).describe("Always the `public` sentinel \u2014 no entity")
|
|
21658
|
+
}),
|
|
21659
|
+
// Pending invitation as principal: lets admins pre-grant group membership and
|
|
21660
|
+
// resource access before the invitee accepts. Never resolved as a Subject —
|
|
21661
|
+
// a pending invitee cannot authenticate, so these bindings stay dormant until
|
|
21662
|
+
// accept-time migration rewrites them to type:"member".
|
|
21663
|
+
zod_default.object({
|
|
21664
|
+
type: zod_default.literal("invitation").describe("Principal type: pending invitation (not yet accepted)"),
|
|
21665
|
+
id: zod_default.string().describe("Invitation ID")
|
|
21666
|
+
})
|
|
21667
|
+
]);
|
|
21668
|
+
var subjectSchema = zod_default.discriminatedUnion("type", [
|
|
21669
|
+
zod_default.object({
|
|
21670
|
+
type: zod_default.literal("member").describe("Subject type: authenticated member"),
|
|
21671
|
+
id: zod_default.string().describe("Member ID")
|
|
21672
|
+
}),
|
|
21673
|
+
zod_default.object({
|
|
21674
|
+
type: zod_default.literal("public").describe("Subject type: unauthenticated visitor")
|
|
21675
|
+
})
|
|
21676
|
+
]);
|
|
21677
|
+
var resourceTypeSchema = zod_default.enum(["table", "table_view", "app", "automation", "skill", "document_template", "instruction", "knowledge_doc", "connected_account"]);
|
|
21678
|
+
var RESOURCE_ROLE_ACTIONS = {
|
|
21679
|
+
table: {
|
|
21680
|
+
editor: ["read_data", "write_data"],
|
|
21681
|
+
viewer: ["read_data"]
|
|
21682
|
+
},
|
|
21683
|
+
app: { manager: ["use", "manage"], user: ["use"] },
|
|
21684
|
+
skill: { manager: ["use", "manage"], user: ["use"] },
|
|
21685
|
+
document_template: { manager: ["use", "manage"], user: ["use"] },
|
|
21686
|
+
instruction: { manager: ["use", "manage"], user: ["use"] },
|
|
21687
|
+
knowledge_doc: { manager: ["use", "manage"], user: ["use"] },
|
|
21688
|
+
connected_account: { manager: ["use", "manage"], user: ["use"] },
|
|
21689
|
+
table_view: {},
|
|
21690
|
+
automation: {}
|
|
21691
|
+
};
|
|
21692
|
+
function shareableRolesFor(type) {
|
|
21693
|
+
return Object.keys(RESOURCE_ROLE_ACTIONS[type]);
|
|
21694
|
+
}
|
|
21695
|
+
var SHAREABLE_RESOURCE_TYPES = resourceTypeSchema.options.filter(
|
|
21696
|
+
(type) => shareableRolesFor(type).length > 0
|
|
21697
|
+
);
|
|
21698
|
+
var accessPrincipalSchema = zod_default.discriminatedUnion("type", [
|
|
21699
|
+
zod_default.object({
|
|
21700
|
+
type: zod_default.literal("member").describe("Principal type: an individual member"),
|
|
21701
|
+
id: zod_default.string().describe("Member ID")
|
|
21702
|
+
}),
|
|
21703
|
+
zod_default.object({
|
|
21704
|
+
type: zod_default.literal("member_group").describe("Principal type: a member group"),
|
|
21705
|
+
id: zod_default.string().describe("Group ID")
|
|
21706
|
+
}),
|
|
21707
|
+
zod_default.object({
|
|
21708
|
+
type: zod_default.literal("organization").describe("Principal type: everyone in the organization"),
|
|
21709
|
+
id: zod_default.string().describe("Organization ID")
|
|
21710
|
+
})
|
|
21711
|
+
]);
|
|
21712
|
+
var resourceAccessSchema = zod_default.object({
|
|
21713
|
+
resource_id: zod_default.string().describe("ID of the resource these principals can reach"),
|
|
21714
|
+
principals: zod_default.array(accessPrincipalSchema).describe("Members, groups and the organization that have been granted access")
|
|
21715
|
+
});
|
|
21716
|
+
var contentResourceTypeSchema = zod_default.enum(["knowledge_doc", "document_template"]);
|
|
21717
|
+
var contentItemSchema = zod_default.object({
|
|
21718
|
+
id: zod_default.string().describe("ID of the knowledge doc or template"),
|
|
21719
|
+
name: zod_default.string().describe("Its name"),
|
|
21720
|
+
owner_member_id: zod_default.string().nullable().describe("Member who owns it; null when nobody does"),
|
|
21721
|
+
created_at: zod_default.string().describe("When it was created"),
|
|
21722
|
+
updated_at: zod_default.string().nullable().describe("When a knowledge doc was last changed; null for a template"),
|
|
21723
|
+
hidden_at: zod_default.string().nullable().describe("When a knowledge doc was hidden; null when it is in use, and for a template"),
|
|
21724
|
+
template_type: zod_default.string().nullable().describe("A template's type (html, email, word, excel, pdf-form); null for a knowledge doc"),
|
|
21725
|
+
can_open: zod_default.boolean().describe("Whether the caller may open it; false means it is not shared with them"),
|
|
21726
|
+
principals: zod_default.array(accessPrincipalSchema).describe("Members, groups and the organization it has been shared with, besides its owner")
|
|
21727
|
+
});
|
|
21728
|
+
var resourceRoleBindingSchema = zod_default.object({
|
|
21729
|
+
id: zod_default.string().describe("Unique identifier for the role binding"),
|
|
21730
|
+
principal: principalSchema.describe(
|
|
21731
|
+
"Who this role binding applies to (member, group, or organization)"
|
|
21732
|
+
),
|
|
21733
|
+
resource_type: resourceTypeSchema.describe("Type of resource being accessed"),
|
|
21734
|
+
resource_id: zod_default.string().describe("ID of the specific resource"),
|
|
21735
|
+
role: zod_default.string().describe("Role name (e.g., 'viewer', 'editor', 'manager', 'user')")
|
|
21736
|
+
});
|
|
21737
|
+
|
|
21564
21738
|
// ../shared/src/number_unit.ts
|
|
21565
21739
|
var MEASURED_UNITS = [
|
|
21566
21740
|
{ code: "g", dimension: "mass", factor: 1, label: { vi: "g", en: "g" }, scales: true, spellings: ["gram", "grams", "gam"] },
|
|
@@ -21579,9 +21753,11 @@ var MEASURED_UNITS = [
|
|
|
21579
21753
|
{ code: "day", dimension: "duration", factor: 1440, label: { vi: "ng\xE0y", en: "d" }, scales: true, spellings: ["days"] }
|
|
21580
21754
|
];
|
|
21581
21755
|
var COUNTED_UNIT_MAX_LENGTH = 12;
|
|
21582
|
-
var
|
|
21756
|
+
var UNIT_WORDS = `a measured code (${MEASURED_UNITS.map((unit) => unit.code).join(", ")}), which converts and scales within its dimension, or any other noun of at most ${COUNTED_UNIT_MAX_LENGTH} characters (ki\u1EC7n, pallet, TEU), which never does`;
|
|
21757
|
+
var UNIT_DESCRIPTION = `What a plain figure counts or measures, drawn after it: ${UNIT_WORDS}. Only beside format "number".`;
|
|
21583
21758
|
var UNIT_FIELD_DESCRIPTION = 'A single select on the same row, or a lookup of one through a one-link, whose chosen option is that row\'s unit: every option label is a unit as `unit` takes one. In place of `unit`; only beside format "number".';
|
|
21584
21759
|
var CURRENCY_FIELD_DESCRIPTION = 'A single select on the same row, or a lookup of one through a one-link, whose chosen option is that row\'s currency: every option label is an ISO 4217 code. In place of `currency`; only beside format "currency".';
|
|
21760
|
+
var DEFAULT_CURRENCY = "VND";
|
|
21585
21761
|
function unitKey(text2) {
|
|
21586
21762
|
return text2.normalize("NFC").trim().toLocaleLowerCase("vi").replace(/\s+/g, " ");
|
|
21587
21763
|
}
|
|
@@ -21619,88 +21795,151 @@ function numberUnitRefusal(format2, unit) {
|
|
|
21619
21795
|
if (format2 !== void 0 && format2 !== "number") {
|
|
21620
21796
|
return `a unit is for a plain figure (format "number"), not "${format2}": money states its currency and a percent its sign`;
|
|
21621
21797
|
}
|
|
21798
|
+
return unitRefusalWords(unit);
|
|
21799
|
+
}
|
|
21800
|
+
function unitRefusalWords(unit) {
|
|
21622
21801
|
const refusal = unitRefusal(unit);
|
|
21623
21802
|
return refusal === void 0 ? void 0 : refusalWords(unit, refusal);
|
|
21624
21803
|
}
|
|
21625
|
-
|
|
21626
|
-
|
|
21627
|
-
|
|
21628
|
-
|
|
21629
|
-
|
|
21630
|
-
|
|
21631
|
-
|
|
21632
|
-
|
|
21633
|
-
|
|
21634
|
-
return
|
|
21804
|
+
function currencyCodeRefusal(code) {
|
|
21805
|
+
if (Intl.supportedValuesOf("currency").includes(code)) return void 0;
|
|
21806
|
+
const coded = currencyCodeOf(code);
|
|
21807
|
+
return coded !== void 0 ? `a currency is written as its ISO 4217 code: "${coded}"` : `"${code}" is not an ISO 4217 currency code (USD, EUR, VND)`;
|
|
21808
|
+
}
|
|
21809
|
+
var DONG_SPELLINGS = ["vn\u0111", "\u0111", "\u20AB", "\u0111\u1ED3ng"];
|
|
21810
|
+
function currencyCodeOf(written) {
|
|
21811
|
+
const upper2 = written.trim().toUpperCase();
|
|
21812
|
+
if (Intl.supportedValuesOf("currency").includes(upper2)) return upper2;
|
|
21813
|
+
return DONG_SPELLINGS.includes(unitKey(written)) ? "VND" : void 0;
|
|
21814
|
+
}
|
|
21815
|
+
var EXACT_DIGITS = 15;
|
|
21816
|
+
function convert(value, from, to) {
|
|
21817
|
+
return from.code === to.code ? value : Number((value * from.factor / to.factor).toPrecision(EXACT_DIGITS));
|
|
21818
|
+
}
|
|
21819
|
+
function scaleIn(own, pack) {
|
|
21820
|
+
const kin = MEASURED_UNITS.filter((one) => one.dimension === own.dimension);
|
|
21821
|
+
const rung = (one) => ({ label: one.label[pack], factor: convert(1, one, own) });
|
|
21822
|
+
const names = (one) => [...SPELLED].filter(([, spelled]) => spelled.code === one.code).map(([name]) => name);
|
|
21823
|
+
return {
|
|
21824
|
+
label: own.label[pack],
|
|
21825
|
+
ladder: own.scales ? kin.filter((one) => one.scales && one.factor >= own.factor).map(rung) : [rung(own)],
|
|
21826
|
+
entries: [own, ...kin.filter((one) => one.code !== own.code)].map((one) => ({ ...rung(one), names: names(one) }))
|
|
21827
|
+
};
|
|
21635
21828
|
}
|
|
21829
|
+
var SCALES = new Map(
|
|
21830
|
+
MEASURED_UNITS.map((unit) => [unit.code, { vi: scaleIn(unit, "vi"), en: scaleIn(unit, "en") }])
|
|
21831
|
+
);
|
|
21636
21832
|
|
|
21637
|
-
// ../shared/src/
|
|
21638
|
-
|
|
21639
|
-
|
|
21640
|
-
|
|
21641
|
-
|
|
21833
|
+
// ../shared/src/notation.ts
|
|
21834
|
+
var PERCENT = "percent";
|
|
21835
|
+
var DECIMAL = { style: "decimal" };
|
|
21836
|
+
var NOTATION_DESCRIPTION = `How the figure reads: { "style": "decimal" }; money, { "style": "currency", "currency": an ISO 4217 code (USD, VND) }; or a quantity, { "style": "unit", "unit": "${PERCENT}" (10 reads "10%"), or ${UNIT_WORDS} }. A currency or unit read on each row from a single select of that row is { "per_row": that select }.`;
|
|
21837
|
+
function unitIssue(unit, ctx) {
|
|
21838
|
+
const refused = unit === PERCENT ? void 0 : unitRefusalWords(unit);
|
|
21839
|
+
if (refused !== void 0) ctx.addIssue({ code: "custom", message: refused });
|
|
21642
21840
|
}
|
|
21643
|
-
function
|
|
21841
|
+
function notationSchemaOf(reference) {
|
|
21842
|
+
const perRow = external_exports.object({ per_row: reference.describe("The single select of the same row whose option is each row's currency or unit") }).strict();
|
|
21843
|
+
return external_exports.discriminatedUnion("style", [
|
|
21844
|
+
external_exports.object({ style: external_exports.literal("decimal") }).strict(),
|
|
21845
|
+
external_exports.object({ style: external_exports.literal("currency"), currency: external_exports.union([external_exports.string().min(1), perRow]) }).strict(),
|
|
21846
|
+
external_exports.object({ style: external_exports.literal("unit"), unit: external_exports.union([external_exports.string().superRefine(unitIssue), perRow]) }).strict()
|
|
21847
|
+
]).describe(NOTATION_DESCRIPTION);
|
|
21848
|
+
}
|
|
21849
|
+
var notationSchema = notationSchemaOf(external_exports.string().min(1));
|
|
21850
|
+
function notationOfKeys(keys2) {
|
|
21851
|
+
if (keys2.format === "currency") {
|
|
21852
|
+
return { style: "currency", currency: keys2.currency_field ? { per_row: keys2.currency_field } : keys2.currency || DEFAULT_CURRENCY };
|
|
21853
|
+
}
|
|
21854
|
+
if (keys2.unit_field) return { style: "unit", unit: { per_row: keys2.unit_field } };
|
|
21855
|
+
if (keys2.unit) return { style: "unit", unit: keys2.unit };
|
|
21856
|
+
if (keys2.format === "percentage") return { style: "unit", unit: PERCENT };
|
|
21857
|
+
return DECIMAL;
|
|
21858
|
+
}
|
|
21859
|
+
var KEYS_BEFORE_NOTATION = ["format", "currency", "unit", "unit_field", "currency_field"];
|
|
21860
|
+
function keysStated(keys2) {
|
|
21861
|
+
return KEYS_BEFORE_NOTATION.some((key) => Boolean(keys2[key]));
|
|
21862
|
+
}
|
|
21863
|
+
function sameValue(a, b) {
|
|
21864
|
+
return typeof a === "string" || typeof b === "string" ? a === b : a.per_row === b.per_row;
|
|
21865
|
+
}
|
|
21866
|
+
function sameNotation(a, b) {
|
|
21867
|
+
if (a === void 0 || b === void 0) return a === b;
|
|
21868
|
+
if (a.style === "currency" && b.style === "currency") return sameValue(a.currency, b.currency);
|
|
21869
|
+
if (a.style === "unit" && b.style === "unit") return sameValue(a.unit, b.unit);
|
|
21870
|
+
return a.style === "decimal" && b.style === "decimal";
|
|
21871
|
+
}
|
|
21872
|
+
function storedNotation(notation, keys2) {
|
|
21873
|
+
if (notation == null) return notationOfKeys(keys2);
|
|
21874
|
+
if (!keysStated(keys2)) return notation;
|
|
21875
|
+
const derived = notationOfKeys(keys2);
|
|
21876
|
+
return sameNotation(notation, derived) ? notation : derived;
|
|
21877
|
+
}
|
|
21878
|
+
function fieldNotation(field) {
|
|
21644
21879
|
switch (field.type) {
|
|
21645
21880
|
case "number":
|
|
21646
|
-
return
|
|
21881
|
+
return storedNotation(field.notation, field);
|
|
21647
21882
|
case "formula": {
|
|
21648
|
-
const
|
|
21649
|
-
|
|
21883
|
+
const formula = field.formula;
|
|
21884
|
+
const output = formula?.output_type;
|
|
21885
|
+
return output == null || output === "number" ? storedNotation(formula?.notation, formula ?? {}) : void 0;
|
|
21650
21886
|
}
|
|
21651
21887
|
case "rollup": {
|
|
21652
21888
|
const operation = field.aggregate_option?.operation;
|
|
21653
|
-
|
|
21889
|
+
if (!isAggregateOperation(operation) || rollupOutputType(operation) !== "number") return void 0;
|
|
21890
|
+
return storedNotation(field.aggregate_field_notation, {
|
|
21891
|
+
format: field.aggregate_field_format,
|
|
21892
|
+
currency: field.aggregate_field_currency,
|
|
21893
|
+
unit: field.aggregate_field_unit,
|
|
21894
|
+
unit_field: field.aggregate_field_unit_field,
|
|
21895
|
+
currency_field: field.aggregate_field_currency_field
|
|
21896
|
+
});
|
|
21654
21897
|
}
|
|
21898
|
+
case "lookup":
|
|
21899
|
+
return field.lookup_field_type === "number" ? storedNotation(field.lookup_field_notation, { format: field.lookup_field_format, currency: field.lookup_field_currency, unit: field.lookup_field_unit }) : void 0;
|
|
21655
21900
|
default:
|
|
21656
21901
|
return void 0;
|
|
21657
21902
|
}
|
|
21658
21903
|
}
|
|
21659
|
-
function
|
|
21660
|
-
if (
|
|
21661
|
-
|
|
21662
|
-
if (typeof entry === "string") return entry;
|
|
21663
|
-
const inner = firstOptionKey(entry);
|
|
21664
|
-
if (inner !== void 0) return inner;
|
|
21665
|
-
}
|
|
21904
|
+
function notationRowSelect(notation) {
|
|
21905
|
+
if (notation?.style === "currency" && typeof notation.currency !== "string") return { vocabulary: "currency", key: notation.currency.per_row };
|
|
21906
|
+
if (notation?.style === "unit" && typeof notation.unit !== "string") return { vocabulary: "unit", key: notation.unit.per_row };
|
|
21666
21907
|
return void 0;
|
|
21667
21908
|
}
|
|
21668
|
-
function
|
|
21669
|
-
return
|
|
21909
|
+
function notationCurrency(notation) {
|
|
21910
|
+
return notation?.style === "currency" && typeof notation.currency === "string" ? notation.currency : void 0;
|
|
21670
21911
|
}
|
|
21671
|
-
function
|
|
21672
|
-
return
|
|
21912
|
+
function notationSaid(figure) {
|
|
21913
|
+
return { stated: figure.notation ?? void 0, byKeys: keysStated(figure) ? notationOfKeys(figure) : void 0, keys: figure };
|
|
21673
21914
|
}
|
|
21674
|
-
function
|
|
21675
|
-
|
|
21676
|
-
const stated = condition2.unit_option;
|
|
21677
|
-
const read2 = figureRowSelect(field);
|
|
21678
|
-
if (read2 === void 0) {
|
|
21679
|
-
return stated === void 0 ? { ok: true, unit: void 0 } : { ok: false, reason: `${nameOf(field)} is read in one unit for every row, so a condition on it states no unit_option.` };
|
|
21680
|
-
}
|
|
21681
|
-
const select = fieldOf2(read2.key);
|
|
21682
|
-
const options = effectiveSelectOptions(select) ?? [];
|
|
21683
|
-
const held2 = options.length === 0 ? `${select === void 0 ? `"${read2.key}"` : nameOf(select)} holds no ${read2.vocabulary} yet` : `one of ${options.map((option2) => `${option2.name} (${option2.key})`).join(", ")}`;
|
|
21684
|
-
const reads = `${nameOf(field)} is read in each row's own ${read2.vocabulary} (${select === void 0 ? `"${read2.key}"` : nameOf(select)})`;
|
|
21685
|
-
if (stated === void 0) {
|
|
21686
|
-
const unstated = condition2.value === null || condition2.value === void 0 || condition2.value === "";
|
|
21687
|
-
return unstated ? { ok: true, unit: void 0 } : { ok: false, reason: `${reads}, so '${condition2.operator}' states the ${read2.vocabulary} its value is in as unit_option: ${held2}.` };
|
|
21688
|
-
}
|
|
21689
|
-
const option = typeof stated === "string" ? options.find((candidate) => candidate.key === stated) : void 0;
|
|
21690
|
-
if (option === void 0) {
|
|
21691
|
-
return { ok: false, reason: `${reads}; unit_option ${JSON.stringify(stated)} is none of them: ${held2}.` };
|
|
21692
|
-
}
|
|
21693
|
-
const target = read2.vocabulary === "unit" ? measuredUnit(option.name) : void 0;
|
|
21694
|
-
if (target === void 0) return { ok: true, unit: { select: read2, options: [{ key: option.key, factor: 1 }], factor: 1 } };
|
|
21695
|
-
const kin = options.flatMap((candidate) => {
|
|
21696
|
-
const measured = measuredUnit(candidate.name);
|
|
21697
|
-
return measured?.dimension === target.dimension ? [{ key: candidate.key, factor: measured.factor }] : [];
|
|
21698
|
-
});
|
|
21699
|
-
return { ok: true, unit: { select: read2, options: kin, factor: target.factor } };
|
|
21915
|
+
function sameReading(a, b) {
|
|
21916
|
+
return a === "link" || b === "link" ? a === b : sameNotation(a, b);
|
|
21700
21917
|
}
|
|
21701
|
-
function
|
|
21702
|
-
|
|
21703
|
-
|
|
21918
|
+
function readingWords(reading) {
|
|
21919
|
+
return reading === "link" ? "a link" : JSON.stringify(reading);
|
|
21920
|
+
}
|
|
21921
|
+
function settledReading(written, stored) {
|
|
21922
|
+
const held2 = stored === void 0 ? void 0 : stored.byKeys ?? stored.stated;
|
|
21923
|
+
const { stated, byKeys } = written;
|
|
21924
|
+
const parted = partedReadings(written);
|
|
21925
|
+
if (parted === void 0) return checkedReading(stated ?? byKeys ?? held2, held2);
|
|
21926
|
+
const changed2 = stored === void 0 ? void 0 : sameReading(stated, stored.stated) ? byKeys : sameReading(byKeys, stored.byKeys) ? stated : void 0;
|
|
21927
|
+
return changed2 === void 0 ? { refusal: parted } : checkedReading(changed2, held2);
|
|
21928
|
+
}
|
|
21929
|
+
function partedReadings(written) {
|
|
21930
|
+
const { stated, byKeys } = written;
|
|
21931
|
+
if (stated === void 0 || byKeys === void 0 || sameReading(stated, byKeys)) return void 0;
|
|
21932
|
+
const key = stated === "link" ? "link" : "notation";
|
|
21933
|
+
const keys2 = KEYS_BEFORE_NOTATION.flatMap((name) => written.keys[name] ? [`${name} ${JSON.stringify(written.keys[name])}`] : []);
|
|
21934
|
+
return `"${key}" says ${readingWords(stated)} and ${keys2.join(", ")} say ${readingWords(byKeys)} \u2014 state "${key}" alone`;
|
|
21935
|
+
}
|
|
21936
|
+
function checkedReading(reading, held2) {
|
|
21937
|
+
const refused = changedCurrencyRefusal(reading, held2);
|
|
21938
|
+
return refused === void 0 ? { reading } : { refusal: refused };
|
|
21939
|
+
}
|
|
21940
|
+
function changedCurrencyRefusal(reading, held2) {
|
|
21941
|
+
const currency = reading === "link" || sameReading(reading, held2) ? void 0 : notationCurrency(reading);
|
|
21942
|
+
return currency === void 0 ? void 0 : currencyCodeRefusal(currency);
|
|
21704
21943
|
}
|
|
21705
21944
|
|
|
21706
21945
|
// ../shared/src/icon_names.generated.ts
|
|
@@ -23625,7 +23864,11 @@ var KIT_GLYPH_NAMES = [
|
|
|
23625
23864
|
"align-center",
|
|
23626
23865
|
"align-left",
|
|
23627
23866
|
"align-right",
|
|
23867
|
+
"align-vertical-justify-center",
|
|
23868
|
+
"align-vertical-justify-end",
|
|
23869
|
+
"align-vertical-justify-start",
|
|
23628
23870
|
"arrow-down",
|
|
23871
|
+
"arrow-down-a-z",
|
|
23629
23872
|
"arrow-down-up",
|
|
23630
23873
|
"arrow-down-wide-narrow",
|
|
23631
23874
|
"arrow-left",
|
|
@@ -23636,10 +23879,13 @@ var KIT_GLYPH_NAMES = [
|
|
|
23636
23879
|
"arrow-up",
|
|
23637
23880
|
"arrow-up-down",
|
|
23638
23881
|
"arrow-up-wide-narrow",
|
|
23882
|
+
"arrow-up-z-a",
|
|
23639
23883
|
"ban",
|
|
23640
23884
|
"banknote",
|
|
23641
23885
|
"bed",
|
|
23642
23886
|
"bell",
|
|
23887
|
+
"between-horizontal-start",
|
|
23888
|
+
"between-vertical-start",
|
|
23643
23889
|
"bold",
|
|
23644
23890
|
"bolt",
|
|
23645
23891
|
"book-marked",
|
|
@@ -23667,17 +23913,23 @@ var KIT_GLYPH_NAMES = [
|
|
|
23667
23913
|
"chevrons-up-down",
|
|
23668
23914
|
"circle-alert",
|
|
23669
23915
|
"circle-check",
|
|
23916
|
+
"circle-x",
|
|
23670
23917
|
"clipboard-list",
|
|
23918
|
+
"clipboard-paste",
|
|
23671
23919
|
"clock",
|
|
23672
23920
|
"code",
|
|
23673
23921
|
"code-xml",
|
|
23674
23922
|
"columns-3",
|
|
23675
23923
|
"columns-3-cog",
|
|
23924
|
+
"combine",
|
|
23676
23925
|
"construction",
|
|
23677
23926
|
"container",
|
|
23678
23927
|
"copy",
|
|
23679
23928
|
"credit-card",
|
|
23680
23929
|
"database",
|
|
23930
|
+
"decimals-arrow-left",
|
|
23931
|
+
"decimals-arrow-right",
|
|
23932
|
+
"dollar-sign",
|
|
23681
23933
|
"download",
|
|
23682
23934
|
"ellipsis",
|
|
23683
23935
|
"eraser",
|
|
@@ -23704,9 +23956,11 @@ var KIT_GLYPH_NAMES = [
|
|
|
23704
23956
|
"gauge",
|
|
23705
23957
|
"globe",
|
|
23706
23958
|
"gpu",
|
|
23959
|
+
"grid-2x2",
|
|
23707
23960
|
"grip-vertical",
|
|
23708
23961
|
"group",
|
|
23709
23962
|
"hand-coins",
|
|
23963
|
+
"hash",
|
|
23710
23964
|
"heading",
|
|
23711
23965
|
"heading-1",
|
|
23712
23966
|
"heading-2",
|
|
@@ -23759,6 +24013,7 @@ var KIT_GLYPH_NAMES = [
|
|
|
23759
24013
|
"notepad-text-dashed",
|
|
23760
24014
|
"package",
|
|
23761
24015
|
"paint-bucket",
|
|
24016
|
+
"paintbrush-vertical",
|
|
23762
24017
|
"palette",
|
|
23763
24018
|
"panel-left",
|
|
23764
24019
|
"panel-left-close",
|
|
@@ -23769,6 +24024,7 @@ var KIT_GLYPH_NAMES = [
|
|
|
23769
24024
|
"paperclip",
|
|
23770
24025
|
"pause",
|
|
23771
24026
|
"pencil",
|
|
24027
|
+
"percent",
|
|
23772
24028
|
"phone",
|
|
23773
24029
|
"pin",
|
|
23774
24030
|
"pin-off",
|
|
@@ -23783,7 +24039,9 @@ var KIT_GLYPH_NAMES = [
|
|
|
23783
24039
|
"repeat",
|
|
23784
24040
|
"rotate-ccw",
|
|
23785
24041
|
"rotate-cw",
|
|
24042
|
+
"rows-3",
|
|
23786
24043
|
"scan",
|
|
24044
|
+
"scissors",
|
|
23787
24045
|
"search",
|
|
23788
24046
|
"send",
|
|
23789
24047
|
"settings",
|
|
@@ -23793,9 +24051,11 @@ var KIT_GLYPH_NAMES = [
|
|
|
23793
24051
|
"shield-alert",
|
|
23794
24052
|
"shield-check",
|
|
23795
24053
|
"shopping-cart",
|
|
24054
|
+
"sigma",
|
|
23796
24055
|
"sliders-horizontal",
|
|
23797
24056
|
"smile",
|
|
23798
24057
|
"smile-plus",
|
|
24058
|
+
"snowflake",
|
|
23799
24059
|
"sparkles",
|
|
23800
24060
|
"split",
|
|
23801
24061
|
"square",
|
|
@@ -23804,11 +24064,13 @@ var KIT_GLYPH_NAMES = [
|
|
|
23804
24064
|
"square-sigma",
|
|
23805
24065
|
"stethoscope",
|
|
23806
24066
|
"sticky-note",
|
|
24067
|
+
"strikethrough",
|
|
23807
24068
|
"table",
|
|
23808
24069
|
"table-2",
|
|
23809
24070
|
"tag",
|
|
23810
24071
|
"target",
|
|
23811
24072
|
"text-quote",
|
|
24073
|
+
"text-wrap",
|
|
23812
24074
|
"thumbs-down",
|
|
23813
24075
|
"thumbs-up",
|
|
23814
24076
|
"ticket",
|
|
@@ -23819,6 +24081,7 @@ var KIT_GLYPH_NAMES = [
|
|
|
23819
24081
|
"truck",
|
|
23820
24082
|
"tv-minimal",
|
|
23821
24083
|
"twitter",
|
|
24084
|
+
"type",
|
|
23822
24085
|
"underline",
|
|
23823
24086
|
"undo",
|
|
23824
24087
|
"upload",
|
|
@@ -23831,7 +24094,9 @@ var KIT_GLYPH_NAMES = [
|
|
|
23831
24094
|
"workflow",
|
|
23832
24095
|
"wrench",
|
|
23833
24096
|
"x",
|
|
23834
|
-
"zap"
|
|
24097
|
+
"zap",
|
|
24098
|
+
"zoom-in",
|
|
24099
|
+
"zoom-out"
|
|
23835
24100
|
];
|
|
23836
24101
|
|
|
23837
24102
|
// ../shared/src/icon_names.ts
|
|
@@ -23971,6 +24236,68 @@ function everyOptionMarked(nameOf2) {
|
|
|
23971
24236
|
};
|
|
23972
24237
|
}
|
|
23973
24238
|
|
|
24239
|
+
// ../shared/src/select_option_enrichment.ts
|
|
24240
|
+
function effectiveSelectOptions(field) {
|
|
24241
|
+
if (field === void 0) return null;
|
|
24242
|
+
if (field.type === "select") return field.options ?? null;
|
|
24243
|
+
if (field.type === "formula") return field.formula?.options ?? null;
|
|
24244
|
+
if (field.type === "lookup" && field.lookup_field_type === "select") {
|
|
24245
|
+
return field.lookup_field_options ?? null;
|
|
24246
|
+
}
|
|
24247
|
+
return null;
|
|
24248
|
+
}
|
|
24249
|
+
|
|
24250
|
+
// ../shared/src/row_figure.ts
|
|
24251
|
+
function figureRowSelect(field) {
|
|
24252
|
+
return notationRowSelect(fieldNotation(field));
|
|
24253
|
+
}
|
|
24254
|
+
function firstOptionKey(cell) {
|
|
24255
|
+
if (!Array.isArray(cell)) return void 0;
|
|
24256
|
+
for (const entry of cell) {
|
|
24257
|
+
if (typeof entry === "string") return entry;
|
|
24258
|
+
const inner = firstOptionKey(entry);
|
|
24259
|
+
if (inner !== void 0) return inner;
|
|
24260
|
+
}
|
|
24261
|
+
return void 0;
|
|
24262
|
+
}
|
|
24263
|
+
function comparesFigure(operator) {
|
|
24264
|
+
return operator !== "is_empty" && operator !== "is_not_empty";
|
|
24265
|
+
}
|
|
24266
|
+
function nameOf(field) {
|
|
24267
|
+
return `"${field.name ?? field.key}"`;
|
|
24268
|
+
}
|
|
24269
|
+
function conditionUnit(condition2, field, fieldOf2) {
|
|
24270
|
+
if (!comparesFigure(condition2.operator)) return { ok: true, unit: void 0 };
|
|
24271
|
+
const stated = condition2.unit_option;
|
|
24272
|
+
const read2 = figureRowSelect(field);
|
|
24273
|
+
if (read2 === void 0) {
|
|
24274
|
+
return stated === void 0 ? { ok: true, unit: void 0 } : { ok: false, reason: `${nameOf(field)} is read in one unit for every row, so a condition on it states no unit_option.` };
|
|
24275
|
+
}
|
|
24276
|
+
const select = fieldOf2(read2.key);
|
|
24277
|
+
const options = effectiveSelectOptions(select) ?? [];
|
|
24278
|
+
const held2 = options.length === 0 ? `${select === void 0 ? `"${read2.key}"` : nameOf(select)} holds no ${read2.vocabulary} yet` : `one of ${options.map((option2) => `${option2.name} (${option2.key})`).join(", ")}`;
|
|
24279
|
+
const reads = `${nameOf(field)} is read in each row's own ${read2.vocabulary} (${select === void 0 ? `"${read2.key}"` : nameOf(select)})`;
|
|
24280
|
+
if (stated === void 0) {
|
|
24281
|
+
const unstated = condition2.value === null || condition2.value === void 0 || condition2.value === "";
|
|
24282
|
+
return unstated ? { ok: true, unit: void 0 } : { ok: false, reason: `${reads}, so '${condition2.operator}' states the ${read2.vocabulary} its value is in as unit_option: ${held2}.` };
|
|
24283
|
+
}
|
|
24284
|
+
const option = typeof stated === "string" ? options.find((candidate) => candidate.key === stated) : void 0;
|
|
24285
|
+
if (option === void 0) {
|
|
24286
|
+
return { ok: false, reason: `${reads}; unit_option ${JSON.stringify(stated)} is none of them: ${held2}.` };
|
|
24287
|
+
}
|
|
24288
|
+
const target = read2.vocabulary === "unit" ? measuredUnit(option.name) : void 0;
|
|
24289
|
+
if (target === void 0) return { ok: true, unit: { select: read2, options: [{ key: option.key, factor: 1 }], factor: 1 } };
|
|
24290
|
+
const kin = options.flatMap((candidate) => {
|
|
24291
|
+
const measured = measuredUnit(candidate.name);
|
|
24292
|
+
return measured?.dimension === target.dimension ? [{ key: candidate.key, factor: measured.factor }] : [];
|
|
24293
|
+
});
|
|
24294
|
+
return { ok: true, unit: { select: read2, options: kin, factor: target.factor } };
|
|
24295
|
+
}
|
|
24296
|
+
function rowUnitFactor(unit, data) {
|
|
24297
|
+
const key = firstOptionKey(data[unit.select.key]);
|
|
24298
|
+
return key === void 0 ? void 0 : unit.options.find((option) => option.key === key)?.factor;
|
|
24299
|
+
}
|
|
24300
|
+
|
|
23974
24301
|
// ../shared/src/diacritics.ts
|
|
23975
24302
|
var COMBINING_MARKS = /[̀-ͯ]/g;
|
|
23976
24303
|
function foldDiacritics(value) {
|
|
@@ -24564,22 +24891,35 @@ function perRowRefusals(value) {
|
|
|
24564
24891
|
...currencyField.map((message2) => ({ key: "currency_field", message: message2 }))
|
|
24565
24892
|
];
|
|
24566
24893
|
}
|
|
24894
|
+
function figureKeysRefusals(value) {
|
|
24895
|
+
const refused = numberUnitRefusal(value.format, value.unit);
|
|
24896
|
+
return [...refused === void 0 ? [] : [{ key: "unit", message: refused }], ...perRowRefusals(value)];
|
|
24897
|
+
}
|
|
24567
24898
|
function figureIssue(path) {
|
|
24568
24899
|
return (value, ctx) => {
|
|
24569
|
-
const
|
|
24570
|
-
if (refused !== void 0) ctx.addIssue({ code: "custom", message: refused, path: [...path, "unit"] });
|
|
24571
|
-
for (const { key, message: message2 } of perRowRefusals(value)) ctx.addIssue({ code: "custom", message: message2, path: [...path, key] });
|
|
24900
|
+
for (const { key, message: message2 } of figureKeysRefusals(value)) ctx.addIssue({ code: "custom", message: message2, path: [...path, key] });
|
|
24572
24901
|
};
|
|
24573
24902
|
}
|
|
24574
|
-
var
|
|
24903
|
+
var BEFORE_NOTATION = 'Before "notation", and read as it: state "notation" instead.';
|
|
24904
|
+
function notationStatedIssue(path) {
|
|
24905
|
+
return (value, ctx) => {
|
|
24906
|
+
if (value.notation === void 0) return;
|
|
24907
|
+
const settled = settledReading(notationSaid(value), void 0);
|
|
24908
|
+
if ("refusal" in settled) ctx.addIssue({ code: "custom", message: settled.refusal, path: [...path, "notation"] });
|
|
24909
|
+
};
|
|
24910
|
+
}
|
|
24911
|
+
var tableNumberFieldShape = tableFieldBaseSchema.extend({
|
|
24575
24912
|
type: zod_default.literal("number"),
|
|
24576
|
-
|
|
24577
|
-
|
|
24578
|
-
|
|
24579
|
-
|
|
24580
|
-
|
|
24913
|
+
notation: notationSchema.optional(),
|
|
24914
|
+
format: numberFormatSchema.describe(BEFORE_NOTATION),
|
|
24915
|
+
currency: zod_default.string().nullish().describe(`ISO 4217 code. null clears it. ${BEFORE_NOTATION}`),
|
|
24916
|
+
unit: zod_default.string().nullish().describe(`${UNIT_DESCRIPTION} null clears it. ${BEFORE_NOTATION}`),
|
|
24917
|
+
unit_field: zod_default.string().nullish().describe(`${UNIT_FIELD_DESCRIPTION} null clears it. ${BEFORE_NOTATION}`),
|
|
24918
|
+
currency_field: zod_default.string().nullish().describe(`${CURRENCY_FIELD_DESCRIPTION} null clears it. ${BEFORE_NOTATION}`),
|
|
24581
24919
|
default_value: numberDefaultValueSchema
|
|
24582
|
-
})
|
|
24920
|
+
});
|
|
24921
|
+
var tableNumberFieldSchema = tableNumberFieldShape.superRefine(figureIssue([]));
|
|
24922
|
+
var tableNumberFieldInputSchema = tableNumberFieldShape.extend({ format: numberFormatSchema.optional().describe(BEFORE_NOTATION) }).superRefine(figureIssue([]));
|
|
24583
24923
|
var tableTextFieldSchema = tableFieldBaseSchema.extend({
|
|
24584
24924
|
type: zod_default.literal("text"),
|
|
24585
24925
|
unique: zod_default.boolean().optional().describe("Unique values required"),
|
|
@@ -24672,6 +25012,9 @@ var tableRollupFieldSchema = tableFieldBaseSchema.extend({
|
|
|
24672
25012
|
aggregate_field_type: tableFieldTypeNameSchema.optional().describe(
|
|
24673
25013
|
"What this rollup's CELL holds \u2014 'date' for earliest/latest, 'number' for every other operation (counts, sums, percentages). Derived from the operation, not from the aggregated field: a 'filled' count over a files column is a number. Server-derived at write time; ignored on input."
|
|
24674
25014
|
),
|
|
25015
|
+
aggregate_field_notation: notationSchema.optional().describe(
|
|
25016
|
+
`How this rollup's figure reads. Operations that preserve the aggregated value's unit (sum/avg/median/min/max/range) inherit the target field's; counts are a decimal, percentages the unit "percent". Server-derived at write time; ignored on input.`
|
|
25017
|
+
),
|
|
24675
25018
|
aggregate_field_format: zod_default.string().optional().describe(
|
|
24676
25019
|
"The format of this rollup's own value. Operations that preserve the aggregated value's unit (sum/avg/median/min/max/range/earliest/latest) inherit the target field's format; counting operations are 'number', percentages 'percentage'. Server-derived at write time; ignored on input."
|
|
24677
25020
|
),
|
|
@@ -24699,6 +25042,9 @@ var tableLookupFieldSchema = tableFieldBaseSchema.extend({
|
|
|
24699
25042
|
lookup_field_type: tableFieldTypeNameSchema.optional().describe(
|
|
24700
25043
|
"The type of the target lookup field (e.g. 'text', 'number', 'date'). Resolved from the linked table's field definition at read time."
|
|
24701
25044
|
),
|
|
25045
|
+
lookup_field_notation: notationSchema.optional().describe(
|
|
25046
|
+
"How the looked-up figure reads, where the target lookup field holds a number. Resolved from the linked table's field definition at write time."
|
|
25047
|
+
),
|
|
24702
25048
|
lookup_field_format: zod_default.string().optional().describe(
|
|
24703
25049
|
"The format of the target lookup field (e.g. 'currency', 'percentage', 'datetime'). Resolved from the linked table's field definition at read time."
|
|
24704
25050
|
),
|
|
@@ -24711,6 +25057,9 @@ var tableLookupFieldSchema = tableFieldBaseSchema.extend({
|
|
|
24711
25057
|
lookup_field_options: zod_default.array(zod_default.object({ key: zod_default.string(), name: zod_default.string(), color: zod_default.string().optional(), mark: storedOptionMarkSchema.optional() })).optional().describe(
|
|
24712
25058
|
"Options for select-type lookup fields. Synced from the source select field's options."
|
|
24713
25059
|
),
|
|
25060
|
+
lookup_field_autonumber: zod_default.boolean().optional().describe(
|
|
25061
|
+
"True where the looked-up value is an autonumber's text, which sorts by its number where it is a bare one. Synced from the looked-up field."
|
|
25062
|
+
),
|
|
24714
25063
|
order_by: lookupOrderBySchema.optional().describe(
|
|
24715
25064
|
"When set, sort the linked records by this field on the linked table and return ONLY the picked field from the single extreme record (desc=latest, asc=earliest), as a one-element array. Omit to return every linked record's value as an array. field_key must be a field on the linked table."
|
|
24716
25065
|
)
|
|
@@ -24723,25 +25072,36 @@ var formulaInputSchema = zod_default.object({
|
|
|
24723
25072
|
expression: zod_default.string().describe(
|
|
24724
25073
|
"JavaScript expression. Uses {Field Name} for field references."
|
|
24725
25074
|
),
|
|
24726
|
-
|
|
24727
|
-
|
|
24728
|
-
),
|
|
24729
|
-
currency: zod_default.string().optional().describe(
|
|
24730
|
-
unit: zod_default.string().optional().describe(UNIT_DESCRIPTION),
|
|
24731
|
-
unit_field: zod_default.string().optional().describe(UNIT_FIELD_DESCRIPTION),
|
|
24732
|
-
currency_field: zod_default.string().optional().describe(CURRENCY_FIELD_DESCRIPTION),
|
|
25075
|
+
notation: notationSchema.optional().describe(`${NOTATION_DESCRIPTION} For a formula yielding a number.`),
|
|
25076
|
+
link: zod_default.literal(true).optional().describe("The formula yields a URL as text, drawn as a link that opens."),
|
|
25077
|
+
format: zod_default.enum(["number", "currency", "percentage", "link"]).optional().describe(`'number' / 'currency' / 'percentage' for numeric results; 'link' for a URL. ${BEFORE_NOTATION} 'link' is "link": true.`),
|
|
25078
|
+
currency: zod_default.string().optional().describe(`ISO 4217 currency code, e.g. USD, VND, EUR. ${BEFORE_NOTATION}`),
|
|
25079
|
+
unit: zod_default.string().optional().describe(`${UNIT_DESCRIPTION} ${BEFORE_NOTATION}`),
|
|
25080
|
+
unit_field: zod_default.string().optional().describe(`${UNIT_FIELD_DESCRIPTION} ${BEFORE_NOTATION}`),
|
|
25081
|
+
currency_field: zod_default.string().optional().describe(`${CURRENCY_FIELD_DESCRIPTION} ${BEFORE_NOTATION}`),
|
|
24733
25082
|
options: zod_default.array(tableSelectFieldOptionSchema).min(1).optional().describe(
|
|
24734
25083
|
"The categories the formula yields, drawn as a single select's options are. The expression yields one option's `key` (text) or null; a key it does not declare computes an error. Omit for a formula yielding a plain value."
|
|
24735
25084
|
)
|
|
24736
25085
|
});
|
|
25086
|
+
var formulaToolInputSchema = formulaInputSchema.omit({ format: true, currency: true, unit: true, unit_field: true, currency_field: true });
|
|
24737
25087
|
var formulaSchema = formulaInputSchema.extend({
|
|
24738
25088
|
output_type: formulaOutputTypeSchema.optional().describe("Output type of the formula. Inferred by the backend from the expression \u2014 read-only on input. `datetime` when the result carries a time of day (references a datetime field or a time-bearing helper); `select` when the formula declares `options`."),
|
|
24739
25089
|
volatile: zod_default.boolean().optional().describe("Whether the formula's result depends on `now()` or other non-deterministic helpers. Inferred by the backend \u2014 read-only on input.")
|
|
24740
25090
|
});
|
|
24741
|
-
var
|
|
25091
|
+
var tableFormulaFieldShape = tableFieldBaseSchema.extend({
|
|
24742
25092
|
type: zod_default.literal("formula").describe("Field type for calculated values based on expressions"),
|
|
24743
25093
|
formula: formulaSchema.describe("Formula configuration and expression")
|
|
24744
|
-
})
|
|
25094
|
+
});
|
|
25095
|
+
var tableFormulaFieldSchema = tableFormulaFieldShape.superRefine((field, ctx) => figureIssue(["formula"])(field.formula, ctx));
|
|
25096
|
+
function formulaLinks(formula) {
|
|
25097
|
+
return formula.format == null ? formula.link === true : formula.format === "link";
|
|
25098
|
+
}
|
|
25099
|
+
function formulaLinkIssue(formula, ctx) {
|
|
25100
|
+
if (formula.link === true && formula.notation !== void 0) {
|
|
25101
|
+
ctx.addIssue({ code: "custom", message: "a formula yielding a link yields text, which reads in no notation", path: ["formula", "link"] });
|
|
25102
|
+
}
|
|
25103
|
+
}
|
|
25104
|
+
var tableFormulaFieldInputSchema = tableFormulaFieldShape.superRefine((field, ctx) => figureIssue(["formula"])(field.formula, ctx)).superRefine((field, ctx) => formulaLinkIssue(field.formula, ctx));
|
|
24745
25105
|
var workflowMetadataSchema = zod_default.object({
|
|
24746
25106
|
table_ids: zod_default.array(zod_default.string()).describe("IDs of the tables this workflow affects"),
|
|
24747
25107
|
staged_for_app_id: zod_default.string().optional().describe(
|
|
@@ -24797,7 +25157,7 @@ var tableFieldSchema = zod_default.discriminatedUnion("type", [
|
|
|
24797
25157
|
tableAutonumberFieldSchema
|
|
24798
25158
|
]);
|
|
24799
25159
|
var tableFieldInputSchema = zod_default.discriminatedUnion("type", [
|
|
24800
|
-
|
|
25160
|
+
tableNumberFieldInputSchema,
|
|
24801
25161
|
tableTextFieldSchema,
|
|
24802
25162
|
tableDateFieldSchema,
|
|
24803
25163
|
tableBooleanFieldSchema,
|
|
@@ -24807,16 +25167,28 @@ var tableFieldInputSchema = zod_default.discriminatedUnion("type", [
|
|
|
24807
25167
|
tableRollupFieldSchema,
|
|
24808
25168
|
tableLookupFieldSchema,
|
|
24809
25169
|
tableFilesFieldSchema,
|
|
24810
|
-
|
|
25170
|
+
tableFormulaFieldInputSchema,
|
|
24811
25171
|
tableButtonFieldSchema,
|
|
24812
25172
|
tableAutonumberFieldSchema
|
|
24813
25173
|
]);
|
|
24814
25174
|
var tableFieldsSchema = zod_default.array(tableFieldSchema);
|
|
24815
|
-
|
|
24816
|
-
|
|
24817
|
-
|
|
24818
|
-
|
|
24819
|
-
|
|
25175
|
+
var tableFieldsInputSchema = zod_default.array(
|
|
25176
|
+
zod_default.discriminatedUnion("type", [
|
|
25177
|
+
tableNumberFieldInputSchema,
|
|
25178
|
+
tableTextFieldSchema,
|
|
25179
|
+
tableDateFieldSchema,
|
|
25180
|
+
tableBooleanFieldSchema,
|
|
25181
|
+
tableSelectFieldSchema,
|
|
25182
|
+
tableSelectMemberFieldSchema,
|
|
25183
|
+
tableSelectRecordLinkFieldSchema,
|
|
25184
|
+
tableRollupFieldSchema,
|
|
25185
|
+
tableLookupFieldSchema,
|
|
25186
|
+
tableFilesFieldSchema,
|
|
25187
|
+
tableFormulaFieldInputSchema,
|
|
25188
|
+
tableButtonFieldSchema,
|
|
25189
|
+
tableAutonumberFieldSchema
|
|
25190
|
+
])
|
|
25191
|
+
);
|
|
24820
25192
|
var tableFieldCreateBaseSchema = zod_default.object({
|
|
24821
25193
|
name: zod_default.string().describe("Display name"),
|
|
24822
25194
|
description: zod_default.string().describe("Field description"),
|
|
@@ -24830,13 +25202,9 @@ var tableSelectFieldOptionCreateSchema = zod_default.object({
|
|
|
24830
25202
|
var tableFieldTypeConfigSchema = zod_default.discriminatedUnion("type", [
|
|
24831
25203
|
zod_default.object({
|
|
24832
25204
|
type: zod_default.literal("number"),
|
|
24833
|
-
|
|
24834
|
-
currency: zod_default.string().optional().describe("ISO 4217 code"),
|
|
24835
|
-
unit: zod_default.string().optional().describe(UNIT_DESCRIPTION),
|
|
24836
|
-
unit_field: zod_default.string().optional().describe(UNIT_FIELD_DESCRIPTION),
|
|
24837
|
-
currency_field: zod_default.string().optional().describe(CURRENCY_FIELD_DESCRIPTION),
|
|
25205
|
+
notation: notationSchema.optional().describe(`${NOTATION_DESCRIPTION} Omitted, a decimal.`),
|
|
24838
25206
|
default_value: numberDefaultValueSchema
|
|
24839
|
-
}).superRefine(
|
|
25207
|
+
}).superRefine(notationStatedIssue([])),
|
|
24840
25208
|
zod_default.object({
|
|
24841
25209
|
type: zod_default.literal("text"),
|
|
24842
25210
|
unique: zod_default.boolean().optional().describe("Unique values required"),
|
|
@@ -24900,8 +25268,8 @@ var tableFieldTypeConfigSchema = zod_default.discriminatedUnion("type", [
|
|
|
24900
25268
|
}),
|
|
24901
25269
|
zod_default.object({
|
|
24902
25270
|
type: zod_default.literal("formula"),
|
|
24903
|
-
formula:
|
|
24904
|
-
}).superRefine((field, ctx) =>
|
|
25271
|
+
formula: formulaToolInputSchema
|
|
25272
|
+
}).superRefine((field, ctx) => notationStatedIssue(["formula"])(field.formula, ctx)).superRefine((field, ctx) => formulaLinkIssue(field.formula, ctx)),
|
|
24905
25273
|
// `button` is deliberately absent: button fields are legacy — this union
|
|
24906
25274
|
// shapes CREATE input only, and new buttons can no longer be created
|
|
24907
25275
|
// (see LEGACY_FIELD_TYPES). Stored button fields still parse via the
|
|
@@ -24972,10 +25340,8 @@ function projectCell(field, value) {
|
|
|
24972
25340
|
}
|
|
24973
25341
|
}
|
|
24974
25342
|
|
|
24975
|
-
// ../shared/src/
|
|
24976
|
-
var
|
|
24977
|
-
var GRAMMAR_NAME_SHAPE = `${LINKED_CALL}(record["fld_link"])[0] fetches one linked row`;
|
|
24978
|
-
var RUNTIME_KEYS = /* @__PURE__ */ new Set([
|
|
25343
|
+
// ../shared/src/schemas/workflow_expressions.ts
|
|
25344
|
+
var runtimeKeySchema = zod_default.enum([
|
|
24979
25345
|
"timezone",
|
|
24980
25346
|
"workflow_id",
|
|
24981
25347
|
"execution_id",
|
|
@@ -24983,184 +25349,10 @@ var RUNTIME_KEYS = /* @__PURE__ */ new Set([
|
|
|
24983
25349
|
"organization_id",
|
|
24984
25350
|
"now",
|
|
24985
25351
|
"change_origin",
|
|
24986
|
-
"execution_principal",
|
|
24987
25352
|
"triggered_by_member_id"
|
|
24988
25353
|
]);
|
|
24989
|
-
var
|
|
24990
|
-
|
|
24991
|
-
[
|
|
24992
|
-
"execution_principal",
|
|
24993
|
-
`runtime.execution_principal is not readable \u2014 a workflow runs under the OWNER's authority, so it never answers "is the person who triggered this allowed?". Authorize the caller with ${CURRENT_MEMBER_IN_ANY_GROUP}(["grp_\u2026"]) or read runtime.triggered_by_member_id.`
|
|
24994
|
-
]
|
|
24995
|
-
]);
|
|
24996
|
-
var READABLE_RUNTIME_KEYS = Array.from(RUNTIME_KEYS).filter(
|
|
24997
|
-
(key) => !PARKED_RUNTIME_KEYS.has(key)
|
|
24998
|
-
);
|
|
24999
|
-
var INLINE_HELPERS = [
|
|
25000
|
-
"formatCurrency",
|
|
25001
|
-
"randomNumber",
|
|
25002
|
-
"randomAlphaNumeric",
|
|
25003
|
-
"sample",
|
|
25004
|
-
// Actor authorization predicate — resolves the triggering member's groups
|
|
25005
|
-
// server-side (bound in the backend helper registry, not a pure shared
|
|
25006
|
-
// helper).
|
|
25007
|
-
CURRENT_MEMBER_IN_ANY_GROUP
|
|
25008
|
-
];
|
|
25009
|
-
var HELPERS = /* @__PURE__ */ new Set([
|
|
25010
|
-
...Object.keys(expression_array_exports),
|
|
25011
|
-
...Object.keys(expression_string_exports),
|
|
25012
|
-
...Object.keys(expression_math_exports),
|
|
25013
|
-
...Object.keys(expression_object_exports),
|
|
25014
|
-
...Object.keys(expression_type_exports),
|
|
25015
|
-
...Object.keys(getDateExpressionFunctions()),
|
|
25016
|
-
...INLINE_HELPERS
|
|
25017
|
-
]);
|
|
25018
|
-
function isHelper(name) {
|
|
25019
|
-
return HELPERS.has(name);
|
|
25020
|
-
}
|
|
25021
|
-
var HELPER_MENU = [
|
|
25022
|
-
`text \u2014 ${Object.keys(expression_string_exports).sort().join(", ")}`,
|
|
25023
|
-
`number \u2014 ${Object.keys(expression_math_exports).sort().join(", ")}`,
|
|
25024
|
-
`array \u2014 ${Object.keys(expression_array_exports).sort().join(", ")}`,
|
|
25025
|
-
`object \u2014 ${Object.keys(expression_object_exports).sort().join(", ")}`,
|
|
25026
|
-
`type/null \u2014 ${Object.keys(expression_type_exports).sort().join(", ")}`,
|
|
25027
|
-
`date \u2014 ${Object.keys(getDateExpressionFunctions()).sort().join(", ")}`,
|
|
25028
|
-
`other \u2014 ${[...INLINE_HELPERS].sort().join(", ")}`
|
|
25029
|
-
].join("; ");
|
|
25030
|
-
var AWAIT_IF_FORM = "Write the if form: let x = null; if (<condition>) { x = await tool({...}); }";
|
|
25031
|
-
var AWAIT_IN_OPTIONAL_CHAIN = `An await after \`?.\` runs only when the value before it is not null. ${AWAIT_IF_FORM}`;
|
|
25032
|
-
var CALLBACK_HELPERS = /* @__PURE__ */ new Set([
|
|
25033
|
-
"filter",
|
|
25034
|
-
"find",
|
|
25035
|
-
"pluck",
|
|
25036
|
-
"sortBy",
|
|
25037
|
-
"sumBy",
|
|
25038
|
-
"meanBy",
|
|
25039
|
-
"minBy",
|
|
25040
|
-
"maxBy",
|
|
25041
|
-
"countBy",
|
|
25042
|
-
"groupBy",
|
|
25043
|
-
"uniqueBy",
|
|
25044
|
-
"some",
|
|
25045
|
-
"every",
|
|
25046
|
-
"differenceBy",
|
|
25047
|
-
"intersectionBy",
|
|
25048
|
-
"reduce"
|
|
25049
|
-
]);
|
|
25050
|
-
var LAMBDA_POSITION_HINT = `Function expressions are not supported here. A lambda \u2014 either \`(x) => <expr>\` or \`function (x) { return <expr>; }\` \u2014 is legal only INLINE as a callback argument to ${[...CALLBACK_HELPERS].sort().join(" / ")}, e.g. pluck(rows, (r) => r.qty * r.price). To NAME reusable logic, declare it at the top level instead: \`function toLine(l = {}) { return { ... }; }\` \u2014 every parameter needs a default, and the body is inlined at each call site. Binding a lambda to a name (const f = (x) => ...) or calling one directly stays unsupported.`;
|
|
25051
|
-
var HELPER_ALIASES = /* @__PURE__ */ new Map([
|
|
25052
|
-
["String", "toString"],
|
|
25053
|
-
["Number", "toNumber"],
|
|
25054
|
-
["parseFloat", "toNumber"],
|
|
25055
|
-
// faithful: toNumber IS parseFloat semantics
|
|
25056
|
-
["toUpperCase", "upper"],
|
|
25057
|
-
["toLowerCase", "lower"],
|
|
25058
|
-
["map", "pluck"],
|
|
25059
|
-
// arr.map(x => …) ≡ pluck(arr, x => …)
|
|
25060
|
-
["toFixed", "formatNumber"]
|
|
25061
|
-
// x.toFixed(2) ≡ formatNumber(x, 2)
|
|
25062
|
-
]);
|
|
25063
|
-
var REJECTED_HELPERS = /* @__PURE__ */ new Map([
|
|
25064
|
-
[
|
|
25065
|
-
"parseInt",
|
|
25066
|
-
{
|
|
25067
|
-
message: "parseInt is not supported \u2014 parse with toNumber(x), then apply floor(...), ceil(...), or round(...) to get a whole number. floor rounds down (toward negative infinity), so for negative values choose the rounding deliberately.",
|
|
25068
|
-
construct: "parse_int"
|
|
25069
|
-
}
|
|
25070
|
-
]
|
|
25071
|
-
]);
|
|
25072
|
-
var NAMESPACE_HELPERS = /* @__PURE__ */ new Map([
|
|
25073
|
-
["JSON", /* @__PURE__ */ new Map([["parse", "parseJson"], ["stringify", "toJson"]])],
|
|
25074
|
-
["Array", /* @__PURE__ */ new Map([["isArray", "isArray"]])],
|
|
25075
|
-
["Object", /* @__PURE__ */ new Map([["keys", "keys"], ["values", "values"], ["entries", "entries"]])],
|
|
25076
|
-
["Number", /* @__PURE__ */ new Map([["parseFloat", "toNumber"]])]
|
|
25077
|
-
]);
|
|
25078
|
-
var METHOD_FORM_NAMES = /* @__PURE__ */ new Set([
|
|
25079
|
-
// String.prototype
|
|
25080
|
-
"trim",
|
|
25081
|
-
"toUpperCase",
|
|
25082
|
-
"toLowerCase",
|
|
25083
|
-
"replace",
|
|
25084
|
-
"replaceAll",
|
|
25085
|
-
"split",
|
|
25086
|
-
"substring",
|
|
25087
|
-
"padStart",
|
|
25088
|
-
"padEnd",
|
|
25089
|
-
"startsWith",
|
|
25090
|
-
"endsWith",
|
|
25091
|
-
// String.prototype + Array.prototype
|
|
25092
|
-
"includes",
|
|
25093
|
-
"slice",
|
|
25094
|
-
"at",
|
|
25095
|
-
"concat",
|
|
25096
|
-
// Array.prototype
|
|
25097
|
-
"join",
|
|
25098
|
-
"reverse",
|
|
25099
|
-
"map",
|
|
25100
|
-
"filter",
|
|
25101
|
-
"find",
|
|
25102
|
-
"some",
|
|
25103
|
-
"every",
|
|
25104
|
-
"reduce",
|
|
25105
|
-
// Number.prototype / Object.prototype
|
|
25106
|
-
"toFixed",
|
|
25107
|
-
"toString"
|
|
25108
|
-
]);
|
|
25109
|
-
var METHOD_FORM_MENU = [...METHOD_FORM_NAMES].sort().join(", ");
|
|
25110
|
-
var PROPERTY_HELPERS = /* @__PURE__ */ new Map([["length", "length"]]);
|
|
25111
|
-
var HELPER_SPELLINGS = (() => {
|
|
25112
|
-
const out = /* @__PURE__ */ new Map();
|
|
25113
|
-
const add = (helper, spelling) => {
|
|
25114
|
-
if (isHelper(helper) && !out.has(helper)) out.set(helper, spelling);
|
|
25115
|
-
};
|
|
25116
|
-
for (const name of METHOD_FORM_NAMES) add(HELPER_ALIASES.get(name) ?? name, { kind: "method", name });
|
|
25117
|
-
for (const [name, helper] of PROPERTY_HELPERS) add(helper, { kind: "property", name });
|
|
25118
|
-
for (const [namespace, members2] of NAMESPACE_HELPERS) {
|
|
25119
|
-
for (const [member, helper] of members2) add(helper, { kind: "namespace", namespace, member });
|
|
25120
|
-
}
|
|
25121
|
-
for (const fn of Object.keys(expression_math_exports)) {
|
|
25122
|
-
if (fn !== "random" && typeof Reflect.get(Math, fn) === "function") {
|
|
25123
|
-
add(fn, { kind: "namespace", namespace: "Math", member: fn });
|
|
25124
|
-
}
|
|
25125
|
-
}
|
|
25126
|
-
return out;
|
|
25127
|
-
})();
|
|
25128
|
-
var RESERVED_CALLABLE_NAMES = /* @__PURE__ */ new Set([
|
|
25129
|
-
...REJECTED_HELPERS.keys(),
|
|
25130
|
-
...NAMESPACE_HELPERS.keys(),
|
|
25131
|
-
"Math",
|
|
25132
|
-
"Boolean"
|
|
25133
|
-
]);
|
|
25134
|
-
var LINKED_ARITY = `${LINKED_CALL}(...) takes exactly one argument \u2014 the read of the link field, e.g. ${LINKED_CALL}(record["fld_link"])[0] for one row or ${LINKED_CALL}(record["fld_link"]) for every row.`;
|
|
25135
|
-
var LINKED_ARGUMENT_SHAPE = `The argument of ${LINKED_CALL}(...) must END on the link field, because that field is what it follows \u2014 ${LINKED_CALL}(record["fld_link"])[0]. A value that names no field (a binding, a literal, a helper result) cannot say which link to follow; read the field on it: ${LINKED_CALL}(ids["fld_link"]).`;
|
|
25136
|
-
var LINKED_OPTIONAL_RESULT = `${LINKED_CALL}(...) always returns an array, never null, so \`?.\` on its result can never fire. The argument takes a guard \u2014 ${LINKED_CALL}(record?.["fld_link"])[0] \u2014 and so does the fetched row, which is null where the linked record is deleted or unreadable: ${LINKED_CALL}(record["fld_link"])[0]?.["fld_x"].`;
|
|
25137
|
-
var LINKED_METHOD_FORM = `${LINKED_CALL} has no method form \u2014 write ${LINKED_CALL}(record["fld_link"])[0], with the link read as the argument.`;
|
|
25138
|
-
var LINKED_ON_NON_RECORD = `${LINKED_CALL}(...) follows a link field on a record, and this value is not one. Read the record first, then follow the link: ${LINKED_CALL}(record["fld_link"])[0].`;
|
|
25139
|
-
var LINKED_ON_CHANGES = `A change diff is not a record, so ${LINKED_CALL}(...) cannot follow a link off it. Read the post-state with ${LINKED_CALL}(record["fld_link"]) or the pre-state with ${LINKED_CALL}(prev_record["fld_link"]).`;
|
|
25140
|
-
var READ_ROOT_HINT = `A read starts from a name: a reserved identifier (record, prev_record, changes, runtime, trigger, index), a binding, or ${LINKED_CALL}(record["fld_link"]). Bind the value first \u2014 const x = <expression>; \u2014 then read x.y.`;
|
|
25141
|
-
|
|
25142
|
-
// ../shared/src/schemas/workflow_expressions.ts
|
|
25143
|
-
var runtimeKeySchema = zod_default.enum([
|
|
25144
|
-
"timezone",
|
|
25145
|
-
"workflow_id",
|
|
25146
|
-
"execution_id",
|
|
25147
|
-
"workspace_id",
|
|
25148
|
-
"organization_id",
|
|
25149
|
-
"now",
|
|
25150
|
-
"change_origin",
|
|
25151
|
-
// PARKED — accepted in stored ASTs, rejected for new saves at parse (see
|
|
25152
|
-
// `PARKED_RUNTIME_KEYS` in walk_workflow_expression.ts). It is the OWNER's
|
|
25153
|
-
// principal (a workflow runs under owner authority), so it can't answer the
|
|
25154
|
-
// caller-authorization question anyone reads it for; the generated `.d.ts`
|
|
25155
|
-
// omits it and the docs point at `current_member_in_any_group` /
|
|
25156
|
-
// `runtime.triggered_by_member_id` instead. The entry stays so any stored
|
|
25157
|
-
// AST keeps validating and executing — drop it only once a prod probe shows
|
|
25158
|
-
// zero references (`workflows.steps_v2::text LIKE '%execution_principal%'`).
|
|
25159
|
-
"execution_principal",
|
|
25160
|
-
"triggered_by_member_id"
|
|
25161
|
-
]);
|
|
25162
|
-
var nestedExpressionSchema = zod_default.lazy(
|
|
25163
|
-
() => workflowExpressionSchema
|
|
25354
|
+
var nestedExpressionSchema = zod_default.lazy(
|
|
25355
|
+
() => workflowExpressionSchema
|
|
25164
25356
|
);
|
|
25165
25357
|
var readSourceSchema = zod_default.discriminatedUnion("from", [
|
|
25166
25358
|
zod_default.object({ from: zod_default.literal("trigger") }),
|
|
@@ -25329,6 +25521,154 @@ var templatePartSchema = zod_default.lazy(
|
|
|
25329
25521
|
])
|
|
25330
25522
|
);
|
|
25331
25523
|
|
|
25524
|
+
// ../shared/src/walk_workflow_expression.ts
|
|
25525
|
+
var LINKED_CALL = "linked";
|
|
25526
|
+
var GRAMMAR_NAME_SHAPE = `${LINKED_CALL}(record["fld_link"])[0] fetches one linked row`;
|
|
25527
|
+
var RUNTIME_KEYS = new Set(runtimeKeySchema.options);
|
|
25528
|
+
var CURRENT_MEMBER_IN_ANY_GROUP = "current_member_in_any_group";
|
|
25529
|
+
var INLINE_HELPERS = [
|
|
25530
|
+
"formatCurrency",
|
|
25531
|
+
"randomNumber",
|
|
25532
|
+
"randomAlphaNumeric",
|
|
25533
|
+
"sample",
|
|
25534
|
+
// Actor authorization predicate — resolves the triggering member's groups
|
|
25535
|
+
// server-side (bound in the backend helper registry, not a pure shared
|
|
25536
|
+
// helper).
|
|
25537
|
+
CURRENT_MEMBER_IN_ANY_GROUP
|
|
25538
|
+
];
|
|
25539
|
+
var HELPERS = /* @__PURE__ */ new Set([
|
|
25540
|
+
...Object.keys(expression_array_exports),
|
|
25541
|
+
...Object.keys(expression_string_exports),
|
|
25542
|
+
...Object.keys(expression_math_exports),
|
|
25543
|
+
...Object.keys(expression_object_exports),
|
|
25544
|
+
...Object.keys(expression_type_exports),
|
|
25545
|
+
...Object.keys(getDateExpressionFunctions()),
|
|
25546
|
+
...INLINE_HELPERS
|
|
25547
|
+
]);
|
|
25548
|
+
function isHelper(name) {
|
|
25549
|
+
return HELPERS.has(name);
|
|
25550
|
+
}
|
|
25551
|
+
var HELPER_MENU = [
|
|
25552
|
+
`text \u2014 ${Object.keys(expression_string_exports).sort().join(", ")}`,
|
|
25553
|
+
`number \u2014 ${Object.keys(expression_math_exports).sort().join(", ")}`,
|
|
25554
|
+
`array \u2014 ${Object.keys(expression_array_exports).sort().join(", ")}`,
|
|
25555
|
+
`object \u2014 ${Object.keys(expression_object_exports).sort().join(", ")}`,
|
|
25556
|
+
`type/null \u2014 ${Object.keys(expression_type_exports).sort().join(", ")}`,
|
|
25557
|
+
`date \u2014 ${Object.keys(getDateExpressionFunctions()).sort().join(", ")}`,
|
|
25558
|
+
`other \u2014 ${[...INLINE_HELPERS].sort().join(", ")}`
|
|
25559
|
+
].join("; ");
|
|
25560
|
+
var AWAIT_IF_FORM = "Write the if form: let x = null; if (<condition>) { x = await tool({...}); }";
|
|
25561
|
+
var AWAIT_IN_OPTIONAL_CHAIN = `An await after \`?.\` runs only when the value before it is not null. ${AWAIT_IF_FORM}`;
|
|
25562
|
+
var CALLBACK_HELPERS = /* @__PURE__ */ new Set([
|
|
25563
|
+
"filter",
|
|
25564
|
+
"find",
|
|
25565
|
+
"pluck",
|
|
25566
|
+
"sortBy",
|
|
25567
|
+
"sumBy",
|
|
25568
|
+
"meanBy",
|
|
25569
|
+
"minBy",
|
|
25570
|
+
"maxBy",
|
|
25571
|
+
"countBy",
|
|
25572
|
+
"groupBy",
|
|
25573
|
+
"uniqueBy",
|
|
25574
|
+
"some",
|
|
25575
|
+
"every",
|
|
25576
|
+
"differenceBy",
|
|
25577
|
+
"intersectionBy",
|
|
25578
|
+
"reduce"
|
|
25579
|
+
]);
|
|
25580
|
+
var LAMBDA_POSITION_HINT = `Function expressions are not supported here. A lambda \u2014 either \`(x) => <expr>\` or \`function (x) { return <expr>; }\` \u2014 is legal only INLINE as a callback argument to ${[...CALLBACK_HELPERS].sort().join(" / ")}, e.g. pluck(rows, (r) => r.qty * r.price). To NAME reusable logic, declare it at the top level instead: \`function toLine(l = {}) { return { ... }; }\` \u2014 every parameter needs a default, and the body is inlined at each call site. Binding a lambda to a name (const f = (x) => ...) or calling one directly stays unsupported.`;
|
|
25581
|
+
var HELPER_ALIASES = /* @__PURE__ */ new Map([
|
|
25582
|
+
["String", "toString"],
|
|
25583
|
+
["Number", "toNumber"],
|
|
25584
|
+
["parseFloat", "toNumber"],
|
|
25585
|
+
// faithful: toNumber IS parseFloat semantics
|
|
25586
|
+
["toUpperCase", "upper"],
|
|
25587
|
+
["toLowerCase", "lower"],
|
|
25588
|
+
["map", "pluck"],
|
|
25589
|
+
// arr.map(x => …) ≡ pluck(arr, x => …)
|
|
25590
|
+
["toFixed", "formatNumber"]
|
|
25591
|
+
// x.toFixed(2) ≡ formatNumber(x, 2)
|
|
25592
|
+
]);
|
|
25593
|
+
var REJECTED_HELPERS = /* @__PURE__ */ new Map([
|
|
25594
|
+
[
|
|
25595
|
+
"parseInt",
|
|
25596
|
+
{
|
|
25597
|
+
message: "parseInt is not supported \u2014 parse with toNumber(x), then apply floor(...), ceil(...), or round(...) to get a whole number. floor rounds down (toward negative infinity), so for negative values choose the rounding deliberately.",
|
|
25598
|
+
construct: "parse_int"
|
|
25599
|
+
}
|
|
25600
|
+
]
|
|
25601
|
+
]);
|
|
25602
|
+
var NAMESPACE_HELPERS = /* @__PURE__ */ new Map([
|
|
25603
|
+
["JSON", /* @__PURE__ */ new Map([["parse", "parseJson"], ["stringify", "toJson"]])],
|
|
25604
|
+
["Array", /* @__PURE__ */ new Map([["isArray", "isArray"]])],
|
|
25605
|
+
["Object", /* @__PURE__ */ new Map([["keys", "keys"], ["values", "values"], ["entries", "entries"]])],
|
|
25606
|
+
["Number", /* @__PURE__ */ new Map([["parseFloat", "toNumber"]])]
|
|
25607
|
+
]);
|
|
25608
|
+
var METHOD_FORM_NAMES = /* @__PURE__ */ new Set([
|
|
25609
|
+
// String.prototype
|
|
25610
|
+
"trim",
|
|
25611
|
+
"toUpperCase",
|
|
25612
|
+
"toLowerCase",
|
|
25613
|
+
"replace",
|
|
25614
|
+
"replaceAll",
|
|
25615
|
+
"split",
|
|
25616
|
+
"substring",
|
|
25617
|
+
"padStart",
|
|
25618
|
+
"padEnd",
|
|
25619
|
+
"startsWith",
|
|
25620
|
+
"endsWith",
|
|
25621
|
+
// String.prototype + Array.prototype
|
|
25622
|
+
"includes",
|
|
25623
|
+
"slice",
|
|
25624
|
+
"at",
|
|
25625
|
+
"concat",
|
|
25626
|
+
// Array.prototype
|
|
25627
|
+
"join",
|
|
25628
|
+
"reverse",
|
|
25629
|
+
"map",
|
|
25630
|
+
"filter",
|
|
25631
|
+
"find",
|
|
25632
|
+
"some",
|
|
25633
|
+
"every",
|
|
25634
|
+
"reduce",
|
|
25635
|
+
// Number.prototype / Object.prototype
|
|
25636
|
+
"toFixed",
|
|
25637
|
+
"toString"
|
|
25638
|
+
]);
|
|
25639
|
+
var METHOD_FORM_MENU = [...METHOD_FORM_NAMES].sort().join(", ");
|
|
25640
|
+
var PROPERTY_HELPERS = /* @__PURE__ */ new Map([["length", "length"]]);
|
|
25641
|
+
var HELPER_SPELLINGS = (() => {
|
|
25642
|
+
const out = /* @__PURE__ */ new Map();
|
|
25643
|
+
const add = (helper, spelling) => {
|
|
25644
|
+
if (isHelper(helper) && !out.has(helper)) out.set(helper, spelling);
|
|
25645
|
+
};
|
|
25646
|
+
for (const name of METHOD_FORM_NAMES) add(HELPER_ALIASES.get(name) ?? name, { kind: "method", name });
|
|
25647
|
+
for (const [name, helper] of PROPERTY_HELPERS) add(helper, { kind: "property", name });
|
|
25648
|
+
for (const [namespace, members2] of NAMESPACE_HELPERS) {
|
|
25649
|
+
for (const [member, helper] of members2) add(helper, { kind: "namespace", namespace, member });
|
|
25650
|
+
}
|
|
25651
|
+
for (const fn of Object.keys(expression_math_exports)) {
|
|
25652
|
+
if (fn !== "random" && typeof Reflect.get(Math, fn) === "function") {
|
|
25653
|
+
add(fn, { kind: "namespace", namespace: "Math", member: fn });
|
|
25654
|
+
}
|
|
25655
|
+
}
|
|
25656
|
+
return out;
|
|
25657
|
+
})();
|
|
25658
|
+
var RESERVED_CALLABLE_NAMES = /* @__PURE__ */ new Set([
|
|
25659
|
+
...REJECTED_HELPERS.keys(),
|
|
25660
|
+
...NAMESPACE_HELPERS.keys(),
|
|
25661
|
+
"Math",
|
|
25662
|
+
"Boolean"
|
|
25663
|
+
]);
|
|
25664
|
+
var LINKED_ARITY = `${LINKED_CALL}(...) takes exactly one argument \u2014 the read of the link field, e.g. ${LINKED_CALL}(record["fld_link"])[0] for one row or ${LINKED_CALL}(record["fld_link"]) for every row.`;
|
|
25665
|
+
var LINKED_ARGUMENT_SHAPE = `The argument of ${LINKED_CALL}(...) must END on the link field, because that field is what it follows \u2014 ${LINKED_CALL}(record["fld_link"])[0]. A value that names no field (a binding, a literal, a helper result) cannot say which link to follow; read the field on it: ${LINKED_CALL}(ids["fld_link"]).`;
|
|
25666
|
+
var LINKED_OPTIONAL_RESULT = `${LINKED_CALL}(...) always returns an array, never null, so \`?.\` on its result can never fire. The argument takes a guard \u2014 ${LINKED_CALL}(record?.["fld_link"])[0] \u2014 and so does the fetched row, which is null where the linked record is deleted or unreadable: ${LINKED_CALL}(record["fld_link"])[0]?.["fld_x"].`;
|
|
25667
|
+
var LINKED_METHOD_FORM = `${LINKED_CALL} has no method form \u2014 write ${LINKED_CALL}(record["fld_link"])[0], with the link read as the argument.`;
|
|
25668
|
+
var LINKED_ON_NON_RECORD = `${LINKED_CALL}(...) follows a link field on a record, and this value is not one. Read the record first, then follow the link: ${LINKED_CALL}(record["fld_link"])[0].`;
|
|
25669
|
+
var LINKED_ON_CHANGES = `A change diff is not a record, so ${LINKED_CALL}(...) cannot follow a link off it. Read the post-state with ${LINKED_CALL}(record["fld_link"]) or the pre-state with ${LINKED_CALL}(prev_record["fld_link"]).`;
|
|
25670
|
+
var READ_ROOT_HINT = `A read starts from a name: a reserved identifier (record, prev_record, changes, runtime, trigger, index), a binding, or ${LINKED_CALL}(record["fld_link"]). Bind the value first \u2014 const x = <expression>; \u2014 then read x.y.`;
|
|
25671
|
+
|
|
25332
25672
|
// ../shared/src/chat_models.ts
|
|
25333
25673
|
var MODEL_TIERS = ["haiku", "sonnet", "opus"];
|
|
25334
25674
|
var TIER_MODELS = {
|
|
@@ -26976,36 +27316,46 @@ var WorkflowEvalError = class extends Error {
|
|
|
26976
27316
|
detail;
|
|
26977
27317
|
};
|
|
26978
27318
|
var WorkflowTimeBudgetError = class extends Error {
|
|
26979
|
-
|
|
26980
|
-
|
|
27319
|
+
/** `waitedFor`: what the run's deadline passed waiting on, when that was not the run's own work. */
|
|
27320
|
+
constructor(subject, budgetMs, waitedFor) {
|
|
27321
|
+
super(`${subject} exceeded its time budget of ${budgetMs / 1e3}s${waitedFor === void 0 ? "" : ` waiting for ${waitedFor}`}.`);
|
|
26981
27322
|
this.name = "WorkflowTimeBudgetError";
|
|
26982
27323
|
}
|
|
26983
27324
|
};
|
|
26984
27325
|
var WorkflowExpressionBudgetError = class extends Error {
|
|
26985
|
-
constructor(
|
|
26986
|
-
super(
|
|
26987
|
-
|
|
26988
|
-
);
|
|
26989
|
-
this.exceeded = exceeded;
|
|
27326
|
+
constructor(budget) {
|
|
27327
|
+
super(budgetMessage(budget));
|
|
27328
|
+
this.budget = budget;
|
|
26990
27329
|
this.name = "WorkflowExpressionBudgetError";
|
|
26991
27330
|
}
|
|
26992
|
-
|
|
27331
|
+
budget;
|
|
26993
27332
|
};
|
|
26994
|
-
|
|
27333
|
+
function budgetMessage(budget) {
|
|
27334
|
+
switch (budget.exceeded) {
|
|
27335
|
+
case "bytes":
|
|
27336
|
+
return `The run built more than ${MAX_RUN_BUILT_BYTES / 1024 / 1024}MB of arrays, objects and text.`;
|
|
27337
|
+
case "heap":
|
|
27338
|
+
return `The expression used more than ${budget.heap_mb}MB of memory.`;
|
|
27339
|
+
case "compute":
|
|
27340
|
+
return `The expression computed for more than ${budget.compute_ms / 1e3}s.`;
|
|
27341
|
+
}
|
|
27342
|
+
}
|
|
26995
27343
|
var SLOT_BYTES = 8;
|
|
26996
27344
|
var CHAR_BYTES = 2;
|
|
27345
|
+
var OBJECT_BYTES = 56;
|
|
26997
27346
|
var EVALUATION_SLICE_MS = 20;
|
|
26998
27347
|
var turn = {
|
|
26999
27348
|
slice_started_ms: performance.now(),
|
|
27000
27349
|
pause: null
|
|
27001
27350
|
};
|
|
27002
|
-
function startRunBudget(subject, budgetMs) {
|
|
27003
|
-
return { deadline_ms: Date.now() + budgetMs, budget_ms: budgetMs, subject, built_bytes: 0 };
|
|
27351
|
+
function startRunBudget(subject, budgetMs, path) {
|
|
27352
|
+
return { host: "shared", deadline_ms: Date.now() + budgetMs, budget_ms: budgetMs, subject, path, built_bytes: 0 };
|
|
27004
27353
|
}
|
|
27005
27354
|
function runClock(run2) {
|
|
27006
27355
|
if (Date.now() > run2.deadline_ms) {
|
|
27007
27356
|
throw new WorkflowTimeBudgetError(run2.subject, run2.budget_ms);
|
|
27008
27357
|
}
|
|
27358
|
+
if (run2.host === "isolated") return null;
|
|
27009
27359
|
if (turn.pause === null && performance.now() - turn.slice_started_ms >= EVALUATION_SLICE_MS) {
|
|
27010
27360
|
turn.pause = new Promise((resolve) => setTimeout(resolve, 0)).then(() => {
|
|
27011
27361
|
turn.pause = null;
|
|
@@ -27015,15 +27365,16 @@ function runClock(run2) {
|
|
|
27015
27365
|
return turn.pause;
|
|
27016
27366
|
}
|
|
27017
27367
|
function chargeBuilt(run2, bytes) {
|
|
27368
|
+
if (run2.host === "isolated") return;
|
|
27018
27369
|
run2.built_bytes += bytes;
|
|
27019
27370
|
if (run2.built_bytes > MAX_RUN_BUILT_BYTES) {
|
|
27020
|
-
throw new WorkflowExpressionBudgetError("bytes");
|
|
27371
|
+
throw new WorkflowExpressionBudgetError({ exceeded: "bytes" });
|
|
27021
27372
|
}
|
|
27022
27373
|
}
|
|
27023
27374
|
function builtSize(value) {
|
|
27024
27375
|
if (typeof value === "string") return value.length * CHAR_BYTES;
|
|
27025
|
-
if (Array.isArray(value)) return value.length * SLOT_BYTES;
|
|
27026
|
-
if (typeof value === "object" && value !== null) return Object.keys(value).length * SLOT_BYTES;
|
|
27376
|
+
if (Array.isArray(value)) return OBJECT_BYTES + value.length * SLOT_BYTES;
|
|
27377
|
+
if (typeof value === "object" && value !== null) return OBJECT_BYTES + Object.keys(value).length * SLOT_BYTES;
|
|
27027
27378
|
return 0;
|
|
27028
27379
|
}
|
|
27029
27380
|
var PARSED_NODE_BYTES = 40;
|
|
@@ -27053,13 +27404,13 @@ function callbackWorkers() {
|
|
|
27053
27404
|
};
|
|
27054
27405
|
}
|
|
27055
27406
|
function evaluateWorkflowExpression(expr2, ctx) {
|
|
27056
|
-
const budget = {
|
|
27407
|
+
const budget = { workers: callbackWorkers(), settled: false };
|
|
27057
27408
|
return evaluateExpression(expr2, { ...ctx, evaluation_budget: budget }).finally(() => {
|
|
27058
27409
|
budget.settled = true;
|
|
27059
27410
|
});
|
|
27060
27411
|
}
|
|
27061
27412
|
async function evaluateExpression(expr2, ctx) {
|
|
27062
|
-
for (let pause =
|
|
27413
|
+
for (let pause = checkClock(ctx); pause !== null; pause = checkClock(ctx)) await pause;
|
|
27063
27414
|
switch (expr2.kind) {
|
|
27064
27415
|
case "lit":
|
|
27065
27416
|
return expr2.value;
|
|
@@ -27096,15 +27447,6 @@ async function evaluateExpression(expr2, ctx) {
|
|
|
27096
27447
|
return assertNever(expr2);
|
|
27097
27448
|
}
|
|
27098
27449
|
}
|
|
27099
|
-
function spendNode(ctx) {
|
|
27100
|
-
const budget = ctx.evaluation_budget;
|
|
27101
|
-
assertUnsettled(budget);
|
|
27102
|
-
budget.nodes += 1;
|
|
27103
|
-
if (budget.nodes > MAX_EVALUATION_NODES) {
|
|
27104
|
-
throw new WorkflowExpressionBudgetError("nodes");
|
|
27105
|
-
}
|
|
27106
|
-
return runClock(ctx.run_budget);
|
|
27107
|
-
}
|
|
27108
27450
|
function checkClock(ctx) {
|
|
27109
27451
|
assertUnsettled(ctx.evaluation_budget);
|
|
27110
27452
|
return runClock(ctx.run_budget);
|
|
@@ -28096,9 +28438,6 @@ function clientRuntime(input) {
|
|
|
28096
28438
|
},
|
|
28097
28439
|
get change_origin() {
|
|
28098
28440
|
return unread("change_origin");
|
|
28099
|
-
},
|
|
28100
|
-
get execution_principal() {
|
|
28101
|
-
return unread("execution_principal");
|
|
28102
28441
|
}
|
|
28103
28442
|
};
|
|
28104
28443
|
}
|
|
@@ -28131,7 +28470,7 @@ async function predictWorkflowEffects(input) {
|
|
|
28131
28470
|
trigger_table: null,
|
|
28132
28471
|
member_lookup: async () => unread("member display"),
|
|
28133
28472
|
lexical_bindings: [{}],
|
|
28134
|
-
run_budget: startRunBudget("Write prediction", PREDICTION_BUDGET_MS)
|
|
28473
|
+
run_budget: startRunBudget("Write prediction", PREDICTION_BUDGET_MS, "write")
|
|
28135
28474
|
};
|
|
28136
28475
|
const walk = { ctx, effects: [], written, input, unsure: false, aligned: true };
|
|
28137
28476
|
try {
|
|
@@ -28144,6 +28483,9 @@ async function predictWorkflowEffects(input) {
|
|
|
28144
28483
|
}
|
|
28145
28484
|
|
|
28146
28485
|
// ../shared/src/lookup_display.ts
|
|
28486
|
+
function flattenLookupValues(values2) {
|
|
28487
|
+
return values2.flatMap((value) => Array.isArray(value) ? flattenLookupValues(value) : [value]);
|
|
28488
|
+
}
|
|
28147
28489
|
function lookupElementToString(element) {
|
|
28148
28490
|
if (element === null || element === void 0) return "";
|
|
28149
28491
|
if (typeof element === "boolean") return element ? "True" : "False";
|
|
@@ -29882,9 +30224,6 @@ function evaluateCondition(record2, fieldByKey, looseCondition, memberContext, f
|
|
|
29882
30224
|
}
|
|
29883
30225
|
return matchCell(columnValue, field, filterCondition, looseCondition, memberContext, fileFacts);
|
|
29884
30226
|
}
|
|
29885
|
-
function flattenLookupValues(values2) {
|
|
29886
|
-
return values2.flatMap((value) => Array.isArray(value) ? flattenLookupValues(value) : [value]);
|
|
29887
|
-
}
|
|
29888
30227
|
function matchLookup(cell, field, filterCondition, looseCondition, memberContext, fileFacts) {
|
|
29889
30228
|
switch (filterCondition.type) {
|
|
29890
30229
|
case "select":
|
|
@@ -30302,197 +30641,378 @@ function matchCell(cell, field, filterCondition, looseCondition, memberContext,
|
|
|
30302
30641
|
if (!term) return null;
|
|
30303
30642
|
matches = files !== null && files.some((entry) => fileProperty(entry, property, fileFacts, fieldKey, filterCondition.operator).toLowerCase().includes(term));
|
|
30304
30643
|
}
|
|
30305
|
-
} else {
|
|
30306
|
-
const op = typeof looseCondition.operator === "string" ? looseCondition.operator : "(unset)";
|
|
30307
|
-
const source = field ? `'${String(resolvedType)}', resolved from field '${fieldKey}'` : resolvedType === void 0 ? `missing, and field '${fieldKey}' is not on this table to resolve it from` : `'${String(resolvedType)}', stated on the condition (field '${fieldKey}' is not on this table)`;
|
|
30308
|
-
throw new Error(
|
|
30309
|
-
`Filter condition cannot be evaluated: filter type ${source} has no evaluator. Evaluable: text, number, date, boolean, select, select_member, select_record_link, files, locked. Condition operator was "${op}".`
|
|
30310
|
-
);
|
|
30311
|
-
}
|
|
30312
|
-
return matches;
|
|
30644
|
+
} else {
|
|
30645
|
+
const op = typeof looseCondition.operator === "string" ? looseCondition.operator : "(unset)";
|
|
30646
|
+
const source = field ? `'${String(resolvedType)}', resolved from field '${fieldKey}'` : resolvedType === void 0 ? `missing, and field '${fieldKey}' is not on this table to resolve it from` : `'${String(resolvedType)}', stated on the condition (field '${fieldKey}' is not on this table)`;
|
|
30647
|
+
throw new Error(
|
|
30648
|
+
`Filter condition cannot be evaluated: filter type ${source} has no evaluator. Evaluable: text, number, date, boolean, select, select_member, select_record_link, files, locked. Condition operator was "${op}".`
|
|
30649
|
+
);
|
|
30650
|
+
}
|
|
30651
|
+
return matches;
|
|
30652
|
+
}
|
|
30653
|
+
|
|
30654
|
+
// ../shared/src/record_filter_truth.ts
|
|
30655
|
+
var BY_VIEWER = /* @__PURE__ */ new Set(["is_current_member", "is_not_current_member"]);
|
|
30656
|
+
function condition(node, subject) {
|
|
30657
|
+
if (node.type === "locked" || node.type === "record_id" || node.type === "current_member") return "unknown";
|
|
30658
|
+
if (node.field_key === void 0 || node.unit_option !== void 0) return "unknown";
|
|
30659
|
+
if (typeof node.value === "string" && node.value.includes("{{")) return "unknown";
|
|
30660
|
+
if (BY_VIEWER.has(node.operator) && subject.member_id === null) return "unknown";
|
|
30661
|
+
if (FILE_NAME_OPERATORS.has(node.operator)) return "unknown";
|
|
30662
|
+
const field = subject.field(node.field_key);
|
|
30663
|
+
const held2 = subject.cell(node.field_key);
|
|
30664
|
+
if (field === void 0 || held2 === void 0) return "unknown";
|
|
30665
|
+
const decided = evaluateCondition(
|
|
30666
|
+
{ data: { [node.field_key]: held2.value } },
|
|
30667
|
+
{ [node.field_key]: field },
|
|
30668
|
+
node,
|
|
30669
|
+
subject.member_id === null ? null : { member_id: subject.member_id, group_ids: [] }
|
|
30670
|
+
);
|
|
30671
|
+
return decided === null ? "unknown" : decided;
|
|
30672
|
+
}
|
|
30673
|
+
function recordFilterTruth(filter2, subject) {
|
|
30674
|
+
switch (filter2.node_type) {
|
|
30675
|
+
case "condition":
|
|
30676
|
+
return condition(filter2, subject);
|
|
30677
|
+
case "traversal":
|
|
30678
|
+
return "unknown";
|
|
30679
|
+
case "group": {
|
|
30680
|
+
const each = filter2.children.map((child) => recordFilterTruth(child, subject));
|
|
30681
|
+
if (filter2.logic === "and") {
|
|
30682
|
+
if (each.includes(false)) return false;
|
|
30683
|
+
return each.every((one) => one === true) ? true : "unknown";
|
|
30684
|
+
}
|
|
30685
|
+
if (each.includes(true)) return true;
|
|
30686
|
+
return each.every((one) => one === false) ? false : "unknown";
|
|
30687
|
+
}
|
|
30688
|
+
}
|
|
30689
|
+
}
|
|
30690
|
+
|
|
30691
|
+
// ../shared/src/interpolate.ts
|
|
30692
|
+
function interpolateObject(obj, context) {
|
|
30693
|
+
if (obj === null || obj === void 0) {
|
|
30694
|
+
return obj;
|
|
30695
|
+
}
|
|
30696
|
+
if (typeof obj === "string") {
|
|
30697
|
+
const expressionMatches = obj.match(/\{\{.*?\}\}/g);
|
|
30698
|
+
if (expressionMatches && expressionMatches.length > 0) {
|
|
30699
|
+
if (expressionMatches.length === 1 && obj === expressionMatches[0]) {
|
|
30700
|
+
const expression = obj.slice(2, -2).trim();
|
|
30701
|
+
return evaluateJsExpression(expression, context);
|
|
30702
|
+
}
|
|
30703
|
+
const parts = obj.split(/(\{\{.*?\}\})/g);
|
|
30704
|
+
const evaluatedParts = parts.map((part) => {
|
|
30705
|
+
if (part.startsWith("{{") && part.endsWith("}}")) {
|
|
30706
|
+
const expression = part.slice(2, -2).trim();
|
|
30707
|
+
const result = evaluateJsExpression(expression, context);
|
|
30708
|
+
return result != null ? String(result) : "";
|
|
30709
|
+
}
|
|
30710
|
+
return part;
|
|
30711
|
+
});
|
|
30712
|
+
return evaluatedParts.join("");
|
|
30713
|
+
}
|
|
30714
|
+
return obj;
|
|
30715
|
+
}
|
|
30716
|
+
if (Array.isArray(obj)) {
|
|
30717
|
+
return obj.map((item) => interpolateObject(item, context));
|
|
30718
|
+
}
|
|
30719
|
+
if (typeof obj === "object") {
|
|
30720
|
+
const result = {};
|
|
30721
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
30722
|
+
result[key] = interpolateObject(value, context);
|
|
30723
|
+
}
|
|
30724
|
+
return result;
|
|
30725
|
+
}
|
|
30726
|
+
return obj;
|
|
30727
|
+
}
|
|
30728
|
+
|
|
30729
|
+
// ../shared/src/app_query_ast.ts
|
|
30730
|
+
function collectParamTokens(node, found) {
|
|
30731
|
+
if (typeof node === "string") {
|
|
30732
|
+
for (const tok of node.matchAll(/\{\{(.*?)\}\}/g)) {
|
|
30733
|
+
for (const m of tok[1].matchAll(/\bparams\.([a-zA-Z_$][\w$]*)/g)) {
|
|
30734
|
+
found.add(m[1]);
|
|
30735
|
+
}
|
|
30736
|
+
}
|
|
30737
|
+
return;
|
|
30738
|
+
}
|
|
30739
|
+
if (Array.isArray(node)) {
|
|
30740
|
+
for (const item of node) collectParamTokens(item, found);
|
|
30741
|
+
return;
|
|
30742
|
+
}
|
|
30743
|
+
if (node && typeof node === "object") {
|
|
30744
|
+
for (const value of Object.values(node)) collectParamTokens(value, found);
|
|
30745
|
+
}
|
|
30746
|
+
}
|
|
30747
|
+
function paramTokens(node) {
|
|
30748
|
+
const tokens = /* @__PURE__ */ new Set();
|
|
30749
|
+
collectParamTokens(node, tokens);
|
|
30750
|
+
return tokens;
|
|
30751
|
+
}
|
|
30752
|
+
function pruneFilterTree(filter2, survives) {
|
|
30753
|
+
if (filter2.node_type === "group") {
|
|
30754
|
+
const children = filter2.children.map((child) => pruneFilterTree(child, survives)).filter((c) => c !== void 0);
|
|
30755
|
+
if (children.length === 0) return void 0;
|
|
30756
|
+
return { ...filter2, children };
|
|
30757
|
+
}
|
|
30758
|
+
return survives.leaf(filter2) ? filter2 : void 0;
|
|
30759
|
+
}
|
|
30760
|
+
function statedParamNames(params) {
|
|
30761
|
+
return new Set(Object.keys(params).filter((name) => !isUnstatedFilterValue(params[name])));
|
|
30762
|
+
}
|
|
30763
|
+
function statesNothing(leaf, params) {
|
|
30764
|
+
const filled = interpolateObject(leaf.node_type === "traversal" ? leaf.condition : leaf, { params });
|
|
30765
|
+
return isUnstatedConditionValue(filled.operator, filled.value);
|
|
30766
|
+
}
|
|
30767
|
+
function searchStatesNothing(search, params) {
|
|
30768
|
+
const filled = interpolateObject(search, { params });
|
|
30769
|
+
return typeof filled === "string" && searchWords(filled).length === 0;
|
|
30770
|
+
}
|
|
30771
|
+
function survivesCall(params) {
|
|
30772
|
+
const stated = statedParamNames(params);
|
|
30773
|
+
const readsOnlyStated = (node) => {
|
|
30774
|
+
const tokens = paramTokens(node);
|
|
30775
|
+
if (tokens.size === 0) return void 0;
|
|
30776
|
+
return [...tokens].every((name) => stated.has(name));
|
|
30777
|
+
};
|
|
30778
|
+
return {
|
|
30779
|
+
leaf: (leaf) => {
|
|
30780
|
+
const reads = readsOnlyStated(leaf);
|
|
30781
|
+
return reads === void 0 || reads && !statesNothing(leaf, params);
|
|
30782
|
+
},
|
|
30783
|
+
search: (search) => {
|
|
30784
|
+
const reads = readsOnlyStated(search);
|
|
30785
|
+
return reads === void 0 || reads && !searchStatesNothing(search, params);
|
|
30786
|
+
}
|
|
30787
|
+
};
|
|
30788
|
+
}
|
|
30789
|
+
function filterForCall(filter2, params) {
|
|
30790
|
+
const pruned = pruneFilterTree(filter2, survivesCall(params));
|
|
30791
|
+
return pruned === void 0 ? void 0 : interpolateObject(pruned, { params });
|
|
30313
30792
|
}
|
|
30314
30793
|
|
|
30315
|
-
// ../shared/src/
|
|
30316
|
-
|
|
30317
|
-
|
|
30318
|
-
|
|
30319
|
-
|
|
30320
|
-
|
|
30321
|
-
|
|
30322
|
-
|
|
30323
|
-
|
|
30324
|
-
|
|
30325
|
-
|
|
30326
|
-
|
|
30327
|
-
|
|
30328
|
-
|
|
30329
|
-
|
|
30330
|
-
|
|
30331
|
-
|
|
30332
|
-
|
|
30794
|
+
// ../shared/src/app_query_output_schema.ts
|
|
30795
|
+
function fieldTypeToColumnType(field) {
|
|
30796
|
+
switch (field.type) {
|
|
30797
|
+
case "text":
|
|
30798
|
+
return "text";
|
|
30799
|
+
case "number":
|
|
30800
|
+
return "number";
|
|
30801
|
+
case "boolean":
|
|
30802
|
+
return "boolean";
|
|
30803
|
+
case "date":
|
|
30804
|
+
return field.format === "datetime" || field.format === "datetime_range" ? "datetime" : "date";
|
|
30805
|
+
case "select":
|
|
30806
|
+
return "select";
|
|
30807
|
+
case "select_member":
|
|
30808
|
+
return "select_member";
|
|
30809
|
+
case "select_record_link":
|
|
30810
|
+
return "select_record_link";
|
|
30811
|
+
case "files":
|
|
30812
|
+
return "files";
|
|
30813
|
+
case "rollup":
|
|
30814
|
+
return rollupColumnType(field);
|
|
30815
|
+
case "lookup":
|
|
30816
|
+
return lookupOutputType(field);
|
|
30817
|
+
case "formula":
|
|
30818
|
+
return formulaOutputType(field);
|
|
30819
|
+
case "button":
|
|
30820
|
+
return "json";
|
|
30821
|
+
case "autonumber":
|
|
30822
|
+
return "text";
|
|
30823
|
+
default: {
|
|
30824
|
+
const _exhaustive = field;
|
|
30825
|
+
void _exhaustive;
|
|
30826
|
+
return "json";
|
|
30827
|
+
}
|
|
30828
|
+
}
|
|
30333
30829
|
}
|
|
30334
|
-
function
|
|
30335
|
-
switch (
|
|
30336
|
-
case "
|
|
30337
|
-
return
|
|
30338
|
-
case "
|
|
30339
|
-
return "
|
|
30340
|
-
case "
|
|
30341
|
-
|
|
30342
|
-
|
|
30343
|
-
|
|
30344
|
-
|
|
30830
|
+
function formulaOutputType(field) {
|
|
30831
|
+
switch (field.formula.output_type) {
|
|
30832
|
+
case "number":
|
|
30833
|
+
return "number";
|
|
30834
|
+
case "boolean":
|
|
30835
|
+
return "boolean";
|
|
30836
|
+
case "date":
|
|
30837
|
+
return "date";
|
|
30838
|
+
case "datetime":
|
|
30839
|
+
return "datetime";
|
|
30840
|
+
case "text":
|
|
30841
|
+
return "text";
|
|
30842
|
+
case "select":
|
|
30843
|
+
return "select";
|
|
30844
|
+
default:
|
|
30845
|
+
return "json";
|
|
30846
|
+
}
|
|
30847
|
+
}
|
|
30848
|
+
function rollupColumnType(field) {
|
|
30849
|
+
if (rollupOutputType(field.aggregate_option.operation) === "number") return "number";
|
|
30850
|
+
return field.aggregate_field_format === "datetime" || field.aggregate_field_format === "datetime_range" ? "datetime" : "date";
|
|
30851
|
+
}
|
|
30852
|
+
function lookupOutputType(field) {
|
|
30853
|
+
const t = field.lookup_field_type;
|
|
30854
|
+
if (!t) return "json";
|
|
30855
|
+
switch (t) {
|
|
30856
|
+
case "text":
|
|
30857
|
+
return "text";
|
|
30858
|
+
case "number":
|
|
30859
|
+
return "number";
|
|
30860
|
+
case "boolean":
|
|
30861
|
+
return "boolean";
|
|
30862
|
+
case "date":
|
|
30863
|
+
return field.lookup_field_format === "datetime" || field.lookup_field_format === "datetime_range" ? "datetime" : "date";
|
|
30864
|
+
case "select":
|
|
30865
|
+
return "select";
|
|
30866
|
+
case "select_member":
|
|
30867
|
+
return "select_member";
|
|
30868
|
+
case "select_record_link":
|
|
30869
|
+
return "select_record_link";
|
|
30870
|
+
case "files":
|
|
30871
|
+
return "files";
|
|
30872
|
+
default:
|
|
30873
|
+
return "json";
|
|
30874
|
+
}
|
|
30875
|
+
}
|
|
30876
|
+
|
|
30877
|
+
// ../shared/src/field_value.ts
|
|
30878
|
+
function fieldValueInfo(field) {
|
|
30879
|
+
switch (field.type) {
|
|
30880
|
+
case "number":
|
|
30881
|
+
return { type: "number", notation: fieldNotation(field) };
|
|
30882
|
+
case "text":
|
|
30883
|
+
return { type: "text", format: field.format };
|
|
30884
|
+
case "date":
|
|
30885
|
+
return { type: "date", format: field.format };
|
|
30886
|
+
case "select":
|
|
30887
|
+
return { type: "select", options: field.options };
|
|
30888
|
+
case "formula": {
|
|
30889
|
+
const output = field.formula?.output_type;
|
|
30890
|
+
if (field.formula.options !== void 0) return { type: "select", options: field.formula.options };
|
|
30891
|
+
if (output === "date" || output === "datetime") {
|
|
30892
|
+
return { type: "date", format: output === "datetime" ? "datetime" : "date" };
|
|
30345
30893
|
}
|
|
30346
|
-
if (
|
|
30347
|
-
|
|
30894
|
+
if (output === "boolean") return { type: "boolean" };
|
|
30895
|
+
if (output === "text") return { type: "text", format: formulaLinks(field.formula) ? "link" : void 0 };
|
|
30896
|
+
return { type: "number", notation: fieldNotation(field) };
|
|
30897
|
+
}
|
|
30898
|
+
case "rollup": {
|
|
30899
|
+
const type = rollupOutputType(field.aggregate_option.operation);
|
|
30900
|
+
return type === "number" ? { type, notation: fieldNotation(field) } : { type, format: field.aggregate_field_format };
|
|
30348
30901
|
}
|
|
30902
|
+
case "lookup":
|
|
30903
|
+
return {
|
|
30904
|
+
type: field.lookup_field_type ?? "text",
|
|
30905
|
+
...field.lookup_field_type === "number" ? { notation: fieldNotation(field) } : { format: field.lookup_field_format },
|
|
30906
|
+
options: field.lookup_field_options,
|
|
30907
|
+
autonumber: field.lookup_field_autonumber
|
|
30908
|
+
};
|
|
30909
|
+
// The cell stores the composed DISPLAY string ("KH-001"), never the counter.
|
|
30910
|
+
case "autonumber":
|
|
30911
|
+
return { type: "text", autonumber: true };
|
|
30912
|
+
default:
|
|
30913
|
+
return { type: field.type };
|
|
30349
30914
|
}
|
|
30350
30915
|
}
|
|
30351
30916
|
|
|
30352
30917
|
// ../shared/src/field_comparison.ts
|
|
30353
|
-
var
|
|
30354
|
-
|
|
30355
|
-
|
|
30356
|
-
|
|
30357
|
-
|
|
30358
|
-
|
|
30359
|
-
"rollup",
|
|
30360
|
-
"files"
|
|
30361
|
-
]);
|
|
30362
|
-
function isArrayFieldEmpty(value) {
|
|
30363
|
-
if (value === void 0 || value === null) {
|
|
30364
|
-
return true;
|
|
30365
|
-
}
|
|
30366
|
-
if (!Array.isArray(value)) {
|
|
30367
|
-
return false;
|
|
30918
|
+
var MemberNamesUnavailableError = class extends Error {
|
|
30919
|
+
constructor(fieldKey) {
|
|
30920
|
+
super(
|
|
30921
|
+
`Comparing "${fieldKey}" orders members by name, and its cells hold member ids \u2014 the workspace's member names must be supplied to compare them.`
|
|
30922
|
+
);
|
|
30923
|
+
this.name = "MemberNamesUnavailableError";
|
|
30368
30924
|
}
|
|
30369
|
-
|
|
30370
|
-
|
|
30925
|
+
};
|
|
30926
|
+
function firstMember(cell) {
|
|
30927
|
+
const first2 = Array.isArray(cell) ? cell[0] : void 0;
|
|
30928
|
+
return typeof first2 === "string" ? first2 : void 0;
|
|
30929
|
+
}
|
|
30930
|
+
function firstLink(cell) {
|
|
30931
|
+
const first2 = Array.isArray(cell) ? cell[0] : void 0;
|
|
30932
|
+
if (typeof first2 !== "object" || first2 === null || !("id" in first2) || typeof first2.id !== "string") return void 0;
|
|
30933
|
+
const display = "display" in first2 && typeof first2.display === "string" ? first2.display : "";
|
|
30934
|
+
return { name: display, id: first2.id };
|
|
30935
|
+
}
|
|
30936
|
+
function folded(text2) {
|
|
30937
|
+
return text2.trim().toLowerCase();
|
|
30938
|
+
}
|
|
30939
|
+
function compareNamed(a, b) {
|
|
30940
|
+
const byName = folded(a.name).localeCompare(folded(b.name), "en-US");
|
|
30941
|
+
return byName !== 0 ? byName : a.id.localeCompare(b.id, "en-US");
|
|
30942
|
+
}
|
|
30943
|
+
function optionRank(cell, options) {
|
|
30944
|
+
const first2 = Array.isArray(cell) ? cell[0] : void 0;
|
|
30945
|
+
if (first2 === void 0 || first2 === null) return void 0;
|
|
30946
|
+
const at2 = options.findIndex((option) => option.key === first2);
|
|
30947
|
+
return { by: "figure", value: at2 === -1 ? options.length : at2 };
|
|
30948
|
+
}
|
|
30949
|
+
function valueRank(cell, type) {
|
|
30950
|
+
if (cell === void 0 || cell === null) return void 0;
|
|
30951
|
+
switch (type) {
|
|
30952
|
+
case "number":
|
|
30953
|
+
return typeof cell === "number" && Number.isFinite(cell) ? { by: "figure", value: cell } : void 0;
|
|
30954
|
+
case "boolean":
|
|
30955
|
+
return typeof cell === "boolean" ? { by: "figure", value: cell ? 1 : 0 } : void 0;
|
|
30956
|
+
case "date":
|
|
30957
|
+
case "datetime":
|
|
30958
|
+
return typeof cell === "string" && /^\d{4}/.test(cell) ? { by: "day", value: cell } : void 0;
|
|
30959
|
+
case "text":
|
|
30960
|
+
return { by: "text", value: folded(String(cell)) };
|
|
30961
|
+
case "select_member": {
|
|
30962
|
+
const id = firstMember(cell);
|
|
30963
|
+
return id === void 0 ? void 0 : { by: "member", id };
|
|
30964
|
+
}
|
|
30965
|
+
case "select_record_link": {
|
|
30966
|
+
const link2 = firstLink(cell);
|
|
30967
|
+
return link2 === void 0 ? void 0 : { by: "name", value: link2 };
|
|
30968
|
+
}
|
|
30969
|
+
case "files":
|
|
30970
|
+
return Array.isArray(cell) ? { by: "figure", value: cell.length } : void 0;
|
|
30971
|
+
case "select":
|
|
30972
|
+
case "json":
|
|
30973
|
+
return typeof cell === "number" ? { by: "figure", value: cell } : { by: "text", value: folded(String(cell)) };
|
|
30974
|
+
}
|
|
30975
|
+
}
|
|
30976
|
+
function autonumberTerms(cell) {
|
|
30977
|
+
if (cell === void 0 || cell === null) return [void 0, void 0];
|
|
30978
|
+
const text2 = String(cell);
|
|
30979
|
+
return /^-?\d+$/.test(text2) ? [{ by: "figure", value: Number(text2) }, void 0] : [void 0, { by: "text", value: text2 }];
|
|
30980
|
+
}
|
|
30981
|
+
function termsOf(cell, field) {
|
|
30982
|
+
const value = field.type === "lookup" && Array.isArray(cell) ? cell[0] : cell;
|
|
30983
|
+
if (fieldValueInfo(field).autonumber === true) return autonumberTerms(value);
|
|
30984
|
+
const options = effectiveSelectOptions(field);
|
|
30985
|
+
return [options === null ? valueRank(value, fieldTypeToColumnType(field)) : optionRank(value, options)];
|
|
30986
|
+
}
|
|
30987
|
+
function rankText(rank) {
|
|
30988
|
+
if (rank.by === "name") return folded(rank.value.name);
|
|
30989
|
+
if (rank.by === "member") return rank.id;
|
|
30990
|
+
return String(rank.value);
|
|
30991
|
+
}
|
|
30992
|
+
function compareFieldValues(aValue, bValue, field, { blank = "bottom", order = "asc", memberNames } = {}) {
|
|
30993
|
+
if (aValue === bValue) return 0;
|
|
30994
|
+
const a = termsOf(aValue, field);
|
|
30995
|
+
const b = termsOf(bValue, field);
|
|
30996
|
+
const member = (id) => {
|
|
30997
|
+
if (memberNames === void 0) throw new MemberNamesUnavailableError(field.key);
|
|
30998
|
+
return { name: memberNames.get(id) ?? "", id };
|
|
30999
|
+
};
|
|
31000
|
+
for (const [at2, left] of a.entries()) {
|
|
31001
|
+
const right = b[at2];
|
|
31002
|
+
if (left === void 0 && right === void 0) continue;
|
|
31003
|
+
if (left === void 0) return blank === "top" ? -1 : 1;
|
|
31004
|
+
if (right === void 0) return blank === "top" ? 1 : -1;
|
|
31005
|
+
const compared = compareRanks(left, right, member);
|
|
31006
|
+
if (compared !== 0) return order === "asc" ? compared : -compared;
|
|
30371
31007
|
}
|
|
30372
|
-
return
|
|
31008
|
+
return 0;
|
|
30373
31009
|
}
|
|
30374
|
-
function
|
|
30375
|
-
if (
|
|
30376
|
-
|
|
30377
|
-
|
|
30378
|
-
|
|
30379
|
-
|
|
30380
|
-
const aSelectArray = Array.isArray(aValue) ? aValue : null;
|
|
30381
|
-
const bSelectArray = Array.isArray(bValue) ? bValue : null;
|
|
30382
|
-
const aSelectValue = aSelectArray?.[0];
|
|
30383
|
-
const bSelectValue = bSelectArray?.[0];
|
|
30384
|
-
const aIsEmpty2 = isArrayFieldEmpty(aSelectArray);
|
|
30385
|
-
const bIsEmpty2 = isArrayFieldEmpty(bSelectArray);
|
|
30386
|
-
if (aIsEmpty2 && bIsEmpty2) {
|
|
30387
|
-
return 0;
|
|
30388
|
-
}
|
|
30389
|
-
if (aIsEmpty2) {
|
|
30390
|
-
return blankPosition === "top" ? -1 : 1;
|
|
30391
|
-
}
|
|
30392
|
-
if (bIsEmpty2) {
|
|
30393
|
-
return blankPosition === "top" ? 1 : -1;
|
|
30394
|
-
}
|
|
30395
|
-
const aIndex = options.findIndex((option) => option.key === aSelectValue);
|
|
30396
|
-
const bIndex = options.findIndex((option) => option.key === bSelectValue);
|
|
30397
|
-
const aPosition = aIndex === -1 ? Number.MAX_SAFE_INTEGER : aIndex;
|
|
30398
|
-
const bPosition = bIndex === -1 ? Number.MAX_SAFE_INTEGER : bIndex;
|
|
30399
|
-
const diff = aPosition - bPosition;
|
|
30400
|
-
return order === "asc" ? diff : -diff;
|
|
30401
|
-
}
|
|
30402
|
-
const aIsEmpty = aValue === void 0 || aValue === null;
|
|
30403
|
-
const bIsEmpty = bValue === void 0 || bValue === null;
|
|
30404
|
-
if (aIsEmpty && bIsEmpty) {
|
|
30405
|
-
return 0;
|
|
30406
|
-
}
|
|
30407
|
-
if (aIsEmpty) {
|
|
30408
|
-
return blankPosition === "top" ? -1 : 1;
|
|
30409
|
-
}
|
|
30410
|
-
if (bIsEmpty) {
|
|
30411
|
-
return blankPosition === "top" ? 1 : -1;
|
|
30412
|
-
}
|
|
30413
|
-
if (field.type === "number" || field.type === "rollup" || field.type === "formula") {
|
|
30414
|
-
const diff = aValue - bValue;
|
|
30415
|
-
return order === "asc" ? diff : -diff;
|
|
30416
|
-
}
|
|
30417
|
-
if (field.type === "boolean") {
|
|
30418
|
-
const aBool = aValue;
|
|
30419
|
-
const bBool = bValue;
|
|
30420
|
-
if (aBool === bBool) return 0;
|
|
30421
|
-
const diff = aBool === true ? 1 : -1;
|
|
30422
|
-
return order === "asc" ? diff : -diff;
|
|
30423
|
-
}
|
|
30424
|
-
if (field.type === "date") {
|
|
30425
|
-
const aStr = String(aValue);
|
|
30426
|
-
const bStr = String(bValue);
|
|
30427
|
-
const cmp = aStr < bStr ? -1 : aStr > bStr ? 1 : 0;
|
|
30428
|
-
return order === "asc" ? cmp : -cmp;
|
|
30429
|
-
}
|
|
30430
|
-
if (field.type === "files") {
|
|
30431
|
-
const aFiles = aValue;
|
|
30432
|
-
const bFiles = bValue;
|
|
30433
|
-
const aLength = aFiles?.length || 0;
|
|
30434
|
-
const bLength = bFiles?.length || 0;
|
|
30435
|
-
const diff = aLength - bLength;
|
|
30436
|
-
return order === "asc" ? diff : -diff;
|
|
30437
|
-
}
|
|
30438
|
-
if (field.type === "select_member") {
|
|
30439
|
-
const aArray = aValue ?? [];
|
|
30440
|
-
const bArray = bValue ?? [];
|
|
30441
|
-
const aIsEmpty2 = isArrayFieldEmpty(aArray);
|
|
30442
|
-
const bIsEmpty2 = isArrayFieldEmpty(bArray);
|
|
30443
|
-
if (aIsEmpty2 && bIsEmpty2) {
|
|
30444
|
-
return 0;
|
|
30445
|
-
}
|
|
30446
|
-
if (aIsEmpty2) {
|
|
30447
|
-
return blankPosition === "top" ? -1 : 1;
|
|
30448
|
-
}
|
|
30449
|
-
if (bIsEmpty2) {
|
|
30450
|
-
return blankPosition === "top" ? 1 : -1;
|
|
30451
|
-
}
|
|
30452
|
-
const aString2 = String(aArray[0] || "");
|
|
30453
|
-
const bString2 = String(bArray[0] || "");
|
|
30454
|
-
const compareResult2 = aString2.localeCompare(bString2, "en-US");
|
|
30455
|
-
return order === "asc" ? compareResult2 : -compareResult2;
|
|
30456
|
-
}
|
|
30457
|
-
if (field.type === "select_record_link") {
|
|
30458
|
-
const aItems = aValue ?? [];
|
|
30459
|
-
const bItems = bValue ?? [];
|
|
30460
|
-
const aIsEmpty2 = aItems.length === 0;
|
|
30461
|
-
const bIsEmpty2 = bItems.length === 0;
|
|
30462
|
-
if (aIsEmpty2 && bIsEmpty2) {
|
|
30463
|
-
return 0;
|
|
30464
|
-
}
|
|
30465
|
-
if (aIsEmpty2) {
|
|
30466
|
-
return blankPosition === "top" ? -1 : 1;
|
|
30467
|
-
}
|
|
30468
|
-
if (bIsEmpty2) {
|
|
30469
|
-
return blankPosition === "top" ? 1 : -1;
|
|
30470
|
-
}
|
|
30471
|
-
const aString2 = aItems[0]?.display ?? "";
|
|
30472
|
-
const bString2 = bItems[0]?.display ?? "";
|
|
30473
|
-
const compareResult2 = aString2.localeCompare(bString2, "en-US");
|
|
30474
|
-
return order === "asc" ? compareResult2 : -compareResult2;
|
|
30475
|
-
}
|
|
30476
|
-
if (field.type === "lookup") {
|
|
30477
|
-
const lookupField = field;
|
|
30478
|
-
const aArr = Array.isArray(aValue) ? aValue : [aValue];
|
|
30479
|
-
const bArr = Array.isArray(bValue) ? bValue : [bValue];
|
|
30480
|
-
const aFirst = aArr[0] ?? null;
|
|
30481
|
-
const bFirst = bArr[0] ?? null;
|
|
30482
|
-
const sourceType = lookupField.lookup_field_type || "text";
|
|
30483
|
-
if (SIMPLE_LOOKUP_TYPES.has(sourceType)) {
|
|
30484
|
-
const syntheticField = { ...field, type: sourceType };
|
|
30485
|
-
return compareFieldValues(aFirst, bFirst, syntheticField, blankPosition, order);
|
|
30486
|
-
}
|
|
30487
|
-
const aString2 = String(aFirst ?? "");
|
|
30488
|
-
const bString2 = String(bFirst ?? "");
|
|
30489
|
-
const cmp = aString2.localeCompare(bString2, "en-US");
|
|
30490
|
-
return order === "asc" ? cmp : -cmp;
|
|
30491
|
-
}
|
|
30492
|
-
const aString = String(aValue || "");
|
|
30493
|
-
const bString = String(bValue || "");
|
|
30494
|
-
const compareResult = aString.localeCompare(bString, "en-US");
|
|
30495
|
-
return order === "asc" ? compareResult : -compareResult;
|
|
31010
|
+
function compareRanks(a, b, member) {
|
|
31011
|
+
if (a.by === "figure" && b.by === "figure") return a.value - b.value;
|
|
31012
|
+
if (a.by === "day" && b.by === "day") return a.value < b.value ? -1 : a.value > b.value ? 1 : 0;
|
|
31013
|
+
if (a.by === "name" && b.by === "name") return compareNamed(a.value, b.value);
|
|
31014
|
+
if (a.by === "member" && b.by === "member") return compareNamed(member(a.id), member(b.id));
|
|
31015
|
+
return rankText(a).localeCompare(rankText(b), "en-US");
|
|
30496
31016
|
}
|
|
30497
31017
|
|
|
30498
31018
|
// ../shared/src/formula_references.ts
|
|
@@ -30566,7 +31086,7 @@ function prepareFormulaContext(fields) {
|
|
|
30566
31086
|
nonFormulaFields
|
|
30567
31087
|
};
|
|
30568
31088
|
}
|
|
30569
|
-
function computeFormulaFieldsWithContext(row2, fields, context, linkedTableRecords = /* @__PURE__ */ new Map(), linkedTableFields = /* @__PURE__ */ new Map(), timezone, loadedLinkKeys, linkExpandedTableIds, fileFacts) {
|
|
31089
|
+
function computeFormulaFieldsWithContext(row2, fields, context, linkedTableRecords = /* @__PURE__ */ new Map(), linkedTableFields = /* @__PURE__ */ new Map(), timezone, loadedLinkKeys, linkExpandedTableIds, fileFacts, memberNames) {
|
|
30570
31090
|
const result = { ...row2 };
|
|
30571
31091
|
const mayRecompute = (linkKey) => loadedLinkKeys === void 0 || loadedLinkKeys.has(linkKey) || isEmptyFieldValue(row2[linkKey]);
|
|
30572
31092
|
for (const { field, sourceField } of context.rollupFields) {
|
|
@@ -30631,7 +31151,8 @@ function computeFormulaFieldsWithContext(row2, fields, context, linkedTableRecor
|
|
|
30631
31151
|
field.lookup_field_key,
|
|
30632
31152
|
linkedField,
|
|
30633
31153
|
field.order_by,
|
|
30634
|
-
linkedFieldsArray
|
|
31154
|
+
linkedFieldsArray,
|
|
31155
|
+
memberNames
|
|
30635
31156
|
);
|
|
30636
31157
|
result[field.key] = lookupValue;
|
|
30637
31158
|
} else {
|
|
@@ -30961,7 +31482,7 @@ function calculateRollupValue(value, fieldType, allLinkedTableRecords, aggregate
|
|
|
30961
31482
|
}
|
|
30962
31483
|
return aggregateByField(relevantRecords, fieldType, aggregateOption, subject).result;
|
|
30963
31484
|
}
|
|
30964
|
-
function calculateLookupValue(value, linkedRecords, lookupFieldKey, linkedField, orderBy, linkedFields) {
|
|
31485
|
+
function calculateLookupValue(value, linkedRecords, lookupFieldKey, linkedField, orderBy, linkedFields, memberNames) {
|
|
30965
31486
|
if (!linkedRecords.length || !lookupFieldKey) {
|
|
30966
31487
|
return null;
|
|
30967
31488
|
}
|
|
@@ -30986,13 +31507,11 @@ function calculateLookupValue(value, linkedRecords, lookupFieldKey, linkedField,
|
|
|
30986
31507
|
return null;
|
|
30987
31508
|
}
|
|
30988
31509
|
const picked = [...relevantRecords].sort((a, b) => {
|
|
30989
|
-
const cmp = compareFieldValues(
|
|
30990
|
-
|
|
30991
|
-
|
|
30992
|
-
|
|
30993
|
-
|
|
30994
|
-
orderBy.direction
|
|
30995
|
-
);
|
|
31510
|
+
const cmp = compareFieldValues(a.data[orderField.key], b.data[orderField.key], orderField, {
|
|
31511
|
+
blank: "bottom",
|
|
31512
|
+
order: orderBy.direction,
|
|
31513
|
+
memberNames
|
|
31514
|
+
});
|
|
30996
31515
|
if (cmp !== 0) return cmp;
|
|
30997
31516
|
if (a.created_at !== b.created_at) return a.created_at < b.created_at ? 1 : -1;
|
|
30998
31517
|
return a.id < b.id ? 1 : a.id > b.id ? -1 : 0;
|
|
@@ -31008,109 +31527,6 @@ function calculateLookupValue(value, linkedRecords, lookupFieldKey, linkedField,
|
|
|
31008
31527
|
return values2.length > 0 ? values2 : null;
|
|
31009
31528
|
}
|
|
31010
31529
|
|
|
31011
|
-
// ../shared/src/interpolate.ts
|
|
31012
|
-
function interpolateObject(obj, context) {
|
|
31013
|
-
if (obj === null || obj === void 0) {
|
|
31014
|
-
return obj;
|
|
31015
|
-
}
|
|
31016
|
-
if (typeof obj === "string") {
|
|
31017
|
-
const expressionMatches = obj.match(/\{\{.*?\}\}/g);
|
|
31018
|
-
if (expressionMatches && expressionMatches.length > 0) {
|
|
31019
|
-
if (expressionMatches.length === 1 && obj === expressionMatches[0]) {
|
|
31020
|
-
const expression = obj.slice(2, -2).trim();
|
|
31021
|
-
return evaluateJsExpression(expression, context);
|
|
31022
|
-
}
|
|
31023
|
-
const parts = obj.split(/(\{\{.*?\}\})/g);
|
|
31024
|
-
const evaluatedParts = parts.map((part) => {
|
|
31025
|
-
if (part.startsWith("{{") && part.endsWith("}}")) {
|
|
31026
|
-
const expression = part.slice(2, -2).trim();
|
|
31027
|
-
const result = evaluateJsExpression(expression, context);
|
|
31028
|
-
return result != null ? String(result) : "";
|
|
31029
|
-
}
|
|
31030
|
-
return part;
|
|
31031
|
-
});
|
|
31032
|
-
return evaluatedParts.join("");
|
|
31033
|
-
}
|
|
31034
|
-
return obj;
|
|
31035
|
-
}
|
|
31036
|
-
if (Array.isArray(obj)) {
|
|
31037
|
-
return obj.map((item) => interpolateObject(item, context));
|
|
31038
|
-
}
|
|
31039
|
-
if (typeof obj === "object") {
|
|
31040
|
-
const result = {};
|
|
31041
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
31042
|
-
result[key] = interpolateObject(value, context);
|
|
31043
|
-
}
|
|
31044
|
-
return result;
|
|
31045
|
-
}
|
|
31046
|
-
return obj;
|
|
31047
|
-
}
|
|
31048
|
-
|
|
31049
|
-
// ../shared/src/app_query_ast.ts
|
|
31050
|
-
function collectParamTokens(node, found) {
|
|
31051
|
-
if (typeof node === "string") {
|
|
31052
|
-
for (const tok of node.matchAll(/\{\{(.*?)\}\}/g)) {
|
|
31053
|
-
for (const m of tok[1].matchAll(/\bparams\.([a-zA-Z_$][\w$]*)/g)) {
|
|
31054
|
-
found.add(m[1]);
|
|
31055
|
-
}
|
|
31056
|
-
}
|
|
31057
|
-
return;
|
|
31058
|
-
}
|
|
31059
|
-
if (Array.isArray(node)) {
|
|
31060
|
-
for (const item of node) collectParamTokens(item, found);
|
|
31061
|
-
return;
|
|
31062
|
-
}
|
|
31063
|
-
if (node && typeof node === "object") {
|
|
31064
|
-
for (const value of Object.values(node)) collectParamTokens(value, found);
|
|
31065
|
-
}
|
|
31066
|
-
}
|
|
31067
|
-
function paramTokens(node) {
|
|
31068
|
-
const tokens = /* @__PURE__ */ new Set();
|
|
31069
|
-
collectParamTokens(node, tokens);
|
|
31070
|
-
return tokens;
|
|
31071
|
-
}
|
|
31072
|
-
function pruneFilterTree(filter2, survives) {
|
|
31073
|
-
if (filter2.node_type === "group") {
|
|
31074
|
-
const children = filter2.children.map((child) => pruneFilterTree(child, survives)).filter((c) => c !== void 0);
|
|
31075
|
-
if (children.length === 0) return void 0;
|
|
31076
|
-
return { ...filter2, children };
|
|
31077
|
-
}
|
|
31078
|
-
return survives.leaf(filter2) ? filter2 : void 0;
|
|
31079
|
-
}
|
|
31080
|
-
function statedParamNames(params) {
|
|
31081
|
-
return new Set(Object.keys(params).filter((name) => !isUnstatedFilterValue(params[name])));
|
|
31082
|
-
}
|
|
31083
|
-
function statesNothing(leaf, params) {
|
|
31084
|
-
const filled = interpolateObject(leaf.node_type === "traversal" ? leaf.condition : leaf, { params });
|
|
31085
|
-
return isUnstatedConditionValue(filled.operator, filled.value);
|
|
31086
|
-
}
|
|
31087
|
-
function searchStatesNothing(search, params) {
|
|
31088
|
-
const filled = interpolateObject(search, { params });
|
|
31089
|
-
return typeof filled === "string" && searchWords(filled).length === 0;
|
|
31090
|
-
}
|
|
31091
|
-
function survivesCall(params) {
|
|
31092
|
-
const stated = statedParamNames(params);
|
|
31093
|
-
const readsOnlyStated = (node) => {
|
|
31094
|
-
const tokens = paramTokens(node);
|
|
31095
|
-
if (tokens.size === 0) return void 0;
|
|
31096
|
-
return [...tokens].every((name) => stated.has(name));
|
|
31097
|
-
};
|
|
31098
|
-
return {
|
|
31099
|
-
leaf: (leaf) => {
|
|
31100
|
-
const reads = readsOnlyStated(leaf);
|
|
31101
|
-
return reads === void 0 || reads && !statesNothing(leaf, params);
|
|
31102
|
-
},
|
|
31103
|
-
search: (search) => {
|
|
31104
|
-
const reads = readsOnlyStated(search);
|
|
31105
|
-
return reads === void 0 || reads && !searchStatesNothing(search, params);
|
|
31106
|
-
}
|
|
31107
|
-
};
|
|
31108
|
-
}
|
|
31109
|
-
function filterForCall(filter2, params) {
|
|
31110
|
-
const pruned = pruneFilterTree(filter2, survivesCall(params));
|
|
31111
|
-
return pruned === void 0 ? void 0 : interpolateObject(pruned, { params });
|
|
31112
|
-
}
|
|
31113
|
-
|
|
31114
31530
|
// src/overlay.ts
|
|
31115
31531
|
var NONE2 = /* @__PURE__ */ new Set();
|
|
31116
31532
|
function fieldKeyOf(shape, column, tableId) {
|