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
5 changes: 5 additions & 0 deletions .changeset/google-loyalty-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@passmint/node': minor
---

Type `design.google` on templates: `loyaltyPoints` and `secondaryLoyaltyPoints` (`{ fieldKey, label }`) show a template field as the Google Wallet loyalty balance, and `accountNameFieldKey` picks the field shown as the card holder's name. New exported types: `TemplateDesignGoogle`, and `TemplateLocation` (already used by `TemplateDesign.locations`, now importable by name).
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ const { data: scans } = await passmint.passes.redemptions(pass.id, { limit: 20 }
for (const scan of scans) console.log(scan.decision, scan.reason, scan.scanned_at)
```

Templates take a `redemptionPolicy` (`{ mode: 'single_use' | 'reusable' | 'count', maxUses? }`) and `requireDownloadLink` on `create` and `update`. Template responses include `warnings` when the saved design breaks a recommended rule, and template designs accept `issuerName`, `locations` and `relevantDate`.
Templates take a `redemptionPolicy` (`{ mode: 'single_use' | 'reusable' | 'count', maxUses? }`) and `requireDownloadLink` on `create` and `update`. Template responses include `warnings` when the saved design breaks a recommended rule, and template designs accept `issuerName`, `locations`, `relevantDate` and `google`. On storeCard templates, `google` maps template fields to the Google Wallet loyalty card: `loyaltyPoints` and `secondaryLoyaltyPoints` (`{ fieldKey, label }`) show a field as the native balance, and `accountNameFieldKey` picks the card holder name field.

#### Per-pass images

Expand Down
183 changes: 183 additions & 0 deletions openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,72 @@
],
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2}(\\.\\d+)?)?(Z|[+-]\\d{2}:\\d{2})$",
"description": "ISO 8601 with offset. Apple Wallet surfaces the pass around this time. Apple only."
},
"google": {
"type": [
"object",
"null"
],
"properties": {
"loyaltyPoints": {
"type": [
"object",
"null"
],
"properties": {
"fieldKey": {
"type": "string",
"maxLength": 48,
"pattern": "^[A-Za-z0-9_]+$",
"description": "Key of a field declared in this design. Its value on each pass (or the field's default) is the balance, sent to Google as text."
},
"label": {
"type": "string",
"minLength": 1,
"maxLength": 64,
"description": "Shown next to the balance in Google Wallet, e.g. 'Stamps'."
}
},
"required": [
"fieldKey",
"label"
]
},
"secondaryLoyaltyPoints": {
"type": [
"object",
"null"
],
"properties": {
"fieldKey": {
"type": "string",
"maxLength": 48,
"pattern": "^[A-Za-z0-9_]+$",
"description": "Key of a field declared in this design. Its value on each pass (or the field's default) is the balance, sent to Google as text."
},
"label": {
"type": "string",
"minLength": 1,
"maxLength": 64,
"description": "Shown next to the balance in Google Wallet, e.g. 'Stamps'."
}
},
"required": [
"fieldKey",
"label"
]
},
"accountNameFieldKey": {
"type": [
"string",
"null"
],
"maxLength": 48,
"pattern": "^[A-Za-z0-9_]+$",
"description": "Key of a field whose value is the card holder's name in Google Wallet. Omit to keep showing the description there, as cards always have."
}
},
"description": "Google Wallet only, storeCard templates only: show template fields as the loyalty card's native balance and holder name. Apple Wallet is unaffected."
}
},
"required": [
Expand Down Expand Up @@ -872,6 +938,72 @@
],
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2}(\\.\\d+)?)?(Z|[+-]\\d{2}:\\d{2})$",
"description": "ISO 8601 with offset. Apple Wallet surfaces the pass around this time. Apple only."
},
"google": {
"type": [
"object",
"null"
],
"properties": {
"loyaltyPoints": {
"type": [
"object",
"null"
],
"properties": {
"fieldKey": {
"type": "string",
"maxLength": 48,
"pattern": "^[A-Za-z0-9_]+$",
"description": "Key of a field declared in this design. Its value on each pass (or the field's default) is the balance, sent to Google as text."
},
"label": {
"type": "string",
"minLength": 1,
"maxLength": 64,
"description": "Shown next to the balance in Google Wallet, e.g. 'Stamps'."
}
},
"required": [
"fieldKey",
"label"
]
},
"secondaryLoyaltyPoints": {
"type": [
"object",
"null"
],
"properties": {
"fieldKey": {
"type": "string",
"maxLength": 48,
"pattern": "^[A-Za-z0-9_]+$",
"description": "Key of a field declared in this design. Its value on each pass (or the field's default) is the balance, sent to Google as text."
},
"label": {
"type": "string",
"minLength": 1,
"maxLength": 64,
"description": "Shown next to the balance in Google Wallet, e.g. 'Stamps'."
}
},
"required": [
"fieldKey",
"label"
]
},
"accountNameFieldKey": {
"type": [
"string",
"null"
],
"maxLength": 48,
"pattern": "^[A-Za-z0-9_]+$",
"description": "Key of a field whose value is the card holder's name in Google Wallet. Omit to keep showing the description there, as cards always have."
}
},
"description": "Google Wallet only, storeCard templates only: show template fields as the loyalty card's native balance and holder name. Apple Wallet is unaffected."
}
},
"required": [
Expand Down Expand Up @@ -3229,6 +3361,57 @@
"string",
"null"
]
},
"google": {
"type": [
"object",
"null"
],
"properties": {
"loyaltyPoints": {
"type": [
"object",
"null"
],
"properties": {
"fieldKey": {
"type": "string"
},
"label": {
"type": "string"
}
},
"required": [
"fieldKey",
"label"
]
},
"secondaryLoyaltyPoints": {
"type": [
"object",
"null"
],
"properties": {
"fieldKey": {
"type": "string"
},
"label": {
"type": "string"
}
},
"required": [
"fieldKey",
"label"
]
},
"accountNameFieldKey": {
"type": [
"string",
"null"
]
}
},
"additionalProperties": {}
}
},
"additionalProperties": {},
Expand Down
47 changes: 47 additions & 0 deletions src/generated/openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2827,6 +2827,23 @@ export interface components {
}[] | null;
/** @description ISO 8601 with offset. Apple Wallet surfaces the pass around this time. Apple only. */
relevantDate?: string | null;
/** @description Google Wallet only, storeCard templates only: show template fields as the loyalty card's native balance and holder name. Apple Wallet is unaffected. */
google?: {
loyaltyPoints?: {
/** @description Key of a field declared in this design. Its value on each pass (or the field's default) is the balance, sent to Google as text. */
fieldKey: string;
/** @description Shown next to the balance in Google Wallet, e.g. 'Stamps'. */
label: string;
} | null;
secondaryLoyaltyPoints?: {
/** @description Key of a field declared in this design. Its value on each pass (or the field's default) is the balance, sent to Google as text. */
fieldKey: string;
/** @description Shown next to the balance in Google Wallet, e.g. 'Stamps'. */
label: string;
} | null;
/** @description Key of a field whose value is the card holder's name in Google Wallet. Omit to keep showing the description there, as cards always have. */
accountNameFieldKey?: string | null;
} | null;
};
platforms?: ("apple" | "google")[];
starter_template_id?: string;
Expand Down Expand Up @@ -2926,6 +2943,23 @@ export interface components {
}[] | null;
/** @description ISO 8601 with offset. Apple Wallet surfaces the pass around this time. Apple only. */
relevantDate?: string | null;
/** @description Google Wallet only, storeCard templates only: show template fields as the loyalty card's native balance and holder name. Apple Wallet is unaffected. */
google?: {
loyaltyPoints?: {
/** @description Key of a field declared in this design. Its value on each pass (or the field's default) is the balance, sent to Google as text. */
fieldKey: string;
/** @description Shown next to the balance in Google Wallet, e.g. 'Stamps'. */
label: string;
} | null;
secondaryLoyaltyPoints?: {
/** @description Key of a field declared in this design. Its value on each pass (or the field's default) is the balance, sent to Google as text. */
fieldKey: string;
/** @description Shown next to the balance in Google Wallet, e.g. 'Stamps'. */
label: string;
} | null;
/** @description Key of a field whose value is the card holder's name in Google Wallet. Omit to keep showing the description there, as cards always have. */
accountNameFieldKey?: string | null;
} | null;
};
archived?: boolean;
platforms?: ("apple" | "google")[];
Expand Down Expand Up @@ -3493,6 +3527,19 @@ export interface components {
[key: string]: unknown;
}[] | null;
relevantDate?: string | null;
google?: ({
loyaltyPoints?: {
fieldKey: string;
label: string;
} | null;
secondaryLoyaltyPoints?: {
fieldKey: string;
label: string;
} | null;
accountNameFieldKey?: string | null;
} & {
[key: string]: unknown;
}) | null;
} & {
[key: string]: unknown;
};
Expand Down
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,12 @@ export type {
RequestOptions,
Template,
TemplateDesign,
TemplateDesignGoogle,
TemplateField,
TemplateImage,
TemplateImageOptions,
TemplateImageSlot,
TemplateLocation,
TemplateType,
UpdatePassParams,
UpdateTemplateParams,
Expand Down
11 changes: 11 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ export type TemplateLocation = NonNullable<
NonNullable<Schemas['CreateTemplateBody']['design']>['locations']
>[number]

/** Google Wallet loyalty mapping for storeCard templates, derived from the spec's design input. */
export type TemplateDesignGoogle = NonNullable<
NonNullable<Schemas['CreateTemplateBody']['design']>['google']
>

export interface TemplateDesign {
description: string
logoText: string | null
Expand Down Expand Up @@ -72,6 +77,12 @@ export interface TemplateDesign {
locations?: TemplateLocation[] | null
/** ISO 8601 date the pass becomes relevant (lock-screen surfacing). */
relevantDate?: string | null
/**
* Google Wallet only, storeCard only: show template fields as the loyalty card's native
* balance (`loyaltyPoints`, `secondaryLoyaltyPoints`) and holder name
* (`accountNameFieldKey`). `null` clears it.
*/
google?: TemplateDesignGoogle | null
}

/**
Expand Down
18 changes: 18 additions & 0 deletions test/types.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,3 +200,21 @@ describe('TemplateDesign.locations', () => {
expectTypeOf<{ longitude: number }>().not.toExtend<TemplateLocation>()
})
})

describe('TemplateDesign.google', () => {
it('accepts the Google loyalty mapping', () => {
const design: Pick<TemplateDesign, 'google'> = {
google: {
loyaltyPoints: { fieldKey: 'count', label: 'Stamps' },
secondaryLoyaltyPoints: { fieldKey: 'nextReward', label: 'Reward' },
accountNameFieldKey: 'customerName',
},
}
expectTypeOf(design.google?.loyaltyPoints?.fieldKey).toEqualTypeOf<string | undefined>()
const bad: Pick<TemplateDesign, 'google'> = {
// @ts-expect-error label must be a string
google: { loyaltyPoints: { fieldKey: 'count', label: 1 } },
}
void bad
})
})
Loading