@farcaster/snap 1.4.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Named color palette for snaps. Snap authors specify a name; the client maps
3
+ * it to a hex value appropriate for its current light/dark mode.
4
+ *
5
+ * Light-mode hex values (used by emulator):
6
+ * gray=#8F8F8F blue=#006BFF red=#FC0036 amber=#FFAE00
7
+ * green=#28A948 teal=#00AC96 purple=#8B5CF6 pink=#F32782
8
+ *
9
+ * Dark-mode hex values (for reference; client-owned):
10
+ * gray=#8F8F8F blue=#006FFE red=#F13342 amber=#FFAE00
11
+ * green=#00AC3A teal=#00AA96 purple=#A78BFA pink=#F12B82
12
+ */
13
+ export declare const PALETTE_COLOR: {
14
+ readonly gray: "gray";
15
+ readonly blue: "blue";
16
+ readonly red: "red";
17
+ readonly amber: "amber";
18
+ readonly green: "green";
19
+ readonly teal: "teal";
20
+ readonly purple: "purple";
21
+ readonly pink: "pink";
22
+ };
23
+ export declare const PALETTE_COLOR_ACCENT: "accent";
24
+ export declare const DEFAULT_THEME_ACCENT: "purple";
25
+ export declare const PALETTE_COLOR_VALUES: readonly ["gray", "blue", "red", "amber", "green", "teal", "purple", "pink"];
26
+ export type PaletteColor = (typeof PALETTE_COLOR_VALUES)[number];
27
+ /** Light-mode hex for each palette color (emulator / reference client). */
28
+ export declare const PALETTE_LIGHT_HEX: Record<PaletteColor, string>;
29
+ /** Dark-mode hex for each palette color (reference). */
30
+ export declare const PALETTE_DARK_HEX: Record<PaletteColor, string>;
31
+ export declare const PROGRESS_COLOR_VALUES: readonly ["accent", "gray", "blue", "red", "amber", "green", "teal", "purple", "pink"];
32
+ export declare const BAR_CHART_COLOR_VALUES: readonly ["accent", "gray", "blue", "red", "amber", "green", "teal", "purple", "pink"];
package/dist/colors.js ADDED
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Named color palette for snaps. Snap authors specify a name; the client maps
3
+ * it to a hex value appropriate for its current light/dark mode.
4
+ *
5
+ * Light-mode hex values (used by emulator):
6
+ * gray=#8F8F8F blue=#006BFF red=#FC0036 amber=#FFAE00
7
+ * green=#28A948 teal=#00AC96 purple=#8B5CF6 pink=#F32782
8
+ *
9
+ * Dark-mode hex values (for reference; client-owned):
10
+ * gray=#8F8F8F blue=#006FFE red=#F13342 amber=#FFAE00
11
+ * green=#00AC3A teal=#00AA96 purple=#A78BFA pink=#F12B82
12
+ */
13
+ export const PALETTE_COLOR = {
14
+ gray: "gray",
15
+ blue: "blue",
16
+ red: "red",
17
+ amber: "amber",
18
+ green: "green",
19
+ teal: "teal",
20
+ purple: "purple",
21
+ pink: "pink",
22
+ };
23
+ export const PALETTE_COLOR_ACCENT = "accent";
24
+ export const DEFAULT_THEME_ACCENT = PALETTE_COLOR.purple;
25
+ export const PALETTE_COLOR_VALUES = [
26
+ PALETTE_COLOR.gray,
27
+ PALETTE_COLOR.blue,
28
+ PALETTE_COLOR.red,
29
+ PALETTE_COLOR.amber,
30
+ PALETTE_COLOR.green,
31
+ PALETTE_COLOR.teal,
32
+ PALETTE_COLOR.purple,
33
+ PALETTE_COLOR.pink,
34
+ ];
35
+ /** Light-mode hex for each palette color (emulator / reference client). */
36
+ export const PALETTE_LIGHT_HEX = {
37
+ gray: "#8F8F8F",
38
+ blue: "#006BFF",
39
+ red: "#FC0036",
40
+ amber: "#FFAE00",
41
+ green: "#28A948",
42
+ teal: "#00AC96",
43
+ purple: "#8B5CF6",
44
+ pink: "#F32782",
45
+ };
46
+ /** Dark-mode hex for each palette color (reference). */
47
+ export const PALETTE_DARK_HEX = {
48
+ gray: "#8F8F8F",
49
+ blue: "#006FFE",
50
+ red: "#F13342",
51
+ amber: "#FFAE00",
52
+ green: "#00AC3A",
53
+ teal: "#00AA96",
54
+ purple: "#A78BFA",
55
+ pink: "#F12B82",
56
+ };
57
+ export const PROGRESS_COLOR_VALUES = [
58
+ PALETTE_COLOR_ACCENT,
59
+ ...PALETTE_COLOR_VALUES,
60
+ ];
61
+ export const BAR_CHART_COLOR_VALUES = [
62
+ PALETTE_COLOR_ACCENT,
63
+ ...PALETTE_COLOR_VALUES,
64
+ ];
@@ -38,35 +38,6 @@ export declare const SPACER_SIZE: {
38
38
  readonly large: "large";
39
39
  };
40
40
  export declare const SPACER_SIZE_VALUES: readonly ["small", "medium", "large"];
