@tailor-platform/sdk 2.23.0 → 2.25.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.
Files changed (50) hide show
  1. package/CHANGELOG.md +89 -0
  2. package/dist/application-ChqHuhZW.mjs +1 -0
  3. package/dist/application-DS0XKBtK.mjs +200 -0
  4. package/dist/application-DS0XKBtK.mjs.map +1 -0
  5. package/dist/cli/cache/bundle-cache.d.mts +1 -0
  6. package/dist/cli/commands/deploy/deployment-target.d.mts +1 -0
  7. package/dist/cli/commands/machineuser/list.d.mts +1 -0
  8. package/dist/cli/commands/show.d.mts +13 -1
  9. package/dist/cli/lib.d.mts +2 -2
  10. package/dist/cli/lib.mjs +1 -1
  11. package/dist/cli/lib.mjs.map +1 -1
  12. package/dist/cli/main.mjs +43 -43
  13. package/dist/cli/main.mjs.map +1 -1
  14. package/dist/cli/services/application.d.mts +1 -0
  15. package/dist/cli/services/workflow/bundler.d.mts +2 -1
  16. package/dist/cli/shared/forbidden-runtime-globals.d.mts +1 -0
  17. package/dist/cli/shared/start-context.d.mts +1 -0
  18. package/dist/cli/ts-hook.mjs +3 -3
  19. package/dist/completion/zsh-worker.zsh +3 -3
  20. package/dist/configure/config/types.d.mts +42 -2
  21. package/dist/configure/index.d.mts +2 -2
  22. package/dist/configure/index.mjs +1 -1
  23. package/dist/configure/index.mjs.map +1 -1
  24. package/dist/plugin/index.mjs +1 -1
  25. package/dist/plugin/index.mjs.map +1 -1
  26. package/dist/plugin/types.d.mts +97 -0
  27. package/dist/register-ts-hook-DPAW0Z4M.mjs +924 -0
  28. package/dist/register-ts-hook-DPAW0Z4M.mjs.map +1 -0
  29. package/dist/vitest/mocks/file.d.mts +1 -1
  30. package/docs/cli/application.md +23 -0
  31. package/docs/cli/secret.md +24 -16
  32. package/docs/cli-reference.md +25 -13
  33. package/docs/configuration.md +28 -3
  34. package/docs/github-actions.md +236 -56
  35. package/docs/migration/v3.md +46 -0
  36. package/docs/multi-environment.md +3 -1
  37. package/docs/plugin/custom.md +76 -1
  38. package/docs/plugin/frontend.md +124 -0
  39. package/docs/plugin/index.md +24 -2
  40. package/docs/services/auth.md +2 -0
  41. package/docs/services/secret.md +5 -4
  42. package/docs/services/staticwebsite.md +2 -0
  43. package/docs/services/tailordb-migration.md +1 -1
  44. package/docs/services/workflow.md +3 -0
  45. package/package.json +8 -8
  46. package/dist/application-BtZ8hmx9.mjs +0 -1
  47. package/dist/application-m2G91kKI.mjs +0 -199
  48. package/dist/application-m2G91kKI.mjs.map +0 -1
  49. package/dist/register-ts-hook-ztnEFW6n.mjs +0 -922
  50. package/dist/register-ts-hook-ztnEFW6n.mjs.map +0 -1
