Skip to content

Releases: lowdefy/lowdefy

v4.7.1

19 Mar 09:51
ae04ae1

Choose a tag to compare

Highlights

  • Dev server: Icons referenced in page blocks are now dynamically discovered and served without requiring a rebuild or server restart.

  • Date picker e2e testing: All date picker blocks now support do.select() for calendar interaction and do.fill() for typing dates directly. DateTimeSelector also supports time selection.

  • Operators: Fixed _function callback mutation in evaluateOperators that was causing _build.array.map and similar operators to produce duplicate results on repeated invocations.

  • E2E testing: Environment variable LOWDEFY_E2E_SECRET_* can now override LOWDEFY_SECRET_* values, allowing test infrastructure (e.g., MongoMemoryServer) to coexist with secret managers.

  • E2E navigation: Page navigation now waits for domcontentloaded instead of the full load event, preventing hangs on pages with WebSocket connections or slow resources.

  • E2E utils: Renamed MDB_E2E_URI to LOWDEFY_E2E_MONGODB_URI in scaffold templates. Init script no longer auto-installs dependencies — they're added to package.json and the user is prompted to install.

  • Build performance: Sibling refs are now resolved in parallel to interleave CPU and I/O operations.

Fixes & Improvements

  • fix(build): Dev server dynamically loads icons discovered during JIT page builds. (@lowdefy/build, @lowdefy/server-dev)

    Icons referenced only inside page blocks (e.g., icon: FiAperture on a Button) were not available in the dev server's static bundle, causing a fallback icon to render. The JIT page builder now detects missing icons when a page is compiled, extracts their SVG data from react-icons, and serves it via a dynamic API endpoint. The client fetches and merges these icons at runtime without triggering a Next.js rebuild or server restart.

  • Resolve sibling refs in parallel using Promise.all to interleave CPU and I/O during build. (@lowdefy/build)

  • feat(blocks-antd): Add do.select() and do.fill() to date picker e2e helpers. (@lowdefy/blocks-antd)

    All five date picker e2e helpers (DateSelector, DateTimeSelector,
    DateRangeSelector, MonthSelector, WeekSelector) now support
    do.select() for calendar UI interaction and do.fill() for
    typing dates directly. DateTimeSelector also supports time
    selection via the time panel.

  • Fix _function callback template being mutated in-place by evaluateOperators, causing _build.array.map and similar operators to produce duplicate results from repeated callback invocations. (@lowdefy/operators-js)

  • feat(server-e2e): Add LOWDEFYE2E_SECRET* override support. (@lowdefy/server-e2e)

    Secrets can now be overridden in e2e tests using LOWDEFY_E2E_SECRET_* environment variables. These take precedence over LOWDEFY_SECRET_* values, allowing test infrastructure (e.g. MongoMemoryServer) to coexist with secret managers injected via commandPrefix.

  • fix(e2e-utils): Use domcontentloaded for page navigation. (@lowdefy/e2e-utils)

    Page navigation now uses waitUntil: 'domcontentloaded' instead of the default load event. This prevents hangs on pages with WebSocket connections or slow-loading resources, since the Lowdefy client readiness check is already a stronger signal.

  • refactor(e2e-utils): Update scaffold env vars and simplify init. (@lowdefy/e2e-utils)

    Renamed MDB_E2E_URI to LOWDEFY_E2E_MONGODB_URI in scaffold templates to align with the new LOWDEFY_E2E_SECRET_* override pattern. The init script no longer runs install automatically — dependencies are added to package.json and the user is prompted to install.

v4.7.0

11 Mar 13:50
a8c31fd

Choose a tag to compare

Highlights

  • Build Performance: Single-pass async walker replaces multi-pass JSON serialization for ref resolution, eliminating 5+ serializer.copy calls per ref
  • Build Errors: Collect and report all ref errors at once instead of stopping on the first failure — faster fix-rebuild cycles when multiple config files have issues
  • Inline Pages: Fixed inline page content being stripped during JIT builds with no recovery path
  • Template Errors: YAML errors in .yaml.njk templates now show "Nunjucks template produced invalid YAML" instead of misleading line numbers
  • CLI: Build now properly exits with process.exit(1) on errors instead of hanging with a spinner
  • CLI Start: Fixed port availability check when no --port flag is passed (now defaults to port 3000)
  • Build Logs: Removed spurious print: warn fields from build logger output
  • E2E Testing: New ldf.api() assertions for API endpoint testing — expect.toFinish(), expect.toHaveResponse(), expect.toHavePayload(), response(), state()
  • E2E Developer Experience: New scaffold scripts (e2e:headed, e2e:server), SLOW_MO env var support, and fixed template defaults (appDir, health check, fixtures)
  • E2E Block IDs: Dotted block IDs (e.g., form.field.name) now work correctly in CSS selectors with new escapeId() utility
  • Helpers: Fixed makeReplacer mutating object marker enumerability, preventing internal markers from leaking to plugin components

