@bridgeline-digital/hawk-app-cli 0.1.0-dev.20261020202308 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +7 -7
- package/README.md +770 -770
- package/agents/AGENTS.md +192 -192
- package/agents/project/custom.md +21 -21
- package/agents/project/next-mui.md +21 -21
- package/agents/project/next.md +24 -24
- package/agents/project/vanilla.md +22 -22
- package/agents/project/vite.md +19 -19
- package/bin/hawk-app.mjs +0 -0
- package/docs/bridge/README.md +1315 -1315
- package/docs/showcase/README.md +47 -47
- package/docs/showcase/functions/echo.ts +12 -12
- package/docs/showcase/functions/long-task.ts +31 -31
- package/docs/showcase/functions/showcase.ts +186 -186
- package/docs/showcase/hawk-app.json +73 -73
- package/docs/showcase/queries/assistant-prompts-by-day.json +6 -6
- package/docs/showcase/queries/assistant-prompts-by-day.sql +8 -8
- package/docs/showcase/queries/searches-by-day.json +6 -6
- package/docs/showcase/queries/searches-by-day.sql +7 -7
- package/docs/showcase/src/App.tsx +1436 -1436
- package/docs/showcase/src/main.tsx +10 -10
- package/docs/showcase/src/styles.css +71 -71
- package/docs/showcase/src/useHawkApp.ts +44 -44
- package/docs/showcase/src/vite-env.d.ts +1 -1
- package/docs/ui/README.md +166 -166
- package/package.json +1 -1
- package/schema/hawk-app.schema.json +611 -611
- package/src/accessibility.mjs +105 -105
- package/src/agents.mjs +145 -145
- package/src/aliases.mjs +30 -30
- package/src/app-icon.mjs +82 -82
- package/src/channel.mjs +116 -116
- package/src/cli.mjs +825 -825
- package/src/clients.mjs +221 -221
- package/src/config.mjs +148 -148
- package/src/create.mjs +186 -186
- package/src/credentials.mjs +56 -56
- package/src/data.mjs +169 -169
- package/src/deploy.mjs +349 -349
- package/src/dev.mjs +459 -459
- package/src/doctor.mjs +176 -176
- package/src/env.mjs +140 -140
- package/src/functions.mjs +313 -313
- package/src/login.mjs +166 -166
- package/src/logs.mjs +64 -64
- package/src/manifest.mjs +425 -425
- package/src/mcp-docs.mjs +168 -168
- package/src/mcp-hawksearch.mjs +342 -342
- package/src/mcp-reports.mjs +130 -130
- package/src/mcp-rules.mjs +109 -109
- package/src/mcp.mjs +539 -539
- package/src/platform.mjs +116 -116
- package/src/project-checks.mjs +153 -153
- package/src/queries.mjs +289 -289
- package/src/scope-check.mjs +91 -91
- package/src/secrets.mjs +86 -86
- package/src/slug-guard.mjs +80 -80
- package/src/sso.mjs +182 -182
- package/src/telemetry.mjs +50 -50
- package/src/upgrade.mjs +406 -406
- package/src/versions.mjs +102 -102
- package/templates/next/next.config.ts +13 -13
- package/templates/next/package.json +26 -26
- package/templates/next/src/lib/useHawkApp.ts +46 -46
- package/templates/next-mui/next.config.ts +13 -13
- package/templates/next-mui/package.json +30 -30
- package/templates/next-mui/src/app/layout.tsx +19 -19
- package/templates/next-mui/src/app/page.tsx +78 -78
- package/templates/next-mui/src/app/providers.tsx +10 -10
- package/templates/preact/package.json +26 -26
- package/templates/preact/src/useHawkApp.ts +44 -44
- package/templates/preact/src/vite-env.d.ts +1 -1
- package/templates/preact/tsconfig.json +17 -17
- package/templates/preact/vite.config.ts +11 -11
- package/templates/react/package.json +29 -29
- package/templates/react/src/useHawkApp.ts +44 -44
- package/templates/react/src/vite-env.d.ts +1 -1
- package/templates/react/tsconfig.json +16 -16
- package/templates/react/vite.config.ts +11 -11
- package/templates/vanilla/package.json +15 -15
|
@@ -1,611 +1,611 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"$id": "https://hawksearch.com/schemas/hawk-app.schema.json",
|
|
4
|
-
"title": "Hawk App manifest (hawk-app.json)",
|
|
5
|
-
"description": "Registers a Hawk App: its name, settings, visibility and the data it needs. Which clients have the app is managed in the Hawk Analytics portal or with `hawk-app clients`, not here.",
|
|
6
|
-
"type": "object",
|
|
7
|
-
"required": [
|
|
8
|
-
"slug",
|
|
9
|
-
"name",
|
|
10
|
-
"visibility"
|
|
11
|
-
],
|
|
12
|
-
"additionalProperties": false,
|
|
13
|
-
"properties": {
|
|
14
|
-
"$schema": {
|
|
15
|
-
"type": "string"
|
|
16
|
-
},
|
|
17
|
-
"slug": {
|
|
18
|
-
"description": "Unique id, also the app's folder on the apps CDN (/<slug>/). Cannot be changed later.",
|
|
19
|
-
"type": "string",
|
|
20
|
-
"pattern": "^[a-z0-9]+(-[a-z0-9]+)*$",
|
|
21
|
-
"maxLength": 64
|
|
22
|
-
},
|
|
23
|
-
"name": {
|
|
24
|
-
"description": "Shown on the Apps page.",
|
|
25
|
-
"type": "string",
|
|
26
|
-
"minLength": 1,
|
|
27
|
-
"maxLength": 100
|
|
28
|
-
},
|
|
29
|
-
"description": {
|
|
30
|
-
"type": "string"
|
|
31
|
-
},
|
|
32
|
-
"icon": {
|
|
33
|
-
"description": "The app's icon: an .svg or .png file next to hawk-app.json, e.g. icon.svg. Hosts draw an SVG in their own color (only its shape counts: one color, square viewBox, at most 32 KB) and show a PNG as is (square, 64 to 1024 px, at most 256 KB). hawk-app deploy uploads it with each version. Without one, hosts show their default icon.",
|
|
34
|
-
"type": "string",
|
|
35
|
-
"pattern": "^(?!.*\\.\\.)[A-Za-z0-9_-][A-Za-z0-9_.-]*(/[A-Za-z0-9_-][A-Za-z0-9_.-]*)*\\.([sS][vV][gG]|[pP][nN][gG])$",
|
|
36
|
-
"maxLength": 200,
|
|
37
|
-
"examples": ["icon.svg", "assets/app-icon.png"]
|
|
38
|
-
},
|
|
39
|
-
"category": {
|
|
40
|
-
"type": "string"
|
|
41
|
-
},
|
|
42
|
-
"version": {
|
|
43
|
-
"type": "string"
|
|
44
|
-
},
|
|
45
|
-
"entryUrl": {
|
|
46
|
-
"description": "Optional, rarely needed. The platform serves the deployed version (<apps CDN>/<slug>/v<n>/); this is only used until a version has been deployed. Must be on the apps CDN, under /<slug>/.",
|
|
47
|
-
"type": "string",
|
|
48
|
-
"format": "uri"
|
|
49
|
-
},
|
|
50
|
-
"status": {
|
|
51
|
-
"description": "Deprecated and ignored: Bridgeline staff publish apps (draft/live) from the Apps page in HawkSearch. Remove it from hawk-app.json.",
|
|
52
|
-
"deprecated": true,
|
|
53
|
-
"enum": [
|
|
54
|
-
"draft",
|
|
55
|
-
"live",
|
|
56
|
-
"disabled"
|
|
57
|
-
]
|
|
58
|
-
},
|
|
59
|
-
"visibility": {
|
|
60
|
-
"description": "Who can see the app. allowList: only the clients given the app. all: every client except excluded ones. internal: Bridgeline users only. store: the clients given the app have it; every other client sees it on the Store tab of the Apps page (with \"store\": its listing) and can request it, and a Hawk-App-Manager approves or declines. Which clients have the app (or are excluded) is managed in the Hawk Analytics portal or with `hawk-app clients`, not in hawk-app.json.",
|
|
61
|
-
"enum": [
|
|
62
|
-
"allowList",
|
|
63
|
-
"all",
|
|
64
|
-
"internal",
|
|
65
|
-
"store"
|
|
66
|
-
]
|
|
67
|
-
},
|
|
68
|
-
"store": {
|
|
69
|
-
"description": "The store listing, required with visibility \"store\": what clients that don't have the app see on the Store tab of the Apps page, with the app's name, icon, category and description. Bridgeline sets the price label in the portal, not here. Reviewed like other settings on a live app.",
|
|
70
|
-
"type": "object",
|
|
71
|
-
"additionalProperties": false,
|
|
72
|
-
"required": ["tagline", "screenshots"],
|
|
73
|
-
"properties": {
|
|
74
|
-
"tagline": { "description": "One line: what the app does for the client.", "type": "string", "minLength": 1, "maxLength": 120 },
|
|
75
|
-
"highlights": { "description": "Up to 5 short points.", "type": "array", "maxItems": 5, "items": { "type": "string", "minLength": 1, "maxLength": 120 } },
|
|
76
|
-
"screenshots": {
|
|
77
|
-
"description": "1 to 5 images next to hawk-app.json (.png, .jpg or .webp, at most 1 MB each; 1600×1000 is a good size), in order. hawk-app deploy uploads them with each version.",
|
|
78
|
-
"type": "array",
|
|
79
|
-
"minItems": 1,
|
|
80
|
-
"maxItems": 5,
|
|
81
|
-
"items": { "type": "string", "pattern": "^(?!.*\\.\\.)[A-Za-z0-9_-][A-Za-z0-9_.-]*(/[A-Za-z0-9_-][A-Za-z0-9_.-]*)*\\.([pP][nN][gG]|[jJ][pP][eE]?[gG]|[wW][eE][bB][pP])$", "maxLength": 200 }
|
|
82
|
-
}
|
|
83
|
-
},
|
|
84
|
-
"examples": [
|
|
85
|
-
{ "tagline": "Find and fix searches that return nothing", "highlights": ["Zero-result searches by volume", "One-click redirects"], "screenshots": ["store/overview.png", "store/fix.png"] }
|
|
86
|
-
]
|
|
87
|
-
},
|
|
88
|
-
"listed": {
|
|
89
|
-
"description": "Whether hosts show the app on their Apps landing page (default true). false: the app is left off the list and the host hides its own title and back button for it, but it still opens by its direct URL. It does not change who can open the app (visibility and the app's clients still apply). Reviewed like other settings on a live app.",
|
|
90
|
-
"type": "boolean",
|
|
91
|
-
"default": true
|
|
92
|
-
},
|
|
93
|
-
"hosting": {
|
|
94
|
-
"description": "How the app is served. \"static\" (the default): built files (HTML/JS/CSS) on the apps CDN, deployed with hawk-app deploy. \"server\" is reserved for server-rendered apps and is not accepted yet.",
|
|
95
|
-
"enum": [
|
|
96
|
-
"static",
|
|
97
|
-
"server"
|
|
98
|
-
],
|
|
99
|
-
"default": "static"
|
|
100
|
-
},
|
|
101
|
-
"scopes": {
|
|
102
|
-
"description": "Data the app needs. reports:read (HawkSearch Analytics reports), hawksearch:read (read the HawkSearch dashboard API), hawksearch:write (create, update and delete in the HawkSearch dashboard API: banners, boost/bury, campaigns, visibility, visitor targets, redirects, synonyms, spellcheck, pagination and sorting sets, recommendation visibility, landing page layouts, facets and landing pages; site API keys only, limited per app and client per minute, every write audit-logged), data:read (the app's own SQL queries in queries/, run against the current client's analytics data), functions:invoke (the app's own server-side functions in functions/, see \"functions\"), email:send (send email from noreply@hawksearch.com with the app's name, from the app or its functions; sends are limited per app and client per day), hawksearch:sysparams:write (read and set the HawkSearch system parameters listed in \"systemParameters\" for the user's current engine), hawksearch:search (HawkSearch search and autocomplete for the user's current engine, live or in preview; limited per app and client per minute), ai:invoke (Claude through the platform, tiers fast and smart, from the app or its functions; a daily token budget per tier and requests per minute per app and client; an app with it is never auto-approved), lambdas:invoke (call the Lambdas outside Hawk Apps listed in \"lambdas\" that the platform allows, with app.lambdas.invoke; an app with it is never auto-approved) and hawksearch:features:write (turn HawkSearch features on and off for the user's current engine, additional and facet features, one code at a time with app.hawksearch.features; any feature, including paid add-ons, so an app with it is never auto-approved), hawksearch:index (rebuild the user's engine's index from its feed and follow the rebuild with app.hawksearch.index, only where the engine's EnableRebuildIndex system parameter is on, one rebuild at a time per engine, and read the engine's indexes, current index, hierarchy and mappings through HawkSearch's Indexing API; never auto-approved), hawksearch:index:items (add, update and delete items and their attributes in the engine's indexes through the Indexing API, live at once on the current index; at most 125 items a call; never auto-approved), hawksearch:index:manage (create indexes, set the current one, delete others, rebuild autocomplete and the rest, hierarchy and facet mappings through the Indexing API; never auto-approved), hawksearch:recommendations (HawkSearch's recommendation widgets for the user's current engine with app.hawksearch.recommendations, never tracked in the client's recommendation reports; limited per app and client per minute), storage (the app's own key-value data and files kept by the platform with app.storage and app.storage.files, per app and client, within quotas; shared by everyone at the client and the app's functions and schedules) and assistant (ask the host's assistant, Hawk Assistant in HawkSearch, as the user with app.assistant.ask, from a click; the user sees the question and the answer in the assistant's chat; show the buttons only while context.features.assistant is true).",
|
|
103
|
-
"type": "array",
|
|
104
|
-
"items": {
|
|
105
|
-
"enum": [
|
|
106
|
-
"hawksearch:read",
|
|
107
|
-
"hawksearch:write",
|
|
108
|
-
"reports:read",
|
|
109
|
-
"data:read",
|
|
110
|
-
"functions:invoke",
|
|
111
|
-
"email:send",
|
|
112
|
-
"hawksearch:sysparams:write",
|
|
113
|
-
"hawksearch:search",
|
|
114
|
-
"ai:invoke",
|
|
115
|
-
"lambdas:invoke",
|
|
116
|
-
"hawksearch:features:write",
|
|
117
|
-
"hawksearch:index",
|
|
118
|
-
"hawksearch:index:items",
|
|
119
|
-
"hawksearch:index:manage",
|
|
120
|
-
"hawksearch:recommendations",
|
|
121
|
-
"storage",
|
|
122
|
-
"assistant"
|
|
123
|
-
]
|
|
124
|
-
},
|
|
125
|
-
"uniqueItems": true
|
|
126
|
-
},
|
|
127
|
-
"template": {
|
|
128
|
-
"description": "The template the app was created from (hawk-app create writes it). hawk-app upgrade uses it to bring the app's template-owned dependencies and config files up to the template the CLI ships. Local only: not sent to the platform.",
|
|
129
|
-
"enum": [
|
|
130
|
-
"react",
|
|
131
|
-
"preact",
|
|
132
|
-
"next",
|
|
133
|
-
"next-mui",
|
|
134
|
-
"vanilla"
|
|
135
|
-
]
|
|
136
|
-
},
|
|
137
|
-
"lambdas": {
|
|
138
|
-
"description": "Lambdas written outside Hawk Apps that the app calls with app.lambdas.invoke(name, input) (or ctx.platform.lambdas.invoke in a function), by name. Needs the lambdas:invoke scope (and the scope needs a non-empty list). Each name only works on a platform where Bridgeline Engineering allows it; the Lambda gets { caller, input }, where caller (client, user, engine) comes from the app token. Reviewed like scopes.",
|
|
139
|
-
"type": "array",
|
|
140
|
-
"maxItems": 10,
|
|
141
|
-
"uniqueItems": true,
|
|
142
|
-
"items": {
|
|
143
|
-
"type": "string",
|
|
144
|
-
"pattern": "^[A-Za-z0-9_-]{1,64}$"
|
|
145
|
-
},
|
|
146
|
-
"examples": [
|
|
147
|
-
[
|
|
148
|
-
"analytics-client-setup"
|
|
149
|
-
]
|
|
150
|
-
]
|
|
151
|
-
},
|
|
152
|
-
"systemParameters": {
|
|
153
|
-
"description": "HawkSearch system parameters (Sites > System Parameters) the app may read and set for the user's current engine, with app.hawksearch.systemParameters. Needs the hawksearch:sysparams:write scope (and the scope needs a non-empty list). Names match case-insensitively and must be unique. Reviewed like scopes. Encrypted, internal (AE only), global and read-only parameters are never settable; changes apply within about 3 minutes and are not synchronized to other engines of a group.",
|
|
154
|
-
"type": "array",
|
|
155
|
-
"maxItems": 50,
|
|
156
|
-
"uniqueItems": true,
|
|
157
|
-
"items": {
|
|
158
|
-
"type": "string",
|
|
159
|
-
"pattern": "^[A-Za-z0-9_.-]{1,50}$"
|
|
160
|
-
},
|
|
161
|
-
"examples": [
|
|
162
|
-
[
|
|
163
|
-
"Timezone",
|
|
164
|
-
"SearchPreviewURL"
|
|
165
|
-
]
|
|
166
|
-
]
|
|
167
|
-
},
|
|
168
|
-
"views": {
|
|
169
|
-
"description": "Pages of the app's build that hosts show inside other pages, by name: \"preview\" is shown on the Apps page under the description, and views with \"embeddable\": true can be placed by Bridgeline users in other pages (reports, Spark pages). Each is a page at <entry URL><path>/, with the same version, scopes and token as the app; it reads app.context.view ({ name, params, embedded, maxHeight }). A setting: pending on a live app until approved.",
|
|
170
|
-
"type": "object",
|
|
171
|
-
"maxProperties": 10,
|
|
172
|
-
"propertyNames": { "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", "maxLength": 40 },
|
|
173
|
-
"additionalProperties": {
|
|
174
|
-
"type": "object",
|
|
175
|
-
"additionalProperties": false,
|
|
176
|
-
"required": ["path", "title"],
|
|
177
|
-
"properties": {
|
|
178
|
-
"path": { "description": "The page within the build, e.g. views/preview (a Next.js route src/app/views/preview/page.tsx).", "type": "string", "pattern": "^[A-Za-z0-9._-]+(/[A-Za-z0-9._-]+)*/?$", "maxLength": 200 },
|
|
179
|
-
"title": { "description": "Shown in hosts' pickers and while the view loads.", "type": "string", "minLength": 1, "maxLength": 80 },
|
|
180
|
-
"height": { "description": "The height to start at, in px (80-1200, default 300). The view may grow within the host's limit.", "type": "integer", "minimum": 80, "maximum": 1200, "default": 300 },
|
|
181
|
-
"embeddable": { "description": "Bridgeline users may place it in other pages (report builder, Spark).", "type": "boolean", "default": false },
|
|
182
|
-
"params": { "description": "Inputs the page passes in (app.context.view.params), all strings, e.g. [\"sku\"].", "type": "array", "maxItems": 10, "uniqueItems": true, "items": { "type": "string", "pattern": "^[a-z][A-Za-z0-9]{0,39}$" } },
|
|
183
|
-
"trial": { "description": "A store app's trial view (at most one, no params): shown live on its store card to clients that don't have the app, with a read-only trial token (only the app's reports:read, hawksearch:read, hawksearch:search, hawksearch:recommendations and data:read). app.context.trial is true there: hide actions that need other scopes.", "type": "boolean", "default": false },
|
|
184
|
-
"cacheMinutes": { "description": "How long the platform keeps the answers to this view's read calls (data queries, analytics reports, HawkSearch dashboard reads, search, recommendations), per client and engine, in minutes (0-1440; 0 = not cached). Default: 60 for \"preview\", 0 (not cached) for other views. The full app page is never cached. Engineering can change or stop it per app in the Hawk Analytics portal.", "type": "integer", "minimum": 0, "maximum": 1440 }
|
|
185
|
-
}
|
|
186
|
-
},
|
|
187
|
-
"examples": [
|
|
188
|
-
{ "preview": { "path": "views/preview", "title": "Price position", "height": 220, "cacheMinutes": 60 }, "product": { "path": "views/product", "title": "This product", "embeddable": true, "params": ["sku"] } }
|
|
189
|
-
]
|
|
190
|
-
},
|
|
191
|
-
"config": {
|
|
192
|
-
"description": "App config: named, non-secret values the app reads at runtime with app.config.get(key) / app.config.all() (ctx.config in a function). Declare each key here with its type and an optional default; the values are set from the Hawk Analytics portal or with `hawk-app config set`, for the whole app or one client, and apply within about 30 seconds without a deploy. Each key resolves to the client's value, else the global value, else the default, else null. Values reach the browser: never put secrets here (use secrets / clientSecrets). Reviewed like scopes.",
|
|
193
|
-
"type": "object",
|
|
194
|
-
"maxProperties": 50,
|
|
195
|
-
"propertyNames": {
|
|
196
|
-
"pattern": "^[A-Za-z][A-Za-z0-9_]{0,63}$"
|
|
197
|
-
},
|
|
198
|
-
"additionalProperties": {
|
|
199
|
-
"$ref": "#/$defs/configKey"
|
|
200
|
-
},
|
|
201
|
-
"examples": [
|
|
202
|
-
{
|
|
203
|
-
"signupNotifyEmails": {
|
|
204
|
-
"type": "emails",
|
|
205
|
-
"label": "Sign-up notification recipients",
|
|
206
|
-
"description": "Who is emailed when a client signs up.",
|
|
207
|
-
"default": ["support@example.com"]
|
|
208
|
-
},
|
|
209
|
-
"connectorsRequestEmails": {
|
|
210
|
-
"type": "emails",
|
|
211
|
-
"label": "API Connections request recipients"
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
]
|
|
215
|
-
},
|
|
216
|
-
"externalOrigins": {
|
|
217
|
-
"description": "Outside origins the app may load scripts, styles, fonts and images from, embed, and call (fetch/XHR/WebSocket). [\"*\"] (the default when omitted) allows any https origin; a list allows only those; [] allows none. Entries starting with img: are for images only: \"img:*\" shows images from any https origin (e.g. a client's product images) and \"img:https://cdn.example.com\" from one, without allowing scripts, styles or calls there. Enforced by the apps CDN's Content-Security-Policy.",
|
|
218
|
-
"type": "array",
|
|
219
|
-
"default": [
|
|
220
|
-
"*"
|
|
221
|
-
],
|
|
222
|
-
"maxItems": 20,
|
|
223
|
-
"uniqueItems": true,
|
|
224
|
-
"items": {
|
|
225
|
-
"type": "string",
|
|
226
|
-
"anyOf": [
|
|
227
|
-
{
|
|
228
|
-
"const": "*"
|
|
229
|
-
},
|
|
230
|
-
{
|
|
231
|
-
"pattern": "^(https|wss)://(\\*\\.)?([A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?\\.)*[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?(:[0-9]{1,5})?/?$"
|
|
232
|
-
},
|
|
233
|
-
{
|
|
234
|
-
"pattern": "^img:(\\*|https://(\\*\\.)?([A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?\\.)*[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?(:[0-9]{1,5})?/?)$"
|
|
235
|
-
}
|
|
236
|
-
]
|
|
237
|
-
},
|
|
238
|
-
"examples": [
|
|
239
|
-
[
|
|
240
|
-
"*"
|
|
241
|
-
],
|
|
242
|
-
[
|
|
243
|
-
"https://api.example.com",
|
|
244
|
-
"https://*.cdn.example.com"
|
|
245
|
-
],
|
|
246
|
-
[
|
|
247
|
-
"img:*"
|
|
248
|
-
]
|
|
249
|
-
]
|
|
250
|
-
},
|
|
251
|
-
"functions": {
|
|
252
|
-
"description": "Server-side functions, one per functions/<name>.ts (or .js/.mts/.mjs) exporting `handler`. Bundled and deployed with each version as AWS Lambda functions and called from the app with app.functions.call(name, input). Needs the functions:invoke scope, and Engineering must enable functions for the app. A version whose functions changed always needs review.",
|
|
253
|
-
"type": "object",
|
|
254
|
-
"maxProperties": 10,
|
|
255
|
-
"propertyNames": {
|
|
256
|
-
"pattern": "^[a-z0-9]+(-[a-z0-9]+)*$",
|
|
257
|
-
"maxLength": 40
|
|
258
|
-
},
|
|
259
|
-
"additionalProperties": {
|
|
260
|
-
"$ref": "#/$defs/function"
|
|
261
|
-
},
|
|
262
|
-
"examples": [
|
|
263
|
-
{
|
|
264
|
-
"sync-feed": {
|
|
265
|
-
"timeoutSeconds": 20,
|
|
266
|
-
"memoryMb": 512,
|
|
267
|
-
"secrets": [
|
|
268
|
-
"FEED_API_KEY"
|
|
269
|
-
]
|
|
270
|
-
},
|
|
271
|
-
"nightly-report": {
|
|
272
|
-
"job": true,
|
|
273
|
-
"timeoutSeconds": 600
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
]
|
|
277
|
-
},
|
|
278
|
-
"schedules": {
|
|
279
|
-
"description": "Recurring runs of job functions (\"job\": true). A schedule runs only for the clients where a user turns it on from the app (app.schedules.enable), as \"schedule:<name>\" for that client and site. Needs the functions:invoke scope. Reviewed like scopes.",
|
|
280
|
-
"type": "object",
|
|
281
|
-
"maxProperties": 5,
|
|
282
|
-
"propertyNames": {
|
|
283
|
-
"pattern": "^[a-z0-9]+(-[a-z0-9]+)*$",
|
|
284
|
-
"maxLength": 40
|
|
285
|
-
},
|
|
286
|
-
"additionalProperties": {
|
|
287
|
-
"$ref": "#/$defs/schedule"
|
|
288
|
-
},
|
|
289
|
-
"examples": [
|
|
290
|
-
{
|
|
291
|
-
"nightly": {
|
|
292
|
-
"function": "nightly-report",
|
|
293
|
-
"cron": "0 7 ? * MON-FRI *",
|
|
294
|
-
"timezone": "America/Chicago"
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
]
|
|
298
|
-
},
|
|
299
|
-
"minProtocolVersion": {
|
|
300
|
-
"type": "integer",
|
|
301
|
-
"minimum": 1,
|
|
302
|
-
"maximum": 1
|
|
303
|
-
}
|
|
304
|
-
},
|
|
305
|
-
"allOf": [
|
|
306
|
-
{
|
|
307
|
-
"if": {
|
|
308
|
-
"required": ["visibility"],
|
|
309
|
-
"properties": { "visibility": { "const": "store" } }
|
|
310
|
-
},
|
|
311
|
-
"then": { "required": ["store"] }
|
|
312
|
-
},
|
|
313
|
-
{
|
|
314
|
-
"if": {
|
|
315
|
-
"required": [
|
|
316
|
-
"functions"
|
|
317
|
-
],
|
|
318
|
-
"properties": {
|
|
319
|
-
"functions": {
|
|
320
|
-
"minProperties": 1
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
},
|
|
324
|
-
"then": {
|
|
325
|
-
"required": [
|
|
326
|
-
"scopes"
|
|
327
|
-
],
|
|
328
|
-
"properties": {
|
|
329
|
-
"scopes": {
|
|
330
|
-
"contains": {
|
|
331
|
-
"const": "functions:invoke"
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
},
|
|
337
|
-
{
|
|
338
|
-
"if": {
|
|
339
|
-
"required": [
|
|
340
|
-
"schedules"
|
|
341
|
-
],
|
|
342
|
-
"properties": {
|
|
343
|
-
"schedules": {
|
|
344
|
-
"minProperties": 1
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
},
|
|
348
|
-
"then": {
|
|
349
|
-
"required": [
|
|
350
|
-
"scopes"
|
|
351
|
-
],
|
|
352
|
-
"properties": {
|
|
353
|
-
"scopes": {
|
|
354
|
-
"contains": {
|
|
355
|
-
"const": "functions:invoke"
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
}
|
|
360
|
-
},
|
|
361
|
-
{
|
|
362
|
-
"if": {
|
|
363
|
-
"required": [
|
|
364
|
-
"systemParameters"
|
|
365
|
-
],
|
|
366
|
-
"properties": {
|
|
367
|
-
"systemParameters": {
|
|
368
|
-
"minItems": 1
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
},
|
|
372
|
-
"then": {
|
|
373
|
-
"required": [
|
|
374
|
-
"scopes"
|
|
375
|
-
],
|
|
376
|
-
"properties": {
|
|
377
|
-
"scopes": {
|
|
378
|
-
"contains": {
|
|
379
|
-
"const": "hawksearch:sysparams:write"
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
},
|
|
385
|
-
{
|
|
386
|
-
"if": {
|
|
387
|
-
"required": [
|
|
388
|
-
"scopes"
|
|
389
|
-
],
|
|
390
|
-
"properties": {
|
|
391
|
-
"scopes": {
|
|
392
|
-
"contains": {
|
|
393
|
-
"const": "hawksearch:sysparams:write"
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
},
|
|
398
|
-
"then": {
|
|
399
|
-
"required": [
|
|
400
|
-
"systemParameters"
|
|
401
|
-
],
|
|
402
|
-
"properties": {
|
|
403
|
-
"systemParameters": {
|
|
404
|
-
"minItems": 1
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
},
|
|
409
|
-
{
|
|
410
|
-
"if": {
|
|
411
|
-
"required": [
|
|
412
|
-
"lambdas"
|
|
413
|
-
],
|
|
414
|
-
"properties": {
|
|
415
|
-
"lambdas": {
|
|
416
|
-
"minItems": 1
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
},
|
|
420
|
-
"then": {
|
|
421
|
-
"required": [
|
|
422
|
-
"scopes"
|
|
423
|
-
],
|
|
424
|
-
"properties": {
|
|
425
|
-
"scopes": {
|
|
426
|
-
"contains": {
|
|
427
|
-
"const": "lambdas:invoke"
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
},
|
|
433
|
-
{
|
|
434
|
-
"if": {
|
|
435
|
-
"required": [
|
|
436
|
-
"scopes"
|
|
437
|
-
],
|
|
438
|
-
"properties": {
|
|
439
|
-
"scopes": {
|
|
440
|
-
"contains": {
|
|
441
|
-
"const": "lambdas:invoke"
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
},
|
|
446
|
-
"then": {
|
|
447
|
-
"required": [
|
|
448
|
-
"lambdas"
|
|
449
|
-
],
|
|
450
|
-
"properties": {
|
|
451
|
-
"lambdas": {
|
|
452
|
-
"minItems": 1
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
],
|
|
458
|
-
"$defs": {
|
|
459
|
-
"configKey": {
|
|
460
|
-
"type": "object",
|
|
461
|
-
"additionalProperties": false,
|
|
462
|
-
"required": [
|
|
463
|
-
"type"
|
|
464
|
-
],
|
|
465
|
-
"properties": {
|
|
466
|
-
"type": {
|
|
467
|
-
"description": "string (up to 4000 characters), number (finite), boolean, emails (a list of up to 50 different plain addresses), or json (any JSON value except null). Every value is at most 16 KB as JSON.",
|
|
468
|
-
"enum": [
|
|
469
|
-
"string",
|
|
470
|
-
"number",
|
|
471
|
-
"boolean",
|
|
472
|
-
"emails",
|
|
473
|
-
"json"
|
|
474
|
-
]
|
|
475
|
-
},
|
|
476
|
-
"label": {
|
|
477
|
-
"description": "Shown in the Hawk Analytics portal next to the value.",
|
|
478
|
-
"type": "string",
|
|
479
|
-
"minLength": 1,
|
|
480
|
-
"maxLength": 100
|
|
481
|
-
},
|
|
482
|
-
"description": {
|
|
483
|
-
"description": "What the value is for, shown in the portal.",
|
|
484
|
-
"type": "string",
|
|
485
|
-
"maxLength": 500
|
|
486
|
-
},
|
|
487
|
-
"default": {
|
|
488
|
-
"description": "The value when neither the client nor the app has one set. Must be a valid value of the type."
|
|
489
|
-
}
|
|
490
|
-
},
|
|
491
|
-
"allOf": [
|
|
492
|
-
{
|
|
493
|
-
"if": { "properties": { "type": { "const": "string" } } },
|
|
494
|
-
"then": { "properties": { "default": { "type": "string", "maxLength": 4000 } } }
|
|
495
|
-
},
|
|
496
|
-
{
|
|
497
|
-
"if": { "properties": { "type": { "const": "number" } } },
|
|
498
|
-
"then": { "properties": { "default": { "type": "number" } } }
|
|
499
|
-
},
|
|
500
|
-
{
|
|
501
|
-
"if": { "properties": { "type": { "const": "boolean" } } },
|
|
502
|
-
"then": { "properties": { "default": { "type": "boolean" } } }
|
|
503
|
-
},
|
|
504
|
-
{
|
|
505
|
-
"if": { "properties": { "type": { "const": "emails" } } },
|
|
506
|
-
"then": { "properties": { "default": { "type": "array", "maxItems": 50, "uniqueItems": true, "items": { "type": "string", "format": "email", "maxLength": 254 } } } }
|
|
507
|
-
},
|
|
508
|
-
{
|
|
509
|
-
"if": { "properties": { "type": { "const": "json" } } },
|
|
510
|
-
"then": { "properties": { "default": { "not": { "type": "null" } } } }
|
|
511
|
-
}
|
|
512
|
-
]
|
|
513
|
-
},
|
|
514
|
-
"function": {
|
|
515
|
-
"type": "object",
|
|
516
|
-
"additionalProperties": false,
|
|
517
|
-
"properties": {
|
|
518
|
-
"job": {
|
|
519
|
-
"description": "A background job: started with app.functions.start(name, input) (not called), runs up to 900 s, and its result is read later with app.functions.wait/job. Schedules can only run job functions.",
|
|
520
|
-
"type": "boolean",
|
|
521
|
-
"default": false
|
|
522
|
-
},
|
|
523
|
-
"timeoutSeconds": {
|
|
524
|
-
"description": "Maximum run time in seconds: 1-25, or 1-900 for a job. Default 10 (300 for a job).",
|
|
525
|
-
"type": "integer",
|
|
526
|
-
"minimum": 1,
|
|
527
|
-
"maximum": 900
|
|
528
|
-
},
|
|
529
|
-
"memoryMb": {
|
|
530
|
-
"description": "Memory in MB (128-1024); more memory also means more CPU. Default 256.",
|
|
531
|
-
"type": "integer",
|
|
532
|
-
"minimum": 128,
|
|
533
|
-
"maximum": 1024,
|
|
534
|
-
"default": 256
|
|
535
|
-
},
|
|
536
|
-
"secrets": {
|
|
537
|
-
"description": "Names of the app secrets this function receives as ctx.secrets.<NAME>. Set the values with `hawk-app secrets set <NAME>`.",
|
|
538
|
-
"type": "array",
|
|
539
|
-
"maxItems": 20,
|
|
540
|
-
"uniqueItems": true,
|
|
541
|
-
"items": {
|
|
542
|
-
"type": "string",
|
|
543
|
-
"pattern": "^[A-Z][A-Z0-9_]{0,63}$"
|
|
544
|
-
},
|
|
545
|
-
"default": []
|
|
546
|
-
},
|
|
547
|
-
"clientSecrets": {
|
|
548
|
-
"description": "Names of per-client secrets this function receives as ctx.clientSecrets.<NAME>: each client's own value (e.g. their email platform's API key), set by the client's users in the app with app.clientSecrets.set(NAME, value) and never readable again. Missing when the client hasn't set one.",
|
|
549
|
-
"type": "array",
|
|
550
|
-
"maxItems": 10,
|
|
551
|
-
"uniqueItems": true,
|
|
552
|
-
"items": {
|
|
553
|
-
"type": "string",
|
|
554
|
-
"pattern": "^[A-Z][A-Z0-9_]{0,63}$"
|
|
555
|
-
},
|
|
556
|
-
"default": []
|
|
557
|
-
}
|
|
558
|
-
},
|
|
559
|
-
"if": {
|
|
560
|
-
"not": {
|
|
561
|
-
"required": [
|
|
562
|
-
"job"
|
|
563
|
-
],
|
|
564
|
-
"properties": {
|
|
565
|
-
"job": {
|
|
566
|
-
"const": true
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
},
|
|
571
|
-
"then": {
|
|
572
|
-
"properties": {
|
|
573
|
-
"timeoutSeconds": {
|
|
574
|
-
"maximum": 25
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
},
|
|
579
|
-
"schedule": {
|
|
580
|
-
"type": "object",
|
|
581
|
-
"required": [
|
|
582
|
-
"function",
|
|
583
|
-
"cron"
|
|
584
|
-
],
|
|
585
|
-
"additionalProperties": false,
|
|
586
|
-
"properties": {
|
|
587
|
-
"function": {
|
|
588
|
-
"description": "The job function to run (a key of \"functions\" with \"job\": true).",
|
|
589
|
-
"type": "string",
|
|
590
|
-
"pattern": "^[a-z0-9]+(-[a-z0-9]+)*$",
|
|
591
|
-
"maxLength": 40
|
|
592
|
-
},
|
|
593
|
-
"cron": {
|
|
594
|
-
"description": "EventBridge cron, 6 space-separated fields: \"minutes hours day-of-month month day-of-week year\" (no cron( ) wrapper), e.g. \"0 7 ? * MON *\". At most hourly: minutes must be a single number (0-59). Day-of-month or day-of-week must be \"?\".",
|
|
595
|
-
"type": "string",
|
|
596
|
-
"pattern": "^([0-9]|[1-5][0-9]) [0-9A-Za-z*?,/#-]{1,40} (\\? [0-9A-Za-z*?,/#-]{1,40} [0-9A-Za-z*?,/#-]{1,40}|[0-9A-Za-z*?,/#-]{1,40} [0-9A-Za-z*?,/#-]{1,40} \\?) [0-9A-Za-z*?,/#-]{1,40}$",
|
|
597
|
-
"examples": [
|
|
598
|
-
"0 7 ? * MON *",
|
|
599
|
-
"30 * * * ? *"
|
|
600
|
-
]
|
|
601
|
-
},
|
|
602
|
-
"timezone": {
|
|
603
|
-
"description": "IANA time zone the cron is evaluated in, e.g. \"America/Chicago\", or \"UTC\" (the default).",
|
|
604
|
-
"type": "string",
|
|
605
|
-
"pattern": "^(UTC|[A-Za-z0-9_+-]+(/[A-Za-z0-9_+-]+)+)$",
|
|
606
|
-
"default": "UTC"
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://hawksearch.com/schemas/hawk-app.schema.json",
|
|
4
|
+
"title": "Hawk App manifest (hawk-app.json)",
|
|
5
|
+
"description": "Registers a Hawk App: its name, settings, visibility and the data it needs. Which clients have the app is managed in the Hawk Analytics portal or with `hawk-app clients`, not here.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": [
|
|
8
|
+
"slug",
|
|
9
|
+
"name",
|
|
10
|
+
"visibility"
|
|
11
|
+
],
|
|
12
|
+
"additionalProperties": false,
|
|
13
|
+
"properties": {
|
|
14
|
+
"$schema": {
|
|
15
|
+
"type": "string"
|
|
16
|
+
},
|
|
17
|
+
"slug": {
|
|
18
|
+
"description": "Unique id, also the app's folder on the apps CDN (/<slug>/). Cannot be changed later.",
|
|
19
|
+
"type": "string",
|
|
20
|
+
"pattern": "^[a-z0-9]+(-[a-z0-9]+)*$",
|
|
21
|
+
"maxLength": 64
|
|
22
|
+
},
|
|
23
|
+
"name": {
|
|
24
|
+
"description": "Shown on the Apps page.",
|
|
25
|
+
"type": "string",
|
|
26
|
+
"minLength": 1,
|
|
27
|
+
"maxLength": 100
|
|
28
|
+
},
|
|
29
|
+
"description": {
|
|
30
|
+
"type": "string"
|
|
31
|
+
},
|
|
32
|
+
"icon": {
|
|
33
|
+
"description": "The app's icon: an .svg or .png file next to hawk-app.json, e.g. icon.svg. Hosts draw an SVG in their own color (only its shape counts: one color, square viewBox, at most 32 KB) and show a PNG as is (square, 64 to 1024 px, at most 256 KB). hawk-app deploy uploads it with each version. Without one, hosts show their default icon.",
|
|
34
|
+
"type": "string",
|
|
35
|
+
"pattern": "^(?!.*\\.\\.)[A-Za-z0-9_-][A-Za-z0-9_.-]*(/[A-Za-z0-9_-][A-Za-z0-9_.-]*)*\\.([sS][vV][gG]|[pP][nN][gG])$",
|
|
36
|
+
"maxLength": 200,
|
|
37
|
+
"examples": ["icon.svg", "assets/app-icon.png"]
|
|
38
|
+
},
|
|
39
|
+
"category": {
|
|
40
|
+
"type": "string"
|
|
41
|
+
},
|
|
42
|
+
"version": {
|
|
43
|
+
"type": "string"
|
|
44
|
+
},
|
|
45
|
+
"entryUrl": {
|
|
46
|
+
"description": "Optional, rarely needed. The platform serves the deployed version (<apps CDN>/<slug>/v<n>/); this is only used until a version has been deployed. Must be on the apps CDN, under /<slug>/.",
|
|
47
|
+
"type": "string",
|
|
48
|
+
"format": "uri"
|
|
49
|
+
},
|
|
50
|
+
"status": {
|
|
51
|
+
"description": "Deprecated and ignored: Bridgeline staff publish apps (draft/live) from the Apps page in HawkSearch. Remove it from hawk-app.json.",
|
|
52
|
+
"deprecated": true,
|
|
53
|
+
"enum": [
|
|
54
|
+
"draft",
|
|
55
|
+
"live",
|
|
56
|
+
"disabled"
|
|
57
|
+
]
|
|
58
|
+
},
|
|
59
|
+
"visibility": {
|
|
60
|
+
"description": "Who can see the app. allowList: only the clients given the app. all: every client except excluded ones. internal: Bridgeline users only. store: the clients given the app have it; every other client sees it on the Store tab of the Apps page (with \"store\": its listing) and can request it, and a Hawk-App-Manager approves or declines. Which clients have the app (or are excluded) is managed in the Hawk Analytics portal or with `hawk-app clients`, not in hawk-app.json.",
|
|
61
|
+
"enum": [
|
|
62
|
+
"allowList",
|
|
63
|
+
"all",
|
|
64
|
+
"internal",
|
|
65
|
+
"store"
|
|
66
|
+
]
|
|
67
|
+
},
|
|
68
|
+
"store": {
|
|
69
|
+
"description": "The store listing, required with visibility \"store\": what clients that don't have the app see on the Store tab of the Apps page, with the app's name, icon, category and description. Bridgeline sets the price label in the portal, not here. Reviewed like other settings on a live app.",
|
|
70
|
+
"type": "object",
|
|
71
|
+
"additionalProperties": false,
|
|
72
|
+
"required": ["tagline", "screenshots"],
|
|
73
|
+
"properties": {
|
|
74
|
+
"tagline": { "description": "One line: what the app does for the client.", "type": "string", "minLength": 1, "maxLength": 120 },
|
|
75
|
+
"highlights": { "description": "Up to 5 short points.", "type": "array", "maxItems": 5, "items": { "type": "string", "minLength": 1, "maxLength": 120 } },
|
|
76
|
+
"screenshots": {
|
|
77
|
+
"description": "1 to 5 images next to hawk-app.json (.png, .jpg or .webp, at most 1 MB each; 1600×1000 is a good size), in order. hawk-app deploy uploads them with each version.",
|
|
78
|
+
"type": "array",
|
|
79
|
+
"minItems": 1,
|
|
80
|
+
"maxItems": 5,
|
|
81
|
+
"items": { "type": "string", "pattern": "^(?!.*\\.\\.)[A-Za-z0-9_-][A-Za-z0-9_.-]*(/[A-Za-z0-9_-][A-Za-z0-9_.-]*)*\\.([pP][nN][gG]|[jJ][pP][eE]?[gG]|[wW][eE][bB][pP])$", "maxLength": 200 }
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
"examples": [
|
|
85
|
+
{ "tagline": "Find and fix searches that return nothing", "highlights": ["Zero-result searches by volume", "One-click redirects"], "screenshots": ["store/overview.png", "store/fix.png"] }
|
|
86
|
+
]
|
|
87
|
+
},
|
|
88
|
+
"listed": {
|
|
89
|
+
"description": "Whether hosts show the app on their Apps landing page (default true). false: the app is left off the list and the host hides its own title and back button for it, but it still opens by its direct URL. It does not change who can open the app (visibility and the app's clients still apply). Reviewed like other settings on a live app.",
|
|
90
|
+
"type": "boolean",
|
|
91
|
+
"default": true
|
|
92
|
+
},
|
|
93
|
+
"hosting": {
|
|
94
|
+
"description": "How the app is served. \"static\" (the default): built files (HTML/JS/CSS) on the apps CDN, deployed with hawk-app deploy. \"server\" is reserved for server-rendered apps and is not accepted yet.",
|
|
95
|
+
"enum": [
|
|
96
|
+
"static",
|
|
97
|
+
"server"
|
|
98
|
+
],
|
|
99
|
+
"default": "static"
|
|
100
|
+
},
|
|
101
|
+
"scopes": {
|
|
102
|
+
"description": "Data the app needs. reports:read (HawkSearch Analytics reports), hawksearch:read (read the HawkSearch dashboard API), hawksearch:write (create, update and delete in the HawkSearch dashboard API: banners, boost/bury, campaigns, visibility, visitor targets, redirects, synonyms, spellcheck, pagination and sorting sets, recommendation visibility, landing page layouts, facets and landing pages; site API keys only, limited per app and client per minute, every write audit-logged), data:read (the app's own SQL queries in queries/, run against the current client's analytics data), functions:invoke (the app's own server-side functions in functions/, see \"functions\"), email:send (send email from noreply@hawksearch.com with the app's name, from the app or its functions; sends are limited per app and client per day), hawksearch:sysparams:write (read and set the HawkSearch system parameters listed in \"systemParameters\" for the user's current engine), hawksearch:search (HawkSearch search and autocomplete for the user's current engine, live or in preview; limited per app and client per minute), ai:invoke (Claude through the platform, tiers fast and smart, from the app or its functions; a daily token budget per tier and requests per minute per app and client; an app with it is never auto-approved), lambdas:invoke (call the Lambdas outside Hawk Apps listed in \"lambdas\" that the platform allows, with app.lambdas.invoke; an app with it is never auto-approved) and hawksearch:features:write (turn HawkSearch features on and off for the user's current engine, additional and facet features, one code at a time with app.hawksearch.features; any feature, including paid add-ons, so an app with it is never auto-approved), hawksearch:index (rebuild the user's engine's index from its feed and follow the rebuild with app.hawksearch.index, only where the engine's EnableRebuildIndex system parameter is on, one rebuild at a time per engine, and read the engine's indexes, current index, hierarchy and mappings through HawkSearch's Indexing API; never auto-approved), hawksearch:index:items (add, update and delete items and their attributes in the engine's indexes through the Indexing API, live at once on the current index; at most 125 items a call; never auto-approved), hawksearch:index:manage (create indexes, set the current one, delete others, rebuild autocomplete and the rest, hierarchy and facet mappings through the Indexing API; never auto-approved), hawksearch:recommendations (HawkSearch's recommendation widgets for the user's current engine with app.hawksearch.recommendations, never tracked in the client's recommendation reports; limited per app and client per minute), storage (the app's own key-value data and files kept by the platform with app.storage and app.storage.files, per app and client, within quotas; shared by everyone at the client and the app's functions and schedules) and assistant (ask the host's assistant, Hawk Assistant in HawkSearch, as the user with app.assistant.ask, from a click; the user sees the question and the answer in the assistant's chat; show the buttons only while context.features.assistant is true).",
|
|
103
|
+
"type": "array",
|
|
104
|
+
"items": {
|
|
105
|
+
"enum": [
|
|
106
|
+
"hawksearch:read",
|
|
107
|
+
"hawksearch:write",
|
|
108
|
+
"reports:read",
|
|
109
|
+
"data:read",
|
|
110
|
+
"functions:invoke",
|
|
111
|
+
"email:send",
|
|
112
|
+
"hawksearch:sysparams:write",
|
|
113
|
+
"hawksearch:search",
|
|
114
|
+
"ai:invoke",
|
|
115
|
+
"lambdas:invoke",
|
|
116
|
+
"hawksearch:features:write",
|
|
117
|
+
"hawksearch:index",
|
|
118
|
+
"hawksearch:index:items",
|
|
119
|
+
"hawksearch:index:manage",
|
|
120
|
+
"hawksearch:recommendations",
|
|
121
|
+
"storage",
|
|
122
|
+
"assistant"
|
|
123
|
+
]
|
|
124
|
+
},
|
|
125
|
+
"uniqueItems": true
|
|
126
|
+
},
|
|
127
|
+
"template": {
|
|
128
|
+
"description": "The template the app was created from (hawk-app create writes it). hawk-app upgrade uses it to bring the app's template-owned dependencies and config files up to the template the CLI ships. Local only: not sent to the platform.",
|
|
129
|
+
"enum": [
|
|
130
|
+
"react",
|
|
131
|
+
"preact",
|
|
132
|
+
"next",
|
|
133
|
+
"next-mui",
|
|
134
|
+
"vanilla"
|
|
135
|
+
]
|
|
136
|
+
},
|
|
137
|
+
"lambdas": {
|
|
138
|
+
"description": "Lambdas written outside Hawk Apps that the app calls with app.lambdas.invoke(name, input) (or ctx.platform.lambdas.invoke in a function), by name. Needs the lambdas:invoke scope (and the scope needs a non-empty list). Each name only works on a platform where Bridgeline Engineering allows it; the Lambda gets { caller, input }, where caller (client, user, engine) comes from the app token. Reviewed like scopes.",
|
|
139
|
+
"type": "array",
|
|
140
|
+
"maxItems": 10,
|
|
141
|
+
"uniqueItems": true,
|
|
142
|
+
"items": {
|
|
143
|
+
"type": "string",
|
|
144
|
+
"pattern": "^[A-Za-z0-9_-]{1,64}$"
|
|
145
|
+
},
|
|
146
|
+
"examples": [
|
|
147
|
+
[
|
|
148
|
+
"analytics-client-setup"
|
|
149
|
+
]
|
|
150
|
+
]
|
|
151
|
+
},
|
|
152
|
+
"systemParameters": {
|
|
153
|
+
"description": "HawkSearch system parameters (Sites > System Parameters) the app may read and set for the user's current engine, with app.hawksearch.systemParameters. Needs the hawksearch:sysparams:write scope (and the scope needs a non-empty list). Names match case-insensitively and must be unique. Reviewed like scopes. Encrypted, internal (AE only), global and read-only parameters are never settable; changes apply within about 3 minutes and are not synchronized to other engines of a group.",
|
|
154
|
+
"type": "array",
|
|
155
|
+
"maxItems": 50,
|
|
156
|
+
"uniqueItems": true,
|
|
157
|
+
"items": {
|
|
158
|
+
"type": "string",
|
|
159
|
+
"pattern": "^[A-Za-z0-9_.-]{1,50}$"
|
|
160
|
+
},
|
|
161
|
+
"examples": [
|
|
162
|
+
[
|
|
163
|
+
"Timezone",
|
|
164
|
+
"SearchPreviewURL"
|
|
165
|
+
]
|
|
166
|
+
]
|
|
167
|
+
},
|
|
168
|
+
"views": {
|
|
169
|
+
"description": "Pages of the app's build that hosts show inside other pages, by name: \"preview\" is shown on the Apps page under the description, and views with \"embeddable\": true can be placed by Bridgeline users in other pages (reports, Spark pages). Each is a page at <entry URL><path>/, with the same version, scopes and token as the app; it reads app.context.view ({ name, params, embedded, maxHeight }). A setting: pending on a live app until approved.",
|
|
170
|
+
"type": "object",
|
|
171
|
+
"maxProperties": 10,
|
|
172
|
+
"propertyNames": { "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$", "maxLength": 40 },
|
|
173
|
+
"additionalProperties": {
|
|
174
|
+
"type": "object",
|
|
175
|
+
"additionalProperties": false,
|
|
176
|
+
"required": ["path", "title"],
|
|
177
|
+
"properties": {
|
|
178
|
+
"path": { "description": "The page within the build, e.g. views/preview (a Next.js route src/app/views/preview/page.tsx).", "type": "string", "pattern": "^[A-Za-z0-9._-]+(/[A-Za-z0-9._-]+)*/?$", "maxLength": 200 },
|
|
179
|
+
"title": { "description": "Shown in hosts' pickers and while the view loads.", "type": "string", "minLength": 1, "maxLength": 80 },
|
|
180
|
+
"height": { "description": "The height to start at, in px (80-1200, default 300). The view may grow within the host's limit.", "type": "integer", "minimum": 80, "maximum": 1200, "default": 300 },
|
|
181
|
+
"embeddable": { "description": "Bridgeline users may place it in other pages (report builder, Spark).", "type": "boolean", "default": false },
|
|
182
|
+
"params": { "description": "Inputs the page passes in (app.context.view.params), all strings, e.g. [\"sku\"].", "type": "array", "maxItems": 10, "uniqueItems": true, "items": { "type": "string", "pattern": "^[a-z][A-Za-z0-9]{0,39}$" } },
|
|
183
|
+
"trial": { "description": "A store app's trial view (at most one, no params): shown live on its store card to clients that don't have the app, with a read-only trial token (only the app's reports:read, hawksearch:read, hawksearch:search, hawksearch:recommendations and data:read). app.context.trial is true there: hide actions that need other scopes.", "type": "boolean", "default": false },
|
|
184
|
+
"cacheMinutes": { "description": "How long the platform keeps the answers to this view's read calls (data queries, analytics reports, HawkSearch dashboard reads, search, recommendations), per client and engine, in minutes (0-1440; 0 = not cached). Default: 60 for \"preview\", 0 (not cached) for other views. The full app page is never cached. Engineering can change or stop it per app in the Hawk Analytics portal.", "type": "integer", "minimum": 0, "maximum": 1440 }
|
|
185
|
+
}
|
|
186
|
+
},
|
|
187
|
+
"examples": [
|
|
188
|
+
{ "preview": { "path": "views/preview", "title": "Price position", "height": 220, "cacheMinutes": 60 }, "product": { "path": "views/product", "title": "This product", "embeddable": true, "params": ["sku"] } }
|
|
189
|
+
]
|
|
190
|
+
},
|
|
191
|
+
"config": {
|
|
192
|
+
"description": "App config: named, non-secret values the app reads at runtime with app.config.get(key) / app.config.all() (ctx.config in a function). Declare each key here with its type and an optional default; the values are set from the Hawk Analytics portal or with `hawk-app config set`, for the whole app or one client, and apply within about 30 seconds without a deploy. Each key resolves to the client's value, else the global value, else the default, else null. Values reach the browser: never put secrets here (use secrets / clientSecrets). Reviewed like scopes.",
|
|
193
|
+
"type": "object",
|
|
194
|
+
"maxProperties": 50,
|
|
195
|
+
"propertyNames": {
|
|
196
|
+
"pattern": "^[A-Za-z][A-Za-z0-9_]{0,63}$"
|
|
197
|
+
},
|
|
198
|
+
"additionalProperties": {
|
|
199
|
+
"$ref": "#/$defs/configKey"
|
|
200
|
+
},
|
|
201
|
+
"examples": [
|
|
202
|
+
{
|
|
203
|
+
"signupNotifyEmails": {
|
|
204
|
+
"type": "emails",
|
|
205
|
+
"label": "Sign-up notification recipients",
|
|
206
|
+
"description": "Who is emailed when a client signs up.",
|
|
207
|
+
"default": ["support@example.com"]
|
|
208
|
+
},
|
|
209
|
+
"connectorsRequestEmails": {
|
|
210
|
+
"type": "emails",
|
|
211
|
+
"label": "API Connections request recipients"
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
]
|
|
215
|
+
},
|
|
216
|
+
"externalOrigins": {
|
|
217
|
+
"description": "Outside origins the app may load scripts, styles, fonts and images from, embed, and call (fetch/XHR/WebSocket). [\"*\"] (the default when omitted) allows any https origin; a list allows only those; [] allows none. Entries starting with img: are for images only: \"img:*\" shows images from any https origin (e.g. a client's product images) and \"img:https://cdn.example.com\" from one, without allowing scripts, styles or calls there. Enforced by the apps CDN's Content-Security-Policy.",
|
|
218
|
+
"type": "array",
|
|
219
|
+
"default": [
|
|
220
|
+
"*"
|
|
221
|
+
],
|
|
222
|
+
"maxItems": 20,
|
|
223
|
+
"uniqueItems": true,
|
|
224
|
+
"items": {
|
|
225
|
+
"type": "string",
|
|
226
|
+
"anyOf": [
|
|
227
|
+
{
|
|
228
|
+
"const": "*"
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
"pattern": "^(https|wss)://(\\*\\.)?([A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?\\.)*[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?(:[0-9]{1,5})?/?$"
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
"pattern": "^img:(\\*|https://(\\*\\.)?([A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?\\.)*[A-Za-z0-9]([A-Za-z0-9-]*[A-Za-z0-9])?(:[0-9]{1,5})?/?)$"
|
|
235
|
+
}
|
|
236
|
+
]
|
|
237
|
+
},
|
|
238
|
+
"examples": [
|
|
239
|
+
[
|
|
240
|
+
"*"
|
|
241
|
+
],
|
|
242
|
+
[
|
|
243
|
+
"https://api.example.com",
|
|
244
|
+
"https://*.cdn.example.com"
|
|
245
|
+
],
|
|
246
|
+
[
|
|
247
|
+
"img:*"
|
|
248
|
+
]
|
|
249
|
+
]
|
|
250
|
+
},
|
|
251
|
+
"functions": {
|
|
252
|
+
"description": "Server-side functions, one per functions/<name>.ts (or .js/.mts/.mjs) exporting `handler`. Bundled and deployed with each version as AWS Lambda functions and called from the app with app.functions.call(name, input). Needs the functions:invoke scope, and Engineering must enable functions for the app. A version whose functions changed always needs review.",
|
|
253
|
+
"type": "object",
|
|
254
|
+
"maxProperties": 10,
|
|
255
|
+
"propertyNames": {
|
|
256
|
+
"pattern": "^[a-z0-9]+(-[a-z0-9]+)*$",
|
|
257
|
+
"maxLength": 40
|
|
258
|
+
},
|
|
259
|
+
"additionalProperties": {
|
|
260
|
+
"$ref": "#/$defs/function"
|
|
261
|
+
},
|
|
262
|
+
"examples": [
|
|
263
|
+
{
|
|
264
|
+
"sync-feed": {
|
|
265
|
+
"timeoutSeconds": 20,
|
|
266
|
+
"memoryMb": 512,
|
|
267
|
+
"secrets": [
|
|
268
|
+
"FEED_API_KEY"
|
|
269
|
+
]
|
|
270
|
+
},
|
|
271
|
+
"nightly-report": {
|
|
272
|
+
"job": true,
|
|
273
|
+
"timeoutSeconds": 600
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
]
|
|
277
|
+
},
|
|
278
|
+
"schedules": {
|
|
279
|
+
"description": "Recurring runs of job functions (\"job\": true). A schedule runs only for the clients where a user turns it on from the app (app.schedules.enable), as \"schedule:<name>\" for that client and site. Needs the functions:invoke scope. Reviewed like scopes.",
|
|
280
|
+
"type": "object",
|
|
281
|
+
"maxProperties": 5,
|
|
282
|
+
"propertyNames": {
|
|
283
|
+
"pattern": "^[a-z0-9]+(-[a-z0-9]+)*$",
|
|
284
|
+
"maxLength": 40
|
|
285
|
+
},
|
|
286
|
+
"additionalProperties": {
|
|
287
|
+
"$ref": "#/$defs/schedule"
|
|
288
|
+
},
|
|
289
|
+
"examples": [
|
|
290
|
+
{
|
|
291
|
+
"nightly": {
|
|
292
|
+
"function": "nightly-report",
|
|
293
|
+
"cron": "0 7 ? * MON-FRI *",
|
|
294
|
+
"timezone": "America/Chicago"
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
]
|
|
298
|
+
},
|
|
299
|
+
"minProtocolVersion": {
|
|
300
|
+
"type": "integer",
|
|
301
|
+
"minimum": 1,
|
|
302
|
+
"maximum": 1
|
|
303
|
+
}
|
|
304
|
+
},
|
|
305
|
+
"allOf": [
|
|
306
|
+
{
|
|
307
|
+
"if": {
|
|
308
|
+
"required": ["visibility"],
|
|
309
|
+
"properties": { "visibility": { "const": "store" } }
|
|
310
|
+
},
|
|
311
|
+
"then": { "required": ["store"] }
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
"if": {
|
|
315
|
+
"required": [
|
|
316
|
+
"functions"
|
|
317
|
+
],
|
|
318
|
+
"properties": {
|
|
319
|
+
"functions": {
|
|
320
|
+
"minProperties": 1
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
},
|
|
324
|
+
"then": {
|
|
325
|
+
"required": [
|
|
326
|
+
"scopes"
|
|
327
|
+
],
|
|
328
|
+
"properties": {
|
|
329
|
+
"scopes": {
|
|
330
|
+
"contains": {
|
|
331
|
+
"const": "functions:invoke"
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
"if": {
|
|
339
|
+
"required": [
|
|
340
|
+
"schedules"
|
|
341
|
+
],
|
|
342
|
+
"properties": {
|
|
343
|
+
"schedules": {
|
|
344
|
+
"minProperties": 1
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
},
|
|
348
|
+
"then": {
|
|
349
|
+
"required": [
|
|
350
|
+
"scopes"
|
|
351
|
+
],
|
|
352
|
+
"properties": {
|
|
353
|
+
"scopes": {
|
|
354
|
+
"contains": {
|
|
355
|
+
"const": "functions:invoke"
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
"if": {
|
|
363
|
+
"required": [
|
|
364
|
+
"systemParameters"
|
|
365
|
+
],
|
|
366
|
+
"properties": {
|
|
367
|
+
"systemParameters": {
|
|
368
|
+
"minItems": 1
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
},
|
|
372
|
+
"then": {
|
|
373
|
+
"required": [
|
|
374
|
+
"scopes"
|
|
375
|
+
],
|
|
376
|
+
"properties": {
|
|
377
|
+
"scopes": {
|
|
378
|
+
"contains": {
|
|
379
|
+
"const": "hawksearch:sysparams:write"
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
"if": {
|
|
387
|
+
"required": [
|
|
388
|
+
"scopes"
|
|
389
|
+
],
|
|
390
|
+
"properties": {
|
|
391
|
+
"scopes": {
|
|
392
|
+
"contains": {
|
|
393
|
+
"const": "hawksearch:sysparams:write"
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
},
|
|
398
|
+
"then": {
|
|
399
|
+
"required": [
|
|
400
|
+
"systemParameters"
|
|
401
|
+
],
|
|
402
|
+
"properties": {
|
|
403
|
+
"systemParameters": {
|
|
404
|
+
"minItems": 1
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
},
|
|
409
|
+
{
|
|
410
|
+
"if": {
|
|
411
|
+
"required": [
|
|
412
|
+
"lambdas"
|
|
413
|
+
],
|
|
414
|
+
"properties": {
|
|
415
|
+
"lambdas": {
|
|
416
|
+
"minItems": 1
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
},
|
|
420
|
+
"then": {
|
|
421
|
+
"required": [
|
|
422
|
+
"scopes"
|
|
423
|
+
],
|
|
424
|
+
"properties": {
|
|
425
|
+
"scopes": {
|
|
426
|
+
"contains": {
|
|
427
|
+
"const": "lambdas:invoke"
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
},
|
|
433
|
+
{
|
|
434
|
+
"if": {
|
|
435
|
+
"required": [
|
|
436
|
+
"scopes"
|
|
437
|
+
],
|
|
438
|
+
"properties": {
|
|
439
|
+
"scopes": {
|
|
440
|
+
"contains": {
|
|
441
|
+
"const": "lambdas:invoke"
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
},
|
|
446
|
+
"then": {
|
|
447
|
+
"required": [
|
|
448
|
+
"lambdas"
|
|
449
|
+
],
|
|
450
|
+
"properties": {
|
|
451
|
+
"lambdas": {
|
|
452
|
+
"minItems": 1
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
],
|
|
458
|
+
"$defs": {
|
|
459
|
+
"configKey": {
|
|
460
|
+
"type": "object",
|
|
461
|
+
"additionalProperties": false,
|
|
462
|
+
"required": [
|
|
463
|
+
"type"
|
|
464
|
+
],
|
|
465
|
+
"properties": {
|
|
466
|
+
"type": {
|
|
467
|
+
"description": "string (up to 4000 characters), number (finite), boolean, emails (a list of up to 50 different plain addresses), or json (any JSON value except null). Every value is at most 16 KB as JSON.",
|
|
468
|
+
"enum": [
|
|
469
|
+
"string",
|
|
470
|
+
"number",
|
|
471
|
+
"boolean",
|
|
472
|
+
"emails",
|
|
473
|
+
"json"
|
|
474
|
+
]
|
|
475
|
+
},
|
|
476
|
+
"label": {
|
|
477
|
+
"description": "Shown in the Hawk Analytics portal next to the value.",
|
|
478
|
+
"type": "string",
|
|
479
|
+
"minLength": 1,
|
|
480
|
+
"maxLength": 100
|
|
481
|
+
},
|
|
482
|
+
"description": {
|
|
483
|
+
"description": "What the value is for, shown in the portal.",
|
|
484
|
+
"type": "string",
|
|
485
|
+
"maxLength": 500
|
|
486
|
+
},
|
|
487
|
+
"default": {
|
|
488
|
+
"description": "The value when neither the client nor the app has one set. Must be a valid value of the type."
|
|
489
|
+
}
|
|
490
|
+
},
|
|
491
|
+
"allOf": [
|
|
492
|
+
{
|
|
493
|
+
"if": { "properties": { "type": { "const": "string" } } },
|
|
494
|
+
"then": { "properties": { "default": { "type": "string", "maxLength": 4000 } } }
|
|
495
|
+
},
|
|
496
|
+
{
|
|
497
|
+
"if": { "properties": { "type": { "const": "number" } } },
|
|
498
|
+
"then": { "properties": { "default": { "type": "number" } } }
|
|
499
|
+
},
|
|
500
|
+
{
|
|
501
|
+
"if": { "properties": { "type": { "const": "boolean" } } },
|
|
502
|
+
"then": { "properties": { "default": { "type": "boolean" } } }
|
|
503
|
+
},
|
|
504
|
+
{
|
|
505
|
+
"if": { "properties": { "type": { "const": "emails" } } },
|
|
506
|
+
"then": { "properties": { "default": { "type": "array", "maxItems": 50, "uniqueItems": true, "items": { "type": "string", "format": "email", "maxLength": 254 } } } }
|
|
507
|
+
},
|
|
508
|
+
{
|
|
509
|
+
"if": { "properties": { "type": { "const": "json" } } },
|
|
510
|
+
"then": { "properties": { "default": { "not": { "type": "null" } } } }
|
|
511
|
+
}
|
|
512
|
+
]
|
|
513
|
+
},
|
|
514
|
+
"function": {
|
|
515
|
+
"type": "object",
|
|
516
|
+
"additionalProperties": false,
|
|
517
|
+
"properties": {
|
|
518
|
+
"job": {
|
|
519
|
+
"description": "A background job: started with app.functions.start(name, input) (not called), runs up to 900 s, and its result is read later with app.functions.wait/job. Schedules can only run job functions.",
|
|
520
|
+
"type": "boolean",
|
|
521
|
+
"default": false
|
|
522
|
+
},
|
|
523
|
+
"timeoutSeconds": {
|
|
524
|
+
"description": "Maximum run time in seconds: 1-25, or 1-900 for a job. Default 10 (300 for a job).",
|
|
525
|
+
"type": "integer",
|
|
526
|
+
"minimum": 1,
|
|
527
|
+
"maximum": 900
|
|
528
|
+
},
|
|
529
|
+
"memoryMb": {
|
|
530
|
+
"description": "Memory in MB (128-1024); more memory also means more CPU. Default 256.",
|
|
531
|
+
"type": "integer",
|
|
532
|
+
"minimum": 128,
|
|
533
|
+
"maximum": 1024,
|
|
534
|
+
"default": 256
|
|
535
|
+
},
|
|
536
|
+
"secrets": {
|
|
537
|
+
"description": "Names of the app secrets this function receives as ctx.secrets.<NAME>. Set the values with `hawk-app secrets set <NAME>`.",
|
|
538
|
+
"type": "array",
|
|
539
|
+
"maxItems": 20,
|
|
540
|
+
"uniqueItems": true,
|
|
541
|
+
"items": {
|
|
542
|
+
"type": "string",
|
|
543
|
+
"pattern": "^[A-Z][A-Z0-9_]{0,63}$"
|
|
544
|
+
},
|
|
545
|
+
"default": []
|
|
546
|
+
},
|
|
547
|
+
"clientSecrets": {
|
|
548
|
+
"description": "Names of per-client secrets this function receives as ctx.clientSecrets.<NAME>: each client's own value (e.g. their email platform's API key), set by the client's users in the app with app.clientSecrets.set(NAME, value) and never readable again. Missing when the client hasn't set one.",
|
|
549
|
+
"type": "array",
|
|
550
|
+
"maxItems": 10,
|
|
551
|
+
"uniqueItems": true,
|
|
552
|
+
"items": {
|
|
553
|
+
"type": "string",
|
|
554
|
+
"pattern": "^[A-Z][A-Z0-9_]{0,63}$"
|
|
555
|
+
},
|
|
556
|
+
"default": []
|
|
557
|
+
}
|
|
558
|
+
},
|
|
559
|
+
"if": {
|
|
560
|
+
"not": {
|
|
561
|
+
"required": [
|
|
562
|
+
"job"
|
|
563
|
+
],
|
|
564
|
+
"properties": {
|
|
565
|
+
"job": {
|
|
566
|
+
"const": true
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
},
|
|
571
|
+
"then": {
|
|
572
|
+
"properties": {
|
|
573
|
+
"timeoutSeconds": {
|
|
574
|
+
"maximum": 25
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
},
|
|
579
|
+
"schedule": {
|
|
580
|
+
"type": "object",
|
|
581
|
+
"required": [
|
|
582
|
+
"function",
|
|
583
|
+
"cron"
|
|
584
|
+
],
|
|
585
|
+
"additionalProperties": false,
|
|
586
|
+
"properties": {
|
|
587
|
+
"function": {
|
|
588
|
+
"description": "The job function to run (a key of \"functions\" with \"job\": true).",
|
|
589
|
+
"type": "string",
|
|
590
|
+
"pattern": "^[a-z0-9]+(-[a-z0-9]+)*$",
|
|
591
|
+
"maxLength": 40
|
|
592
|
+
},
|
|
593
|
+
"cron": {
|
|
594
|
+
"description": "EventBridge cron, 6 space-separated fields: \"minutes hours day-of-month month day-of-week year\" (no cron( ) wrapper), e.g. \"0 7 ? * MON *\". At most hourly: minutes must be a single number (0-59). Day-of-month or day-of-week must be \"?\".",
|
|
595
|
+
"type": "string",
|
|
596
|
+
"pattern": "^([0-9]|[1-5][0-9]) [0-9A-Za-z*?,/#-]{1,40} (\\? [0-9A-Za-z*?,/#-]{1,40} [0-9A-Za-z*?,/#-]{1,40}|[0-9A-Za-z*?,/#-]{1,40} [0-9A-Za-z*?,/#-]{1,40} \\?) [0-9A-Za-z*?,/#-]{1,40}$",
|
|
597
|
+
"examples": [
|
|
598
|
+
"0 7 ? * MON *",
|
|
599
|
+
"30 * * * ? *"
|
|
600
|
+
]
|
|
601
|
+
},
|
|
602
|
+
"timezone": {
|
|
603
|
+
"description": "IANA time zone the cron is evaluated in, e.g. \"America/Chicago\", or \"UTC\" (the default).",
|
|
604
|
+
"type": "string",
|
|
605
|
+
"pattern": "^(UTC|[A-Za-z0-9_+-]+(/[A-Za-z0-9_+-]+)+)$",
|
|
606
|
+
"default": "UTC"
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
}
|