Skip to content

Latest commit

 

History

History
77 lines (75 loc) · 11.3 KB

File metadata and controls

77 lines (75 loc) · 11.3 KB

AGENTS

Notes:

  • Use React Native elements only; do not replace them with DOM elements in specs or dummy app code.
  • Prefer React Native components for all new code, including spec/dummy pages.
  • Do not edit build/ outputs manually; regenerate with the appropriate build command instead.
  • Do not force-add ignored build/ outputs to git; keep PRs focused on source changes and let release/build workflows regenerate package artifacts.
  • When a debugging or implementation session reveals a reusable lesson, document it before finishing in this repo's README/docs, relevant skills, and the applicable AGENTS.md files.
  • Only run builds when releasing a new package; development runs against source files.
  • When using gh pr create/edit, pass multi-line bodies with real newlines (not literal \n) so GitHub renders them correctly.
  • Before committing, review the current diff and propose commit message(s) grouped by logical change sets.
  • Prefer describe over RSpec.describe in specs.
  • Prefer expect(...).to receive(...) over allow(...) in specs whenever the call is part of the behavior under test; reserve allow for background setup where call verification is intentionally irrelevant.
  • Do not add # frozen_string_literal: true to files.
  • Before adding RuboCop disable directives, check the existing repo RuboCop config first and prefer code that passes under that config without new disables; avoid review-only style churn.
  • Prefer multiple small, individually working commits when possible.
  • If a RuboCop config exists for the current Ruby project, run RuboCop on changed Ruby files before pushing or opening a PR.
  • Always run ESLint on changed or new JavaScript files.
  • Add concise comments for non-obvious groups of code so the intent and invariants are clear without reverse-engineering the flow.
  • ESLint sort-imports orders import lines by member syntax group (none/all/multiple/single) and then the first local specifier name, not by module specifier; adjust import order accordingly.
  • When creating PRs, choose a sensible branch name and commit messages without prompting.
  • When you fix something in this repo, keep the change on a feature branch and make sure there is a matching PR for that branch before you consider the work complete.
  • For system specs, use ruby-gem/scripts/run-system-spec.sh [spec/path.rb:line] (wraps the README system spec command).
  • For Firefox system specs in this repo, prefer the headless Firefox path (SELENIUM_DRIVER=firefox ruby-gem/scripts/run-system-spec.sh ...) and do not wrap that path in xvfb-run; Chrome still uses the xvfb-backed path.
  • Do not add Capybara.reset_sessions! in before(:each) hooks here. Capybara RSpec already resets sessions after each example, and duplicate pre-example resets add major Firefox overhead.
  • When installing gems, run bundle install in both ruby-gem/ and ruby-gem/spec/dummy/ before running specs.
  • If ruby-gem/scripts/run-system-spec.sh fails, run the README system spec command manually from ruby-gem/.
  • In ApiMaker::ModelContentGeneratorService, handle Ransack allowlist runtime errors ("Ransack needs ...") for associations/attributes/scopes by returning [] so frontend model generation does not crash on third-party models.
  • Do not “fix” flaky specs by only increasing waits/timeouts. First determine whether behavior regressed (for example, element never rendered) and collect/inspect CI artifacts before adjusting timing.
  • When waiting for a large incrementally rendered element count in system specs, wait for the final expected element with a single-result selector, then assert one browser-side querySelectorAll(...).length scalar; repeatedly transferring, serializing, or polling large node collections can starve browser rendering.
  • Avoid unnecessary defensive conditions for guaranteed contracts. Prefer failing fast over silently accepting impossible states.
  • In ApiMaker table workplace helpers and commands, current_user may legitimately be nil for websocket/content-parser requests; return nil/empty results for current-workplace lookups instead of dereferencing the user.
  • Before adding fallback logic for hook/context timing, inspect the provider source first; do not assume first-render hydration gaps without source confirmation.
  • Cache JSX object-literal props such as dataSet and pressableProps with typed module-level cache maps (dataSets.name ||= {...}) instead of recreating objects in render.
  • Keep testID values unique within a rendered screen/component so selectors stay unambiguous.
  • In Selenium/spec helpers, do not assume a testID selector points at the editable control itself; React Native Web may put the testID on a wrapper, so descend to the real input/textarea/checkbox element before typing or clearing.
  • In JavaScript class method definitions, use methodName(args) (no space before parentheses).
  • Keep single-tag JSDoc blocks on one line (for example /** @returns {boolean} */).
  • When tightening JSDoc types, do not mechanically replace any with unknown; prefer the real runtime contract, and only keep broad types when the value is genuinely opaque after inspection.
  • In ShapeHook classes, keep setup() as the first instance method.
  • Keep component props ordered alphabetically.
  • To typecheck a single file, run npm run typecheck:file --file=src/path/to/file.js from npm-api-maker/ (you can also pass npm-api-maker/src/... or set FILE=src/path/to/file.js).
  • Do not "fix" render/update bugs by replacing useMemo() with useEffect() as a blanket change; preserve hook semantics and debug the underlying state flow first.
  • In npm-api-maker, keep the checked-in .npmrc with legacy-peer-deps=true while the package targets ESLint 10 and eslint-plugin-react has not yet published an ESLint 10 peer range; remove that workaround only after the upstream peer support lands.
  • In npm-api-maker, keep peer-facing runtime imports that are needed by linked local/CI builds, lint, or tests (for example react-native-vector-icons, flash-notifications, history, and i18n-on-steroids) installed in devDependencies as well when tooling resolves modules from the package directory itself.
  • When regenerating ruby-gem/spec/dummy/yarn.lock, keep the linked npm-api-maker package in place and verify that every linked runtime dependency selector has a lock entry; Yarn can retain the linked package metadata while dropping its dependency graph if the lock is generated from an incomplete workspace.
  • In npm-api-maker source-map handling, normalize stacktrace-parser trace.file values before URL parsing or source-map lookup; Firefox/webpack async frames can arrive as webpackAsyncContext@http://.../packs/js/react.js, and using that raw string produces broken .map requests.
  • In npm-api-maker published build/ code, import.meta.webpackContext(...) is safe to use as long as the call is invoked directly; webpack replaces the whole call with its context module at consumer build time. Do NOT reference bare import.meta in any other form (e.g. assigning (import.meta) to a local for a runtime guard) — raw import.meta survives into classic-script lazy chunks and throws Cannot use 'import.meta' outside a module at runtime.
  • In on-location-changed, WithLocationPath initializes queryParams synchronously from globalThis.location.search via useState(params()); useQueryParams() being undefined indicates a missing/explicitly-undefined provider, not a normal first-render hydration phase.