@@ -0,0 +1,124 @@
1
+ # Frontend Plugin
2
+
3
+ `frontendPlugin` builds frontend assets and uploads them to Static Websites after
4
+ `tailor deploy` applies your application. It can provide deployed URLs and public
5
+ OAuth client IDs as build environment variables.
6
+
7
+ ## Installation
8
+
9
+ ```sh
10
+ pnpm add -D @tailor-platform/sdk-plugin-frontend
11
+ ```
12
+
13
+ Use an SDK version that supports `onDeployed` hooks. When testing a PR before
14
+ that SDK release, install both the SDK and frontend plugin from the same
15
+ `pkg.pr.new` commit.
16
+
17
+ ## Monorepo example
18
+
19
+ Given this layout:
20
+
21
+ ```text
22
+ apps/
23
+ backend/
24
+ tailor.config.ts
25
+ web/
26
+ package.json
27
+ dist/
28
+ ```
29
+
30
+ Register the plugin in `apps/backend/tailor.config.ts`:
31
+
32
+ ```typescript
33
+ import { defineConfig, definePlugins, defineStaticWebSite } from "@tailor-platform/sdk";
34
+ import { frontendPlugin } from "@tailor-platform/sdk-plugin-frontend";
35
+
36
+ const website = defineStaticWebSite("my-frontend", { description: "Web app" });
37
+
38
+ export default defineConfig({
39
+ name: "my-app",
40
+ staticWebsites: [website],
41
+ });
42
+
43
+ export const plugins = definePlugins(
44
+ frontendPlugin({
45
+ site: website,
46
+ workingDir: "../web",
47
+ build: "pnpm run build",
48
+ distDir: "dist",
49
+ env: ({ site, application }) => ({
50
+ ...(application.url ? { VITE_TAILOR_APP_URL: application.url } : {}),
51
+ VITE_SITE_URL: site.url,
52
+ VITE_OAUTH2_CLIENT_ID:
53
+ application.auth?.oauth2Clients.find((client) => client.name === "web")?.clientId ?? "",
54
+ }),
55
+ }),
56
+ );
57
+ ```
58
+
59
+ Run `tailor deploy --config apps/backend/tailor.config.ts` from the repository
60
+ root. `workingDir` is where `build` runs, relative to the config's directory, so
61
+ this example builds in `apps/web`. `distDir` is the directory your build writes
62
+ its assets to, relative to `workingDir`, so this example publishes `apps/web/dist`.
63
+ Set it to match your build tool's output setting; the plugin does not change where
64
+ the build writes. Omitting `workingDir` uses the config's directory. Absolute paths are
65
+ also accepted.
66
+
67
+ `site` accepts either a `defineStaticWebSite()` result or a site name. The site
68
+ must be declared in `staticWebsites` of the same config that registers
69
+ `frontendPlugin`. With multiple configs, register each frontend in the config that
70
+ declares its site; a site from another config fails before the build starts. The
71
+ `env` callback can still read the URLs of other configs' sites from `applications`.
72
+
73
+ ## Build environment
74
+
75
+ `env` is an optional function that returns environment variables, synchronously
76
+ or asynchronously. Its values override matching variables inherited from the
77
+ parent process. Choose variable names for your frontend framework; the plugin
78
+ does not add a prefix.
79
+
80
+ The callback receives the destination `site`, the registering `application`, all
81
+ `applications` in the deploy, and `workspaceId`. Each application lists its static
82
+ websites by name under `staticWebsites`, so `application.staticWebsites.admin?.url`
83
+ reads another site of the same config.
84
+ Only public OAuth client IDs are provided. Values embedded into browser assets
85
+ are visible to visitors, so supply only values intended for public use.
86
+
87
+ Build commands run in a shell. Their stdout and stderr both go to stderr, keeping
88
+ `tailor deploy --json` stdout available for the JSON result. Builds have no timeout.
89
+
90
+ ## Upload existing assets
91
+
92
+ Omit `build` to upload an existing directory:
93
+
94
+ ```typescript
95
+ export const plugins = definePlugins(
96
+ frontendPlugin({ site: "my-frontend", workingDir: "../web", distDir: "dist" }),
97
+ );
98
+ ```
99
+
100
+ For multiple frontends, pass each one as another argument, as in
101
+ `frontendPlugin(web, admin)`; register the plugin only once. Each site may appear
102
+ only once. Frontends are built and uploaded sequentially, in argument order. At
103
+ least one frontend is required, and each `distDir` must be non-empty. A `build` that is empty or only whitespace is rejected; omit `build` instead to publish without building.
104
+
105
+ ## Deploy behavior and failures
106
+
107
+ The plugin runs even if no platform resources changed. It does not run during
108
+ dry-run, build-only, generation, or migration test deployments. Dry-run lists the
109
+ plugin as a pending deploy hook.
110
+
111
+ An unknown site, a site declared in another config, failed build, missing output directory, or failed upload stops
112
+ later frontends and deploy hooks. Platform resources have already been applied;
113
+ fix the error and run `tailor deploy` again. Successfully uploaded frontends are
114
+ not rolled back. Skipped upload files produce warnings and are listed in the result.
115
+
116
+ With `--json`, the result contains a `deployedHooks` entry for
117
+ `@tailor-platform/frontend`. Its `outputs.frontends` array contains each site's
118
+ `site`, published `url`, and `skippedFiles`.
119
+
120
+ The same deploy result includes `workspaceId` and `applications`, including each
121
+ config's Static Website URLs, AI Gateway URLs, and public OAuth client IDs. The
122
+ application endpoint URL and domain are present when a Platform Application with
123
+ the config's name exists. Read these directly from `tailor deploy --json`; a
124
+ separate `show` command is not required.
@@ -115,7 +115,7 @@ e.g. `@example/soft-delete` → `example-soft-delete`), such as:
115
115
 
116
116
  ## Plugin Lifecycle
117
117
 
