@tailor-platform/sdk 2.29.2 → 2.30.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/CHANGELOG.md +22 -0
- package/dist/aigateway-DsWDjzk4.mjs.map +1 -1
- package/dist/{application-Dm_21z-i.mjs → application-C2bPmmbh.mjs} +1 -1
- package/dist/{application-D8jruzwo.mjs → application-D0xNJbag.mjs} +32 -32
- package/dist/{application-D8jruzwo.mjs.map → application-D0xNJbag.mjs.map} +1 -1
- package/dist/assert-WeXvmG4j.mjs.map +1 -1
- package/dist/authconnection-CynFBIv8.mjs.map +1 -1
- package/dist/brand-C8nMKhJC.mjs.map +1 -1
- package/dist/cli/commands/machineuser/list.d.mts +2 -1
- package/dist/cli/lib.mjs +1 -1
- package/dist/cli/lib.mjs.map +1 -1
- package/dist/cli/main.mjs +16 -16
- package/dist/cli/main.mjs.map +1 -1
- package/dist/cli/shared/error-json.d.mts +2 -0
- package/dist/completion/zsh-worker.zsh +1 -1
- package/dist/configure/index.mjs.map +1 -1
- package/dist/context-D0QjfxzD.mjs.map +1 -1
- package/dist/{crashreport-BAG8c7hB.mjs → crashreport-BCIy33Cz.mjs} +2 -2
- package/dist/{crashreport-BAG8c7hB.mjs.map → crashreport-BCIy33Cz.mjs.map} +1 -1
- package/dist/crashreport-IN6H7GX3.mjs +1 -0
- package/dist/date-CgP7gMG_.mjs.map +1 -1
- package/dist/date-representation-Cr7W7Pn2.mjs.map +1 -1
- package/dist/errors-BOF68LJ5.mjs +5 -0
- package/dist/errors-BOF68LJ5.mjs.map +1 -0
- package/dist/es-builtins-SfvXRVoG.mjs.map +1 -1
- package/dist/field-parse-C41e3UAF.mjs.map +1 -1
- package/dist/file-DKBOj5q4.mjs.map +1 -1
- package/dist/globals-BCmGX05J.mjs.map +1 -1
- package/dist/guards-yDXyKC9F.mjs.map +1 -1
- package/dist/iconv-DlFMt2gW.mjs.map +1 -1
- package/dist/idp-G_ojPBB5.mjs.map +1 -1
- package/dist/interceptor-DQg3cR_9.mjs.map +1 -1
- package/dist/kysely/index.mjs.map +1 -1
- package/dist/kysely-type-BWMfV301.mjs.map +1 -1
- package/dist/logger-DP2BjQ93.mjs.map +1 -1
- package/dist/{logger-DuaT2zY3.mjs → logger-RgtbhJ83.mjs} +3 -3
- package/dist/logger-RgtbhJ83.mjs.map +1 -0
- package/dist/manager-Bk-7vkwd.mjs.map +1 -1
- package/dist/migration-steps-C6F3zNdQ.mjs.map +1 -1
- package/dist/multiline-EyzjEwn9.mjs.map +1 -1
- package/dist/node-builtins-DYfhPBnz.mjs.map +1 -1
- package/dist/package-json-C690ceex.mjs.map +1 -1
- package/dist/platform-serialize-DkiTdHOt.mjs.map +1 -1
- package/dist/plugin/builtin/enum-constants/index.mjs.map +1 -1
- package/dist/plugin/builtin/file-utils/index.mjs.map +1 -1
- package/dist/plugin/builtin/seed/index.mjs +1 -1
- package/dist/plugin/index.mjs.map +1 -1
- package/dist/{register-ts-hook-B5ZbbJwS.mjs → register-ts-hook-CDnN_Jx2.mjs} +65 -65
- package/dist/register-ts-hook-CDnN_Jx2.mjs.map +1 -0
- package/dist/registry-BijIDRVA.mjs.map +1 -1
- package/dist/repl-editor-DGJBfIt1.mjs.map +1 -1
- package/dist/schema-B6hJQWp6.mjs.map +1 -1
- package/dist/secret-file-C9wp_FCX.mjs.map +1 -1
- package/dist/secretmanager-vHQoXdQz.mjs.map +1 -1
- package/dist/seed/idp-user-password.d.mts +15 -0
- package/dist/seed/index.d.mts +19 -1
- package/dist/seed/index.mjs +6 -6
- package/dist/seed/index.mjs.map +1 -1
- package/dist/{seed-C3P_T_Eh.mjs → seed-Cn-3JApy.mjs} +12 -8
- package/dist/seed-Cn-3JApy.mjs.map +1 -0
- package/dist/{service-l_tEI8sS.mjs → service-9SBPNpK8.mjs} +2 -2
- package/dist/{service-l_tEI8sS.mjs.map → service-9SBPNpK8.mjs.map} +1 -1
- package/dist/{service-b1g22NN9.mjs → service-9rwi_I4d.mjs} +2 -2
- package/dist/{service-b1g22NN9.mjs.map → service-9rwi_I4d.mjs.map} +1 -1
- package/dist/service-Ca1WwyIt.mjs +1 -0
- package/dist/service_pb-Bbu2QSIr.mjs.map +1 -1
- package/dist/telemetry-Xk7J829P.mjs.map +1 -1
- package/dist/type-source--ZNcV8RJ.mjs.map +1 -1
- package/dist/user-agent-vdHYF3QL.mjs.map +1 -1
- package/dist/utils/test/index.mjs.map +1 -1
- package/dist/vitest/environment.mjs.map +1 -1
- package/dist/vitest/index.mjs.map +1 -1
- package/dist/vitest/setup.mjs.map +1 -1
- package/dist/wait-point-invoker-eiP-IIux.mjs.map +1 -1
- package/dist/wait-point-registry-B-ESkTZX.mjs.map +1 -1
- package/dist/workflow-Cs9ISw6j.mjs.map +1 -1
- package/dist/workspace_resource_pb-CaoM2npP.mjs.map +1 -1
- package/docs/cli/application.md +4 -0
- package/docs/cli/auth.md +4 -0
- package/docs/cli/completion.md +4 -0
- package/docs/cli/crashreport.md +4 -0
- package/docs/cli/data.md +4 -0
- package/docs/cli/executor.md +4 -0
- package/docs/cli/function.md +4 -0
- package/docs/cli/organization.md +4 -0
- package/docs/cli/plugin.md +4 -0
- package/docs/cli/query.md +4 -0
- package/docs/cli/secret.md +4 -0
- package/docs/cli/skills.md +4 -0
- package/docs/cli/staticwebsite.md +4 -0
- package/docs/cli/tailordb.md +4 -0
- package/docs/cli/upgrade.md +4 -0
- package/docs/cli/user.md +4 -0
- package/docs/cli/workflow.md +4 -0
- package/docs/cli/workspace.md +4 -0
- package/docs/cli-reference.md +4 -0
- package/docs/configuration.md +4 -0
- package/docs/data-clone.md +4 -0
- package/docs/github-actions.md +10 -0
- package/docs/migration/v2.md +4 -0
- package/docs/multi-environment.md +4 -0
- package/docs/plugin/custom.md +4 -0
- package/docs/plugin/frontend.md +4 -0
- package/docs/plugin/index.md +4 -0
- package/docs/quickstart.md +4 -0
- package/docs/runtime.md +4 -0
- package/docs/services/aigateway.md +4 -0
- package/docs/services/auth.md +4 -0
- package/docs/services/executor.md +4 -0
- package/docs/services/http-adapter.md +4 -0
- package/docs/services/idp.md +4 -0
- package/docs/services/resolver.md +4 -0
- package/docs/services/secret.md +4 -0
- package/docs/services/staticwebsite.md +4 -0
- package/docs/services/tailordb/index.md +4 -0
- package/docs/services/tailordb/migration.md +4 -0
- package/docs/services/workflow.md +4 -0
- package/docs/testing.md +4 -0
- package/package.json +3 -3
- package/dist/crashreport-BcXuocwI.mjs +0 -1
- package/dist/errors-D3qpNHR6.mjs +0 -7
- package/dist/errors-D3qpNHR6.mjs.map +0 -1
- package/dist/logger-DuaT2zY3.mjs.map +0 -1
- package/dist/register-ts-hook-B5ZbbJwS.mjs.map +0 -1
- package/dist/seed-C3P_T_Eh.mjs.map +0 -1
- package/dist/service-C_CogLQr.mjs +0 -1
- package/docs/migration/v3.md +0 -277
package/docs/cli/application.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Create, generate, deploy, inspect, and remove the application defined in tailor.config.ts, and call Tailor Platform APIs directly with tailor api."
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# Application Commands
|
|
2
6
|
|
|
3
7
|
Commands for managing Tailor Platform applications. These commands work with `tailor.config.ts`.
|
package/docs/cli/auth.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Manage Auth service resources from the tailor CLI: authorize and revoke auth connections, get machine user tokens, and inspect OAuth2 clients."
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# Auth Resource Commands
|
|
2
6
|
|
|
3
7
|
Commands for managing Auth service resources (auth connections, machine users, and OAuth2 clients).
|
package/docs/cli/completion.md
CHANGED
package/docs/cli/crashreport.md
CHANGED
package/docs/cli/data.md
CHANGED
package/docs/cli/executor.md
CHANGED
package/docs/cli/function.md
CHANGED
package/docs/cli/organization.md
CHANGED
package/docs/cli/plugin.md
CHANGED
package/docs/cli/query.md
CHANGED
package/docs/cli/secret.md
CHANGED
package/docs/cli/skills.md
CHANGED
package/docs/cli/tailordb.md
CHANGED
package/docs/cli/upgrade.md
CHANGED
package/docs/cli/user.md
CHANGED
package/docs/cli/workflow.md
CHANGED
package/docs/cli/workspace.md
CHANGED
package/docs/cli-reference.md
CHANGED
package/docs/configuration.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Configure your application in tailor.config.ts, including application settings, services, bundling, auth, static websites, secrets, environment variables, workflows, and plugins."
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# Configuration
|
|
2
6
|
|
|
3
7
|
The SDK uses TypeScript for configuration files. By default, it uses `tailor.config.ts` in the project root. You can specify a different path using the `--config` option.
|
package/docs/data-clone.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Copy the TailorDB records, files, and IdP users of an application from one workspace to another with tailor data clone, and rehearse migrations against cloned data."
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# Cloning Application Data
|
|
2
6
|
|
|
3
7
|
`tailor data clone` copies the data of an application from one workspace to another, for example to fill a staging workspace with production records before testing a release against them. It copies the records of every TailorDB namespace registered in the application, and optionally TailorDB file content and IdP users.
|
package/docs/github-actions.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Generate GitHub Actions deploy workflows and Renovate configuration for your app with tailor setup, including approval gates, secrets, monorepos, and rollback."
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# GitHub Actions Integration
|
|
2
6
|
|
|
3
7
|
`tailor setup` generates GitHub repository automation for your Tailor Platform
|
|
@@ -639,6 +643,12 @@ and apply the data after deploy.
|
|
|
639
643
|
| branch, tag | `tailor seed apply --upsert` | The fields of each committed seed row are written; other rows are kept |
|
|
640
644
|
| preview | `tailor seed apply --truncate --yes` | The preview workspace is emptied, IdP users included, and seeded from scratch |
|
|
641
645
|
|
|
646
|
+
The seed steps read the optional `SEED_USER_PASSWORD` secret of the GitHub
|
|
647
|
+
Environment and pass it to `tailor seed`, which uses it as the password of `_User`
|
|
648
|
+
rows that have none. Set it with `tailor setup ci env`. Validation on pull
|
|
649
|
+
requests gets a fixed placeholder instead of the secret, since it only checks that
|
|
650
|
+
a password exists.
|
|
651
|
+
|
|
642
652
|
Setup stops unless the config uses `seedPlugin` with `machineUserName`, which
|
|
643
653
|
names the machine user that seeds, and an existing `<distPath>/data/` directory.
|
|
644
654
|
Every `--seed-dataset` must name an entry of
|
package/docs/migration/v2.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Upgrade your project to Tailor Platform SDK v2 by running the codemods and finishing the changes they report as not migrated automatically."
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# Migrating to v2
|
|
2
6
|
|
|
3
7
|
<!-- Generated from the sdk-codemod registry. Run `pnpm codemod:docs:update` and edit `packages/sdk-codemod/src/registry.ts` instead of this file. -->
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Deploy one tailor.config.ts to development, staging, and production workspaces, and vary configuration values, secrets, and seed data per environment."
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# Multi-Environment Configuration
|
|
2
6
|
|
|
3
7
|
A project typically runs in more than one environment — for example, each developer's own workspace, a staging workspace, and a production workspace. The SDK has no separate "environment" concept: an environment is a workspace you deploy to, and all environments share the same `tailor.config.ts`. This guide shows how to switch the deployment target and how to vary configuration values per environment.
|
package/docs/plugin/custom.md
CHANGED
package/docs/plugin/frontend.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Build your frontend and upload it to a Static Website on every tailor deploy, with deployed URLs and OAuth client IDs passed in as build variables."
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# Frontend Plugin
|
|
2
6
|
|
|
3
7
|
`frontendPlugin` builds frontend assets and uploads them to Static Websites after
|
package/docs/plugin/index.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Extend TailorDB tables with plugins that generate additional tables, executors, and files, and learn how to register, attach, and configure them."
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# Plugins (Beta)
|
|
2
6
|
|
|
3
7
|
> **Beta Feature**: The plugin system is currently in beta. APIs may change in future releases.
|
package/docs/quickstart.md
CHANGED
package/docs/runtime.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Call Tailor Platform runtime APIs such as secrets, IdP, workflows, file uploads, AI Gateway, and logging from your functions with typed imports from @tailor-platform/sdk/runtime."
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# Runtime API
|
|
2
6
|
|
|
3
7
|
`@tailor-platform/sdk/runtime` provides typed wrappers for the `tailor.*` and `tailordb.file` APIs that the Tailor Platform Function runtime injects into the global scope at execution time. The wrappers are thin and delegate to the platform-provided globals; they exist so that you can:
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Define AI Gateways that give your app one OpenAI-compatible endpoint for multiple LLMs, with workspace authentication and platform-managed credentials."
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# AI Gateway
|
|
2
6
|
|
|
3
7
|
AI Gateway provides a unified endpoint for accessing a range of large language models through a single OpenAI-compatible API, with platform-managed credentials and workspace-scoped authentication.
|
package/docs/services/auth.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Configure authentication and authorization with defineAuth, including user profiles, machine users, OAuth 2.0 clients, identity providers, auth connections, and before-login hooks."
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# Auth
|
|
2
6
|
|
|
3
7
|
Auth is a service for configuring authentication and authorization in your Tailor Platform application.
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Create executors that run functions, webhooks, GraphQL operations, or workflows in response to record changes, schedules, incoming webhooks, and resolver events."
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# Executor
|
|
2
6
|
|
|
3
7
|
Executors are event-driven handlers that automatically trigger in response to data changes, schedules, or external events.
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Expose REST-style HTTP endpoints that translate each request into a GraphQL operation and shape the response for HTTP clients."
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# HTTP Adapter
|
|
2
6
|
|
|
3
7
|
HTTP adapters expose REST-style HTTP endpoints on your application by translating each request into a GraphQL query and (optionally) reshaping the GraphQL response back into an HTTP response.
|
package/docs/services/idp.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Set up the built-in identity provider with defineIdp to register and authenticate users and manage OAuth clients for your Auth service."
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# IdP (Identity Provider)
|
|
2
6
|
|
|
3
7
|
IdP is a built-in identity provider service for managing user authentication.
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Build custom GraphQL queries and mutations in TypeScript with typed input and output schemas, validation, TailorDB access, and permissions."
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# Resolver
|
|
2
6
|
|
|
3
7
|
Resolvers are custom GraphQL endpoints with business logic that execute on the Tailor Platform.
|
package/docs/services/secret.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Store API keys, tokens, and other credentials in Secret Manager vaults, and read them at runtime from executors and workflows."
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# Secret Manager
|
|
2
6
|
|
|
3
7
|
Secret Manager provides secure storage for sensitive values like API keys, tokens, and credentials that your application needs at runtime.
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Host static web applications on the Tailor Platform with defineStaticWebSite, including type-safe URL references, IP restrictions, and custom domains."
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# Static Website
|
|
2
6
|
|
|
3
7
|
Static Website is a service for hosting static web applications on the Tailor Platform.
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Define TailorDB tables in TypeScript with field types, relations, permissions, hooks, and validations, and get a generated GraphQL API."
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# TailorDB
|
|
2
6
|
|
|
3
7
|
TailorDB is a type-safe database service for defining and managing data models on the Tailor Platform.
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Generate, test, and apply TailorDB schema migrations with optional data migration scripts, and recover from failed migrations."
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# TailorDB Migrations
|
|
2
6
|
|
|
3
7
|
> **Beta:** The `tailordb migration` command and the migration runtime are beta features. They may introduce breaking changes in future releases. The CLI emits a beta warning on every invocation.
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Orchestrate multi-step jobs with durable workflows, including job dependencies, wait points, retry and concurrency policies, and starting workflows from resolvers."
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# Workflow
|
|
2
6
|
|
|
3
7
|
Workflows orchestrate multiple jobs that can depend on each other, enabling complex multi-step operations with durable execution.
|
package/docs/testing.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Test SDK applications with Vitest: unit-test resolvers, workflow jobs, and executors with platform API mocks, and run end-to-end tests against a deployed workspace."
|
|
3
|
+
---
|
|
4
|
+
|
|
1
5
|
# Testing Guide
|
|
2
6
|
|
|
3
7
|
Tailor Platform SDK applications are tested with [Vitest](https://vitest.dev/) at two layers:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tailor-platform/sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.30.0",
|
|
4
4
|
"description": "Tailor Platform SDK - The SDK to work with Tailor Platform",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -183,7 +183,7 @@
|
|
|
183
183
|
"graphql": "17.0.2",
|
|
184
184
|
"inflection": "3.0.2",
|
|
185
185
|
"kysely": "0.29.6",
|
|
186
|
-
"lines-db": "0.
|
|
186
|
+
"lines-db": "0.18.0",
|
|
187
187
|
"mime-types": "3.0.2",
|
|
188
188
|
"open": "11.0.4",
|
|
189
189
|
"oxc-parser": "0.154.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.
|
|
194
|
+
"rolldown": "1.2.13",
|
|
195
195
|
"semver": "7.8.5",
|
|
196
196
|
"sql-highlight": "6.1.0",
|
|
197
197
|
"std-env": "4.3.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export{n as reportCrash}from"./crashreport-BAG8c7hB.mjs";
|
package/dist/errors-D3qpNHR6.mjs
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import{c as e}from"./logger-DuaT2zY3.mjs";const t=/^[A-Za-z0-9_./:=@+-]+$/,n=/^[A-Za-z0-9_./:=@+\\-]+$/,r=/[%$"`“”„\p{Cc}]|\\$|^~(?:[\\/]|$)/u,i=/"|\s.*\\$|^~(?:[\\/]|$)/;function quotePosixArg(e){return t.test(e)?e:`'${e.replaceAll(`'`,`'"'"'`)}'`}function isPowerShellBare(e){return n.test(e)&&!/^(@|[+-]?\.?\d)/.test(e)&&e!==`--`&&!/^-[^-].*[.:]/.test(e)}function quotePowerShellArg(e){return isPowerShellBare(e)?e:`'${e.replace(/['‘’‚‛]/g,`$&$&`)}'`}function quoteCmdArg(e){if(n.test(e)&&!e.endsWith(`\\`))return e;let t=`"`,r=0;for(let n of e)n===`\\`?r++:(t+=n===`"`?`${`\\`.repeat(r*2)}""`:`${`\\`.repeat(r)}${n===`%`?`%%cd:~,%`:n}`,r=0);return`${t}${`\\`.repeat(r*2)}"`}function formatWindowsCommandLines(e){if(e.every(e=>isPowerShellBare(e)||e!==``&&!r.test(e)))return{kind:`shared`,commandLine:e.map(e=>isPowerShellBare(e)?e:`"${e}"`).join(` `)};let t=e.map(quoteCmdArg).join(` `);return{kind:`perShell`,powershell:e.some(e=>e===``||i.test(e))?`cmd /d /s /c ${quotePowerShellArg(t)}`:e.map(quotePowerShellArg).join(` `),cmd:t}}function formatShellCommandLines(e){return process.platform===`win32`?formatWindowsCommandLines(e):{kind:`shared`,commandLine:e.map(quotePosixArg).join(` `)}}function formatCommandHint(e){let t=formatShellCommandLines([e.command,...e.args]);return t.kind===`shared`?`\`${t.commandLine}\``:`\`${t.powershell}\` in PowerShell or \`${t.cmd}\` in cmd.exe`}function formatError(t){let n=[e.error(`Error${t.code?` [${t.code}]`:``}: ${t.message}`)];return t.details&&n.push(`\n ${e.dim(`Details:`)} ${t.details.split(`
|
|
2
|
-
`).join(`
|
|
3
|
-
`)}`),t.suggestion&&n.push(`\n ${e.info(`Suggestion:`)} ${t.suggestion.split(`
|
|
4
|
-
`).join(`
|
|
5
|
-
`)}`),t.command&&n.push(`\n ${e.dim(`Help:`)} Run \`tailor ${t.command} --help\` for usage information.`),t.next&&n.push(`\n ${e.info(`Next:`)} Run ${formatCommandHint(t.next)}.`),n.join(``)}function CLIError(e){let t=Error(e.message,e.cause===void 0?void 0:{cause:e.cause});return t.name=`CLIError`,t.code=e.code,t.details=e.details,t.suggestion=e.suggestion,t.command=e.command,t.next=e.next,t.context=e.context,t.format=()=>formatError(t),t}function isCLIError(e){return e instanceof Error&&e.name===`CLIError`}function errorSummary(e){return isCLIError(e)?[e.message,e.details,e.suggestion].filter(Boolean).join(`
|
|
6
|
-
`):e instanceof Error?e.message:String(e)}function internalError(e,t){return Error(e,t)}function toError(e){return e instanceof Error?e:Error(String(e),{cause:e})}const a=/does not provide an export named '(?!default')([^']+)'/;function typeOnlyImportHint(e){if(!(e instanceof SyntaxError))return;let t=a.exec(e.message)?.[1];if(t)return`If '${t}' is a type, import it with \`import type\` (or the inline \`type\` modifier). The CLI runs TypeScript by stripping types from each file in isolation, so type-only exports do not exist at runtime. Set "verbatimModuleSyntax": true in tsconfig.json to catch this at typecheck.`}export{isCLIError as a,internalError as i,errorSummary as n,toError as o,formatCommandHint as r,typeOnlyImportHint as s,CLIError as t};
|
|
7
|
-
//# sourceMappingURL=errors-D3qpNHR6.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"errors-D3qpNHR6.mjs","names":["styles","POSIX_BARE_ARG","CMD_BARE_ARG","WINDOWS_DOUBLE_QUOTE_UNSAFE","POWERSHELL_VERSION_SENSITIVE","value","quoted","backslashes","char","argv","cmd","commandLines","action","parts","error","options","message","MISSING_NAMED_EXPORT_PATTERN","name"],"sources":["../src/cli/shared/shell-quote.ts","../src/cli/shared/errors.ts"],"sourcesContent":["/**\n * Command lines for a suggested command: one line when every supported shell reads it the same\n * way, otherwise one line per Windows shell.\n */\nexport type ShellCommandLines =\n | { kind: \"shared\"; commandLine: string }\n | { kind: \"perShell\"; powershell: string; cmd: string };\n\nconst POSIX_BARE_ARG = /^[A-Za-z0-9_./:=@+-]+$/;\nconst CMD_BARE_ARG = /^[A-Za-z0-9_./:=@+\\\\-]+$/;\n// PowerShell expands `$` and backtick escapes inside double quotes and reads `“ ” „` as `\"`,\n// cmd.exe expands `%` even inside quotes, a `\"` or a trailing backslash changes where the\n// quoted argument ends, and a leading `~` is version-sensitive (below).\nconst WINDOWS_DOUBLE_QUOTE_UNSAFE = /[%$\"`“”„\\p{Cc}]|\\\\$|^~(?:[\\\\/]|$)/u;\n// PowerShell versions pass these to programs differently: Windows PowerShell 5.1 and 7.3+\n// disagree on quotes and trailing backslashes, and 7.6+ expands a leading `~` inside the `.ps1`\n// shim however it was quoted.\nconst POWERSHELL_VERSION_SENSITIVE = /\"|\\s.*\\\\$|^~(?:[\\\\/]|$)/;\n\nfunction quotePosixArg(value: string): string {\n if (POSIX_BARE_ARG.test(value)) return value;\n return `'${value.replaceAll(\"'\", `'\"'\"'`)}'`;\n}\n\nfunction isPowerShellBare(value: string): boolean {\n // A leading `@` splats, a lone `--` ends parameters, a leading digit reads as a number, and a\n // single-dash token with `.` or `:` reads as parameter syntax.\n return (\n CMD_BARE_ARG.test(value) &&\n !/^(@|[+-]?\\.?\\d)/.test(value) &&\n value !== \"--\" &&\n !/^-[^-].*[.:]/.test(value)\n );\n}\n\nfunction quotePowerShellArg(value: string): string {\n if (isPowerShellBare(value)) return value;\n return `'${value.replace(/['‘’‚‛]/g, \"$&$&\")}'`;\n}\n\nfunction quoteCmdArg(value: string): string {\n // Quoting a trailing backslash keeps a command routed through `cmd /c` from ending in one,\n // which PowerShell 7 doubles when it quotes the line.\n if (CMD_BARE_ARG.test(value) && !value.endsWith(\"\\\\\")) return value;\n let quoted = '\"';\n let backslashes = 0;\n for (const char of value) {\n if (char === \"\\\\\") {\n backslashes++;\n continue;\n }\n if (char === '\"') {\n quoted += `${\"\\\\\".repeat(backslashes * 2)}\"\"`;\n } else {\n // `%%cd:~,%` reads back as a literal `%` without cmd.exe expanding a `%NAME%` around it.\n quoted += `${\"\\\\\".repeat(backslashes)}${char === \"%\" ? \"%%cd:~,%\" : char}`;\n }\n backslashes = 0;\n }\n return `${quoted}${\"\\\\\".repeat(backslashes * 2)}\"`;\n}\n\nfunction formatWindowsCommandLines(argv: readonly string[]): ShellCommandLines {\n if (\n argv.every(\n (value) =>\n isPowerShellBare(value) || (value !== \"\" && !WINDOWS_DOUBLE_QUOTE_UNSAFE.test(value)),\n )\n ) {\n return {\n kind: \"shared\",\n commandLine: argv.map((value) => (isPowerShellBare(value) ? value : `\"${value}\"`)).join(\" \"),\n };\n }\n const cmd = argv.map(quoteCmdArg).join(\" \");\n // Both PowerShell versions pass a `cmd` argument the same legacy way, so routing the cmd.exe\n // line through `cmd /c` keeps the arguments identical where their native quoting differs.\n const powershell = argv.some((value) => value === \"\" || POWERSHELL_VERSION_SENSITIVE.test(value))\n ? `cmd /d /s /c ${quotePowerShellArg(cmd)}`\n : argv.map(quotePowerShellArg).join(\" \");\n return { kind: \"perShell\", powershell, cmd };\n}\n\n/**\n * Render an argv array as command lines that the current platform's shells run with every\n * argument delivered unchanged\n * @param {readonly string[]} argv - Executable name followed by its arguments\n * @returns {ShellCommandLines} One shared command line, or one per Windows shell\n */\nexport function formatShellCommandLines(argv: readonly string[]): ShellCommandLines {\n if (process.platform === \"win32\") return formatWindowsCommandLines(argv);\n return { kind: \"shared\", commandLine: argv.map(quotePosixArg).join(\" \") };\n}\n","import { styles } from \"./logger\";\nimport { formatShellCommandLines } from \"./shell-quote\";\nimport type { Jsonifiable } from \"type-fest\";\n\n/**\n * Options for creating a CLI error\n */\ninterface CLIErrorOptions {\n /** Stable machine-readable failure code, such as `WORKSPACE_NOT_FOUND`. */\n code: string;\n message: string;\n details?: string;\n suggestion?: string;\n command?: string;\n next?: CLIErrorNextAction;\n context?: Readonly<Record<string, Jsonifiable | undefined>>;\n cause?: unknown;\n}\n\nexport type CLIErrorNextAction = {\n /** Executable name, such as `tailor`. */\n command: string;\n /** Arguments passed directly to the executable. */\n args: readonly string[];\n};\n\n/**\n * CLI error interface with formatted output\n */\nexport interface CLIError extends Error {\n readonly code: string;\n readonly details?: string;\n readonly suggestion?: string;\n readonly command?: string;\n readonly next?: CLIErrorNextAction;\n readonly context?: Readonly<Record<string, Jsonifiable | undefined>>;\n format(): string;\n}\n\ntype CLIErrorInternal = Error & {\n code: string;\n details?: string;\n suggestion?: string;\n command?: string;\n next?: CLIErrorNextAction;\n context?: Readonly<Record<string, Jsonifiable | undefined>>;\n format(): string;\n};\n\n/**\n * Render a command as a user-facing hint that can be copied into the current platform's shells:\n * one backticked command line, or on Windows, when no single quoting suits both shells, a\n * PowerShell and a cmd.exe line (`` `…` in PowerShell or `…` in cmd.exe ``)\n * @param {CLIErrorNextAction} action - Executable and arguments to suggest\n * @returns {string} The command part of the hint, to follow a verb such as \"Run\"\n */\nexport function formatCommandHint(action: CLIErrorNextAction): string {\n const commandLines = formatShellCommandLines([action.command, ...action.args]);\n if (commandLines.kind === \"shared\") {\n return `\\`${commandLines.commandLine}\\``;\n }\n return `\\`${commandLines.powershell}\\` in PowerShell or \\`${commandLines.cmd}\\` in cmd.exe`;\n}\n\n/**\n * Format CLI error for output\n * @param error - CLIError instance to format\n * @returns Formatted error message\n */\nfunction formatError(error: CLIError): string {\n const parts: string[] = [\n styles.error(`Error${error.code ? ` [${error.code}]` : \"\"}: ${error.message}`),\n ];\n\n if (error.details) {\n parts.push(`\\n ${styles.dim(\"Details:\")} ${error.details.split(\"\\n\").join(\"\\n \")}`);\n }\n\n if (error.suggestion) {\n parts.push(`\\n ${styles.info(\"Suggestion:\")} ${error.suggestion.split(\"\\n\").join(\"\\n \")}`);\n }\n\n if (error.command) {\n parts.push(\n `\\n ${styles.dim(\"Help:\")} Run \\`tailor ${error.command} --help\\` for usage information.`,\n );\n }\n\n if (error.next) {\n parts.push(`\\n ${styles.info(\"Next:\")} Run ${formatCommandHint(error.next)}.`);\n }\n\n return parts.join(\"\");\n}\n\n/**\n * Create a CLI error with formatted output\n * @param options - Options to construct a CLIError\n * @returns Constructed CLIError instance\n */\nexport function CLIError(options: CLIErrorOptions): CLIError {\n const error = new Error(\n options.message,\n options.cause === undefined ? undefined : { cause: options.cause },\n ) as CLIErrorInternal;\n error.name = \"CLIError\";\n error.code = options.code;\n error.details = options.details;\n error.suggestion = options.suggestion;\n error.command = options.command;\n error.next = options.next;\n error.context = options.context;\n error.format = () => formatError(error);\n return error;\n}\n\n/**\n * Type guard to check if an error is a CLIError\n * @param error - Error to check\n * @returns True if the error is a CLIError\n */\nexport function isCLIError(error: unknown): error is CLIError {\n return error instanceof Error && error.name === \"CLIError\";\n}\n\n/**\n * Summarize a failure as plain text for reports that carry a single error string.\n * CLI errors contribute their details and suggestion so the remediation survives.\n * @param error - Failure to summarize\n * @returns Message followed by any details and suggestion, one per line\n */\nexport function errorSummary(error: unknown): string {\n if (isCLIError(error)) {\n return [error.message, error.details, error.suggestion].filter(Boolean).join(\"\\n\");\n }\n return error instanceof Error ? error.message : String(error);\n}\n\n/**\n * Create an error for an SDK invariant violation that no user action can fix.\n * The result is a plain Error, so JSON output reports it as `UNEXPECTED_ERROR`\n * and crash reporting treats it like any other unexpected failure.\n * @param message - Description of the violated invariant\n * @param options - Standard Error options, such as `cause`\n * @returns Plain Error instance\n */\nexport function internalError(message: string, options?: ErrorOptions): Error {\n return new Error(message, options);\n}\n\n/**\n * Convert a caught value into an Error, keeping Error instances as-is\n * @param value - Caught value\n * @returns The value itself when it is an Error, otherwise an Error of its string form with the value as `cause`\n */\nexport function toError(value: unknown): Error {\n return value instanceof Error ? value : new Error(String(value), { cause: value });\n}\n\nconst MISSING_NAMED_EXPORT_PATTERN = /does not provide an export named '(?!default')([^']+)'/;\n\n/**\n * Suggest `import type` when importing user code fails on a missing named\n * export. The CLI strips types from each file in isolation, so a type-only\n * export does not exist at runtime and a plain import of it fails to link.\n * @param error - Error thrown while importing user modules\n * @returns Suggestion text, or undefined when the error is not that failure\n */\nexport function typeOnlyImportHint(error: unknown): string | undefined {\n if (!(error instanceof SyntaxError)) return undefined;\n const name = MISSING_NAMED_EXPORT_PATTERN.exec(error.message)?.[1];\n if (!name) return undefined;\n return (\n `If '${name}' is a type, import it with \\`import type\\` (or the inline \\`type\\` modifier). ` +\n \"The CLI runs TypeScript by stripping types from each file in isolation, so type-only exports do not exist at runtime. \" +\n 'Set \"verbatimModuleSyntax\": true in tsconfig.json to catch this at typecheck.'\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"logger-DuaT2zY3.mjs","names":["styleText","name","text","color","forced","stream","stripVTControlCharacters","ANSI_ESCAPE_PATTERN","CARRIAGE_RETURN_PATTERN","graphemeSegmenter","values","value","max","fallback","codePoint","char","sgrSequences","chars","segment","result","i","cell","ZERO_WIDTH_CLUSTER_PATTERN","RGI_EMOJI_PATTERN","width","eastAsianWidth","cellLine","left","columnWidths","join","right","columnCount","rows","row","index","data","rowCount","rowsCellLines","col","line","config","lineIndex","lines","rowHeight","cellLines","columnLines","cells","rowIndex","TRUTHY_VALUES","FALSY_VALUES","normalized","JSON_OUTPUT_ENV_VAR","isCI","agent","_jsonDefaultAgent","source","reason","_jsonMode","_jsonModeSource","message","styles","symbols","_verbose","_secrets","REDACTED_PLACEHOLDER","root","secret","secrets","node","ch","next","queue","head","parent","child","fail","_automaton","spans","protectedSpans","from","start","end","pStart","pEnd","a","b","merged","span","last","cursor","TYPE_ICONS","TYPE_COLORS","opts","indentPrefix","indent","colorFn","type","mode","icon","coloredOutput","timestamp","inspectOpts","output","formatWithOptions","logger","sizeBefore","jsonEscaped","formEncoded","display","options","formatDistanceToNowStrict","pretty","key","transformer","item","headers","h","t","header"],"sources":["../../shared/src/color.ts","../src/cli/shared/ascii-table.ts","../src/cli/shared/parse-boolean.ts","../src/cli/shared/logger.ts"],"sourcesContent":["import { stripVTControlCharacters, styleText } from \"node:util\";\n\n/** Applies a style to text */\nexport type StyleFn = (text: string) => string;\n\ntype StyleName = Exclude<Parameters<typeof styleText>[0], readonly unknown[] | unknown[]>;\n\nconst style =\n (name: StyleName): StyleFn =>\n (text) =>\n styleText(name, text, { validateStream: false });\n\n/**\n * Style functions by name, so call sites read `color.bold(text)`. Styling is\n * always applied; `renderFor` drops it again when the destination stream has no\n * color support. Add a name here when a package needs one that is not listed.\n */\nexport const color = {\n bold: style(\"bold\"),\n dim: style(\"dim\"),\n italic: style(\"italic\"),\n gray: style(\"gray\"),\n white: style(\"white\"),\n red: style(\"red\"),\n green: style(\"green\"),\n yellow: style(\"yellow\"),\n cyan: style(\"cyan\"),\n magenta: style(\"magenta\"),\n redBright: style(\"redBright\"),\n greenBright: style(\"greenBright\"),\n cyanBright: style(\"cyanBright\"),\n};\n\n// Node's rules for whether a destination gets colors, applied by hand. Asking\n// styleText instead would be shorter but only correct on Node: Bun ignores both\n// the stream option and NO_COLOR (reproduced on 1.3.14), so it reports every\n// destination as color-capable and escapes end up in redirected output.\n//\n// FORCE_COLOR decides on its own when set, which is how CI keeps colors through\n// a pipe. NO_COLOR counts as set at any non-empty value, \"0\" included.\nconst supportsColor = (stream: NodeJS.WriteStream): boolean => {\n const forced = process.env.FORCE_COLOR;\n if (forced !== undefined) return forced !== \"0\" && forced !== \"false\";\n if (process.env.NODE_DISABLE_COLORS !== undefined) return false;\n if ((process.env.NO_COLOR ?? \"\") !== \"\") return false;\n if (process.env.TERM === \"dumb\") return false;\n return stream.isTTY === true;\n};\n\n/**\n * Prepares styled text for the stream it is written to.\n * @param stream - Stream the text is written to\n * @param text - Styled text\n * @returns Text with styling removed when the stream has no color support\n */\nexport function renderFor(stream: NodeJS.WriteStream, text: string): string {\n return supportsColor(stream) ? text : stripVTControlCharacters(text);\n}\n","import { eastAsianWidth } from \"get-east-asian-width\";\n\n// eslint-disable-next-line no-control-regex\nconst ANSI_ESCAPE_PATTERN = /\\x1b\\[[0-9;]*m/g;\nconst CARRIAGE_RETURN_PATTERN = /\\r\\n?/g;\n\nconst graphemeSegmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n\nexport interface AsciiTableConfig {\n /** Suppress horizontal lines between rows, keeping only the outer border. */\n singleLine?: boolean;\n /** Decide whether to draw the horizontal line at `lineIndex` (range `[0, rowCount]` inclusive). */\n drawHorizontalLine?: (lineIndex: number, rowCount: number) => boolean;\n}\n\ninterface CellLine {\n text: string;\n width: number;\n}\n\nfunction maxOf(values: number[], fallback = 0): number {\n return values.reduce((max, value) => (value > max ? value : max), fallback);\n}\n\nconst TAB_WIDTH = 8;\n\nfunction isStrippableControlCharacter(char: string): boolean {\n const codePoint = char.codePointAt(0) ?? 0;\n if (char === \"\\n\") {\n return false;\n }\n return codePoint <= 0x1f || codePoint === 0x7f;\n}\n\n// Only SGR (color/style) escape sequences are meant to survive; a bare ESC\n// that isn't part of a recognized SGR sequence (e.g. a screen-clear CSI\n// sequence, or a BEL-terminated OSC sequence) is treated like any other\n// control character below and stripped, rather than passed through to the\n// terminal or left with its terminator removed.\nfunction normalizeControlCharacters(value: string): string {\n const sgrSequences = value.match(ANSI_ESCAPE_PATTERN) ?? [];\n return value\n .split(ANSI_ESCAPE_PATTERN)\n .map((segment) => {\n const chars: string[] = [];\n for (const char of segment) {\n if (char === \"\\t\") {\n chars.push(\" \".repeat(TAB_WIDTH));\n } else if (!isStrippableControlCharacter(char)) {\n chars.push(char);\n }\n }\n return chars.join(\"\");\n })\n .reduce((result, segment, i) => result + segment + (sgrSequences[i] ?? \"\"), \"\");\n}\n\nfunction sanitizeCell(cell: unknown): string {\n return normalizeControlCharacters(String(cell ?? \"\").replace(CARRIAGE_RETURN_PATTERN, \"\\n\"));\n}\n\n// Clusters made up entirely of non-printing code points (lone joiners,\n// variation selectors, combining marks, etc.) render with no visible glyph.\nconst ZERO_WIDTH_CLUSTER_PATTERN =\n /^(?:\\p{Default_Ignorable_Code_Point}|\\p{Control}|\\p{Format}|\\p{Nonspacing_Mark}|\\p{Enclosing_Mark}|\\p{Surrogate})+$/v;\n// RGI_Emoji covers flags, keycaps, and VS16-forced presentation sequences,\n// which render as 2 columns in terminals even though their first code point\n// alone would measure as narrow/neutral.\nconst RGI_EMOJI_PATTERN = /^\\p{RGI_Emoji}$/v;\n\nfunction displayWidth(value: string): number {\n let width = 0;\n for (const { segment } of graphemeSegmenter.segment(value.replace(ANSI_ESCAPE_PATTERN, \"\"))) {\n if (ZERO_WIDTH_CLUSTER_PATTERN.test(segment)) {\n continue;\n }\n if (RGI_EMOJI_PATTERN.test(segment)) {\n width += 2;\n continue;\n }\n const codePoint = segment.codePointAt(0);\n width += codePoint === undefined ? 0 : eastAsianWidth(codePoint);\n }\n return width;\n}\n\nfunction toCellLines(cell: string): CellLine[] {\n return cell.split(\"\\n\").map((text) => ({ text, width: displayWidth(text) }));\n}\n\nfunction padCell(cellLine: CellLine, width: number): string {\n return cellLine.text + \" \".repeat(Math.max(0, width - cellLine.width));\n}\n\nfunction renderBorder(left: string, join: string, right: string, columnWidths: number[]): string {\n return left + columnWidths.map((width) => \"─\".repeat(width + 2)).join(join) + right;\n}\n\nfunction validateConsistentColumnCount(rows: string[][]): void {\n const columnCount = rows[0]?.length;\n if (columnCount === undefined) {\n return;\n }\n rows.forEach((row, index) => {\n if (row.length !== columnCount) {\n throw new Error(\n `renderTable: all rows must have the same number of columns (expected ${columnCount}, row ${index} has ${row.length}).`,\n );\n }\n });\n}\n\n/**\n * Renders a 2D array of values as a table using single-line Unicode box-drawing borders.\n * Column widths account for East Asian wide characters (measured per grapheme cluster,\n * so combining marks and ZWJ emoji sequences aren't overcounted, non-printing clusters\n * such as a lone joiner or combining mark measure as 0, and flags, keycaps, and\n * VS16-forced emoji presentation are measured as 2 columns) and strip ANSI SGR (color/style)\n * escape codes before measuring. Use this instead of importing a table-rendering package\n * directly.\n * @param data - Table rows; every row must have the same number of columns. Each cell is\n * stringified (`null`/`undefined` become an empty string rather than the literal text\n * \"null\"/\"undefined\"), may contain embedded newlines, has `\\r`/`\\r\\n` normalized to `\\n`,\n * has tabs expanded to spaces, and has other control characters stripped.\n * @param config - Rendering options\n * @returns The rendered table terminated with a trailing newline, or `\"\"` when there are no\n * rows or no columns to display\n */\nexport function renderTable(data: unknown[][], config: AsciiTableConfig = {}): string {\n const rows = data.map((row) => row.map(sanitizeCell));\n validateConsistentColumnCount(rows);\n\n const rowCount = rows.length;\n const columnCount = rows[0]?.length ?? 0;\n if (rowCount === 0 || columnCount === 0) {\n return \"\";\n }\n\n const rowsCellLines = rows.map((row) =>\n Array.from({ length: columnCount }, (_, col) => toCellLines(row[col] ?? \"\")),\n );\n const columnWidths = Array.from({ length: columnCount }, (_, col) =>\n maxOf(rowsCellLines.map((row) => maxOf((row[col] ?? []).map((line) => line.width)))),\n );\n\n const shouldDrawLine = (lineIndex: number): boolean =>\n config.singleLine\n ? lineIndex === 0 || lineIndex === rowCount\n : (config.drawHorizontalLine ?? (() => true))(lineIndex, rowCount);\n\n const lines: string[] = [];\n if (shouldDrawLine(0)) {\n lines.push(renderBorder(\"┌\", \"┬\", \"┐\", columnWidths));\n }\n\n rowsCellLines.forEach((cellLines, rowIndex) => {\n const rowHeight = maxOf(\n cellLines.map((columnLines) => columnLines.length),\n 1,\n );\n for (let line = 0; line < rowHeight; line++) {\n const cells = cellLines.map((columnLines, col) =>\n padCell(columnLines[line] ?? { text: \"\", width: 0 }, columnWidths[col] ?? 0),\n );\n lines.push(`│ ${cells.join(\" │ \")} │`);\n }\n if (rowIndex < rowCount - 1 && shouldDrawLine(rowIndex + 1)) {\n lines.push(renderBorder(\"├\", \"┼\", \"┤\", columnWidths));\n }\n });\n\n if (shouldDrawLine(rowCount)) {\n lines.push(renderBorder(\"└\", \"┴\", \"┘\", columnWidths));\n }\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n","const TRUTHY_VALUES = new Set([\"true\", \"t\", \"yes\", \"y\", \"on\", \"1\"]);\nconst FALSY_VALUES = new Set([\"false\", \"f\", \"no\", \"n\", \"off\", \"0\"]);\n\n/**\n * Parse a string value as a boolean.\n *\n * Recognized values (case-insensitive, trimmed) follow Python's\n * `distutils.util.strtobool` convention:\n * - truthy: `true, t, yes, y, on, 1`\n * - falsy: `false, f, no, n, off, 0`\n *\n * Undefined, empty strings, and unrecognized values return `undefined` so\n * that callers can fall back to their own defaults.\n * @param value - The input string (e.g. an environment variable or CLI flag value)\n * @returns `true`, `false`, or `undefined` when the value is unset or unrecognized\n */\nexport function parseBoolean(value: string | undefined): boolean | undefined {\n if (value === undefined) return undefined;\n const normalized = value.trim().toLowerCase();\n if (normalized === \"\") return undefined;\n if (TRUTHY_VALUES.has(normalized)) return true;\n if (FALSY_VALUES.has(normalized)) return false;\n return undefined;\n}\n","import { formatWithOptions, type InspectOptions } from \"node:util\";\nimport { color, renderFor } from \"@tailor-platform/shared/color\";\nimport { formatDistanceToNowStrict } from \"date-fns\";\nimport { isCI } from \"std-env\";\nimport { renderTable } from \"./ascii-table\";\nimport { parseBoolean } from \"./parse-boolean\";\n\n/** Environment variable selecting JSON as the default output for every command. */\nexport const JSON_OUTPUT_ENV_VAR = \"TAILOR_JSON_OUTPUT\";\n\n/**\n * Whether the process is attached to an interactive terminal outside CI.\n * @returns True when both stdin and stdout are TTYs and CI is not detected\n */\nexport function interactiveTerminal(): boolean {\n return !isCI && process.stdin.isTTY === true && process.stdout.isTTY === true;\n}\n\n/**\n * What selected JSON output: an explicit `--json`, the environment, both, or\n * the AI coding agent running the CLI.\n */\nexport type JsonModeSource = \"flag\" | \"env\" | \"both\" | \"agent\";\n\n/**\n * Explain what selected JSON output and how to turn it off. Under an AI coding\n * agent, dropping `--json` or unsetting the variable falls back to JSON again,\n * so the remedy names the explicit `false` values instead.\n * @param source - What selected JSON output\n * @returns Sentence appended to the prompt refusal\n */\nfunction jsonModeRemedy(source: JsonModeSource): string {\n const agent = _jsonDefaultAgent;\n switch (source) {\n case \"agent\":\n return ` JSON output is enabled because an AI coding agent${agent ? ` (${agent})` : \"\"} was detected; pass --json=false or set ${JSON_OUTPUT_ENV_VAR}=false to restore prompts.`;\n case \"flag\":\n return agent\n ? \" JSON output is enabled by --json; pass --json=false instead to restore prompts.\"\n : \" JSON output is enabled by --json; drop it to restore prompts.\";\n case \"env\":\n return agent\n ? ` JSON output is enabled by ${JSON_OUTPUT_ENV_VAR}; set it to false to restore prompts.`\n : ` JSON output is enabled by ${JSON_OUTPUT_ENV_VAR}; unset it to restore prompts.`;\n case \"both\":\n return agent\n ? ` JSON output is enabled by --json and ${JSON_OUTPUT_ENV_VAR}; pass --json=false instead of the flag to restore prompts.`\n : ` JSON output is enabled by --json and ${JSON_OUTPUT_ENV_VAR}; drop the flag and unset the variable to restore prompts.`;\n }\n}\n\n/**\n * Error thrown when a prompt is attempted in a non-interactive environment.\n *\n * JSON mode suppresses prompts, so name whatever selected it: an explicit\n * `--json` stays enabled however the environment is set, while\n * `TAILOR_JSON_OUTPUT` or a detected AI coding agent leaves nothing in the\n * command line to explain the refusal.\n */\nexport class CIPromptError extends Error {\n constructor(message?: string) {\n const reason =\n _jsonMode && _jsonModeSource !== undefined && interactiveTerminal()\n ? jsonModeRemedy(_jsonModeSource)\n : \"\";\n super(\n (message ??\n \"Interactive prompts are not available in this environment. Provide the required options explicitly.\") +\n reason,\n );\n this.name = \"CIPromptError\";\n }\n}\n\n/**\n * Semantic style functions for inline text styling\n */\nexport const styles = {\n // Status colors\n success: color.green,\n error: color.red,\n warning: color.yellow,\n info: color.cyan,\n\n // Action colors (for change sets)\n create: color.green,\n update: color.yellow,\n delete: color.red,\n replace: color.magenta,\n unchanged: color.gray,\n\n // Emphasis\n bold: color.bold,\n dim: color.gray,\n highlight: color.cyanBright,\n successBright: color.greenBright,\n errorBright: color.redBright,\n\n // Resource types\n resourceType: color.bold,\n resourceName: color.cyan,\n\n // File paths\n path: color.cyan,\n\n // Values\n value: color.white,\n placeholder: (text: string) => color.italic(color.gray(text)),\n};\n\n/**\n * Standardized symbols for CLI output\n */\nexport const symbols = {\n success: styles.success(\"\\u2713\"),\n error: styles.error(\"\\u2716\"),\n warning: styles.warning(\"\\u26a0\"),\n info: styles.info(\"i\"),\n create: styles.create(\"+\"),\n update: styles.update(\"~\"),\n delete: styles.delete(\"-\"),\n replace: styles.replace(\"\\u00b1\"),\n bullet: styles.dim(\"\\u2022\"),\n arrow: styles.dim(\"\\u2192\"),\n};\n\n/**\n * Log output modes\n */\nexport type LogMode = \"default\" | \"stream\" | \"plain\";\n\nexport interface LogOptions {\n /** Output mode (default: \"default\") */\n mode?: LogMode;\n /** Number of spaces to indent the entire line (default: 0) */\n indent?: number;\n}\n\n/** Field transformer function. null excludes the field from table output. */\nexport type FieldTransformer = ((value: unknown, item: object) => string) | null;\n\nexport interface OutOptions {\n /** Table display field transform/exclude settings. Only applied in table mode (not JSON). */\n display?: Record<string, FieldTransformer>;\n\n /** Show null values in table output (default: false) */\n showNull?: boolean;\n}\n\n// In JSON mode, all logs go to stderr to keep stdout clean for JSON data\nlet _jsonMode = false;\nlet _jsonModeSource: JsonModeSource | undefined;\nlet _jsonDefaultAgent: string | undefined;\nlet _verbose = false;\n\n// Values registered via `logger.registerSecret()`, redacted from diagnostic log output\nconst _secrets = new Set<string>();\nconst REDACTED_PLACEHOLDER = \"<redacted>\";\n// Below this length, a registered value is too likely to match unrelated text.\nconst MIN_SECRET_LENGTH = 4;\n\n/**\n * Aho-Corasick trie node. Indexed by individual UTF-16 code units (not Unicode code\n * points), matching how `string.indexOf`/`.slice` already index this file's strings — a\n * surrogate-pair character occupies two nodes, same as it occupies two `string` indices.\n */\ninterface TrieNode {\n children: Map<string, TrieNode>;\n fail: TrieNode;\n /** Secrets ending at this node, including those reached via `fail` links (precomputed). */\n outputs: string[];\n}\n\n/**\n * Builds a multi-pattern matcher for every registered secret, so `findSecretSpans` below\n * can find all of their occurrences in one pass over the text (`O(text.length + matches)`)\n * instead of scanning the full text once per registered secret. Rebuilt only when\n * `registerSecret` adds a genuinely new value (see `_automaton` below), so its\n * `O(total secret length)` construction cost is amortized across every log line redacted\n * while the secret set doesn't change.\n * @param secrets - Currently registered secrets\n * @returns Root of the built trie\n */\nfunction buildAutomaton(secrets: ReadonlySet<string>): TrieNode {\n const root: TrieNode = {\n children: new Map(),\n fail: undefined as unknown as TrieNode,\n outputs: [],\n };\n root.fail = root;\n\n for (const secret of secrets) {\n let node = root;\n for (let i = 0; i < secret.length; i++) {\n const ch = secret[i] as string;\n let next = node.children.get(ch);\n if (!next) {\n next = { children: new Map(), fail: root, outputs: [] };\n node.children.set(ch, next);\n }\n node = next;\n }\n node.outputs.push(secret);\n }\n\n // A head index instead of Array#shift(): shift() re-indexes every remaining element on\n // each call, which would make this loop quadratic in the number of trie nodes rather than\n // the linear BFS this is meant to be.\n const queue: TrieNode[] = [...root.children.values()];\n for (let head = 0; head < queue.length; head++) {\n const parent = queue[head] as TrieNode;\n for (const [ch, child] of parent.children) {\n let fail = parent.fail;\n while (fail !== root && !fail.children.has(ch)) fail = fail.fail;\n child.fail = fail.children.get(ch) ?? root;\n child.outputs = child.outputs.concat(child.fail.outputs);\n queue.push(child);\n }\n }\n return root;\n}\n\n// Cached automaton for the current `_secrets` contents; `null` means rebuild on next use.\n// Invalidated only when `registerSecret` actually grows `_secrets` (Set#add on an existing\n// value is a no-op), so re-registering an already-known secret never triggers a rebuild.\nlet _automaton: TrieNode | null = null;\n\nfunction getAutomaton(): TrieNode {\n _automaton ??= buildAutomaton(_secrets);\n return _automaton;\n}\n\n/**\n * Finds every occurrence of every registered secret in `text`, including overlapping ones,\n * in a single pass over `text` via the Aho-Corasick automaton.\n * @param text - Text to search\n * @returns Match spans as `[start, end)` pairs, in the order found\n */\nfunction findSecretSpans(text: string): Array<[start: number, end: number]> {\n const spans: Array<[start: number, end: number]> = [];\n const root = getAutomaton();\n let node = root;\n for (let i = 0; i < text.length; i++) {\n const ch = text[i] as string;\n while (node !== root && !node.children.has(ch)) node = node.fail;\n node = node.children.get(ch) ?? root;\n for (const secret of node.outputs) {\n spans.push([i + 1 - secret.length, i + 1]);\n }\n }\n return spans;\n}\n\n/**\n * Redacts every registered secret from `text` in a single pass over the original text.\n *\n * Matches are found against the original text only - never against text a previous\n * replacement produced - and overlapping/adjacent matches (whether one secret contains\n * another, or two secrets merely cross, e.g. registering \"abcde\" and \"defghi\" against\n * \"abcdefghi\") are merged into one contiguous span before any substitution happens. This\n * avoids two failure modes an iterative \"replace one secret, then the next\" approach has:\n * a later secret re-matching inside a placeholder a previous replacement already inserted,\n * and a crossing (non-nested) overlap leaving a fragment of one secret unredacted.\n *\n * Idempotent: a match that falls inside an occurrence of `<redacted>` already present in\n * `text` is discarded rather than substituted again. Without this, calling this function\n * twice on the same text (which happens whenever something already redacted, such as a\n * `--json` error envelope, is later passed to a diagnostic log call) could corrupt the\n * placeholder itself if a registered secret happens to be one of its substrings (e.g. a\n * secret literally containing \"redact\").\n * @param text - Text to redact\n * @returns `text` with every registered secret occurrence replaced by `<redacted>`\n */\nexport function redactSecrets(text: string): string {\n if (_secrets.size === 0) return text;\n\n const protectedSpans: Array<[start: number, end: number]> = [];\n for (let from = 0, index: number; (index = text.indexOf(REDACTED_PLACEHOLDER, from)) !== -1;) {\n protectedSpans.push([index, index + REDACTED_PLACEHOLDER.length]);\n from = index + REDACTED_PLACEHOLDER.length;\n }\n\n // Only a match wholly inside a protected placeholder is discarded (it can only be the\n // placeholder's own text, e.g. a registered secret that is a substring of \"redacted\").\n // A match that merely overlaps one — extending outside it, e.g. a registered secret that\n // happens to be \"leak<redacted>\" — still has real secret content outside the placeholder\n // and must still be replaced.\n //\n // A registered secret wholly contained in the placeholder (up to and including a secret\n // equal to \"<redacted>\" itself) is indistinguishable from the placeholder in rendered\n // output either way: substituting REDACTED_PLACEHOLDER for text that already reads\n // REDACTED_PLACEHOLDER is a no-op. Discarding the match here (rather than \"fixing\" it to\n // substitute anyway) isn't a redaction gap — it just skips redundant work on text that's\n // already the safe, masked form.\n const spans = findSecretSpans(text).filter(\n ([start, end]) => !protectedSpans.some(([pStart, pEnd]) => start >= pStart && end <= pEnd),\n );\n if (spans.length === 0) return text;\n spans.sort(([a], [b]) => a - b);\n\n const merged: Array<[start: number, end: number]> = [];\n for (const span of spans) {\n const last = merged.at(-1);\n if (last && span[0] <= last[1]) {\n last[1] = Math.max(last[1], span[1]);\n } else {\n merged.push(span);\n }\n }\n\n let result = \"\";\n let cursor = 0;\n for (const [start, end] of merged) {\n result += text.slice(cursor, start) + REDACTED_PLACEHOLDER;\n cursor = end;\n }\n return result + text.slice(cursor);\n}\n\n/**\n * Reset the registered-secret redaction state. Used for testing.\n *\n * `_secrets` is process-lifetime, module-level state with no production unregister API\n * (a real process should never stop hiding a secret it once saw). Test files that call\n * `logger.registerSecret()` and run in a Vitest project with `isolate: false` share this\n * state across files, so a value registered in one file's test can still be redacted in an\n * unrelated later file's assertions unless cleared between tests.\n */\nexport function resetSecretRegistry(): void {\n _secrets.clear();\n _automaton = null;\n}\n\n// Type icons for log output\nconst TYPE_ICONS: Record<string, string> = {\n info: \"ℹ\",\n success: \"✔\",\n warn: \"⚠\",\n error: \"✖\",\n debug: \"⚙\",\n trace: \"→\",\n log: \"\",\n};\n\n// Color functions for icon and message text\nconst TYPE_COLORS: Record<string, (text: string) => string> = {\n info: styles.info,\n success: styles.success,\n warn: styles.warning,\n error: styles.error,\n debug: styles.dim,\n trace: styles.dim,\n log: (text) => text,\n};\n\ninterface FormatLogLineOptions {\n mode: string;\n indent: number;\n type: string;\n message: string;\n timestamp?: string;\n}\n\n/**\n * Formats a log line with the appropriate prefix and indentation\n * @param opts - Formatting options\n * @returns Formatted log line\n */\nexport function formatLogLine(opts: FormatLogLineOptions): string {\n const { mode, indent, type, message, timestamp } = opts;\n const indentPrefix = indent > 0 ? \" \".repeat(indent) : \"\";\n const colorFn = TYPE_COLORS[type] || ((text: string) => text);\n\n // Plain mode: color only, no icon, no timestamp\n if (mode === \"plain\") {\n return `${indentPrefix}${colorFn(message)}\\n`;\n }\n\n // Default/Stream mode: with icon and color\n const icon = TYPE_ICONS[type] || \"\";\n const prefix = icon ? `${icon} ` : \"\";\n const coloredOutput = colorFn(`${prefix}${message}`);\n const timestampPrefix = timestamp ?? \"\";\n\n return `${indentPrefix}${timestampPrefix}${coloredOutput}\\n`;\n}\n\n/**\n * Writes a formatted log line to stderr.\n * @param type - Log type (info, success, warn, error, log)\n * @param message - Log message\n * @param opts - Log options (mode and indent)\n */\nfunction writeLog(type: string, message: string, opts?: LogOptions): void {\n const mode = opts?.mode ?? \"default\";\n const indent = opts?.indent ?? 0;\n const inspectOpts: InspectOptions = {\n breakLength: process.stdout.columns || 80,\n };\n const formattedMessage = formatWithOptions(inspectOpts, message);\n const timestamp = mode === \"stream\" ? `${new Date().toLocaleTimeString()} ` : \"\";\n const output = formatLogLine({ mode, indent, type, message: formattedMessage, timestamp });\n process.stderr.write(renderFor(process.stderr, redactSecrets(output)));\n}\n\n/**\n * Record the AI coding agent running the Tailor CLI, which makes JSON the\n * default output. CLI plugins never record one, so they keep table output.\n * @param agent - Detected agent id (e.g. `\"claude_code\"`), or undefined when none runs the CLI\n */\nexport function setJsonDefaultAgent(agent: string | undefined): void {\n _jsonDefaultAgent = agent;\n}\n\n/**\n * The AI coding agent recorded by {@link setJsonDefaultAgent}.\n * @returns Detected agent id, or undefined when none was recorded\n */\nexport function jsonDefaultAgent(): string | undefined {\n return _jsonDefaultAgent;\n}\n\n/**\n * The CLI logger. Diagnostics go to stderr; `out()` writes primary output to\n * stdout as a table, or as JSON when `jsonMode` is on. `--json` and\n * `--verbose` feed the `jsonMode` / `verbose` state, which CLI plugins share\n * with the SDK code paths they call.\n */\nexport const logger = {\n get jsonMode(): boolean {\n return _jsonMode;\n },\n set jsonMode(value: boolean) {\n _jsonMode = value;\n if (!value) _jsonModeSource = undefined;\n },\n\n /**\n * Enable or disable JSON mode, recording what selected it so a suppressed\n * prompt can name the right remedy.\n * @param value - Whether JSON output is on\n * @param source - What turned it on; omit when turning it off\n */\n setJsonMode(value: boolean, source?: JsonModeSource): void {\n _jsonMode = value;\n _jsonModeSource = value ? source : undefined;\n },\n\n get verbose(): boolean {\n return _verbose || parseBoolean(process.env.DEBUG) === true || process.env.RUNNER_DEBUG === \"1\";\n },\n set verbose(value: boolean) {\n _verbose = value;\n },\n\n info(message: string, opts?: LogOptions): void {\n writeLog(\"info\", message, opts);\n },\n\n success(message: string, opts?: LogOptions): void {\n writeLog(\"success\", message, opts);\n },\n\n warn(message: string, opts?: LogOptions): void {\n writeLog(\"warn\", message, opts);\n },\n\n error(message: string, opts?: LogOptions): void {\n writeLog(\"error\", message, opts);\n },\n\n log(message: string): void {\n writeLog(\"log\", message, { mode: \"plain\" });\n },\n\n newline(): void {\n process.stderr.write(\"\\n\");\n },\n\n debug(message: string): void {\n if (logger.verbose) {\n writeLog(\"log\", styles.dim(message), { mode: \"plain\" });\n }\n },\n\n /**\n * Registers a value to be redacted from diagnostic log output (`info`/`success`/`warn`/\n * `error`/`log`/`debug`). Any occurrence of `value` — or of its JSON-string-escaped form\n * (so a value embedded in `JSON.stringify`d output, e.g. `--json` mode error envelopes, is\n * also caught) or its `application/x-www-form-urlencoded` form (so a value that reached the\n * process via a URL query string, e.g. an OAuth authorization code decoded from a callback\n * URL via `URLSearchParams`, is still caught if that same URL — still encoded — is later\n * echoed into a diagnostic message) — is replaced with `<redacted>` before it reaches\n * stderr. Does not affect `out()`, since some commands intentionally print secret values as\n * their primary result.\n *\n * Values shorter than 4 characters are ignored, since they are too likely to match\n * unrelated text. A non-string value (e.g. `undefined` from an unvalidated external\n * payload cast to a typed shape) is ignored the same way, rather than throwing, since a\n * logging call must never be what crashes the process.\n * @param value - The secret value to redact from future log output\n */\n registerSecret(value: string): void {\n // Counts Unicode code points, not UTF-16 code units, so a value made of surrogate-pair\n // characters (e.g. emoji) isn't undercounted as longer than it actually is.\n if (typeof value !== \"string\" || [...value].length < MIN_SECRET_LENGTH) return;\n const sizeBefore = _secrets.size;\n _secrets.add(value);\n const jsonEscaped = JSON.stringify(value).slice(1, -1);\n if (jsonEscaped !== value) _secrets.add(jsonEscaped);\n // Uses URLSearchParams rather than encodeURIComponent: form-urlencoding (what\n // URLSearchParams produces, and what a URL query string actually contains) encodes a\n // space as \"+\", not \"%20\", and unlike encodeURIComponent it never throws on a lone\n // surrogate (invalid UTF-16) — it substitutes U+FFFD instead, matching how the URL\n // itself would already have encoded that same malformed input.\n const formEncoded = new URLSearchParams([[\"v\", value]]).toString().slice(2);\n if (formEncoded !== value) _secrets.add(formEncoded);\n // Set#add on an already-registered value is a no-op, so this only invalidates the\n // cached automaton (see findSecretSpans) when a genuinely new secret was added.\n if (_secrets.size !== sizeBefore) _automaton = null;\n },\n\n out(data: string | object | object[], options?: OutOptions): void {\n if (typeof data === \"string\") {\n process.stdout.write(renderFor(process.stdout, data.endsWith(\"\\n\") ? data : data + \"\\n\"));\n return;\n }\n\n if (this.jsonMode) {\n // eslint-disable-next-line no-restricted-syntax\n console.log(JSON.stringify(data));\n return;\n }\n\n const display = options?.display;\n\n // Helper to format a value for table display\n const formatValue = (value: unknown, pretty = false): string => {\n if (options?.showNull && value === null) return \"NULL\";\n if (value === null || value === undefined) return \"N/A\";\n if (value instanceof Date) {\n return formatDistanceToNowStrict(value, { addSuffix: true });\n }\n if (typeof value === \"object\") {\n return pretty ? JSON.stringify(value, null, 2) : JSON.stringify(value);\n }\n return String(value);\n };\n\n // Helper to check if field should be excluded\n const isExcluded = (key: string): boolean => {\n return display !== undefined && key in display && display[key] === null;\n };\n\n // Helper to apply transformer or default formatting\n const transformValue = (key: string, value: unknown, item: object, pretty = false): string => {\n if (display && key in display) {\n const transformer = display[key];\n if (transformer) {\n return transformer(value, item);\n }\n }\n return formatValue(value, pretty);\n };\n\n if (!Array.isArray(data)) {\n const entries = Object.entries(data).filter(([key]) => !isExcluded(key));\n const formattedEntries = entries.map(([key, value]) => [\n key,\n transformValue(key, value, data, true),\n ]);\n const t = renderTable(formattedEntries, { singleLine: false });\n process.stdout.write(renderFor(process.stdout, t));\n return;\n }\n\n if (data.length === 0) {\n return;\n }\n\n const allHeaders = Array.from(new Set(data.flatMap((item) => Object.keys(item))));\n const headers = allHeaders.filter((h) => !isExcluded(h));\n if (headers.length === 0) {\n return;\n }\n const rows = data.map((item) =>\n headers.map((header) =>\n transformValue(header, (item as Record<string, unknown>)[header], item),\n ),\n );\n\n const t = renderTable([headers, ...rows], {\n drawHorizontalLine: (lineIndex, rowCount) => {\n return lineIndex === 0 || lineIndex === 1 || lineIndex === rowCount;\n },\n });\n process.stdout.write(renderFor(process.stdout, t));\n },\n};\n"],"mappings":"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"}
|