41
- /**
42
- * Named color palette for snaps. Snap authors specify a name; the client maps
43
- * it to a hex value appropriate for its current light/dark mode.
44
- *
45
- * Light-mode hex values (used by emulator):
46
- * gray=#8F8F8F blue=#006BFF red=#FC0036 amber=#FFAE00
47
- * green=#28A948 teal=#00AC96 purple=#8B5CF6 pink=#F32782
48
- *
49
- * Dark-mode hex values (for reference; client-owned):
50
- * gray=#8F8F8F blue=#006FFE red=#F13342 amber=#FFAE00
51
- * green=#00AC3A teal=#00AA96 purple=#A78BFA pink=#F12B82
52
- */
53
- export declare const PALETTE_COLOR: {
54
- readonly gray: "gray";
55
- readonly blue: "blue";
56
- readonly red: "red";
57
- readonly amber: "amber";
58
- readonly green: "green";
59
- readonly teal: "teal";
60
- readonly purple: "purple";
61
- readonly pink: "pink";
62
- };
63
- export declare const PALETTE_COLOR_VALUES: readonly ["gray", "blue", "red", "amber", "green", "teal", "purple", "pink"];
64
- export type PaletteColor = (typeof PALETTE_COLOR_VALUES)[number];
65
- /** Light-mode hex for each palette color (emulator / reference client). */
66
- export declare const PALETTE_LIGHT_HEX: Record<PaletteColor, string>;
67
- /** Dark-mode hex for each palette color (reference). */
68
- export declare const PALETTE_DARK_HEX: Record<PaletteColor, string>;
69
- export declare const PROGRESS_COLOR_VALUES: readonly ["accent", "gray", "blue", "red", "amber", "green", "teal", "purple", "pink"];
70
41
  export declare const LIST_STYLE_VALUES: readonly ["ordered", "unordered", "plain"];
71
42
  export declare const DEFAULT_LIST_STYLE: "ordered";
72
43
  export declare const GRID_CELL_SIZE_VALUES: readonly ["auto", "square"];
