chore: upgrade @objectstack/* from 1.1.0 to 2.0.0#224
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…eaking changes Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
…ermission context Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR upgrades the monorepo to @objectstack/* v2.0.0 and updates code to accommodate the main breaking changes in the spec (workflow Flow shape, hook typing, and UI branding schema), plus aligns permissions types with engine usage.
Changes:
- Bump
@objectstack/*dependencies to2.0.0across packages/apps/examples (including lockfile updates). - Update workflow Flow conversion + tests for
FlowNode.name → labelandFlow.version: string → number(and requiredFlow.type/label). - Extend permissions types/context to support profile arrays and additional permission modeling; adjust in-memory storage indexing and plugin request context assembly.
Reviewed changes
Copilot reviewed 27 out of 28 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm-lock.yaml | Locks upgraded @objectstack/* v2 dependency graph and related transitive changes. |
| package.json | Bumps root dependencies/devDependencies to @objectstack/* 2.0.0. |
| apps/web/package.json | Updates web console to @objectstack/client@2.0.0. |
| packages/audit/package.json | Bumps runtime/spec dependencies to 2.0.0. |
| packages/auth/package.json | Bumps runtime/spec dependencies to 2.0.0. |
| packages/automation/package.json | Bumps runtime/spec dependencies to 2.0.0. |
| packages/browser/package.json | Bumps runtime/spec dependencies to 2.0.0. |
| packages/cache/package.json | Bumps runtime dependency to 2.0.0. |
| packages/i18n/package.json | Bumps runtime dependency to 2.0.0. |
| packages/jobs/package.json | Bumps runtime/spec dependencies to 2.0.0. |
| packages/metrics/package.json | Bumps runtime dependency to 2.0.0. |
| packages/notification/package.json | Bumps runtime dependency to 2.0.0. |
| packages/permissions/package.json | Bumps runtime/spec dependencies to 2.0.0. |
| packages/permissions/src/types.ts | Adds/aligns permissions model types (PermissionSet fields, ObjectPermissions, PermissionContext profiles array, FieldPermission visibility/editability). |
| packages/permissions/src/storage.ts | Guards optional objectName when indexing permission sets by object. |
| packages/permissions/src/plugin.ts | Builds PermissionContext.profiles from request payload / profileName. |
| packages/realtime/package.json | Bumps runtime dependency to 2.0.0. |
| packages/storage/package.json | Bumps runtime dependency to 2.0.0. |
| packages/workflow/package.json | Bumps runtime/spec dependencies to 2.0.0. |
| packages/workflow/src/flow-converter.ts | Updates Flow conversion logic for v2 Flow schema changes (label/type/version). |
| packages/workflow/test/flow-converter.test.ts | Updates workflow converter tests for v2 Flow schema changes. |
| examples/todo/package.json | Pins examples to @objectstack/*@2.0.0 (no workspace refs). |
| examples/todo/src/apps/todo.app.ts | Removes branding.secondaryColor (removed from v2 schema). |
| examples/todo/src/objects/task.hook.ts | Adjusts hook handler signature and attempts to adapt to HookContext.input: Record<string, unknown>. |
| examples/crm/package.json | Pins examples to @objectstack/*@2.0.0 (no workspace refs). |
| examples/crm/src/apps/crm.app.ts | Removes branding.secondaryColor (removed from v2 schema). |
| examples/crm/src/objects/account.hook.ts | Adjusts hook handler signature for v2 handler typing. |
| examples/crm/src/objects/lead.hook.ts | Adjusts hook handler signature and attempts to adapt to HookContext.input: Record<string, unknown>. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
Comments suppressed due to low confidence (1)
examples/crm/src/objects/account.hook.ts:15
input.websiteisunknown(fromHookContext.input: Record<string, unknown>), but it’s used in a truthiness check (if (input.website && ...)). InstrictTS,unknowncan’t be used as a boolean. Narrow directly withtypeof input.website === 'string'(and then validatestartsWith('http')) to keep the hook type-safe under the v2 spec.
if (ctx.event === 'beforeInsert' || ctx.event === 'beforeUpdate') {
// Validation: Ensure website is valid format if provided
if (input.website && typeof input.website === 'string' && !input.website.startsWith('http')) {
throw new Error('Website must start with http or https');
}
|
|
||
| if (!userId || !profileName || !objectName || !action) { | ||
| return c.json({ success: false, error: 'Missing required fields' }, 400); | ||
| } | ||
|
|
||
| const permissionContext = { | ||
| const permissionContext: PermissionContext = { | ||
| userId, | ||
| profileName, | ||
| profiles: body.profiles || (profileName ? [profileName] : []), |
There was a problem hiding this comment.
The /api/v1/permissions/check endpoint still treats profileName as required (if (!userId || !profileName || ...)) even though PermissionContext.profileName is now optional and the code now supports body.profiles. This makes requests that send only profiles fail validation. Adjust the validation to require either a non-empty profiles array or profileName, and normalize into permissionContext.profiles.
| @@ -16,7 +16,7 @@ | |||
| input.status = 'not_started'; | |||
| } | |||
There was a problem hiding this comment.
ctx.input is now Record<string, unknown> (per v2 spec), but this hook uses truthiness checks and assignments on unknown values (e.g. if (!input.priority), if (!input.status)). In strict TS this won’t type-check. Narrow with explicit checks (input.priority == null, typeof input.priority !== 'string', etc.) before reading, and keep assignments on the narrowed Record<string, unknown> object.
| if (ctx.event === 'afterUpdate') { | ||
| // Check if completed | ||
| if (ctx.input.status === 'completed' && ctx.previous && ctx.previous.status !== 'completed') { | ||
| console.log(`Task ${ctx.id} completed by ${ctx.session?.userId || 'unknown'}`); | ||
| // Could trigger notifications or integrations here | ||
| } | ||
|
|
||
| // Check if task became overdue | ||
| if (ctx.input.is_overdue && ctx.previous && !ctx.previous.is_overdue) { | ||
| console.log(`Task ${ctx.id} is now overdue`); | ||
| } |
There was a problem hiding this comment.
In the afterUpdate branch, ctx.input.status / ctx.input.is_overdue are still unknown properties. ctx.input.is_overdue is used directly in a condition (if (ctx.input.is_overdue && ...)), which won’t type-check under strict when the property type is unknown. Cast/narrow ctx.input (and ctx.previous) to a record and use typeof ... === 'string' | 'boolean' checks before comparisons / truthiness checks.
| let score = 0; | ||
| if (input.email && typeof input.email === 'string' && input.email.endsWith('@enterprise.com')) { | ||
| score += 50; | ||
| } | ||
| if (input.phone) { | ||
| score += 20; | ||
| } | ||
| input.score = score; | ||
| (input as Record<string, unknown>).score = score; |
There was a problem hiding this comment.
const { input } = ctx; leaves input as Record<string, unknown>. Accessing properties like input.phone in a condition (if (input.phone)) uses an unknown value as a boolean, which fails under strict TypeScript. Prefer narrowing first (e.g., const phone = input.phone; if (typeof phone === 'string' && phone.length > 0) ...).
| description: definition.description, | ||
| version: definition.version, | ||
| type: 'autolaunched', | ||
| version: typeof definition.version === 'string' ? parseInt(definition.version, 10) || 1 : (definition.version ?? 1), | ||
| nodes, |
There was a problem hiding this comment.
legacyToFlow() uses parseInt(definition.version, 10) || 1. Using || will coerce valid numeric values like 0 to the fallback 1, and it also silently treats non-numeric strings the same way. Prefer parsing to a number and falling back only on NaN/null/undefined (e.g., use a Number.isNaN check and ??) so version conversion is deterministic.
| description: flow.description, | ||
| type: options?.type || 'sequential', | ||
| version: flow.version || '1.0.0', | ||
| version: String(flow.version || '1.0.0'), |
There was a problem hiding this comment.
In flowToLegacy(), version: String(flow.version || '1.0.0') mixes a numeric Flow.version with a semver-looking string fallback, and || will also treat 0 as missing. Use nullish coalescing and a single version representation (either always semver-like strings for legacy, or always numeric-to-string without '1.0.0'), so downstream code that keys by definition.version remains consistent.
| version: String(flow.version || '1.0.0'), | |
| version: String(flow.version ?? 1), |
Upgrades all
@objectstack/*packages to v2.0.0 across the monorepo and fixes breaking API changes.Version bumps
@objectstack/{cli,runtime,spec,client,objectql,driver-memory,plugin-hono-server}→ 2.0.0workspace:*refs to fixed2.0.0versionsBreaking changes addressed
@objectstack/spec/automation— FlowNode renamedname→label, Flowversionchanged fromstringtonumber, Flow now requirestypeandlabelfields:@objectstack/spec/data— Hookhandlertype tightened to(...args: unknown[]) => unknown,HookContext.inputnarrowed fromRecord<string, any>toRecord<string, unknown>:@objectstack/spec/ui—App.branding.secondaryColorremoved from schemapackages/permissions— Local types were out of sync with engine usage; aligned them:ObjectPermissionsinterface (profile-level:allowCreate/Read/Edit/Delete/viewFilters)objectName,profilestoPermissionSetprofiles: string[]toPermissionContextvisibleTo,editableBytoFieldPermissionobjectNamein storage operations💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.