API Maker Usage in Consuming Projects

  • For Peakflow/API Maker-style frontend-model backends, keep resource metadata and authorization abilities co-located in one resource class tree; do not split them into parallel resources and authorization/resources directories.
  • Prefer ApiMaker commands in app/api_maker/commands for new app actions instead of adding custom Rails controllers when ApiMaker can support the flow.
  • In Rails apps using ApiMaker, prefer ApiMaker model/model-class websocket events over custom ActionCable channels when possible; add a custom channel only when ApiMaker events cannot represent the required stream.
  • In ApiMaker realtime UIs, use model-level update subscriptions when the UI needs updated model attributes; model-class events carry event names/args, not serialized updated models.
  • For realtime UI backed by ApiMaker events, do one initial fetch and then rely on websocket/model events; do not add browser polling unless there is a documented hard requirement that events cannot satisfy.
  • Use the Layout header prop for screen titles; avoid custom per-screen headers unless explicitly requested.
  • Use Text from @kaspernj/api-maker/build/utils/text for default styles.
  • Prefer useBreakpoint() (responsive-breakpoints via Api Maker dependencies) over useWindowDimensions() for responsive logic.
  • When using API Maker Link on web (renders as an <a>), center content with an inner View instead of relying on flex alignment on the anchor itself.
  • Import Formmeld directly with import {Form, FormInputs, useForm} from "formmeld"; API Maker no longer exports these APIs. Keep inputs uncontrolled to avoid state-driven re-renders.
  • Reusable inputs that can render outside Form must use Formmeld's useOptionalFieldRegistration; one logical field owns one registration, while duplicate names synchronize through Formmeld.
  • Give controls explicit Formmeld apply adapters: DOM/RN text normalizes null to "" and other values to strings, checkboxes normalize to booleans, and composite controls update every visible/canonical ref from one adapter.
  • When multiple screens repeat the same label + input form markup, extract a shared form input component (for example a screen-specific base text input) instead of duplicating blocks.
  • Use Formmeld Form and formObjectRef to track uncontrolled input values instead of manual instance fields.
  • In ShapeComponents using Formmeld Form, pass both formObjectRef and setForm, then read values via this.formObjectRef.current || this.form to avoid mount-timing races.
  • Use Api Maker Icon for icons instead of raw <i> tags or FontAwesome class names on Text.
  • In app code, prefer importing frontend models from individual files (for example models/project.js) instead of aggregating through models.
  • In app code, avoid import {...} from "models"; import each frontend model from its dedicated model file path.
  • Prefer link-based navigation (Link with to) for navigation-only actions so users can open routes in new tabs/windows; use AppHistory.push/Params.changeParams only when imperative navigation is required by side effects or control flow.
  • For Api Maker Link on web (anchor rendering), use mouse events (onMouseEnter/onMouseLeave) for hover behavior instead of onHoverIn/onHoverOut.
  • For Link rows that render text, keep visual text styles (for example color and underline decoration) on the inner Text element rather than the Link wrapper.
  • Use useQueryParams when building filterable routes in React UI.
  • Layout controls props must be callbacks; do not pass React nodes directly.
  • In ShapeComponent routes, pass controls={this.tt.controls} and assign route-local instance fields directly.
  • Prefer passing navbarControls as a callback and let Layout resolve it, rather than pre-rendering.
  • When layout controls depend on a model, pass cacheKey (like model?.id()) to force re-renders.