Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ jobs:
path: |
/home/linuxbrew/.linuxbrew
~/.cache/Homebrew
key: ${{ runner.os }}-homebrew-fragment-cli
# v2: the previous key holds a Homebrew too old to pour current bottles.
key: ${{ runner.os }}-homebrew-fragment-cli-v2
restore-keys: |
${{ runner.os }}-homebrew-

Expand All @@ -63,6 +64,11 @@ jobs:
fi
echo "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" >> $GITHUB_ENV
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
# The cache restores whatever Homebrew was current when the key was first
# written, and the runner disables auto-update. A months-old Homebrew
# cannot pour a current bottle -- it fails with `unknown install step:
# run` -- so bring Homebrew itself up to date before installing.
/home/linuxbrew/.linuxbrew/bin/brew update --quiet
/home/linuxbrew/.linuxbrew/bin/brew tap fragment-dev/tap || true
if ! /home/linuxbrew/.linuxbrew/bin/brew list fragment-dev/tap/fragment-cli &>/dev/null; then
/home/linuxbrew/.linuxbrew/bin/brew install fragment-dev/tap/fragment-cli
Expand Down
39 changes: 39 additions & 0 deletions src/typedBatchEntries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/
import {
Kind,
parseType,
valueFromASTUntyped,
type DocumentNode,
type ListTypeNode,
Expand Down Expand Up @@ -114,6 +115,28 @@ const defaultWarn: Warn = (message) => {
*/
const DERIVED_ENTRY_FIELDS = ["type", "typeVersion", "parameters"];

/**
* The `LedgerEntryInput` fields every payload exposes, whatever its operation
* binds, with their declared types (spec 2.3a).
*
* Deliberately not derived from the operation. An operation binds only the entry
* fields the CLI version that generated it chose to expose, and that choice has
* already changed between versions -- so deriving the set would invent a
* restriction the API does not have, and would move a payload's surface whenever
* the CLI changed. A payload travels as an `AddLedgerEntryInput`, so what the
* operation binds places no limit on what the payload may carry.
*
* `ik` and `ledgerIk` are always present already. `lines` is excluded: it cannot
* be combined with an entry that has a `type`.
*/
const COMMON_ENTRY_FIELDS: ReadonlyArray<{ name: string; type: string }> = [
{ name: "posted", type: "DateTime" },
{ name: "description", type: "String" },
{ name: "tags", type: "[LedgerEntryTagInput!]" },
{ name: "groups", type: "[LedgerEntryGroupInput!]" },
{ name: "conditions", type: "[LedgerEntryConditionInput!]" },
];

const findObjectField = (object: ObjectValueNode, name: string) =>
object.fields.find((field) => field.name.value === name);

Expand Down Expand Up @@ -265,6 +288,22 @@ const getFields = (
});
});

// Spec 2.3a: every payload carries these, whether or not its operation binds
// them. Appended rather than interleaved, so the operation's own fields keep
// their source order.
COMMON_ENTRY_FIELDS.forEach(({ name, type }) => {
if (fields.some((field) => field.name === name)) {
return;
}
fields.push({
name,
wireName: name,
source: "variable",
type: parseType(type),
required: false,
});
});

return fields;
};