What's New

feat: Single-pass async walker for ref resolution

Packages: @lowdefy/build, @lowdefy/operators, @lowdefy/helpers

Single-Pass Walker (@lowdefy/build)

  • New walker module replaces the multi-pass JSON round-trip architecture in buildRefs with a single async tree walk
  • Resolves _ref markers, evaluates _build.* operators, and tags ~r provenance in one pass instead of 5+ serializer.copy calls per ref
  • Wired into both buildRefs (production) and buildPageJit (dev server)
  • Added isPageContentPath for semantic shallow build matching, replacing brittle path-index checks
  • Deleted redundant code replaced by walker: getRefsFromFile, populateRefs, createRefReviver, and the evaluateStaticOperators wrapper

In-Place Operator Evaluation (@lowdefy/operators)

  • New evaluateOperators function walks a tree in-place and evaluates operator nodes, avoiding JSON serialization round-trips
  • Used by the walker module to evaluate _build.* operators inline during ref resolution

Serializer Fix (@lowdefy/helpers)

  • Added skipMarkers option to serializer.serializeToString to exclude internal markers (~k, ~r, ~l, ~arr) from serialized output

feat(e2e-utils): Add ldf.api() assertions for API endpoint testing

Packages: @lowdefy/e2e-utils

  • New api.js core module with getApiState, getApiResponse, expectApi functions
  • Reads from window.lowdefy.apiResponses[endpointId][0] (mirrors request pattern)
  • ldf.api(endpointId).expect.toFinish() — wait for API call completion
  • ldf.api(endpointId).expect.toHaveResponse(response) — assert response
  • ldf.api(endpointId).expect.toHavePayload(payload) — assert sent payload
  • ldf.api(endpointId).response() — get raw response value
  • ldf.api(endpointId).state() — get full API state object
  • ldf.mock.api() now captures payloads for assertion
  • ldf.mock.getCapturedApi(endpointId) — retrieve captured API data

Fixes & Improvements

  • fix(build): Report all ref errors at once instead of stopping on the first one. (@lowdefy/build)

    When multiple referenced files have errors (missing files, YAML parse errors, invalid refs), the build now collects and reports all errors at once instead of stopping on the first failure. This reduces the fix-rebuild-fix cycle when multiple config files have issues.

  • fix(build): Preserve inline page content in JIT builds (@lowdefy/build, lowdefy, @lowdefy/docs)

    Pages declared inline in lowdefy.yaml (not via _ref) had their content stripped during shallow builds with no way to recover at JIT time, resulting in empty page shells. Detect inline pages by checking refId matches root ref with no sourceRef, and skip stripping. Set refId to null for inline pages in createPageRegistry so buildPageJit reads the pre-built artifact instead of attempting JIT resolution.

  • fix(build): Improve error message for YAML errors in njk templates (@lowdefy/build)

    When a .yaml.njk nunjucks template produces invalid YAML, the error now says "Nunjucks template produced invalid YAML" instead of showing a misleading line number from the generated output.

  • fix(cli): Exit process and stop spinner on build errors. (lowdefy)

    The CLI error handler logged errors but never called process.exit(1), so the process continued running with a spinning indicator after a build failure. Added process.exit(1) to runCommand after error handling, and added { spin: 'fail' } to stop the spinner in runLowdefyBuild, runNextBuild, and installServer catch blocks.

  • fix(cli): Fix port availability check for start command (lowdefy, @lowdefy/server-dev)

    The CLI's checkPortAvailable was called with undefined port when no --port flag was passed, causing net.listen(undefined) to bind a random port instead of checking port 3000. Added default port: 3000 in getOptions. Removed redundant checkPortAvailable from server-dev manager since the CLI now catches port conflicts before the server starts.

  • fix(e2e-utils): Escape dotted block IDs in e2e CSS selectors. (@lowdefy/blocks-antd, @lowdefy/blocks-basic, @lowdefy/e2e-utils)

    Block IDs containing dots (e.g., form.field.name) now work correctly in e2e test locators. Added escapeId() utility to @lowdefy/e2e-utils that escapes CSS special characters, and updated all block e2e helpers and test specs to use it.

  • fix(server): Remove unused print mixin from build logger (@lowdefy/server)

    Removed the pino mixin that added a print field to every build log entry. This field was a leftover from a previous CLI display system and caused spurious print: warn lines in build output.

  • feat(e2e-utils): Improved e2e scaffold with new scripts and SLOW_MO support. (@lowdefy/e2e-utils)

    New scaffold scripts:

    • e2e:headed — Run tests with a visible browser in slow motion (SLOW_MO=500, --workers=1)
    • e2e:server — Start the e2e server once, then rerun tests without rebuilding

    SLOW_MO env var:

    • createConfig now reads the SLOW_MO environment variable and passes it to Playwright's launchOptions.slowMo
    • No manual config extension needed — just set SLOW_MO=500 in your npm script

    Scaffold template fixes:

    • Fixed appDir from '../' to './'path.resolve resolves relative to cwd, not the config file
    • Fixed fixtures.js template to use mdbFixtures (plural) from /fixtures subpath with mergeTests
    • Simplified example.spec.js to use /api/auth/session health check — works on auth-protected apps
    • Fixed README template with correct appDir values, "Faster Test Runs" section, and "Common Patterns" section
  • fix(helpers): Prevent makeReplacer from mutating original object marker enumerability. (@lowdefy/helpers)

    makeReplacer used Object.defineProperty to make ~k, ~r, ~l enumerable for JSON.stringify, but operated on the original object reference instead of a copy. This permanently mutated the original, causing internal markers to leak to plugin components via Object.entries/Object.keys.