118
- Plugins have 5 hooks across two lifecycle phases. Each hook fires at a specific point in the `tailor generate` pipeline:
118
+ Plugins have definition-time, generation-time, and deploy-time hooks. The generation lifecycle is:
119
119
 
120
120
  ```
121
121
  tailor generate
@@ -156,7 +156,29 @@ These hooks produce TailorDB tables, resolvers, and executors that become part o
156
156
 
157
157
  These hooks receive all finalized data and produce output files (TypeScript code, etc.). No `importPath` required.
158
158
 
159
- A plugin can implement hooks from either or both phases.
159
+ ### Deploy-time hooks
160
+
161
+ ```
162
+ tailor deploy
163
+ │
164
+ ├─ Build and review resource changes
165
+ ├─ Apply all applications and services
166
+ └─ onDeployed ← each registered plugin, in config order
167
+ ```
168
+
169
+ | Hook | Available data | Can do |
170
+ | ------------ | ---------------------------------------------------------------- | ---------------------------------------- |
171
+ | `onDeployed` | Deployed application URLs, website URLs, public OAuth client IDs | Build assets and publish static websites |
172
+
173
+ Deploy hooks run even when there are no resource changes. They do not run during
174
+ `tailor generate`, dry-run, build-only, or migration test deployments. Dry-run lists
175
+ which hooks would run. A deploy-only plugin needs neither `importPath` nor table attachments.
176
+
177
+ A plugin can implement hooks from any combination of phases.
178
+
179
+ ## Deploying Frontends
180
+
181
+ See [Frontend Plugin](./frontend.md) to build frontends and upload them to static websites as part of `tailor deploy`.
160
182
 
161
183
  ## Creating Custom Plugins
162
184
 
@@ -351,6 +351,8 @@ Get OAuth2 client credentials using the CLI:
351
351
  tailor oauth2client get <name>
352
352
  ```
353
353
 
354
+ `tailor show` also lists the client ID, without the secret, of each OAuth2 client defined in `oauth2Clients` once it has been deployed. If your credentials cannot list OAuth2 clients, as with the workspace viewer role, it warns and reports `oauth2Clients` as `null`.
355
+
354
356
  ## Identity Provider
355
357
 
356
358
  Connect to an external identity provider:
@@ -197,13 +197,14 @@ tailor secret create \
197
197
  --name stripe-secret-key \
198
198
  --value sk_live_xxxxx
199
199
 
200
- # Update a secret
201
- tailor secret update \
200
+ # Update a secret, reading the value from standard input
201
+ printf '%s' "$STRIPE_SECRET_KEY" | tailor secret update \
202
202
  --vault-name api-keys \
203
- --name stripe-secret-key \
204
- --value sk_live_yyyyy
203
+ --name stripe-secret-key
205
204
  ```
206
205
 
206
+ A value passed with `--value` can show up in your shell history and in process listings. Without `--value`, the command reads the value from standard input instead, accepting up to 128 KiB and removing one trailing newline.
207
+
207
208
  ### List Secrets
208
209
 
209
210
  ```bash