@@ -91,7 +62,6 @@ export declare const BUTTON_STYLE: {
91
62
  export declare const BUTTON_STYLE_VALUES: readonly ["primary", "secondary"];
92
63
  export declare const BUTTON_LAYOUT_VALUES: readonly ["stack", "row", "grid"];
93
64
  export declare const DEFAULT_BUTTON_LAYOUT: "stack";
94
- export declare const BAR_CHART_COLOR_VALUES: readonly ["accent", "gray", "blue", "red", "amber", "green", "teal", "purple", "pink"];
95
65
  export declare const EFFECT_VALUES: readonly ["confetti"];
96
66
  export declare const GROUP_LAYOUT_VALUES: readonly ["row"];
97
67
  /** Only valid as `page.elements`: vertical container for the page body (matches json-render trees). */
@@ -118,8 +88,6 @@ export declare const HTTPS_PREFIX: "https://";
118
88
  export declare const HTTP_PREFIX: "http://";
119
89
  /** 6-digit hex only (#RRGGBB); used for grid cell backgrounds (free hex). */
120
90
  export declare const HEX_COLOR_6_RE: RegExp;
121
- /** Default snap accent when `page.theme` or `page.theme.accent` is omitted (SPEC.md). */
122
- export declare const DEFAULT_THEME_ACCENT: "purple";
123
91
  export declare const TEXT_CONTENT_MAX: {
124
92
  readonly title: 80;
125
93
  readonly body: 160;
package/dist/constants.js CHANGED
@@ -53,64 +53,6 @@ export const SPACER_SIZE_VALUES = [
53
53
  SPACER_SIZE.medium,
54
54
  SPACER_SIZE.large,
55
55
  ];
56
- /**
57
- * Named color palette for snaps. Snap authors specify a name; the client maps
58
- * it to a hex value appropriate for its current light/dark mode.
59
- *
60
- * Light-mode hex values (used by emulator):
61
- * gray=#8F8F8F blue=#006BFF red=#FC0036 amber=#FFAE00
62
- * green=#28A948 teal=#00AC96 purple=#8B5CF6 pink=#F32782
63
- *
64
- * Dark-mode hex values (for reference; client-owned):
65
- * gray=#8F8F8F blue=#006FFE red=#F13342 amber=#FFAE00
66
- * green=#00AC3A teal=#00AA96 purple=#A78BFA pink=#F12B82
67
- */
68
- export const PALETTE_COLOR = {
69
- gray: "gray",
70
- blue: "blue",
71
- red: "red",
72
- amber: "amber",
73
- green: "green",
74
- teal: "teal",
75
- purple: "purple",
76
- pink: "pink",
77
- };
78
- export const PALETTE_COLOR_VALUES = [
79
- PALETTE_COLOR.gray,
80
- PALETTE_COLOR.blue,
81
- PALETTE_COLOR.red,
82
- PALETTE_COLOR.amber,
83
- PALETTE_COLOR.green,
84
- PALETTE_COLOR.teal,
85
- PALETTE_COLOR.purple,
86
- PALETTE_COLOR.pink,
87
- ];
88
- /** Light-mode hex for each palette color (emulator / reference client). */
89
- export const PALETTE_LIGHT_HEX = {
90
- gray: "#8F8F8F",
91
- blue: "#006BFF",
92
- red: "#FC0036",
93
- amber: "#FFAE00",
94
- green: "#28A948",
95
- teal: "#00AC96",
96
- purple: "#8B5CF6",
97
- pink: "#F32782",
98
- };
99
- /** Dark-mode hex for each palette color (reference). */
100
- export const PALETTE_DARK_HEX = {
101
- gray: "#8F8F8F",
102
- blue: "#006FFE",
103
- red: "#F13342",
104
- amber: "#FFAE00",
105
- green: "#00AC3A",
106
- teal: "#00AA96",
107
- purple: "#A78BFA",
108
- pink: "#F12B82",
109
- };
110
- export const PROGRESS_COLOR_VALUES = [
111
- "accent",
112
- ...PALETTE_COLOR_VALUES,
113
- ];
114
56
  export const LIST_STYLE_VALUES = ["ordered", "unordered", "plain"];
115
57
  export const DEFAULT_LIST_STYLE = "ordered";
116
58
  export const GRID_CELL_SIZE_VALUES = ["auto", "square"];
@@ -147,10 +89,6 @@ export const BUTTON_STYLE_VALUES = [
147
89
  ];
148
90
  export const BUTTON_LAYOUT_VALUES = ["stack", "row", "grid"];
149
91
  export const DEFAULT_BUTTON_LAYOUT = BUTTON_LAYOUT_VALUES[0];
150
- export const BAR_CHART_COLOR_VALUES = [
151
- "accent",
152
- ...PALETTE_COLOR_VALUES,
153
- ];
154
92
  export const EFFECT_VALUES = ["confetti"];
155
93
  export const GROUP_LAYOUT_VALUES = ["row"];
156
94
  /** Only valid as `page.elements`: vertical container for the page body (matches json-render trees). */
@@ -176,8 +114,6 @@ export const HTTPS_PREFIX = "https://";
176
114
  export const HTTP_PREFIX = "http://";
177
115
  /** 6-digit hex only (#RRGGBB); used for grid cell backgrounds (free hex). */
178
116
  export const HEX_COLOR_6_RE = /^#[0-9a-fA-F]{6}$/;
179
- /** Default snap accent when `page.theme` or `page.theme.accent` is omitted (SPEC.md). */
180
- export const DEFAULT_THEME_ACCENT = PALETTE_COLOR.purple;
181
117
  export const TEXT_CONTENT_MAX = {
182
118
  [TEXT_STYLE.title]: 80,
183
119
  [TEXT_STYLE.body]: 160,
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
- export { POST_GRID_TAP_KEY, PAGE_ROOT_TYPE, ELEMENT_TYPE, MEDIA_TYPE, DEFAULT_THEME_ACCENT, DEFAULT_LIST_STYLE, DEFAULT_SLIDER_STEP, PALETTE_COLOR, PALETTE_COLOR_VALUES, PALETTE_LIGHT_HEX, PALETTE_DARK_HEX, type PaletteColor, } from "./constants.js";
2
- export { snapResponseSchema, firstPageResponseSchema, payloadSchema, type SnapAction, type SnapContext, type SnapResponse, type SnapHandlerResult, type SnapFunction, type SnapPayload, } from "./schemas.js";
1
+ export { POST_GRID_TAP_KEY, PAGE_ROOT_TYPE, ELEMENT_TYPE, MEDIA_TYPE, DEFAULT_LIST_STYLE, DEFAULT_SLIDER_STEP, } from "./constants.js";
2
+ export { DEFAULT_THEME_ACCENT, PALETTE_COLOR, PALETTE_COLOR_ACCENT, PALETTE_COLOR_VALUES, PALETTE_LIGHT_HEX, PALETTE_DARK_HEX, type PaletteColor, } from "./colors.js";
3
+ export { ACTION_TYPE_GET, ACTION_TYPE_POST, snapResponseSchema, firstPageResponseSchema, payloadSchema, createDefaultDataStore, type Button, type Element, type Elements, type GroupChildElement, type SnapAction, type SnapPageElementInput, type SnapContext, type SnapResponse, type SnapHandlerResult, type SnapFunction, type SnapPayload, type DataStoreValue, type SnapDataStore, type SnapDataStoreOperations, } from "./schemas.js";
3
4
  export { validateSnapResponse, validateFirstPageResponse, type ValidationResult, } from "./validator.js";
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
- export { POST_GRID_TAP_KEY, PAGE_ROOT_TYPE, ELEMENT_TYPE, MEDIA_TYPE, DEFAULT_THEME_ACCENT, DEFAULT_LIST_STYLE, DEFAULT_SLIDER_STEP, PALETTE_COLOR, PALETTE_COLOR_VALUES, PALETTE_LIGHT_HEX, PALETTE_DARK_HEX, } from "./constants.js";
2
- export { snapResponseSchema, firstPageResponseSchema, payloadSchema, } from "./schemas.js";
1
+ export { POST_GRID_TAP_KEY, PAGE_ROOT_TYPE, ELEMENT_TYPE, MEDIA_TYPE, DEFAULT_LIST_STYLE, DEFAULT_SLIDER_STEP, } from "./constants.js";
2
+ export { DEFAULT_THEME_ACCENT, PALETTE_COLOR, PALETTE_COLOR_ACCENT, PALETTE_COLOR_VALUES, PALETTE_LIGHT_HEX, PALETTE_DARK_HEX, } from "./colors.js";
3
+ export { ACTION_TYPE_GET, ACTION_TYPE_POST, snapResponseSchema, firstPageResponseSchema, payloadSchema, createDefaultDataStore, } from "./schemas.js";
3
4
  export { validateSnapResponse, validateFirstPageResponse, } from "./validator.js";
package/dist/schemas.d.ts CHANGED
@@ -14,6 +14,146 @@ declare const buttonSchema: z.ZodObject<{
14
14
  }>>;
15
15
  }, z.core.$strip>;
16
16
  export type Button = z.infer<typeof buttonSchema>;
17
+ /** Child elements allowed inside `group` (no media, no nested group) */
18
+ declare const groupChildElementSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
19
+ type: z.ZodLiteral<"text">;
20
+ style: z.ZodEnum<{
21
+ title: "title";
22
+ body: "body";
23
+ caption: "caption";
24
+ label: "label";
25
+ }>;
26
+ content: z.ZodString;
27
+ align: z.ZodOptional<z.ZodEnum<{
28
+ left: "left";
29
+ center: "center";
30
+ right: "right";
31
+ }>>;
32
+ }, z.core.$strip>, z.ZodObject<{
33
+ type: z.ZodLiteral<"divider">;
34
+ }, z.core.$strip>, z.ZodObject<{
35
+ type: z.ZodLiteral<"spacer">;
36
+ size: z.ZodDefault<z.ZodEnum<{
37
+ small: "small";
38
+ medium: "medium";
39
+ large: "large";
40
+ }>>;
41
+ }, z.core.$strip>, z.ZodObject<{
42
+ type: z.ZodLiteral<"progress">;
43
+ value: z.ZodNumber;
44
+ max: z.ZodNumber;
45
+ label: z.ZodOptional<z.ZodString>;
46
+ color: z.ZodOptional<z.ZodEnum<{
47
+ gray: "gray";
48
+ blue: "blue";
49
+ red: "red";
50
+ amber: "amber";
51
+ green: "green";
52
+ teal: "teal";
53
+ purple: "purple";
54
+ pink: "pink";
55
+ accent: "accent";
56
+ }>>;
57
+ }, z.core.$strip>, z.ZodObject<{
58
+ type: z.ZodLiteral<"list">;
59
+ style: z.ZodDefault<z.ZodEnum<{
60
+ ordered: "ordered";
61
+ unordered: "unordered";
62
+ plain: "plain";
63
+ }>>;
64
+ items: z.ZodArray<z.ZodObject<{
65
+ content: z.ZodString;
66
+ trailing: z.ZodOptional<z.ZodString>;
67
+ }, z.core.$strip>>;
68
+ }, z.core.$strip>, z.ZodObject<{
69
+ type: z.ZodLiteral<"text_input">;
70
+ name: z.ZodString;
71
+ placeholder: z.ZodOptional<z.ZodString>;
72
+ maxLength: z.ZodOptional<z.ZodNumber>;
73
+ }, z.core.$strip>, z.ZodPipe<z.ZodObject<{
74
+ type: z.ZodLiteral<"slider">;
75
+ name: z.ZodString;
76
+ min: z.ZodNumber;
77
+ max: z.ZodNumber;
78
+ step: z.ZodDefault<z.ZodNumber>;
79
+ value: z.ZodOptional<z.ZodNumber>;
80
+ label: z.ZodOptional<z.ZodString>;
81
+ minLabel: z.ZodOptional<z.ZodString>;
82
+ maxLabel: z.ZodOptional<z.ZodString>;
83
+ }, z.core.$strip>, z.ZodTransform<{
84
+ value: number;
85
+ type: "slider";
86
+ name: string;
87
+ min: number;
88
+ max: number;
89
+ step: number;
90
+ label?: string | undefined;
91
+ minLabel?: string | undefined;
92
+ maxLabel?: string | undefined;
93
+ }, {
94
+ type: "slider";
95
+ name: string;
96
+ min: number;
97
+ max: number;
98
+ step: number;
99
+ value?: number | undefined;
100
+ label?: string | undefined;
101
+ minLabel?: string | undefined;
102
+ maxLabel?: string | undefined;
103
+ }>>, z.ZodPipe<z.ZodObject<{
104
+ type: z.ZodLiteral<"button_group">;
105
+ name: z.ZodString;
106
+ options: z.ZodArray<z.ZodString>;
107
+ style: z.ZodOptional<z.ZodEnum<{
108
+ row: "row";
109
+ stack: "stack";
110
+ grid: "grid";
111
+ }>>;
112
+ }, z.core.$strip>, z.ZodTransform<{
113
+ style: "row" | "stack" | "grid";
114
+ type: "button_group";
115
+ name: string;
116
+ options: string[];
117
+ }, {
118
+ type: "button_group";
119
+ name: string;
120
+ options: string[];
121
+ style?: "row" | "stack" | "grid" | undefined;
122
+ }>>, z.ZodObject<{
123
+ type: z.ZodLiteral<"toggle">;
124
+ name: z.ZodString;
125
+ label: z.ZodString;
126
+ value: z.ZodDefault<z.ZodBoolean>;
127
+ }, z.core.$strip>, z.ZodObject<{
128
+ type: z.ZodLiteral<"bar_chart">;
129
+ bars: z.ZodArray<z.ZodObject<{
130
+ label: z.ZodString;
131
+ value: z.ZodNumber;
132
+ color: z.ZodOptional<z.ZodEnum<{
133
+ gray: "gray";
134
+ blue: "blue";
135
+ red: "red";
136
+ amber: "amber";
137
+ green: "green";
138
+ teal: "teal";
139
+ purple: "purple";
140
+ pink: "pink";
141
+ }>>;
142
+ }, z.core.$strip>>;
143
+ max: z.ZodOptional<z.ZodNumber>;
144
+ color: z.ZodOptional<z.ZodEnum<{
145
+ gray: "gray";
146
+ blue: "blue";
147
+ red: "red";
148
+ amber: "amber";
149
+ green: "green";
150
+ teal: "teal";
151
+ purple: "purple";
152
+ pink: "pink";
153
+ accent: "accent";
154
+ }>>;
155
+ }, z.core.$strip>], "type">;
156
+ export type GroupChildElement = z.infer<typeof groupChildElementSchema>;
17
157
  /** Any single page element, including media and `group` */