v4.6.0

09 Mar 14:01

Choose a tag to compare

Highlights

Looking at the release notes file and the changelog entries you've provided, here are the developer-friendly bullet points organized by theme:

Error Handling & Debugging

  • Config-aware error tracing shows exact YAML file:line locations with clickable VSCode links in terminal and browser
  • Unified error system in @lowdefy/errors package with standardized TC39 constructor signatures (new MyError(message, { cause, ...options }))
  • Build-time validation provides "Did you mean?" suggestions for typos and catches NEXTAUTH_SECRET configuration issues
  • Plugin errors simplified — operators, actions, and connections throw plain messages; interface layer adds context (received value, location)
  • Sentry integration (zero-config: just set SENTRY_DSN) captures errors on client and server with Lowdefy context (pageId, blockId, config location)
  • New UserError class for expected user-facing errors (validation, intentional throws) — logs to browser console only, never to server terminal

Build & Performance

  • JIT page building for dev server — pages build on-demand when requested instead of all at once, speeding up development
  • Shallow _ref resolution leaves on-demand markers for faster initial builds with file dependency tracking for targeted rebuilds
  • New ~ignoreBuildChecks property suppresses specific build validation errors/warnings, with cascade support to suppress entire page subtrees
  • Build now collects all errors before stopping instead of failing on first error, showing developers all issues at once
  • Schema validation errors stop the build immediately to prevent cascading failures

Developer Experience

  • New @lowdefy/logger package with environment-specific variants (Node, CLI, browser) and standardized logging interface
  • Dev server now accepts LOWDEFY_DEV_USER env var or auth.dev.mockUser config for mock user support in e2e testing
  • Port-in-use check displays clear error message before starting server
  • Build-time validation no longer warns about _state references set by SetState actions

Testing

  • New @lowdefy/e2e-utils package for Playwright e2e testing with locator-first API (ldf.block('id').do.*), request mocking, and state assertions
  • Comprehensive e2e tests for blocks-antd (~700 tests covering 63 blocks) and blocks-basic (~40 tests)
  • npx @lowdefy/e2e-utils scaffold command sets up e2e testing in your project

Bug Fixes

  • Fixed env vars not being passed to Next.js build subprocess (NEXT_TELEMETRY_DISABLED was being ignored)
  • Array line number metadata (~l) now preserved through serializer.copy() — schema validation errors show correct line numbers
  • Error cause chains properly preserved across plugin boundaries and CLI
  • Input block onChange events now pass the input value

What's New

feat: Config-aware error tracing and Sentry integration