Expand Down
33 changes: 33 additions & 0 deletions tests/__snapshots__/typed-batch-entries.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ export type UserFundsAccountV1 = {
ik: Scalars['SafeString']['input'];
/** The Idempotency Key of the Ledger to add this Ledger Entry to. */
ledgerIk: Scalars['SafeString']['input'];
/** ISO 8601 timestamp to post this Ledger Entry at. */
posted?: Scalars['DateTime']['input'] | undefined;
description?: Scalars['String']['input'] | undefined;
tags?: Array<LedgerEntryTagInput> | undefined;
groups?: Array<LedgerEntryGroupInput> | undefined;
conditions?: Array<LedgerEntryConditionInput> | undefined;
parameters: {
amount: Scalars['String']['input'];
};
Expand All @@ -40,10 +46,15 @@ export const userFundsAccountV1 = (
input: UserFundsAccountV1,
): AddLedgerEntryInput => ({
entry: {
...(input.conditions !== undefined && { conditions: input.conditions }),
...(input.description !== undefined && { description: input.description }),
...(input.groups !== undefined && { groups: input.groups }),
ledger: { ik: input.ledgerIk },
parameters: {
amount: input.parameters.amount,
},
...(input.posted !== undefined && { posted: input.posted }),
...(input.tags !== undefined && { tags: input.tags }),
type: 'user-funds-account',
typeVersion: 1,
},
Expand All @@ -61,6 +72,12 @@ export type UserFundsAccountV2 = {
ik: Scalars['SafeString']['input'];
/** The Idempotency Key of the Ledger to add this Ledger Entry to. */
ledgerIk: Scalars['SafeString']['input'];
/** ISO 8601 timestamp to post this Ledger Entry at. */
posted?: Scalars['DateTime']['input'] | undefined;
description?: Scalars['String']['input'] | undefined;
tags?: Array<LedgerEntryTagInput> | undefined;
groups?: Array<LedgerEntryGroupInput> | undefined;
conditions?: Array<LedgerEntryConditionInput> | undefined;
parameters: {
amount: Scalars['String']['input'];
feeAmount: Scalars['Int64']['input'];
Expand All @@ -73,12 +90,17 @@ export const userFundsAccountV2 = (
input: UserFundsAccountV2,
): AddLedgerEntryInput => ({
entry: {
...(input.conditions !== undefined && { conditions: input.conditions }),
...(input.description !== undefined && { description: input.description }),
...(input.groups !== undefined && { groups: input.groups }),
ledger: { ik: input.ledgerIk },
parameters: {
amount: input.parameters.amount,
feeAmount: input.parameters.feeAmount,
...(input.parameters.memo !== undefined && { memo: input.parameters.memo }),
},
...(input.posted !== undefined && { posted: input.posted }),
...(input.tags !== undefined && { tags: input.tags }),
type: 'user-funds-account',
typeVersion: 2,
},
Expand All @@ -96,6 +118,12 @@ export type RuntimeThingV1 = {
ik: Scalars['SafeString']['input'];
/** The Idempotency Key of the Ledger to add this Ledger Entry to. */
ledgerIk: Scalars['SafeString']['input'];
/** ISO 8601 timestamp to post this Ledger Entry at. */
posted?: Scalars['DateTime']['input'] | undefined;
description?: Scalars['String']['input'] | undefined;
tags?: Array<LedgerEntryTagInput> | undefined;
groups?: Array<LedgerEntryGroupInput> | undefined;
conditions?: Array<LedgerEntryConditionInput> | undefined;
/**
* This entry type's operation does not bind its parameters to typed
* variables, so they cannot be typed individually.
Expand All @@ -108,8 +136,13 @@ export const runtimeThingV1 = (
input: RuntimeThingV1,
): AddLedgerEntryInput => ({
entry: {
...(input.conditions !== undefined && { conditions: input.conditions }),
...(input.description !== undefined && { description: input.description }),
...(input.groups !== undefined && { groups: input.groups }),
ledger: { ik: input.ledgerIk },
parameters: input.parameters,
...(input.posted !== undefined && { posted: input.posted }),
...(input.tags !== undefined && { tags: input.tags }),
type: 'runtime-thing',
typeVersion: 1,
},
Expand Down
46 changes: 46 additions & 0 deletions tests/fixtures/generated-edge-case-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3493,17 +3493,23 @@ export type RuntimeLinesV1 = {
description?: Scalars['String']['input'] | undefined;
/** The Ledger Lines to create, for entry types whose lines the Schema does not fix. */
lines: Array<LedgerLineInput>;
tags?: Array<LedgerEntryTagInput> | undefined;
groups?: Array<LedgerEntryGroupInput> | undefined;
conditions?: Array<LedgerEntryConditionInput> | undefined;
};

/** Builds an `addLedgerEntries` entry for `runtime_lines` (typeVersion 1). */
export const runtimeLinesV1 = (
input: RuntimeLinesV1,
): AddLedgerEntryInput => ({
entry: {
...(input.conditions !== undefined && { conditions: input.conditions }),
...(input.description !== undefined && { description: input.description }),
...(input.groups !== undefined && { groups: input.groups }),
ledger: { ik: input.ledgerIk },
lines: input.lines,
...(input.posted !== undefined && { posted: input.posted }),
...(input.tags !== undefined && { tags: input.tags }),
type: 'runtime_lines',
typeVersion: 1,
},
Expand All @@ -3521,6 +3527,12 @@ export type UntypedParametersV1 = {
ik: Scalars['SafeString']['input'];
/** The Idempotency Key of the Ledger to add this Ledger Entry to. */
ledgerIk: Scalars['SafeString']['input'];
/** ISO 8601 timestamp to post this Ledger Entry at. */
posted?: Scalars['DateTime']['input'] | undefined;
description?: Scalars['String']['input'] | undefined;
tags?: Array<LedgerEntryTagInput> | undefined;
groups?: Array<LedgerEntryGroupInput> | undefined;
conditions?: Array<LedgerEntryConditionInput> | undefined;
/**
* This entry type's operation does not bind its parameters to typed
* variables, so they cannot be typed individually.
Expand All @@ -3533,8 +3545,13 @@ export const untypedParametersV1 = (
input: UntypedParametersV1,
): AddLedgerEntryInput => ({
entry: {
...(input.conditions !== undefined && { conditions: input.conditions }),
...(input.description !== undefined && { description: input.description }),
...(input.groups !== undefined && { groups: input.groups }),
ledger: { ik: input.ledgerIk },
parameters: input.parameters,
...(input.posted !== undefined && { posted: input.posted }),
...(input.tags !== undefined && { tags: input.tags }),
type: 'untyped_parameters',
typeVersion: 1,
},
Expand All @@ -3552,6 +3569,12 @@ export type AllOptionalV2 = {
ik: Scalars['SafeString']['input'];
/** The Idempotency Key of the Ledger to add this Ledger Entry to. */
ledgerIk: Scalars['SafeString']['input'];
/** ISO 8601 timestamp to post this Ledger Entry at. */
posted?: Scalars['DateTime']['input'] | undefined;
description?: Scalars['String']['input'] | undefined;
tags?: Array<LedgerEntryTagInput> | undefined;
groups?: Array<LedgerEntryGroupInput> | undefined;
conditions?: Array<LedgerEntryConditionInput> | undefined;
parameters?: {
memo?: Scalars['String']['input'] | undefined;
note?: Scalars['String']['input'] | undefined;
Expand All @@ -3568,8 +3591,13 @@ export const allOptionalV2 = (
};
return {
entry: {
...(input.conditions !== undefined && { conditions: input.conditions }),
...(input.description !== undefined && { description: input.description }),
...(input.groups !== undefined && { groups: input.groups }),
ledger: { ik: input.ledgerIk },
...(Object.keys(parameters).length > 0 && { parameters }),
...(input.posted !== undefined && { posted: input.posted }),
...(input.tags !== undefined && { tags: input.tags }),
type: 'all_optional',
typeVersion: 2,
},
Expand All @@ -3589,6 +3617,12 @@ export type EitherLedgerKeyV1 = {
ledgerId?: Scalars['ID']['input'] | undefined;
/** The Idempotency Key of the Ledger to add this Ledger Entry to. */
ledgerIk?: Scalars['SafeString']['input'] | undefined;
/** ISO 8601 timestamp to post this Ledger Entry at. */
posted?: Scalars['DateTime']['input'] | undefined;
description?: Scalars['String']['input'] | undefined;
tags?: Array<LedgerEntryTagInput> | undefined;
groups?: Array<LedgerEntryGroupInput> | undefined;
conditions?: Array<LedgerEntryConditionInput> | undefined;
parameters: {
amount: Scalars['String']['input'];
};
Expand All @@ -3604,10 +3638,15 @@ export const eitherLedgerKeyV1 = (
};
return {
entry: {
...(input.conditions !== undefined && { conditions: input.conditions }),
...(input.description !== undefined && { description: input.description }),
...(input.groups !== undefined && { groups: input.groups }),
...(Object.keys(ledger).length > 0 && { ledger }),
parameters: {
amount: input.parameters.amount,
},
...(input.posted !== undefined && { posted: input.posted }),
...(input.tags !== undefined && { tags: input.tags }),
type: 'either_ledger_key',
typeVersion: 1,
},
Expand All @@ -3626,6 +3665,10 @@ export type FixedValuesV1 = {
ik: Scalars['SafeString']['input'];
/** The Idempotency Key of the Ledger to add this Ledger Entry to. */
ledgerIk: Scalars['SafeString']['input'];
/** ISO 8601 timestamp to post this Ledger Entry at. */
posted?: Scalars['DateTime']['input'] | undefined;
groups?: Array<LedgerEntryGroupInput> | undefined;
conditions?: Array<LedgerEntryConditionInput> | undefined;
parameters: {
amount: Scalars['String']['input'];
};
Expand All @@ -3636,12 +3679,15 @@ export const fixedValuesV1 = (
input: FixedValuesV1,
): AddLedgerEntryInput => ({
entry: {
...(input.conditions !== undefined && { conditions: input.conditions }),
description: 'posted by the nightly sweep',
...(input.groups !== undefined && { groups: input.groups }),
ledger: { ik: input.ledgerIk },
parameters: {
amount: input.parameters.amount,
currency: 'USD',
},
...(input.posted !== undefined && { posted: input.posted }),
tags: [{ key: 'source', value: 'sweep' }],
type: 'fixed_values',
typeVersion: 1,
Expand Down
Loading
Loading