@@ -130,6 +130,8 @@ export default defineConfig({
130
130
 
131
131
  Resolver, executor, workflow job, and auth before-login hook code, and TailorDB migration scripts, that read [`env`](../configuration.md#environment-variables) receive the deployed URL, even when the same deploy both creates the website and reads its URL — one `deploy` call resolves it, with no second, manually-triggered `deploy` needed. If the referenced website does not exist at all, the CLI warns and leaves the unresolved reference in place. If the reference still can't be resolved after this deploy's rebuild, the deploy fails instead of shipping the unresolved reference. This platform lookup only happens during `deploy`; `function run` passes the literal `<name>:url` string unchanged, since it never talks to the platform to resolve it.
132
132
 
133
+ The deployed URL is also shown by `tailor show`, which lists the URL of each static website defined in `staticWebsites` once it has been deployed.
134
+
133
135
  ## Complete Example
134
136
 
135
137
  ```typescript
@@ -240,7 +240,7 @@ This writes a numbered migration with an empty `diff.json`, a `migrate.ts` skele
240
240
 
241
241
  The command requires a clean state: if the namespace has schema changes that are not yet in migration files, generate the schema migration first. With multiple namespaces, pass `--namespace` to name the target. `--data-only` cannot be combined with `--init`, `--rename`, `--drop`, or `--expand-contract`.
242
242
 
243
- A data-only migration runs in **every** workspace the history is applied to, including freshly created ones. Write the script so it is safe against tables with no matching rows (a set-based `UPDATE` with a `WHERE` clause is naturally a no-op on an empty table). For a fix that should run in a single environment only, or that is too large for one transaction, run it outside the migration history instead.
243
+ A data-only migration runs in **every** workspace the history is applied to, including freshly created ones. Write the script so it is safe against tables with no matching rows (a set-based `UPDATE` with a `WHERE` clause is naturally a no-op on an empty table). For a fix that should run in a single environment only, or that is too large for one transaction, run it outside the migration history instead, for example as a one-off script scaffolded with [`tailor function script`](../cli/function.md#function-script) and executed against a single workspace with [`tailor function run`](../cli/function.md#function-run).
244
244
 
245
245
  ## Configuration
246
246
 
@@ -516,6 +516,9 @@ You can start a workflow execution from a resolver using `workflow.start()`.
516
516
 
517
517
  - `workflow.start(args, options?)` returns a workflow run ID (`Promise<string>`).
518
518
  - To run with machine-user permissions, pass `{ invoker: "<machine-user>" }`. The name is type-narrowed to the machine users defined in your auth config.
519
+ - Import the workflow from its workflow file with a default import (or a namespace import, calling `wf.default.start(...)`), using a relative path or a `tsconfig.json` `paths` alias. The build replaces the `.start()` call with a platform call, so it has to recognize the workflow: export it as the file's default export — either `createWorkflow({ name: "..." })` itself or the result of a helper function that calls `createWorkflow()`.
520
+ - Call `.start()` directly on the imported name (`orderProcessingWorkflow.start(...)`, or `wf.default.start(...)` for a namespace import). If you first assign the workflow to another variable (`const wf = orderProcessingWorkflow; wf.start(...)`) or pass it to a function, the call is neither rewritten nor checked, and fails at runtime.
521
+ - If a `.start()` call is made on an export of a workflow file that the build cannot recognize as a workflow or job defined that way, the build fails. A `.start()` on a workflow imported from anywhere other than a workflow file (for example re-exported from a shared package) cannot be checked, and fails at runtime.
519
522
 
520
523
  ```typescript
521
524
  import { createResolver, t } from "@tailor-platform/sdk";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tailor-platform/sdk",
3
- "version": "2.23.0",
3
+ "version": "2.25.0",
4
4
  "description": "Tailor Platform SDK - The SDK to work with Tailor Platform",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -164,10 +164,10 @@
164
164
  "@opentelemetry/resources": "2.11.0",
165
165
  "@opentelemetry/sdk-trace-node": "2.11.0",
166
166
  "@opentelemetry/semantic-conventions": "1.43.0",
167
- "@oxc-project/types": "0.151.0",
167
+ "@oxc-project/types": "0.152.0",
168
168
  "@politty/zod": "0.3.0",
169
- "@secretlint/core": "13.0.5",
170
- "@secretlint/secretlint-rule-preset-recommend": "13.0.5",
169
+ "@secretlint/core": "13.0.6",
170
+ "@secretlint/secretlint-rule-preset-recommend": "13.0.6",
171
171
  "@standard-schema/spec": "1.1.0",
172
172
  "@tailor-platform/function-kysely-tailordb": "0.1.3",
173
173
  "@toiroakr/lines-db": "0.13.0",
@@ -191,7 +191,7 @@
191
191
  "pathe": "2.0.3",
192
192
  "pgsql-ast-parser": "12.0.2",
193
193
  "pkg-types": "2.3.3",
194
- "rolldown": "1.2.11",
194
+ "rolldown": "1.2.12",
195
195
  "semver": "7.8.5",
196
196
  "sql-highlight": "6.1.0",
197
197
  "std-env": "4.2.0",
@@ -208,13 +208,13 @@
208
208
  "@tailor-platform/shared": "^0.0.0",
209
209
  "@tailor-platform/tailor-proto": "^0.0.1",
210
210
  "@types/mime-types": "3.0.1",
211
- "@types/node": "24.13.6",
211
+ "@types/node": "24.19.0",
212
212
  "@types/semver": "7.8.0",
213
213
  "@typescript/native-preview": "7.0.0-dev.20260707.2",
214
214
  "@vitest/coverage-v8": "5.0.1",
215
215
  "eslint-plugin-zod": "4.14.2",
216
- "oxfmt": "0.70.0",
217
- "oxlint": "1.85.0",
216
+ "oxfmt": "0.71.0",
217
+ "oxlint": "1.86.0",
218
218
  "oxlint-tsgolint": "7.0.2003",
219
219
  "sonda": "0.14.0",
220
220
  "tsdown": "0.23.0",
@@ -1 +0,0 @@
1
- import{n as e,t}from"./application-m2G91kKI.mjs";export{t as defineApplication,e as generatePluginFilesIfNeeded};