Packages: @lowdefy/api, @lowdefy/build, lowdefy, @lowdefy/client, @lowdefy/engine, @lowdefy/operators, @lowdefy/actions-core, @lowdefy/blocks-basic, @lowdefy/connection-axios-http, @lowdefy/connection-knex, @lowdefy/connection-redis, @lowdefy/connection-sendgrid, @lowdefy/operators-change-case, @lowdefy/operators-diff, @lowdefy/operators-js, @lowdefy/operators-jsonata, @lowdefy/operators-moment, @lowdefy/operators-mql, @lowdefy/operators-nunjucks, @lowdefy/operators-uuid, @lowdefy/operators-yaml, @lowdefy/server, @lowdefy/server, @lowdefy/server-dev, @lowdefy/server-dev, @lowdefy/block-utils, @lowdefy/errors, @lowdefy/helpers, @lowdefy/node-utils

Config-Aware Error Tracing (#1940)

  • Errors now trace back to exact YAML config locations with file:line
  • Clickable VSCode links in terminal and browser
  • Build-time validation catches typos with "Did you mean?" suggestions
  • Service vs Config error classification

Plugin Error Refactoring

  • Operators throw simple error messages without formatting
  • Parsers (WebParser, ServerParser, BuildParser) format errors with received value and location
  • Removed redundant "Operator Error:" prefix from error messages
  • Consistent error format: "{message} Received: {params} at {location}."
  • Actions and connections also simplified: removed inline received from error messages (interface layer adds it)
  • Connection plugins (axios-http, knex, redis, sendgrid) no longer expose raw response data in errors

Error Class Hierarchy

  • Unified error system in @lowdefy/errors with all error classes
    • @lowdefy/errors/build - Build-time classes with sync location resolution
  • Error classes: LowdefyError, ConfigError, ConfigWarning, PluginError, ServiceError
  • ConfigWarning supports prodError flag to throw in production builds
  • ServiceError.isServiceError() detects network/timeout/5xx errors
  • ~ignoreBuildChecks cascades through descendants to suppress warnings/errors

Build Error Collection

  • Errors collected in context.errors[] instead of throwing immediately
  • tryBuildStep() wrapper catches and collects errors from build steps
  • All errors logged together before summary message for proper ordering

Sentry Integration (#1945)

  • Zero-config Sentry support - just set SENTRY_DSN
  • Client and server error capture with Lowdefy context (pageId, blockId, config location)
  • Configurable sampling rates, session replay, user feedback
  • Graceful no-op when DSN not set

feat(server-dev): Add mock user support for e2e testing

Packages: @lowdefy/api, @lowdefy/build, @lowdefy/server-dev

Set LOWDEFY_DEV_USER env var or auth.dev.mockUser in config to bypass login in dev server.

Collect all build errors before stopping

Packages: @lowdefy/build, @lowdefy/build, @lowdefy/helpers

feat: JIT page building for dev server

Packages: @lowdefy/build, @lowdefy/operators-js, @lowdefy/server, @lowdefy/server-dev

Shallow Refs and JIT Build (@lowdefy/build)

  • Shallow _ref resolution stops at configured JSON paths, leaving ~shallow markers for on-demand resolution
  • shallowBuild produces a page registry with dependency tracking instead of fully built pages
  • buildPageJit fully resolves a single page on demand using the shallow build output
  • File dependency map tracks which config files affect which pages for targeted rebuilds
  • Build package reorganized: jit/ folder for dev-server-only files, full/ folder for production-only files

JIT Page Building (@lowdefy/server-dev)

  • Pages are built on-demand when requested instead of all at once during initial build
  • Page cache with file-watcher invalidation for fast rebuilds
  • /api/page/[pageId] endpoint triggers JIT build if page not cached
  • /api/js/[env] endpoint serves operator JS maps
  • Build error page component displays errors inline in the browser

Operator JS Hash Check (@lowdefy/operators-js)

  • Added hash validation for jsMap to detect stale operator definitions

Add build-time validation for NEXTAUTH_SECRET environment variable when auth providers are configured

Packages: @lowdefy/build

feat(build): Add ~ignoreBuildChecks property to suppress build validation

Packages: @lowdefy/build, @lowdefy/docs

Build Validation Suppression (#1949, #1963)

  • New ~ignoreBuildChecks property suppresses build-time validation errors and warnings
  • Supports true (suppress all) or array of specific check slugs (e.g., ['state-refs', 'types'])
  • Cascades to all descendant config objects - set on a page to suppress for all child blocks
  • Silent suppression - no log output when validation is skipped (visible with --log-level debug)

Renamed: Previously ~ignoreBuildCheck (singular) - using the old name throws a helpful migration error.

Available Check Slugs:

  • state-refs, payload-refs, step-refs - Reference validation warnings
  • link-refs, request-refs, connection-refs - Action reference validation
  • types - All type validation (blocks, operators, actions, etc.)
  • schema - JSON schema validation errors

Use Cases:

  • Dynamic state references created at runtime by custom blocks
  • Multi-app monorepos with conditional configurations
  • Work-in-progress features during development
  • Plugin development with custom types not yet registered

Example:

# Suppress all checks for this page and descendants
pages:
  - id: dynamic-page
    type: Box
    ~ignoreBuildChecks: true
    blocks:
      - id: block1
        type: TextInput
        properties:
          value:
            _state: dynamicField # No warning

# Suppress only specific checks
blocks:
  - id: custom_block
    type: CustomBlock
    ~ignoreBuildChecks:
      - state-refs
      - types
    properties:
      onClick:
        _state: dynamicState # No warning (state-refs suppressed)

Add e2e testing package for Lowdefy apps

Packages: lowdefy, @lowdefy/client, @lowdefy/blocks-antd, @lowdefy/block-dev-e2e, @lowdefy/e2e-utils

@lowdefy/e2e-utils (new package)

  • Locator-first API via ldf Playwright fixture: ldf.block('id').do.*, ldf.block('id').expect.*
  • Request mocking with static YAML files (mocks.yaml) and inline per-test overrides
  • Request assertion API: ldf.request('id').expect.toFinish(), .toHaveResponse(), .toHavePayload()
  • State and URL assertions: ldf.state('key').expect.toBe(), ldf.url().expect.toBe()
  • Manifest generation from build artifacts for block type resolution and helper loading
  • createConfig() and createMultiAppConfig() for Playwright config with automatic build/server management
  • Scaffold command (`npx @lowdefy/e...
Read more

v4.5.2

10 Nov 14:51
ed504dd

Choose a tag to compare

Patch Changes

  • d573e8f: Add guard to prevent TypeError in icon formatTitle.

v4.5.1

03 Nov 10:05
3295fd1

Choose a tag to compare

Patch Changes

  • 51f7f9d: Use uuid instead of crypto.randomUUID(), update uuid to v13.

v4.5.0

20 Oct 08:24
e1c4936

Choose a tag to compare

Minor Changes

  • 16084c1: Adds Lowdefy APIs. Lowdefy APIs allow you to create custom server-side API endpoints within your Lowdefy application. See https://docs.lowdefy.com/lowdefy-api for more info.
  • abc90f3: Change to Apache 2.0 license for all packages. All license checks and restrictions have been removed.
  • 09ae496: Add JSONata operator.
  • d6c58fe: Add minItems property to ControlledList block.
  • b3a2e66: Add afterOpenChange and afterClose events to Drawer block.
  • d9512d9: Refactor build to create individual block instances.
  • d9512d9: Add hybrid block type to extend block functionality.
  • 4f610de: Allow custom icon titles and format the icon name if a title is not specified.

Patch Changes

  • fe3676c: Add missing events to S3Upload block schemas.

v4.4.0

06 Dec 15:23
1ecedb5

Choose a tag to compare

Minor Changes

  • bcfbb1a: Add autoClearSearchValue property to MultipleSelector block.
  • 156fa7f: Add urlQuery filter to the nunjucks operator.
  • 1a81e10: Update echarts dependecy to 5.5.1

Patch Changes

  • a491106: Fix spawnProcess options on Windows

v4.3.0

31 Jul 15:05
0c39a17

Choose a tag to compare

Minor Changes

  • fe1347f: Init VSCode extension with syntax highlighting for yaml.

Patch Changes

  • fe1347f: VSCode extension to read activeAppRoot from local dev server for clickable _ref links.

v4.2.2

17 Jul 06:44
aa1bfa0

Choose a tag to compare

Patch Changes

  • e4ec435: Fix undefined property access in PhoneNumberInput component
  • 50af1e8: Add MongoDbBulkWrite to MongoDBCollection requests.

v4.2.1

04 Jul 15:06
cc8e2ca

Choose a tag to compare

Minor Changes

  • 143c83e: Add request type MongoDBBulkWrite to the MongoDB connection.
  • 95663d1: Add unique filter to _nunjucks operator.

Patch Changes

  • 47d8559: Move layoutParamsToArea into Area component.
  • 47d8559: Remove highlightBorders from layout.