18
158
  declare const elementSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
19
159
  type: z.ZodLiteral<"text">;
@@ -328,6 +468,7 @@ declare const elementSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
328
468
  }>>;
329
469
  }, z.core.$strip>], "type">;
330
470
  export type Element = z.infer<typeof elementSchema>;
471
+ export type SnapPageElementInput = z.input<typeof elementSchema>;
331
472
  declare const elementsSchema: z.ZodObject<{
332
473
  type: z.ZodLiteral<"stack">;
333
474
  children: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
@@ -1395,9 +1536,21 @@ export declare const snapActionSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
1395
1536
  type: z.ZodLiteral<"post">;
1396
1537
  }, z.core.$strict>], "type">;
1397
1538
  export type SnapAction = z.infer<typeof snapActionSchema>;
1539
+ export type DataStoreValue = string | number | boolean | null | DataStoreValue[] | {
1540
+ [key: string]: DataStoreValue;
1541
+ };
1542
+ export type SnapDataStoreOperations = {
1543
+ get(key: string): Promise<DataStoreValue | null>;
1544
+ set(key: string, value: DataStoreValue): Promise<void>;
1545
+ };
1546
+ export type SnapDataStore = SnapDataStoreOperations & {
1547
+ withLock<T>(fn: (store: SnapDataStoreOperations) => Promise<T>): Promise<T>;
1548
+ };
1549
+ export declare function createDefaultDataStore(): SnapDataStore;
1398
1550
  export type SnapContext = {
1399
1551
  action: SnapAction;
1400
1552
  request: Request;
1553
+ data: SnapDataStore;
1401
1554
  };
