Skip to content

Commit 641675d

Browse files
os-zhuangclaude
andauthored
fix(examples): typecheck example apps clean + gate in CI (#2023)
The example apps failed their own `tsc --noEmit`. Root cause: app-crm imported types from the root `@objectstack/spec`, which intentionally exports no types — those imports resolved to `any` and silently suppressed all object-literal type checking, masking ~30 real errors. tsup builds the apps without a full typecheck, so nothing caught it. - Repoint app-crm type imports to canonical subpaths (`@objectstack/spec/data`, `/ui`, `/security`, ...). - Type authored literals with input types: add the missing `*Input` aliases to @objectstack/spec (following the existing FieldInput/ ActionInput/ReportInput/PortalInput convention) so `.default()` fields stay optional and CEL fields accept string shorthands. - Fix genuine content drift: drop unsupported `description` on agent/Action/PermissionSet; `parentRole` -> `parent` on roles. - app-todo: drop unmodeled `Field.color` options, guard `input.subject.includes` on an `unknown` value, add the `vitest` devDep its `src/` test needs. - CI (lint.yml): build workspace packages, then typecheck every example via the path filter `./examples/*` (the `@objectstack/example-*` scope glob silently skips `@example/app-todo`). Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent f943f3b commit 641675d

37 files changed

Lines changed: 88 additions & 56 deletions
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@objectstack/spec": patch
3+
---
4+
5+
Add `*Input` authoring-type aliases (`DatasourceInput`, `ConnectorInput`, `SharingRuleInput`, `JobInput`, `WebhookInput`, `EmailTemplateDefinitionInput`, `RoleInput`, `PermissionSetInput`, `ObjectExtensionInput`) alongside the existing `FieldInput`/`ActionInput`/`ReportInput`/`PortalInput` convention. These are `z.input<typeof XSchema>` aliases so authored literals keep `.default()` fields optional and accept CEL/Expression string shorthands — matching how `defineX()` helpers already accept input. No runtime change.

.github/workflows/lint.yml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,16 @@ jobs:
4646
- name: Install dependencies
4747
run: pnpm install --frozen-lockfile
4848

49-
- name: Type check
49+
- name: Type check (@objectstack/spec)
5050
run: pnpm --filter @objectstack/spec exec tsc --noEmit
51+
52+
# Example apps are AI-authoring reference templates; a red typecheck is a
53+
# bad signal to copy from. tsup transpiles them without a full typecheck,
54+
# so build alone will not catch type drift — typecheck them explicitly.
55+
# They import from built workspace packages, so the packages must be built
56+
# first for cross-package type resolution to succeed.
57+
- name: Build workspace packages
58+
run: pnpm exec turbo run build --filter='./packages/*'
59+
60+
- name: Type check example apps
61+
run: pnpm --filter './examples/*' run typecheck

examples/app-crm/src/actions/convert-lead.action.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
22

3-
import type { UI } from '@objectstack/spec';
3+
import type * as UI from '@objectstack/spec/ui';
44

55
/**
66
* Row-level action on crm_lead — launches the Convert Lead screen flow wizard.
77
* Shown as a button in the lead list row menu and in the lead record header.
88
*/
9-
export const ConvertLeadAction: UI.Action = {
9+
export const ConvertLeadAction: UI.ActionInput = {
1010
name: 'crm_convert_lead',
1111
label: 'Convert Lead',
12-
description: 'Open the Convert Lead wizard to create an Opportunity from this Lead.',
1312
icon: 'ArrowRightCircle',
1413
objectName: 'crm_lead',
1514
type: 'flow',

examples/app-crm/src/actions/park-lead.action.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
22

3-
import type { UI } from '@objectstack/spec';
3+
import type * as UI from '@objectstack/spec/ui';
44

55
/**
66
* Row-level action on crm_lead — reassign the lead's owner.
@@ -11,10 +11,9 @@ import type { UI } from '@objectstack/spec';
1111
* UndoManager — Ctrl+Z works too). Prompts for the new owner via one param
1212
* (pre-filled with "Triage Queue").
1313
*/
14-
export const ParkLeadAction: UI.Action = {
14+
export const ParkLeadAction: UI.ActionInput = {
1515
name: 'crm_park_lead',
1616
label: 'Reassign Lead',
17-
description: 'Reassign this lead to a new owner (undoable).',
1817
icon: 'UserPlus',
1918
objectName: 'crm_lead',
2019
// `type: 'api'` with a non-URL target routes to the console runtime's generic

examples/app-crm/src/agents/sales-assistant.agent.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ export const DealManagementSkill = defineSkill({
4242
export const SalesAssistantAgent = defineAgent({
4343
name: 'crm_sales_assistant',
4444
label: 'Sales Assistant',
45-
description: 'AI assistant that helps sales reps manage their pipeline.',
4645
role: 'You are a helpful sales operations assistant for a CRM system.',
4746
instructions:
4847
'Help sales reps find contacts, update opportunities, and summarise their pipeline. Always be concise and ask before making destructive changes.',

examples/app-crm/src/analytics/crm.cube.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
22

3-
import type { Cube } from '@objectstack/spec';
3+
import type { Cube } from '@objectstack/spec/data';
44

55
/**
66
* Opportunity Pipeline Cube — revenue metrics broken down by stage,

examples/app-crm/src/api/crm-endpoints.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
22

3-
import type { ApiEndpoint } from '@objectstack/spec';
3+
import type { ApiEndpoint } from '@objectstack/spec/api';
44

55
/**
66
* Custom REST endpoint — exposes pipeline summary metrics.

examples/app-crm/src/connectors/crm-connectors.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
22

3-
import type { Connector } from '@objectstack/spec';
3+
import type { ConnectorInput } from '@objectstack/spec/integration';
44

55
/**
66
* HubSpot connector — sync contacts and deals bi-directionally.
77
* Uses OAuth2 for authentication; actual credentials come from environment.
88
*/
9-
export const HubSpotConnector: Connector = {
9+
export const HubSpotConnector: ConnectorInput = {
1010
name: 'hubspot_crm',
1111
label: 'HubSpot CRM',
1212
type: 'saas',
@@ -91,7 +91,7 @@ export const HubSpotConnector: Connector = {
9191
/**
9292
* Slack connector — post notifications to channels.
9393
*/
94-
export const SlackConnector: Connector = {
94+
export const SlackConnector: ConnectorInput = {
9595
name: 'slack_notifications',
9696
label: 'Slack',
9797
type: 'api',

examples/app-crm/src/data/crm-mappings.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
22

3-
import type { Mapping } from '@objectstack/spec';
3+
import type { Mapping } from '@objectstack/spec/data';
44

55
/**
66
* CSV import mapping for bulk lead upload.

examples/app-crm/src/datasources/crm.datasource.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
22

3-
import type { Datasource } from '@objectstack/spec';
3+
import type { DatasourceInput } from '@objectstack/spec/data';
44

55
/**
66
* Primary CRM datasource — in-memory SQLite for the example.
77
* In production, swap `driver` to 'postgres' and supply real `config`.
88
*/
9-
export const CrmDatasource: Datasource = {
9+
export const CrmDatasource: DatasourceInput = {
1010
name: 'crm_primary',
1111
label: 'CRM Primary Database',
1212
driver: 'sqlite',
@@ -23,7 +23,7 @@ export const CrmDatasource: Datasource = {
2323
/**
2424
* Read-replica for analytics queries — demonstrates datasource routing.
2525
*/
26-
export const CrmAnalyticsDatasource: Datasource = {
26+
export const CrmAnalyticsDatasource: DatasourceInput = {
2727
name: 'crm_analytics',
2828
label: 'CRM Analytics Read Replica',
2929
driver: 'sqlite',

0 commit comments

Comments
 (0)