wizards 0.1.9
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 +110 -0
- package/README.md +170 -0
- package/apps/runtime/dist/agents/architect.js +453 -0
- package/apps/runtime/dist/agents/project-assistant.js +354 -0
- package/apps/runtime/dist/agents/subscription.js +206 -0
- package/apps/runtime/dist/agents/thought.js +21 -0
- package/apps/runtime/dist/agents/website.js +197 -0
- package/apps/runtime/dist/app.js +153 -0
- package/apps/runtime/dist/auth/account.js +121 -0
- package/apps/runtime/dist/auth/index.js +329 -0
- package/apps/runtime/dist/auth/keys.js +55 -0
- package/apps/runtime/dist/auth/local-ticket.js +23 -0
- package/apps/runtime/dist/authoring/example.js +73 -0
- package/apps/runtime/dist/authoring/guide.js +259 -0
- package/apps/runtime/dist/authoring/ops.js +117 -0
- package/apps/runtime/dist/cli/autostart.js +134 -0
- package/apps/runtime/dist/cli/clients.js +44 -0
- package/apps/runtime/dist/cli/environment.js +81 -0
- package/apps/runtime/dist/cli/exec.js +45 -0
- package/apps/runtime/dist/cli/home.js +74 -0
- package/apps/runtime/dist/cli/machine.js +145 -0
- package/apps/runtime/dist/cli/main.js +125 -0
- package/apps/runtime/dist/cli/setup.js +273 -0
- package/apps/runtime/dist/cli/start.js +190 -0
- package/apps/runtime/dist/cli/status.js +120 -0
- package/apps/runtime/dist/cli/ui.js +12 -0
- package/apps/runtime/dist/cli/update.js +58 -0
- package/apps/runtime/dist/connectors/builtin.js +70 -0
- package/apps/runtime/dist/connectors/external.js +400 -0
- package/apps/runtime/dist/connectors/gmail.js +107 -0
- package/apps/runtime/dist/connectors/imap.js +217 -0
- package/apps/runtime/dist/connectors/index.js +266 -0
- package/apps/runtime/dist/connectors/mail.js +72 -0
- package/apps/runtime/dist/connectors/outlook.js +90 -0
- package/apps/runtime/dist/credits/credits.js +103 -0
- package/apps/runtime/dist/credits/estimate.js +132 -0
- package/apps/runtime/dist/db/adopt.js +149 -0
- package/apps/runtime/dist/db/client.js +146 -0
- package/apps/runtime/dist/db/control-schema.js +70 -0
- package/apps/runtime/dist/db/migrations/control/0000_last_absorbing_man.sql +47 -0
- package/apps/runtime/dist/db/migrations/control/0001_gorgeous_nicolaos.sql +41 -0
- package/apps/runtime/dist/db/migrations/control/0002_secret_penance.sql +1 -0
- package/apps/runtime/dist/db/migrations/control/0003_nasty_mordo.sql +3 -0
- package/apps/runtime/dist/db/migrations/control/0004_breezy_eddie_brock.sql +6 -0
- package/apps/runtime/dist/db/migrations/control/meta/0000_snapshot.json +311 -0
- package/apps/runtime/dist/db/migrations/control/meta/0001_snapshot.json +599 -0
- package/apps/runtime/dist/db/migrations/control/meta/0002_snapshot.json +607 -0
- package/apps/runtime/dist/db/migrations/control/meta/0003_snapshot.json +311 -0
- package/apps/runtime/dist/db/migrations/control/meta/0004_snapshot.json +350 -0
- package/apps/runtime/dist/db/migrations/control/meta/_journal.json +41 -0
- package/apps/runtime/dist/db/migrations/tenant/0000_eminent_freak.sql +188 -0
- package/apps/runtime/dist/db/migrations/tenant/0001_salty_master_chief.sql +1 -0
- package/apps/runtime/dist/db/migrations/tenant/0002_cloudy_firebird.sql +1 -0
- package/apps/runtime/dist/db/migrations/tenant/0003_brown_warbound.sql +52 -0
- package/apps/runtime/dist/db/migrations/tenant/0004_romantic_nocturne.sql +6 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0000_snapshot.json +1323 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0001_snapshot.json +1330 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0002_snapshot.json +1337 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0003_snapshot.json +1605 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/0004_snapshot.json +1645 -0
- package/apps/runtime/dist/db/migrations/tenant/meta/_journal.json +41 -0
- package/apps/runtime/dist/db/schema.js +278 -0
- package/apps/runtime/dist/documents/parse.js +230 -0
- package/apps/runtime/dist/engenty/connections-external/build-connector.js +193 -0
- package/apps/runtime/dist/engenty/connections-external/errors.js +11 -0
- package/apps/runtime/dist/engenty/connections-external/import-service.js +270 -0
- package/apps/runtime/dist/engenty/connections-external/importer/classify.js +34 -0
- package/apps/runtime/dist/engenty/connections-external/importer/map-auth.js +185 -0
- package/apps/runtime/dist/engenty/connections-external/importer/normalize-mcp.js +63 -0
- package/apps/runtime/dist/engenty/connections-external/importer/normalize-openapi.js +130 -0
- package/apps/runtime/dist/engenty/connections-external/invoke/http-invoker.js +143 -0
- package/apps/runtime/dist/engenty/connections-external/invoke/mcp-client.js +143 -0
- package/apps/runtime/dist/engenty/connections-external/net/guarded-fetch.js +119 -0
- package/apps/runtime/dist/engenty/connections-external/oauth-dcr.js +88 -0
- package/apps/runtime/dist/engenty/connections-external/registry-client.js +336 -0
- package/apps/runtime/dist/engenty/connections-external/registry-source.js +82 -0
- package/apps/runtime/dist/engenty/connections-external/types.js +7 -0
- package/apps/runtime/dist/engenty/connections-github/connector.js +209 -0
- package/apps/runtime/dist/engenty/connections-google/connectors/calendar.js +359 -0
- package/apps/runtime/dist/engenty/connections-google/connectors/contacts.js +94 -0
- package/apps/runtime/dist/engenty/connections-google/connectors/drive.js +290 -0
- package/apps/runtime/dist/engenty/connections-google/connectors/gmail.js +567 -0
- package/apps/runtime/dist/engenty/connections-google/definitions.js +11 -0
- package/apps/runtime/dist/engenty/connections-google/shared.js +73 -0
- package/apps/runtime/dist/engenty/connections-hubspot/connector.js +140 -0
- package/apps/runtime/dist/engenty/connections-microsoft/action.js +17 -0
- package/apps/runtime/dist/engenty/connections-microsoft/graph.js +114 -0
- package/apps/runtime/dist/engenty/connections-microsoft/onedrive.js +286 -0
- package/apps/runtime/dist/engenty/connections-microsoft/outlook.js +464 -0
- package/apps/runtime/dist/engenty/connections-s3/s3.js +328 -0
- package/apps/runtime/dist/engenty/connections-sdk/files-capability.js +86 -0
- package/apps/runtime/dist/engenty/connections-sdk/oauth2.js +150 -0
- package/apps/runtime/dist/engenty/connections-sdk/registry.js +89 -0
- package/apps/runtime/dist/engenty/connections-sdk/storage-capability.js +84 -0
- package/apps/runtime/dist/engenty/connections-sdk/types.js +30 -0
- package/apps/runtime/dist/engenty/connections-slack/connector.js +360 -0
- package/apps/runtime/dist/engenty/csv-import/csv-matrix.js +178 -0
- package/apps/runtime/dist/engenty/csv-import/import-sources.js +87 -0
- package/apps/runtime/dist/engenty/csv-import/parse-csv.js +129 -0
- package/apps/runtime/dist/engenty/csv-import/serialize-csv.js +20 -0
- package/apps/runtime/dist/engenty/csv-import/types.js +1 -0
- package/apps/runtime/dist/engenty/csv-import/xlsx-workbook.js +159 -0
- package/apps/runtime/dist/engenty/doc-converter/interface.js +9 -0
- package/apps/runtime/dist/engenty/doc-converter/page-break.js +92 -0
- package/apps/runtime/dist/engenty/doc-converter/providers/local/index.js +72 -0
- package/apps/runtime/dist/engenty/document-scanner/schemas/classifier.js +30 -0
- package/apps/runtime/dist/engenty/document-scanner/schemas/index.js +4 -0
- package/apps/runtime/dist/engenty/document-scanner/schemas/invoice.js +73 -0
- package/apps/runtime/dist/engenty/document-scanner/schemas/receipt.js +63 -0
- package/apps/runtime/dist/engenty/document-scanner/schemas/shared.js +40 -0
- package/apps/runtime/dist/engenty/search-index/chunks.js +164 -0
- package/apps/runtime/dist/engenty/search-index/contracts.js +9 -0
- package/apps/runtime/dist/engenty/shims/connections-sdk.js +39 -0
- package/apps/runtime/dist/engenty/shims/plugin-sdk.js +1 -0
- package/apps/runtime/dist/engenty/shims/web-ingest.js +3 -0
- package/apps/runtime/dist/engenty/web-ingest/ssrf.js +277 -0
- package/apps/runtime/dist/engine/asks.js +60 -0
- package/apps/runtime/dist/engine/events.js +46 -0
- package/apps/runtime/dist/engine/input.js +170 -0
- package/apps/runtime/dist/engine/prepare.js +51 -0
- package/apps/runtime/dist/engine/requirements.js +124 -0
- package/apps/runtime/dist/engine/resources.js +89 -0
- package/apps/runtime/dist/engine/runner.js +560 -0
- package/apps/runtime/dist/engine/steps.js +598 -0
- package/apps/runtime/dist/engine/template.js +183 -0
- package/apps/runtime/dist/engine/types.js +3 -0
- package/apps/runtime/dist/env.js +224 -0
- package/apps/runtime/dist/files/blobs.js +22 -0
- package/apps/runtime/dist/files/objects.js +86 -0
- package/apps/runtime/dist/files/storage.js +95 -0
- package/apps/runtime/dist/geocode.js +58 -0
- package/apps/runtime/dist/harness/claude.js +138 -0
- package/apps/runtime/dist/harness/codex.js +228 -0
- package/apps/runtime/dist/harness/cursor.js +93 -0
- package/apps/runtime/dist/harness/env.js +124 -0
- package/apps/runtime/dist/harness/gemini.js +126 -0
- package/apps/runtime/dist/harness/index.js +99 -0
- package/apps/runtime/dist/harness/model.js +267 -0
- package/apps/runtime/dist/harness/prompt.js +121 -0
- package/apps/runtime/dist/harness/terminal.js +193 -0
- package/apps/runtime/dist/harness/types.js +7 -0
- package/apps/runtime/dist/index.js +76 -0
- package/apps/runtime/dist/limits.js +57 -0
- package/apps/runtime/dist/link-preview.js +59 -0
- package/apps/runtime/dist/manage.js +151 -0
- package/apps/runtime/dist/mcp/auth.js +102 -0
- package/apps/runtime/dist/mcp/bridge.js +59 -0
- package/apps/runtime/dist/mcp/handler.js +42 -0
- package/apps/runtime/dist/mcp/scopes.js +5 -0
- package/apps/runtime/dist/mcp/tools.js +401 -0
- package/apps/runtime/dist/media/ffmpeg.js +121 -0
- package/apps/runtime/dist/media/generate.js +120 -0
- package/apps/runtime/dist/media/marking.js +121 -0
- package/apps/runtime/dist/media/transcribe.js +30 -0
- package/apps/runtime/dist/model-errors.js +3 -0
- package/apps/runtime/dist/models.js +489 -0
- package/apps/runtime/dist/plugin.js +61 -0
- package/apps/runtime/dist/render/chromium.js +85 -0
- package/apps/runtime/dist/render/convert.js +161 -0
- package/apps/runtime/dist/render/downloads.js +277 -0
- package/apps/runtime/dist/render/guard.js +25 -0
- package/apps/runtime/dist/routes/api.js +74 -0
- package/apps/runtime/dist/routes/delivery.js +52 -0
- package/apps/runtime/dist/routes/internal.js +49 -0
- package/apps/runtime/dist/routes/marketplace.js +36 -0
- package/apps/runtime/dist/routes/runs.js +805 -0
- package/apps/runtime/dist/routes/studio.js +702 -0
- package/apps/runtime/dist/routes/wizard-stream.js +30 -0
- package/apps/runtime/dist/running.js +39 -0
- package/apps/runtime/dist/sandbox/agentos.js +191 -0
- package/apps/runtime/dist/sandbox/docker.js +77 -0
- package/apps/runtime/dist/sandbox/index.js +30 -0
- package/apps/runtime/dist/sandbox/types.js +1 -0
- package/apps/runtime/dist/secrets/crypto.js +28 -0
- package/apps/runtime/dist/secrets/signing.js +34 -0
- package/apps/runtime/dist/secrets/vault.js +59 -0
- package/apps/runtime/dist/services/architect.js +92 -0
- package/apps/runtime/dist/services/brand.js +20 -0
- package/apps/runtime/dist/services/cloud.js +52 -0
- package/apps/runtime/dist/services/draft-events.js +27 -0
- package/apps/runtime/dist/services/errors.js +24 -0
- package/apps/runtime/dist/services/files.js +129 -0
- package/apps/runtime/dist/services/links.js +16 -0
- package/apps/runtime/dist/services/marketplace.js +292 -0
- package/apps/runtime/dist/services/package.js +202 -0
- package/apps/runtime/dist/services/profile.js +23 -0
- package/apps/runtime/dist/services/project-files.js +266 -0
- package/apps/runtime/dist/services/project-index.js +109 -0
- package/apps/runtime/dist/services/projects.js +181 -0
- package/apps/runtime/dist/services/runs.js +224 -0
- package/apps/runtime/dist/services/shares.js +129 -0
- package/apps/runtime/dist/services/widgets.js +34 -0
- package/apps/runtime/dist/services/wizards.js +342 -0
- package/apps/runtime/dist/settings.js +16 -0
- package/apps/runtime/dist/store/index.js +279 -0
- package/apps/runtime/dist/tenants/control.js +106 -0
- package/apps/runtime/dist/tenants/tenant.js +26 -0
- package/apps/runtime/dist/tools/browser.js +380 -0
- package/apps/runtime/dist/tools/connector.js +204 -0
- package/apps/runtime/dist/tools/index.js +234 -0
- package/apps/runtime/dist/tools/mail.js +104 -0
- package/apps/runtime/dist/tools/net-guard.js +59 -0
- package/apps/runtime/dist/tools/project.js +53 -0
- package/apps/runtime/dist/tools/shared.js +42 -0
- package/apps/runtime/dist/tools/store.js +238 -0
- package/apps/runtime/dist/update.js +118 -0
- package/apps/runtime/dist/widgets/bundle.js +99 -0
- package/apps/runtime/dist/widgets/render.js +312 -0
- package/apps/runtime/dist/widgets/runtime.js +84 -0
- package/apps/runtime/dist/widgets/script.js +30 -0
- package/apps/runtime/dist/widgets/step.js +192 -0
- package/apps/web/dist/ai-labels/ai-black.svg +20 -0
- package/apps/web/dist/ai-labels/ai-generated-black.svg +31 -0
- package/apps/web/dist/ai-labels/ai-generated-white.svg +32 -0
- package/apps/web/dist/ai-labels/ai-modified-black.svg +30 -0
- package/apps/web/dist/ai-labels/ai-modified-white.svg +31 -0
- package/apps/web/dist/ai-labels/ai-white.svg +21 -0
- package/apps/web/dist/assets/ChangelogDialog-O00vEnbm.js +1 -0
- package/apps/web/dist/assets/ChatPanel-CH9ry0Hp.js +1 -0
- package/apps/web/dist/assets/CreditsDialog-DRzecwUw.js +1 -0
- package/apps/web/dist/assets/EditorPage-BRnBf02Q.js +2 -0
- package/apps/web/dist/assets/FlowPreview-DDOj8IAH.js +1 -0
- package/apps/web/dist/assets/HomePage-CAGTTG3N.js +1 -0
- package/apps/web/dist/assets/ImportWizard-0RRrAnX3.js +1 -0
- package/apps/web/dist/assets/LocalRuntime-BrP-ENHg.css +1 -0
- package/apps/web/dist/assets/LocalRuntime-C-TBYrzs.js +16 -0
- package/apps/web/dist/assets/NewWizardPage-kI90h3_9.js +2 -0
- package/apps/web/dist/assets/PublicRunner-CKRDeIVd.js +1 -0
- package/apps/web/dist/assets/RunnerView-Rc4H8wYH.js +2 -0
- package/apps/web/dist/assets/SettingsPage-CESMuZxq.js +2 -0
- package/apps/web/dist/assets/SetupPage-D1rrYU14.js +1 -0
- package/apps/web/dist/assets/SharePage-COTAmOgh.js +1 -0
- package/apps/web/dist/assets/api-BY28cjGY.js +10 -0
- package/apps/web/dist/assets/arrow-left-UpjOBfQp.js +1 -0
- package/apps/web/dist/assets/arrow-right-CucQycEy.js +1 -0
- package/apps/web/dist/assets/changelog-p3wsaDDS.js +1 -0
- package/apps/web/dist/assets/check-Bjx41xbB.js +1 -0
- package/apps/web/dist/assets/createLucideIcon-DBu2Ovxj.js +1 -0
- package/apps/web/dist/assets/definition-cy7uvY5L.js +55 -0
- package/apps/web/dist/assets/engenty-CWIFpgKq.js +1 -0
- package/apps/web/dist/assets/esm-D1OEhjTK.js +7 -0
- package/apps/web/dist/assets/external-link-CRg6DVdO.js +1 -0
- package/apps/web/dist/assets/fluffy-engenty-CJ3wCQgT.js +456 -0
- package/apps/web/dist/assets/index-CQ_q9iMO.css +1 -0
- package/apps/web/dist/assets/index-D0gxh90t.js +10 -0
- package/apps/web/dist/assets/jsx-runtime-Dk72oS4N.js +1 -0
- package/apps/web/dist/assets/meta-BbSdtTUa.js +1 -0
- package/apps/web/dist/assets/mic-CeqQ89Dj.js +1 -0
- package/apps/web/dist/assets/oss-credits-cPuZUFHD.js +1 -0
- package/apps/web/dist/assets/outputs-D6pxH6ve.js +69 -0
- package/apps/web/dist/assets/plus-HA210wXA.js +1 -0
- package/apps/web/dist/assets/preload-helper-CNEI7N0N.js +1 -0
- package/apps/web/dist/assets/qr-scanner-worker.min-CJaXo3yu.js +98 -0
- package/apps/web/dist/assets/qr-scanner.min-C_UI0gH-.js +1 -0
- package/apps/web/dist/assets/type-BzYgVWKL.js +1 -0
- package/apps/web/dist/assets/ui-Ddwl35A6.js +1 -0
- package/apps/web/dist/assets/upload-DsgLfQ3U.js +1 -0
- package/apps/web/dist/assets/video-Dk1fuTDl.js +1 -0
- package/apps/web/dist/assets/wand-sparkles-Bf97fs8T.js +1 -0
- package/apps/web/dist/embed.js +102 -0
- package/apps/web/dist/favicon.svg +1 -0
- package/apps/web/dist/icons/apple-touch-icon.png +0 -0
- package/apps/web/dist/icons/icon-192.png +0 -0
- package/apps/web/dist/icons/icon-512.png +0 -0
- package/apps/web/dist/icons/icon-maskable-512.png +0 -0
- package/apps/web/dist/index.html +46 -0
- package/apps/web/dist/install.sh +532 -0
- package/apps/web/dist/manifest.webmanifest +20 -0
- package/apps/web/dist/sw.js +15 -0
- package/bin/wizards.mjs +13 -0
- package/node_modules/@engenty-wizards/shared/dist/connectors.d.ts +77 -0
- package/node_modules/@engenty-wizards/shared/dist/connectors.js +2 -0
- package/node_modules/@engenty-wizards/shared/dist/definition.d.ts +1415 -0
- package/node_modules/@engenty-wizards/shared/dist/definition.js +762 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns-format.d.ts +5 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns-format.js +132 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns-value.d.ts +11 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns-value.js +209 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns.d.ts +532 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/columns.js +216 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/index.d.ts +3 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/data-tables/index.js +3 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/search-index/catalog-lexical.d.ts +14 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/search-index/catalog-lexical.js +166 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/search-index/catalog-rank.d.ts +33 -0
- package/node_modules/@engenty-wizards/shared/dist/engenty/search-index/catalog-rank.js +99 -0
- package/node_modules/@engenty-wizards/shared/dist/marketplace-entry.d.ts +35 -0
- package/node_modules/@engenty-wizards/shared/dist/marketplace-entry.js +86 -0
- package/node_modules/@engenty-wizards/shared/dist/marketplace-search.d.ts +20 -0
- package/node_modules/@engenty-wizards/shared/dist/marketplace-search.js +133 -0
- package/node_modules/@engenty-wizards/shared/dist/marketplace.d.ts +298 -0
- package/node_modules/@engenty-wizards/shared/dist/marketplace.js +211 -0
- package/node_modules/@engenty-wizards/shared/dist/merge.d.ts +7 -0
- package/node_modules/@engenty-wizards/shared/dist/merge.js +40 -0
- package/node_modules/@engenty-wizards/shared/dist/projects.d.ts +74 -0
- package/node_modules/@engenty-wizards/shared/dist/projects.js +96 -0
- package/node_modules/@engenty-wizards/shared/dist/run.d.ts +219 -0
- package/node_modules/@engenty-wizards/shared/dist/run.js +1 -0
- package/node_modules/@engenty-wizards/shared/dist/store.d.ts +100 -0
- package/node_modules/@engenty-wizards/shared/dist/store.js +44 -0
- package/node_modules/@engenty-wizards/shared/dist/workspace.d.ts +16 -0
- package/node_modules/@engenty-wizards/shared/dist/workspace.js +51 -0
- package/node_modules/@engenty-wizards/shared/package.json +10 -0
- package/package.json +62 -0
- package/plugin/.claude-plugin/plugin.json +9 -0
- package/plugin/.mcp.json +8 -0
- package/plugin/commands/wizard.md +8 -0
- package/plugin/skills/build-wizard/SKILL.md +27 -0
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { DateFormat, DurationFormat, NumberFormat, TableColumn } from "./columns.js";
|
|
2
|
+
export declare function formatNumberCell(value: unknown, format: NumberFormat, locale?: string): string;
|
|
3
|
+
export declare function formatDateCell(value: unknown, format: DateFormat, locale?: string): string;
|
|
4
|
+
export declare function formatDurationCell(value: unknown, format: DurationFormat): string;
|
|
5
|
+
export declare function formatTableCell(column: TableColumn, value: unknown, locale?: string): string;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
const MS_HOUR = 3_600_000;
|
|
2
|
+
const MS_MINUTE = 60_000;
|
|
3
|
+
const MS_SECOND = 1000;
|
|
4
|
+
function fractionDigits(format) {
|
|
5
|
+
if (format.fractionDigits !== undefined) {
|
|
6
|
+
return format.fractionDigits;
|
|
7
|
+
}
|
|
8
|
+
return format.style === "integer" ? 0 : 2;
|
|
9
|
+
}
|
|
10
|
+
export function formatNumberCell(value, format, locale = "en") {
|
|
11
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
12
|
+
return "";
|
|
13
|
+
}
|
|
14
|
+
const digits = fractionDigits(format);
|
|
15
|
+
const grouping = format.grouping !== false;
|
|
16
|
+
if (format.style === "percent") {
|
|
17
|
+
return new Intl.NumberFormat(locale, {
|
|
18
|
+
maximumFractionDigits: digits,
|
|
19
|
+
minimumFractionDigits: digits,
|
|
20
|
+
style: "percent",
|
|
21
|
+
useGrouping: grouping,
|
|
22
|
+
}).format(value);
|
|
23
|
+
}
|
|
24
|
+
if (format.style === "currency" && format.currency) {
|
|
25
|
+
return new Intl.NumberFormat(locale, {
|
|
26
|
+
currency: format.currency,
|
|
27
|
+
maximumFractionDigits: digits,
|
|
28
|
+
minimumFractionDigits: digits,
|
|
29
|
+
style: "currency",
|
|
30
|
+
useGrouping: grouping,
|
|
31
|
+
}).format(value);
|
|
32
|
+
}
|
|
33
|
+
return new Intl.NumberFormat(locale, {
|
|
34
|
+
maximumFractionDigits: digits,
|
|
35
|
+
minimumFractionDigits: digits,
|
|
36
|
+
useGrouping: grouping,
|
|
37
|
+
}).format(value);
|
|
38
|
+
}
|
|
39
|
+
export function formatDateCell(value, format, locale = "en") {
|
|
40
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
41
|
+
return "";
|
|
42
|
+
}
|
|
43
|
+
if (format.kind === "time") {
|
|
44
|
+
return formatClock(value, format.timePrecision ?? "minutes");
|
|
45
|
+
}
|
|
46
|
+
if (format.dateStyle === "iso") {
|
|
47
|
+
return format.kind === "date" ? value.slice(0, 10) : value;
|
|
48
|
+
}
|
|
49
|
+
const date = format.kind === "date" ? new Date(`${value}T00:00:00`) : new Date(value);
|
|
50
|
+
if (Number.isNaN(date.getTime())) {
|
|
51
|
+
return value;
|
|
52
|
+
}
|
|
53
|
+
const dateStyle = format.dateStyle ?? "medium";
|
|
54
|
+
if (format.kind === "date") {
|
|
55
|
+
return new Intl.DateTimeFormat(locale, { dateStyle }).format(date);
|
|
56
|
+
}
|
|
57
|
+
const timePrecision = format.timePrecision ?? "minutes";
|
|
58
|
+
return new Intl.DateTimeFormat(locale, {
|
|
59
|
+
dateStyle,
|
|
60
|
+
timeStyle: timePrecision === "hours" ? "short" : "medium",
|
|
61
|
+
}).format(date);
|
|
62
|
+
}
|
|
63
|
+
function formatClock(value, precision) {
|
|
64
|
+
const [hours = "0", minutes = "00", seconds = "00"] = value.split(":");
|
|
65
|
+
if (precision === "hours") {
|
|
66
|
+
return `${hours.padStart(2, "0")}:00`;
|
|
67
|
+
}
|
|
68
|
+
if (precision === "minutes") {
|
|
69
|
+
return `${hours.padStart(2, "0")}:${minutes.padStart(2, "0")}`;
|
|
70
|
+
}
|
|
71
|
+
return `${hours.padStart(2, "0")}:${minutes.padStart(2, "0")}:${seconds.padStart(2, "0")}`;
|
|
72
|
+
}
|
|
73
|
+
export function formatDurationCell(value, format) {
|
|
74
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
75
|
+
return "";
|
|
76
|
+
}
|
|
77
|
+
const ms = Math.max(0, Math.round(value));
|
|
78
|
+
if (format.display === "iso") {
|
|
79
|
+
return toIsoDuration(ms);
|
|
80
|
+
}
|
|
81
|
+
if (format.display === "minutes") {
|
|
82
|
+
return `${Math.round(ms / MS_MINUTE)} min`;
|
|
83
|
+
}
|
|
84
|
+
if (format.display === "hours") {
|
|
85
|
+
return `${(ms / MS_HOUR).toFixed(2)} h`;
|
|
86
|
+
}
|
|
87
|
+
if (format.display === "decimal-hours") {
|
|
88
|
+
return (ms / MS_HOUR).toFixed(2);
|
|
89
|
+
}
|
|
90
|
+
const hours = Math.floor(ms / MS_HOUR);
|
|
91
|
+
const minutes = Math.floor((ms % MS_HOUR) / MS_MINUTE);
|
|
92
|
+
const seconds = Math.floor((ms % MS_MINUTE) / MS_SECOND);
|
|
93
|
+
return `${hours}:${String(minutes).padStart(2, "0")}:${String(seconds).padStart(2, "0")}`;
|
|
94
|
+
}
|
|
95
|
+
function toIsoDuration(ms) {
|
|
96
|
+
const hours = Math.floor(ms / MS_HOUR);
|
|
97
|
+
const minutes = Math.floor((ms % MS_HOUR) / MS_MINUTE);
|
|
98
|
+
const seconds = Math.floor((ms % MS_MINUTE) / MS_SECOND);
|
|
99
|
+
const dayPart = hours >= 24 ? `P${Math.floor(hours / 24)}D` : "P";
|
|
100
|
+
const h = hours % 24;
|
|
101
|
+
return `${dayPart}T${h}H${minutes}M${seconds}S`;
|
|
102
|
+
}
|
|
103
|
+
export function formatTableCell(column, value, locale = "en") {
|
|
104
|
+
if (value === null || value === undefined) {
|
|
105
|
+
return "";
|
|
106
|
+
}
|
|
107
|
+
switch (column.type) {
|
|
108
|
+
case "number":
|
|
109
|
+
return formatNumberCell(value, column.format, locale);
|
|
110
|
+
case "date":
|
|
111
|
+
return formatDateCell(value, column.format, locale);
|
|
112
|
+
case "duration":
|
|
113
|
+
return formatDurationCell(value, column.format);
|
|
114
|
+
case "boolean":
|
|
115
|
+
return value === true ? "true" : value === false ? "false" : "";
|
|
116
|
+
case "select":
|
|
117
|
+
return formatSelectCell(column, value);
|
|
118
|
+
default:
|
|
119
|
+
return String(value);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function formatSelectCell(column, value) {
|
|
123
|
+
const ids = Array.isArray(value) ? value : [value];
|
|
124
|
+
const labels = column.format.options.reduce((acc, option) => {
|
|
125
|
+
acc[option.id] = option.label;
|
|
126
|
+
return acc;
|
|
127
|
+
}, {});
|
|
128
|
+
return ids
|
|
129
|
+
.filter((id) => typeof id === "string" && id.length > 0)
|
|
130
|
+
.map((id) => labels[id] ?? id)
|
|
131
|
+
.join(", ");
|
|
132
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type TableColumn } from "./columns.js";
|
|
2
|
+
export declare class TableColumnValueError extends Error {
|
|
3
|
+
readonly code = "invalid_table_value";
|
|
4
|
+
readonly columnId: string;
|
|
5
|
+
constructor(columnId: string, message: string);
|
|
6
|
+
}
|
|
7
|
+
export declare function parseTableColumns(input: unknown): TableColumn[];
|
|
8
|
+
/** Turn a writer-facing cell into the stored JSON value for one column. */
|
|
9
|
+
export declare function coerceColumnValue(column: TableColumn, value: unknown): unknown;
|
|
10
|
+
export declare function coerceRowValues(columns: readonly TableColumn[], values: Record<string, unknown>): Record<string, unknown>;
|
|
11
|
+
export declare function mergeRowValues(columns: readonly TableColumn[], current: Record<string, unknown>, patch: Record<string, unknown>): Record<string, unknown>;
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { tableColumnsSchema, textColumnStyle, } from "./columns.js";
|
|
2
|
+
export class TableColumnValueError extends Error {
|
|
3
|
+
code = "invalid_table_value";
|
|
4
|
+
columnId;
|
|
5
|
+
constructor(columnId, message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = "TableColumnValueError";
|
|
8
|
+
this.columnId = columnId;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
const MS = {
|
|
12
|
+
days: 86_400_000,
|
|
13
|
+
hours: 3_600_000,
|
|
14
|
+
milliseconds: 1,
|
|
15
|
+
minutes: 60_000,
|
|
16
|
+
seconds: 1000,
|
|
17
|
+
};
|
|
18
|
+
export function parseTableColumns(input) {
|
|
19
|
+
return tableColumnsSchema.parse(input);
|
|
20
|
+
}
|
|
21
|
+
function isBlank(value) {
|
|
22
|
+
return value === null || value === undefined || value === "";
|
|
23
|
+
}
|
|
24
|
+
function optionIds(format) {
|
|
25
|
+
return new Set(format.options.map((option) => option.id));
|
|
26
|
+
}
|
|
27
|
+
function coerceDurationMs(value, format) {
|
|
28
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
29
|
+
return value * MS[format.inputUnit];
|
|
30
|
+
}
|
|
31
|
+
if (typeof value === "object" && value !== null && "value" in value) {
|
|
32
|
+
const raw = value;
|
|
33
|
+
if (typeof raw.value === "number" && Number.isFinite(raw.value)) {
|
|
34
|
+
const unit = typeof raw.unit === "string" && raw.unit in MS
|
|
35
|
+
? raw.unit
|
|
36
|
+
: format.inputUnit;
|
|
37
|
+
return raw.value * MS[unit];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (typeof value === "string") {
|
|
41
|
+
const iso = parseIsoDurationMs(value.trim());
|
|
42
|
+
if (iso !== null) {
|
|
43
|
+
return iso;
|
|
44
|
+
}
|
|
45
|
+
const asNumber = Number(value);
|
|
46
|
+
if (Number.isFinite(asNumber)) {
|
|
47
|
+
return asNumber * MS[format.inputUnit];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
throw new Error("duration must be a number in the column's input unit");
|
|
51
|
+
}
|
|
52
|
+
function parseIsoDurationMs(raw) {
|
|
53
|
+
const match = /^P(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+(?:\.\d+)?)S)?)?$/i.exec(raw);
|
|
54
|
+
if (!match) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
const days = Number(match[1] ?? 0);
|
|
58
|
+
const hours = Number(match[2] ?? 0);
|
|
59
|
+
const minutes = Number(match[3] ?? 0);
|
|
60
|
+
const seconds = Number(match[4] ?? 0);
|
|
61
|
+
if (days + hours + minutes + seconds === 0 && raw === "P") {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
return (days * MS.days +
|
|
65
|
+
hours * MS.hours +
|
|
66
|
+
minutes * MS.minutes +
|
|
67
|
+
seconds * MS.seconds);
|
|
68
|
+
}
|
|
69
|
+
function pad(value, size = 2) {
|
|
70
|
+
return String(value).padStart(size, "0");
|
|
71
|
+
}
|
|
72
|
+
function coerceDate(value, format) {
|
|
73
|
+
if (typeof value !== "string" && typeof value !== "number") {
|
|
74
|
+
throw new Error("date must be a string");
|
|
75
|
+
}
|
|
76
|
+
const raw = String(value).trim();
|
|
77
|
+
if (format.kind === "date") {
|
|
78
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(raw)) {
|
|
79
|
+
throw new Error("date must be YYYY-MM-DD");
|
|
80
|
+
}
|
|
81
|
+
return raw;
|
|
82
|
+
}
|
|
83
|
+
if (format.kind === "datetime") {
|
|
84
|
+
const parsed = Date.parse(raw);
|
|
85
|
+
if (Number.isNaN(parsed)) {
|
|
86
|
+
throw new Error("datetime must be an ISO-8601 timestamp");
|
|
87
|
+
}
|
|
88
|
+
return new Date(parsed).toISOString();
|
|
89
|
+
}
|
|
90
|
+
const precision = format.timePrecision ?? "minutes";
|
|
91
|
+
const time = normalizeClockTime(raw, precision);
|
|
92
|
+
if (!time) {
|
|
93
|
+
throw new Error(precision === "hours"
|
|
94
|
+
? "time must be an hour (0–23 or HH:00)"
|
|
95
|
+
: "time must be HH:mm");
|
|
96
|
+
}
|
|
97
|
+
return time;
|
|
98
|
+
}
|
|
99
|
+
function normalizeClockTime(raw, precision) {
|
|
100
|
+
const hourOnly = /^(\d{1,2})$/.exec(raw);
|
|
101
|
+
const hm = /^(\d{1,2}):(\d{2})(?::(\d{2}))?$/.exec(raw);
|
|
102
|
+
const match = hourOnly ?? hm;
|
|
103
|
+
if (!match) {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
const hours = Number(match[1]);
|
|
107
|
+
const minutes = hourOnly ? 0 : Number(match[2] ?? 0);
|
|
108
|
+
const seconds = hourOnly ? 0 : Number(match[3] ?? 0);
|
|
109
|
+
if (hours < 0 || hours > 23 || minutes > 59 || seconds > 59) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
if (precision === "hours") {
|
|
113
|
+
return `${pad(hours)}:00`;
|
|
114
|
+
}
|
|
115
|
+
if (precision === "minutes") {
|
|
116
|
+
return `${pad(hours)}:${pad(minutes)}`;
|
|
117
|
+
}
|
|
118
|
+
return `${pad(hours)}:${pad(minutes)}:${pad(seconds)}`;
|
|
119
|
+
}
|
|
120
|
+
function coerceSelect(value, format) {
|
|
121
|
+
const allowed = optionIds(format);
|
|
122
|
+
const asList = format.multiple
|
|
123
|
+
? Array.isArray(value)
|
|
124
|
+
? value
|
|
125
|
+
: [value]
|
|
126
|
+
: [value];
|
|
127
|
+
const ids = asList.map((item) => {
|
|
128
|
+
if (typeof item !== "string" || item.trim() === "") {
|
|
129
|
+
throw new Error("select values must be non-empty strings");
|
|
130
|
+
}
|
|
131
|
+
const id = item.trim();
|
|
132
|
+
if (!(format.allowCustom || allowed.has(id))) {
|
|
133
|
+
throw new Error(`"${id}" is not an allowed value`);
|
|
134
|
+
}
|
|
135
|
+
return id;
|
|
136
|
+
});
|
|
137
|
+
return format.multiple ? ids : (ids[0] ?? "");
|
|
138
|
+
}
|
|
139
|
+
function coerceNumber(value, integer) {
|
|
140
|
+
const n = typeof value === "number" ? value : Number(value);
|
|
141
|
+
if (!Number.isFinite(n)) {
|
|
142
|
+
throw new Error("number must be finite");
|
|
143
|
+
}
|
|
144
|
+
if (integer && !Number.isInteger(n)) {
|
|
145
|
+
throw new Error("this column only accepts whole numbers");
|
|
146
|
+
}
|
|
147
|
+
return n;
|
|
148
|
+
}
|
|
149
|
+
function coerceText(column, value) {
|
|
150
|
+
const text = String(value);
|
|
151
|
+
if (textColumnStyle(column) === "single") {
|
|
152
|
+
return text.replace(/[\r\n]+/g, " ");
|
|
153
|
+
}
|
|
154
|
+
return text;
|
|
155
|
+
}
|
|
156
|
+
/** Turn a writer-facing cell into the stored JSON value for one column. */
|
|
157
|
+
export function coerceColumnValue(column, value) {
|
|
158
|
+
if (isBlank(value)) {
|
|
159
|
+
if (column.required) {
|
|
160
|
+
throw new TableColumnValueError(column.id, `"${column.name}" is required`);
|
|
161
|
+
}
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
try {
|
|
165
|
+
switch (column.type) {
|
|
166
|
+
case "text":
|
|
167
|
+
return coerceText(column, value);
|
|
168
|
+
case "boolean":
|
|
169
|
+
if (typeof value === "boolean") {
|
|
170
|
+
return value;
|
|
171
|
+
}
|
|
172
|
+
if (value === "true" || value === "1") {
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
if (value === "false" || value === "0") {
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
throw new Error("boolean must be true or false");
|
|
179
|
+
case "number":
|
|
180
|
+
return coerceNumber(value, column.format.style === "integer");
|
|
181
|
+
case "date":
|
|
182
|
+
return coerceDate(value, column.format);
|
|
183
|
+
case "duration":
|
|
184
|
+
return coerceDurationMs(value, column.format);
|
|
185
|
+
case "select":
|
|
186
|
+
return coerceSelect(value, column.format);
|
|
187
|
+
default:
|
|
188
|
+
return value;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
catch (error) {
|
|
192
|
+
throw new TableColumnValueError(column.id, error instanceof Error ? error.message : String(error));
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
export function coerceRowValues(columns, values) {
|
|
196
|
+
const known = new Set(columns.map((column) => column.id));
|
|
197
|
+
const extra = Object.keys(values).filter((key) => !known.has(key));
|
|
198
|
+
if (extra.length > 0) {
|
|
199
|
+
throw new TableColumnValueError(extra[0] ?? "", `unknown column "${extra[0]}"`);
|
|
200
|
+
}
|
|
201
|
+
const next = {};
|
|
202
|
+
for (const column of columns) {
|
|
203
|
+
next[column.id] = coerceColumnValue(column, values[column.id]);
|
|
204
|
+
}
|
|
205
|
+
return next;
|
|
206
|
+
}
|
|
207
|
+
export function mergeRowValues(columns, current, patch) {
|
|
208
|
+
return coerceRowValues(columns, { ...current, ...patch });
|
|
209
|
+
}
|