1402
1555
  export type SnapFunction = (ctx: SnapContext) => Promise<SnapHandlerResult>;
1403
1556
  export {};
package/dist/schemas.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { z } from "zod";
2
- import { BAR_CHART_COLOR_VALUES, BUTTON_ACTION, BUTTON_ACTION_VALUES, BUTTON_GROUP_STYLE, BUTTON_GROUP_STYLE_VALUES, BUTTON_LAYOUT_VALUES, BUTTON_STYLE_VALUES, DEFAULT_BUTTON_LAYOUT, DEFAULT_LIST_STYLE, DEFAULT_SLIDER_STEP, DEFAULT_THEME_ACCENT, EFFECT_VALUES, ELEMENT_TYPE, GRID_CELL_SIZE_VALUES, GRID_GAP_VALUES, GROUP_LAYOUT_VALUES, HEX_COLOR_6_RE, HTTP_PREFIX, HTTPS_PREFIX, IMAGE_ASPECT_VALUES, INTERACTIVE_ELEMENT_TYPES, LIMITS, LIST_STYLE_VALUES, MEDIA_ELEMENT_TYPES, PAGE_ROOT_TYPE, PALETTE_COLOR_VALUES, PROGRESS_COLOR_VALUES, SLIDER_STEP_ALIGN_EPS, SPACER_SIZE, SPACER_SIZE_VALUES, SPEC_VERSION, TEXT_ALIGN_VALUES, TEXT_CONTENT_MAX, TEXT_STYLE, TEXT_STYLE_VALUES, } from "./constants.js";
2
+ import { BUTTON_ACTION, BUTTON_ACTION_VALUES, BUTTON_GROUP_STYLE, BUTTON_GROUP_STYLE_VALUES, BUTTON_LAYOUT_VALUES, BUTTON_STYLE_VALUES, DEFAULT_BUTTON_LAYOUT, DEFAULT_LIST_STYLE, DEFAULT_SLIDER_STEP, EFFECT_VALUES, ELEMENT_TYPE, GRID_CELL_SIZE_VALUES, GRID_GAP_VALUES, GROUP_LAYOUT_VALUES, HEX_COLOR_6_RE, HTTP_PREFIX, HTTPS_PREFIX, IMAGE_ASPECT_VALUES, INTERACTIVE_ELEMENT_TYPES, LIMITS, LIST_STYLE_VALUES, MEDIA_ELEMENT_TYPES, PAGE_ROOT_TYPE, SLIDER_STEP_ALIGN_EPS, SPACER_SIZE, SPACER_SIZE_VALUES, SPEC_VERSION, TEXT_ALIGN_VALUES, TEXT_CONTENT_MAX, TEXT_STYLE, TEXT_STYLE_VALUES, } from "./constants.js";
3
+ import { BAR_CHART_COLOR_VALUES, DEFAULT_THEME_ACCENT, PALETTE_COLOR_VALUES, PROGRESS_COLOR_VALUES, } from "./colors.js";
3
4
  /**
4
5
  * post/link/mini_app targets must be HTTPS in production; allow HTTP only for
5
6
  * loopback hosts so local snap servers (e.g. http://localhost:3014/snap) validate.
@@ -457,3 +458,17 @@ export const snapActionSchema = z.discriminatedUnion("type", [
457
458
  snapGetActionSchema,
458
459
  snapPostActionSchema,
459
460
  ]);
461
+ export function createDefaultDataStore() {
462
+ const err = new Error("Data store is not configured. Use withUpstash() from @farcaster/snap-upstash or provide a data store implementation.");
463
+ return {
464
+ get(_key) {
465
+ return Promise.reject(err);
466
+ },
467
+ set(_key, _value) {
468
+ return Promise.reject(err);
469
+ },
470
+ withLock(_fn) {
471
+ return Promise.reject(err);
472
+ },
473
+ };
474
+ }
@@ -1,5 +1,6 @@
1
1
  import { z } from "zod";
2
- import { BAR_CHART_COLOR_VALUES, LIMITS, PALETTE_COLOR_VALUES, } from "../constants.js";
2
+ import { LIMITS } from "../constants.js";
3
+ import { BAR_CHART_COLOR_VALUES, PALETTE_COLOR_VALUES } from "../colors.js";
3
4
  export const barChartProps = z.object({
4
5
  bars: z
5
6
  .array(z.object({
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import { PROGRESS_COLOR_VALUES } from "../constants.js";
2
+ import { PROGRESS_COLOR_VALUES } from "../colors.js";
3
3
  export const progressProps = z.object({
4
4
  value: z.number(),
5
5
  max: z.number(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farcaster/snap",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "Farcaster Snaps 🫰",
5
5
  "repository": {
6
6
  "type": "git",
package/src/colors.ts ADDED
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Named color palette for snaps. Snap authors specify a name; the client maps
3
+ * it to a hex value appropriate for its current light/dark mode.
4
+ *
5
+ * Light-mode hex values (used by emulator):
6
+ * gray=#8F8F8F blue=#006BFF red=#FC0036 amber=#FFAE00
7
+ * green=#28A948 teal=#00AC96 purple=#8B5CF6 pink=#F32782
8
+ *
9
+ * Dark-mode hex values (for reference; client-owned):
10
+ * gray=#8F8F8F blue=#006FFE red=#F13342 amber=#FFAE00
11
+ * green=#00AC3A teal=#00AA96 purple=#A78BFA pink=#F12B82
12
+ */
13
+ export const PALETTE_COLOR = {
14
+ gray: "gray",
15
+ blue: "blue",
16
+ red: "red",
17
+ amber: "amber",
18
+ green: "green",
19
+ teal: "teal",
20
+ purple: "purple",
21
+ pink: "pink",
22
+ } as const;
23
+
24
+ export const PALETTE_COLOR_ACCENT = "accent" as const;
25
+
26
+ export const DEFAULT_THEME_ACCENT = PALETTE_COLOR.purple;
27
+
28
+ export const PALETTE_COLOR_VALUES = [
29
+ PALETTE_COLOR.gray,
30
+ PALETTE_COLOR.blue,
31
+ PALETTE_COLOR.red,
32
+ PALETTE_COLOR.amber,
33
+ PALETTE_COLOR.green,
34
+ PALETTE_COLOR.teal,
35
+ PALETTE_COLOR.purple,
36
+ PALETTE_COLOR.pink,
37
+ ] as const;
38
+
39
+ export type PaletteColor = (typeof PALETTE_COLOR_VALUES)[number];
40
+
41
+ /** Light-mode hex for each palette color (emulator / reference client). */
42
+ export const PALETTE_LIGHT_HEX: Record<PaletteColor, string> = {
43
+ gray: "#8F8F8F",
44
+ blue: "#006BFF",
45
+ red: "#FC0036",
46
+ amber: "#FFAE00",
47
+ green: "#28A948",
48
+ teal: "#00AC96",
49
+ purple: "#8B5CF6",
50
+ pink: "#F32782",
51
+ };
52
+
53
+ /** Dark-mode hex for each palette color (reference). */
54
+ export const PALETTE_DARK_HEX: Record<PaletteColor, string> = {
55
+ gray: "#8F8F8F",
56
+ blue: "#006FFE",
57
+ red: "#F13342",
58
+ amber: "#FFAE00",
59
+ green: "#00AC3A",
60
+ teal: "#00AA96",
61
+ purple: "#A78BFA",
62
+ pink: "#F12B82",
63
+ };
64
+
65
+ export const PROGRESS_COLOR_VALUES = [
66
+ PALETTE_COLOR_ACCENT,
67
+ ...PALETTE_COLOR_VALUES,
68
+ ] as const;
69
+
70
+ export const BAR_CHART_COLOR_VALUES = [
71
+ PALETTE_COLOR_ACCENT,
72
+ ...PALETTE_COLOR_VALUES,
73
+ ] as const;
package/src/constants.ts CHANGED
@@ -62,71 +62,6 @@ export const SPACER_SIZE_VALUES = [
62
62
  SPACER_SIZE.large,
63
63
  ] as const;
