mirror of
https://github.com/actualbudget/actual.git
synced 2026-05-07 04:18:51 -05:00
* [AI] Fix type errors for API consumers by shipping .d.ts declarations from loot-core Downstream consumers of @actual-app/api with strict: true get type errors because @actual-app/core exports raw .ts source files. Consumers' tsc follows the import chain into core's source (compiled with strict: false), and skipLibCheck doesn't help since it only skips .d.ts files. Add "types" conditions to all imports/exports entries in loot-core's package.json, pointing to the pre-built declarations in lib-dist/decl/. Add .npmignore to include lib-dist/decl/ in the published package. Fixes #7410 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * [AI] Use prepack/postpack scripts instead of inflating package.json Replace the inline "types" conditions in imports/exports with a prepack script that adds them at pack/publish time. This keeps the checked-in package.json clean while still shipping .d.ts declarations to npm consumers. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * [AI] Convert prepack/postpack scripts to TypeScript Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * [AI] Add release notes for #7468 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * [AI] Fix recursive ExportValue type and remove redundant comment Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * [AI] Rename scripts to .mts and inline types conditions Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * [AI] Make backup/restore scripts safer - Check if backup exists before creating it in prepack - Make restore idempotent by checking if backup exists in postpack - Prevents overwriting existing backups from interrupted runs - Addresses CodeRabbit review feedback Co-authored-by: Matiss Janis Aboltins <MatissJanis@users.noreply.github.com> * [AI] Type api-handlers.ts fields to drop implicit any The `fields` / export-args slots in the ApiHandlers contract were untyped, surfacing as TS7008 errors in strict consumers. Replace them with the `Partial<APIXxxEntity>` shapes the `@actual-app/api` wrappers already pass, and annotate the matching call sites in `api.ts` with `@ts-expect-error` where the legacy helpers still declare full-entity parameters despite accepting partial updates at runtime. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * [AI] Replace vite-plugin-dts with tsgo for api types Drops vite-plugin-dts in favor of running tsgo --emitDeclarationOnly after the vite bundle, eliminating a heavy dev dependency tree (api-extractor, volar, vue language-core) from the api package build. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * [AI] Add build script to loot-core to emit declarations via lage `yarn build:cli` failed in CI with TS6305 because api's `tsgo --emitDeclarationOnly` depends on loot-core's pre-built `lib-dist/decl/*.d.ts`, but loot-core had no `build` script, so lage's `^build` cascade silently skipped it. Add `"build": "tsgo -b"` so loot-core slots into the dependency chain; its tsconfig already has `emitDeclarationOnly: true`, so the output is declarations only. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Simplify API build * [AI] Document TypeScript moduleResolution requirement for @actual-app/api The published declarations rely on package.json exports conditions, which classic node / node10 resolvers don't honor. Document the supported modes (bundler / nodenext / node16) in the package README and in the Getting Started section of the API docs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * [AI] Type-guard default value in add-types-conditions prepack `value.default` is typed `ExportValue | undefined`, which allows nested conditional objects. The previous truthy check fell through to `shouldSkip(defaultValue)` and would crash on `.endsWith()` if that shape ever appeared. Replace with a `typeof === 'string'` narrowing and drop a now-redundant "Insert types as the first key" comment. No runtime change on current package.json — no nested `default` values exist today — but the script is not covered by loot-core's tsconfig include, so the latent type issue was silent. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * [AI] Allow "nodenext" in docs spellcheck expect list Referenced in the new TypeScript moduleResolution note in the API docs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * [AI] Move loot-core declarations to @types and whitelist publish with files Relocate loot-core's composite TypeScript output from lib-dist/decl to the top-level @types directory, matching the api package's convention. Replace the old .npmignore blacklist with an explicit package.json files whitelist. - tsconfig.json: outDir @types, exclude test/mock dirs from decl emission - scripts/add-types-conditions.mts: rewrite paths to ./@types/src/... - package.json: files whitelist shipping only src, @types, migrations, typings, default-db.sqlite; drop legacy typesVersions (docs now require moduleResolution bundler/nodenext/node16, so the classic-resolution fallback is unused) - .gitignore: ignore the new @types build artifact - lage.config.js: factor outputGlob into a shared BUILD_OUTPUT_GLOBS constant and add @types/** so lage caches loot-core's decl output - root tsconfig.json: tighten exclude from packages/api/@types to packages/*/@types to cover both api and loot-core - delete .npmignore entirely Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * [AI] Build loot-core declarations inside prepack yarn workspace @actual-app/core pack is the first non-setup step in the publish workflow, running before any build. Without a build chained into prepack the @types/ tree is empty at pack time, so the tarball shipped a transformed package.json pointing at ./@types/src/... paths that didn't exist. npm publish doesn't re-run hooks on a pre-packed tarball, so the frozen snapshot must be self-contained; prepack now runs yarn build first to populate @types/ before add-types-conditions rewrites the exports. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Matiss Janis Aboltins <MatissJanis@users.noreply.github.com>
116 lines
2.3 KiB
JavaScript
116 lines
2.3 KiB
JavaScript
class Query {
|
|
/** @type {import('@actual-app/core/shared/query').QueryState} */
|
|
state;
|
|
|
|
constructor(state) {
|
|
this.state = {
|
|
filterExpressions: state.filterExpressions || [],
|
|
selectExpressions: state.selectExpressions || [],
|
|
groupExpressions: state.groupExpressions || [],
|
|
orderExpressions: state.orderExpressions || [],
|
|
calculation: false,
|
|
rawMode: false,
|
|
withDead: false,
|
|
validateRefs: true,
|
|
limit: null,
|
|
offset: null,
|
|
...state,
|
|
};
|
|
}
|
|
|
|
filter(expr) {
|
|
return new Query({
|
|
...this.state,
|
|
filterExpressions: [...this.state.filterExpressions, expr],
|
|
});
|
|
}
|
|
|
|
unfilter(exprs) {
|
|
const exprSet = new Set(exprs);
|
|
return new Query({
|
|
...this.state,
|
|
filterExpressions: this.state.filterExpressions.filter(
|
|
expr => !exprSet.has(Object.keys(expr)[0]),
|
|
),
|
|
});
|
|
}
|
|
|
|
select(exprs = []) {
|
|
if (!Array.isArray(exprs)) {
|
|
exprs = [exprs];
|
|
}
|
|
|
|
const query = new Query({ ...this.state, selectExpressions: exprs });
|
|
query.state.calculation = false;
|
|
return query;
|
|
}
|
|
|
|
calculate(expr) {
|
|
const query = this.select({ result: expr });
|
|
query.state.calculation = true;
|
|
return query;
|
|
}
|
|
|
|
groupBy(exprs) {
|
|
if (!Array.isArray(exprs)) {
|
|
exprs = [exprs];
|
|
}
|
|
|
|
return new Query({
|
|
...this.state,
|
|
groupExpressions: [...this.state.groupExpressions, ...exprs],
|
|
});
|
|
}
|
|
|
|
orderBy(exprs) {
|
|
if (!Array.isArray(exprs)) {
|
|
exprs = [exprs];
|
|
}
|
|
|
|
return new Query({
|
|
...this.state,
|
|
orderExpressions: [...this.state.orderExpressions, ...exprs],
|
|
});
|
|
}
|
|
|
|
limit(num) {
|
|
return new Query({ ...this.state, limit: num });
|
|
}
|
|
|
|
offset(num) {
|
|
return new Query({ ...this.state, offset: num });
|
|
}
|
|
|
|
raw() {
|
|
return new Query({ ...this.state, rawMode: true });
|
|
}
|
|
|
|
withDead() {
|
|
return new Query({ ...this.state, withDead: true });
|
|
}
|
|
|
|
withoutValidatedRefs() {
|
|
return new Query({ ...this.state, validateRefs: false });
|
|
}
|
|
|
|
options(opts) {
|
|
return new Query({ ...this.state, tableOptions: opts });
|
|
}
|
|
|
|
serialize() {
|
|
return this.state;
|
|
}
|
|
|
|
reset() {
|
|
return q(this.state.table);
|
|
}
|
|
|
|
serializeAsString() {
|
|
return JSON.stringify(this.serialize());
|
|
}
|
|
}
|
|
|
|
export function q(table) {
|
|
return new Query({ table });
|
|
}
|