64
64
 
65
- /**
66
- * Named color palette for snaps. Snap authors specify a name; the client maps
67
- * it to a hex value appropriate for its current light/dark mode.
68
- *
69
- * Light-mode hex values (used by emulator):
70
- * gray=#8F8F8F blue=#006BFF red=#FC0036 amber=#FFAE00
71
- * green=#28A948 teal=#00AC96 purple=#8B5CF6 pink=#F32782
72
- *
73
- * Dark-mode hex values (for reference; client-owned):
74
- * gray=#8F8F8F blue=#006FFE red=#F13342 amber=#FFAE00
75
- * green=#00AC3A teal=#00AA96 purple=#A78BFA pink=#F12B82
76
- */
77
- export const PALETTE_COLOR = {
78
- gray: "gray",
79
- blue: "blue",
80
- red: "red",
81
- amber: "amber",
82
- green: "green",
83
- teal: "teal",
84
- purple: "purple",
85
- pink: "pink",
86
- } as const;
87
-
88
- export const PALETTE_COLOR_VALUES = [
89
- PALETTE_COLOR.gray,
90
- PALETTE_COLOR.blue,
91
- PALETTE_COLOR.red,
92
- PALETTE_COLOR.amber,
93
- PALETTE_COLOR.green,
94
- PALETTE_COLOR.teal,
95
- PALETTE_COLOR.purple,
96
- PALETTE_COLOR.pink,
97
- ] as const;
98
-
99
- export type PaletteColor = (typeof PALETTE_COLOR_VALUES)[number];
100
-
101
- /** Light-mode hex for each palette color (emulator / reference client). */
102
- export const PALETTE_LIGHT_HEX: Record<PaletteColor, string> = {
103
- gray: "#8F8F8F",
104
- blue: "#006BFF",
105
- red: "#FC0036",
106
- amber: "#FFAE00",
107
- green: "#28A948",
108
- teal: "#00AC96",
109
- purple: "#8B5CF6",
110
- pink: "#F32782",
111
- };
112
-
113
- /** Dark-mode hex for each palette color (reference). */
114
- export const PALETTE_DARK_HEX: Record<PaletteColor, string> = {
115
- gray: "#8F8F8F",
116
- blue: "#006FFE",
117
- red: "#F13342",
118
- amber: "#FFAE00",
119
- green: "#00AC3A",
120
- teal: "#00AA96",
121
- purple: "#A78BFA",
122
- pink: "#F12B82",
123
- };
124
-
125
- export const PROGRESS_COLOR_VALUES = [
126
- "accent",
127
- ...PALETTE_COLOR_VALUES,
128
- ] as const;
129
-
130
65
  export const LIST_STYLE_VALUES = ["ordered", "unordered", "plain"] as const;
131
66
 
132
67
  export const DEFAULT_LIST_STYLE = "ordered" as const;
@@ -173,11 +108,6 @@ export const BUTTON_STYLE_VALUES = [
173
108
  export const BUTTON_LAYOUT_VALUES = ["stack", "row", "grid"] as const;
174
109
  export const DEFAULT_BUTTON_LAYOUT = BUTTON_LAYOUT_VALUES[0];
175
110
 
176
- export const BAR_CHART_COLOR_VALUES = [
177
- "accent",
178
- ...PALETTE_COLOR_VALUES,
179
- ] as const;
180
-
181
111
  export const EFFECT_VALUES = ["confetti"] as const;
182
112
 
183
113
  export const GROUP_LAYOUT_VALUES = ["row"] as const;
@@ -211,9 +141,6 @@ export const HTTP_PREFIX = "http://" as const;
211
141
  /** 6-digit hex only (#RRGGBB); used for grid cell backgrounds (free hex). */
212
142
  export const HEX_COLOR_6_RE = /^#[0-9a-fA-F]{6}$/;
213
143
 
214
- /** Default snap accent when `page.theme` or `page.theme.accent` is omitted (SPEC.md). */
215
- export const DEFAULT_THEME_ACCENT = PALETTE_COLOR.purple;
216
-
217
144
  export const TEXT_CONTENT_MAX = {
218
145
  [TEXT_STYLE.title]: 80,
219
146
  [TEXT_STYLE.body]: 160,
package/src/index.ts CHANGED
@@ -3,25 +3,39 @@ export {
3
3
  PAGE_ROOT_TYPE,
4
4
  ELEMENT_TYPE,
5
5
  MEDIA_TYPE,
6
- DEFAULT_THEME_ACCENT,
7
6
  DEFAULT_LIST_STYLE,
8
7
  DEFAULT_SLIDER_STEP,
8
+ } from "./constants";
9
+ export {
10
+ DEFAULT_THEME_ACCENT,
9
11
  PALETTE_COLOR,
12
+ PALETTE_COLOR_ACCENT,
10
13
  PALETTE_COLOR_VALUES,
11
14
  PALETTE_LIGHT_HEX,
12
15
  PALETTE_DARK_HEX,
13
16
  type PaletteColor,
14
- } from "./constants";
17
+ } from "./colors";
15
18
  export {
19
+ ACTION_TYPE_GET,
20
+ ACTION_TYPE_POST,
16
21
  snapResponseSchema,
17
22
  firstPageResponseSchema,
18
23
  payloadSchema,
24
+ createDefaultDataStore,
25
+ type Button,
26
+ type Element,
27
+ type Elements,
28
+ type GroupChildElement,
19
29
  type SnapAction,
30
+ type SnapPageElementInput,
20
31
  type SnapContext,
21
32
  type SnapResponse,
22
33
  type SnapHandlerResult,
23
34
  type SnapFunction,
24
35
  type SnapPayload,
36
+ type DataStoreValue,
37
+ type SnapDataStore,
38
+ type SnapDataStoreOperations,
25
39
  } from "./schemas";
26
40
  export {
27
41
  validateSnapResponse,
package/src/schemas.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { z } from "zod";
2
2
  import {
3
- BAR_CHART_COLOR_VALUES,
4
3
  BUTTON_ACTION,
5
4
  BUTTON_ACTION_VALUES,
6
5
  BUTTON_GROUP_STYLE,
@@ -10,7 +9,6 @@ import {
10
9
  DEFAULT_BUTTON_LAYOUT,
11
10
  DEFAULT_LIST_STYLE,
12
11
  DEFAULT_SLIDER_STEP,
13
- DEFAULT_THEME_ACCENT,
14
12
  EFFECT_VALUES,
15
13
  ELEMENT_TYPE,
16
14
  GRID_CELL_SIZE_VALUES,
@@ -25,8 +23,6 @@ import {
25
23
  LIST_STYLE_VALUES,
26
24
  MEDIA_ELEMENT_TYPES,
27
25
  PAGE_ROOT_TYPE,
28
- PALETTE_COLOR_VALUES,
29
- PROGRESS_COLOR_VALUES,
30
26
  SLIDER_STEP_ALIGN_EPS,
31
27
  SPACER_SIZE,
32
28
  SPACER_SIZE_VALUES,
@@ -36,6 +32,12 @@ import {
36
32
  TEXT_STYLE,
37
33
  TEXT_STYLE_VALUES,
38
34
  } from "./constants";
35
+ import {
36
+ BAR_CHART_COLOR_VALUES,
37
+ DEFAULT_THEME_ACCENT,
38
+ PALETTE_COLOR_VALUES,
39
+ PROGRESS_COLOR_VALUES,
40
+ } from "./colors";
39
41
 
40
42
  /**
41
43
  * post/link/mini_app targets must be HTTPS in production; allow HTTP only for
@@ -407,6 +409,8 @@ const groupChildElementSchema = z.discriminatedUnion("type", [
407
409
  barChartElementSchema,
408
410
  ]);
409
411
 
412
+ export type GroupChildElement = z.infer<typeof groupChildElementSchema>;
413
+
410
414
  const groupElementSchema = z.object({
411
415
  type: z.literal(ELEMENT_TYPE.group),
412
416
  layout: z.enum(GROUP_LAYOUT_VALUES),
@@ -435,6 +439,8 @@ const elementSchema = z.discriminatedUnion("type", [
435
439
 
436
440
  export type Element = z.infer<typeof elementSchema>;
437
441
 
442
+ export type SnapPageElementInput = z.input<typeof elementSchema>;
443
+
438
444
  const elementsSchema = z
439
445
  .object({
440
446
  type: z.literal(PAGE_ROOT_TYPE.stack),
@@ -574,9 +580,44 @@ export const snapActionSchema = z.discriminatedUnion("type", [
574
580
 
575
581
  export type SnapAction = z.infer<typeof snapActionSchema>;
576
582
 
583
+ export type DataStoreValue =
584
+ | string
585
+ | number
586
+ | boolean
587
+ | null
588
+ | DataStoreValue[]
589
+ | { [key: string]: DataStoreValue };
590
+
591
+ export type SnapDataStoreOperations = {
592
+ get(key: string): Promise<DataStoreValue | null>;
593
+ set(key: string, value: DataStoreValue): Promise<void>;
594
+ };
595
+
596
+ export type SnapDataStore = SnapDataStoreOperations & {
597
+ withLock<T>(fn: (store: SnapDataStoreOperations) => Promise<T>): Promise<T>;
598
+ };
599
+
600
+ export function createDefaultDataStore(): SnapDataStore {
601
+ const err = new Error(
602
+ "Data store is not configured. Use withUpstash() from @farcaster/snap-upstash or provide a data store implementation.",
603
+ );
604
+ return {
605
+ get(_key: string): Promise<never> {
606
+ return Promise.reject(err);
607
+ },
608
+ set(_key: string, _value: DataStoreValue): Promise<never> {
609
+ return Promise.reject(err);
610
+ },
611
+ withLock<T>(_fn: (store: SnapDataStoreOperations) => Promise<T>): Promise<never> {
612
+ return Promise.reject(err);
613
+ },
614
+ };
615
+ }
616
+
577
617
  export type SnapContext = {
578
618
  action: SnapAction;
579
619
  request: Request;
620
+ data: SnapDataStore;
580
621
  };
581
622
 
582
623
  export type SnapFunction = (ctx: SnapContext) => Promise<SnapHandlerResult>;
@@ -1,9 +1,6 @@
1
1
  import { z } from "zod";
2
- import {
3
- BAR_CHART_COLOR_VALUES,
4
- LIMITS,
5
- PALETTE_COLOR_VALUES,
6
- } from "../constants.js";
2
+ import { LIMITS } from "../constants.js";
3
+ import { BAR_CHART_COLOR_VALUES, PALETTE_COLOR_VALUES } from "../colors.js";
7
4
 
8
5
  export const barChartProps = z.object({
9
6
  bars: z
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import { PROGRESS_COLOR_VALUES } from "../constants.js";
2
+ import { PROGRESS_COLOR_VALUES } from "../colors.js";
3
3
 
4
4
  export const progressProps = z.object({
5
5
  value: z.number(),