@astrale-os/sdk 0.6.0-beta.43 → 0.6.0-beta.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/README.md +6 -6
  2. package/dist/application/action/authoring.d.ts +1 -1
  3. package/dist/application/action/context.d.ts +9 -8
  4. package/dist/application/error/error.d.ts +7 -7
  5. package/dist/application/error/error.js +12 -12
  6. package/dist/application/error/index.d.ts +1 -1
  7. package/dist/application/error/index.js +1 -1
  8. package/dist/application/mutation/authoring/builder.d.ts +12 -12
  9. package/dist/application/mutation/authoring/builder.js +3 -3
  10. package/dist/application/mutation/authoring/guard.d.ts +2 -2
  11. package/dist/application/mutation/authoring/index.d.ts +1 -1
  12. package/dist/application/mutation/define.d.ts +8 -8
  13. package/dist/application/mutation/define.js +12 -12
  14. package/dist/application/mutation/execution/execute.d.ts +2 -2
  15. package/dist/application/mutation/execution/execute.js +10 -10
  16. package/dist/application/mutation/execution/executor.d.ts +2 -2
  17. package/dist/application/mutation/execution/executor.js +2 -2
  18. package/dist/application/mutation/index.d.ts +2 -2
  19. package/dist/application/mutation/legacy/v6/define.d.ts +1 -1
  20. package/dist/application/mutation/legacy/v6/mutation.d.ts +1 -1
  21. package/dist/application/mutation/mutation.d.ts +12 -12
  22. package/dist/application/query/composite/builder.js +1 -1
  23. package/dist/application/query/define.d.ts +1 -1
  24. package/dist/application/query/define.js +3 -3
  25. package/dist/application/query/defined/define.d.ts +45 -0
  26. package/dist/application/query/defined/define.js +96 -0
  27. package/dist/application/query/{recipe/recipe.d.ts → defined/query.d.ts} +21 -20
  28. package/dist/application/query/definition.d.ts +5 -5
  29. package/dist/application/query/definition.js +4 -4
  30. package/dist/application/query/execution/bounds.d.ts +5 -5
  31. package/dist/application/query/execution/bounds.js +2 -2
  32. package/dist/application/query/execution/client.d.ts +21 -0
  33. package/dist/application/query/execution/client.js +1 -0
  34. package/dist/application/query/execution/crossings.d.ts +3 -3
  35. package/dist/application/query/execution/crossings.js +23 -23
  36. package/dist/application/query/execution/error.d.ts +8 -8
  37. package/dist/application/query/execution/error.js +5 -5
  38. package/dist/application/query/execution/execute.d.ts +4 -4
  39. package/dist/application/query/execution/executor.d.ts +2 -2
  40. package/dist/application/query/execution/rows.d.ts +5 -5
  41. package/dist/application/query/execution/rows.js +42 -30
  42. package/dist/application/query/execution/{recipe.d.ts → run.d.ts} +21 -31
  43. package/dist/application/query/execution/{recipe.js → run.js} +49 -49
  44. package/dist/application/query/execution/split.d.ts +3 -3
  45. package/dist/application/query/execution/split.js +1 -1
  46. package/dist/application/query/handles/build.d.ts +1 -1
  47. package/dist/application/query/handles/domain.d.ts +1 -1
  48. package/dist/application/query/handles/handles.d.ts +14 -12
  49. package/dist/application/query/handles/plan.d.ts +10 -9
  50. package/dist/application/query/handles/plan.js +1 -1
  51. package/dist/application/query/handles/reads.js +4 -4
  52. package/dist/application/query/handles/rows.d.ts +1 -1
  53. package/dist/application/query/index.d.ts +9 -6
  54. package/dist/application/query/index.js +3 -3
  55. package/dist/application/query/language/index.d.ts +1 -1
  56. package/dist/application/query/language/query.d.ts +5 -5
  57. package/dist/application/query/legacy/v6/collection/union.d.ts +1 -1
  58. package/dist/application/query/legacy/v6/collection/union.js +3 -3
  59. package/dist/application/query/legacy/v6/define.d.ts +1 -1
  60. package/dist/application/query/legacy/v6/define.js +3 -3
  61. package/dist/application/query/legacy/v6/execution/execute.d.ts +6 -4
  62. package/dist/application/query/legacy/v6/index.d.ts +2 -1
  63. package/dist/application/query/legacy/v6/index.js +1 -1
  64. package/dist/application/query/query.d.ts +3 -3
  65. package/dist/application/routes/admission.d.ts +1 -1
  66. package/dist/application/routes/admission.js +2 -2
  67. package/dist/application/routes/index.d.ts +3 -2
  68. package/dist/application/routes/route.d.ts +1 -1
  69. package/dist/application/runtime/declarations.d.ts +6 -6
  70. package/dist/application/runtime/define.d.ts +5 -5
  71. package/dist/application/workflow/durable.d.ts +9 -9
  72. package/dist/execution/invocation/capabilities/bind.d.ts +1 -1
  73. package/dist/execution/invocation/capabilities/bind.js +8 -8
  74. package/dist/execution/invocation/dispatch/action.js +2 -2
  75. package/dist/execution/invocation/dispatch/workflow.js +2 -2
  76. package/dist/execution/invocation/result/index.d.ts +1 -1
  77. package/dist/execution/invocation/result/index.js +1 -1
  78. package/dist/execution/invocation/result/undeclared.d.ts +7 -0
  79. package/dist/execution/invocation/result/undeclared.js +18 -0
  80. package/dist/execution/workflows/failure.d.ts +7 -7
  81. package/dist/execution/workflows/failure.js +19 -18
  82. package/dist/execution/workflows/receiver.d.ts +1 -1
  83. package/dist/execution/workflows/run.js +2 -2
  84. package/dist/execution/workflows/steps.d.ts +1 -1
  85. package/dist/platform/schema/class-authoring.d.ts +2 -8
  86. package/dist/platform/schema/index.d.ts +1 -1
  87. package/dist/platform/schema/kernel-compiled.d.ts +1 -1
  88. package/dist/platform/schema/kernel-compiled.js +1 -1
  89. package/dist/platform/schema/kernel.d.ts +4 -2
  90. package/dist/testing/index.d.ts +2 -2
  91. package/dist/testing/index.js +1 -1
  92. package/dist/testing/{recipe.d.ts → query.d.ts} +5 -5
  93. package/dist/testing/{recipe.js → query.js} +9 -9
  94. package/dist/tooling/cli/orchestrate.js +7 -6
  95. package/dist/tooling/linter/adapters/typescript/{recipe-definitions.d.ts → definition-calls.d.ts} +10 -10
  96. package/dist/tooling/linter/adapters/typescript/{recipe-definitions.js → definition-calls.js} +10 -10
  97. package/dist/tooling/linter/adapters/typescript/index.d.ts +1 -1
  98. package/dist/tooling/linter/adapters/typescript/index.js +1 -1
  99. package/dist/tooling/linter/adapters/typescript/query-observation.js +6 -6
  100. package/dist/tooling/linter/implementations/source/definitions.d.ts +2 -0
  101. package/dist/tooling/linter/implementations/source/{recipes.js → definitions.js} +27 -27
  102. package/dist/tooling/linter/implementations/source/global.js +8 -6
  103. package/dist/tooling/linter/implementations/source/mutations.js +5 -5
  104. package/dist/tooling/linter/implementations/source/shared.d.ts +2 -2
  105. package/dist/tooling/linter/implementations/source/shared.js +7 -7
  106. package/dist/tooling/linter/implementations/source/verifiers.js +2 -2
  107. package/dist/tooling/linter/policy/generated.js +3 -3
  108. package/dist/tooling/linter/requirements/registry.js +4 -4
  109. package/docs/durable-workflows.md +8 -8
  110. package/docs/handler-dependencies.md +1 -1
  111. package/docs/legacy/query-v6.md +6 -6
  112. package/docs/queries.md +38 -38
  113. package/package.json +6 -6
  114. package/dist/application/query/recipe/define.d.ts +0 -44
  115. package/dist/application/query/recipe/define.js +0 -95
  116. package/dist/execution/invocation/result/recipe.d.ts +0 -6
  117. package/dist/execution/invocation/result/recipe.js +0 -17
  118. package/dist/tooling/linter/implementations/source/recipes.d.ts +0 -2
  119. /package/dist/application/query/{recipe/recipe.js → defined/query.js} +0 -0
@@ -17,6 +17,8 @@ export interface KernelDomain extends schema.DomainOf<CoreKernelSchema> {
17
17
  export interface KernelSchema extends DefinedSchema<CoreKernelSchema['origin'], KernelDomain> {
18
18
  }
19
19
  export declare const KernelSchema: KernelSchema;
20
- export declare const K: schema.ResolvedDomainOf<KernelSchema>;
21
- export type Kernel = typeof K;
20
+ /** The Kernel Domain, resolved: the SDK-owned name of `K`'s type. */
21
+ export interface Kernel extends schema.ResolvedDomainOf<KernelSchema> {
22
+ }
23
+ export declare const K: Kernel;
22
24
  export {};
@@ -12,5 +12,5 @@ export { isTests, tests } from './tests.js';
12
12
  export type { Tests, TestsInput } from './tests.js';
13
13
  export { createTestWorkflowEngine } from './durable/index.js';
14
14
  export type { TestExecution, TestJournalEntry, TestStartOptions, TestStepCapabilities, TestWorkflowEngine, TestWorkflowEngineOptions, } from './durable/index.js';
15
- export { checkRecipe } from './recipe.js';
16
- export type { CheckRecipeOptions } from './recipe.js';
15
+ export { checkQuery } from './query.js';
16
+ export type { CheckQueryOptions } from './query.js';
@@ -7,4 +7,4 @@ export { loadDataset, loadDatasets } from './load.js';
7
7
  export { dataset, isDatasetReference } from './reference.js';
8
8
  export { isTests, tests } from './tests.js';
9
9
  export { createTestWorkflowEngine } from './durable/index.js';
10
- export { checkRecipe } from './recipe.js';
10
+ export { checkQuery } from './query.js';
@@ -1,17 +1,17 @@
1
1
  import type { DomainDefinitionIdentity } from '../application/domain.js';
2
- import type { InputOf, Recipe } from '../application/query/recipe/recipe.js';
2
+ import type { InputOf, DefinedQuery } from '../application/query/defined/query.js';
3
3
  import type { schema } from '../platform/schema/index.js';
4
- export interface CheckRecipeOptions {
4
+ export interface CheckQueryOptions {
5
5
  /**
6
- * The Domain the recipe reads: its definition, whose requirements S12 checks a relation
6
+ * The Domain the Query reads: its definition, whose requirements S12 checks a relation
7
7
  * against, or its Schema alone, which holds no requirements, so S12 is not checked.
8
8
  */
9
9
  readonly domain: DomainDefinitionIdentity | schema.DomainSchema;
10
10
  }
11
11
  /**
12
- * Build a recipe for `sampleInput` and lower its first step, as a call would, without a Kernel:
12
+ * Build a Query for `sampleInput` and lower its first step, as a call would, without a Kernel:
13
13
  * it throws what the call would raise before sending, a bound past S11 (`QueryError` `TOO_MANY` or
14
14
  * `INPUT_INVALID`), a relation across a Class the Domain's definition does not declare (S12), or a
15
15
  * step that does not build.
16
16
  */
17
- export declare function checkRecipe<R extends Recipe>(recipe: R, sampleInput: InputOf<R>, options: CheckRecipeOptions): void;
17
+ export declare function checkQuery<R extends DefinedQuery>(query: R, sampleInput: InputOf<R>, options: CheckQueryOptions): void;
@@ -1,31 +1,31 @@
1
1
  import { isDomainDefinition } from '../application/define.js';
2
- import { planStep, Run, stepsFor, stepsOf } from '../application/query/execution/recipe.js';
2
+ import { querySpecOf } from '../application/query/defined/define.js';
3
+ import { planStep, Run, stepsFor, stepsOf } from '../application/query/execution/run.js';
3
4
  import { handlesOf } from '../application/query/handles/build.js';
4
5
  import { describe } from '../application/query/handles/terms.js';
5
- import { recipeSpecOf } from '../application/query/recipe/define.js';
6
6
  import { schema as schemaApi } from '../platform/schema/index.js';
7
7
  /** Never reached: a check sends nothing. */
8
8
  const NO_KERNEL = Object.freeze({
9
- query: () => Promise.reject(new Error('checkRecipe sends no read.')),
9
+ query: () => Promise.reject(new Error('checkQuery sends no read.')),
10
10
  });
11
11
  /**
12
- * Build a recipe for `sampleInput` and lower its first step, as a call would, without a Kernel:
12
+ * Build a Query for `sampleInput` and lower its first step, as a call would, without a Kernel:
13
13
  * it throws what the call would raise before sending, a bound past S11 (`QueryError` `TOO_MANY` or
14
14
  * `INPUT_INVALID`), a relation across a Class the Domain's definition does not declare (S12), or a
15
15
  * step that does not build.
16
16
  */
17
- export function checkRecipe(recipe, sampleInput, options) {
18
- const spec = recipeSpecOf(recipe);
17
+ export function checkQuery(query, sampleInput, options) {
18
+ const spec = querySpecOf(query);
19
19
  if (spec === undefined)
20
- throw new TypeError(`Not a v7 recipe: define one with defineQuery<Schema>()(id, { build }); got ${describe(recipe)}.`);
20
+ throw new TypeError(`Not a Query v7: define one with defineQuery<Schema>()(id, { build }); got ${describe(query)}.`);
21
21
  const definition = isDomainDefinition(options?.domain) ? options.domain : undefined;
22
22
  const domain = schemaApi.resolve(definition?.schema ?? options?.domain);
23
23
  // A definition types its requirements as written; the check reads any.
24
24
  const requirements = definition?.requirements;
25
25
  const declared = definition === undefined ? undefined : (requirements?.classes ?? []);
26
- const run = new Run(NO_KERNEL, domain, recipe.id, declared);
26
+ const run = new Run(NO_KERNEL, domain, query.id, declared);
27
27
  const build = spec.build;
28
- const built = build(sampleInput, handlesOf(domain), stepsFor(recipe.id));
28
+ const built = build(sampleInput, handlesOf(domain), stepsFor(query.id));
29
29
  const steps = stepsOf(built);
30
30
  if (steps === undefined)
31
31
  planStep(run, built, true);
@@ -1,6 +1,6 @@
1
1
  import { existsSync } from 'node:fs';
2
2
  import { dirname, join, resolve } from 'node:path';
3
- import { admitRecipes, collectRecipes, } from '../../application/query/recipe/define.js';
3
+ import { admitDefinitions, collectDefinitions, } from '../../application/query/defined/define.js';
4
4
  import { admitRuntime, compile, resolveRuntime } from '../../deployment/index.js';
5
5
  import { packageDomain } from '../packaging/index.js';
6
6
  import { runAdapterCommand } from './adapter-command.js';
@@ -61,9 +61,10 @@ export async function run(argv) {
61
61
  error(`No astrale.config.ts found in ${projectDir}.`);
62
62
  return 1;
63
63
  }
64
- // The recipes loading this project and its runtime define: the ones the build checks together.
65
- const recipes = [];
66
- const project = await collectRecipes(recipes, () => loadProject(configPath));
64
+ // The Queries and Mutations loading this project and its runtime define: the ones the build
65
+ // checks together.
66
+ const queries = [];
67
+ const project = await collectDefinitions(queries, () => loadProject(configPath));
67
68
  if (parsed.command === 'list')
68
69
  return list(parsed, project, projectDir);
69
70
  if (parsed.command === 'adapter') {
@@ -104,9 +105,9 @@ export async function run(argv) {
104
105
  });
105
106
  }
106
107
  const build = compile(project.domain);
107
- const resolved = await collectRecipes(recipes, () => resolveRuntime(runtimeEntrypoint(project), (path) => importModule(resolve(dirname(configPath), path))));
108
+ const resolved = await collectDefinitions(queries, () => resolveRuntime(runtimeEntrypoint(project), (path) => importModule(resolve(dirname(configPath), path))));
108
109
  admitRuntime({ runtime: build.runtime }, resolved);
109
- admitRecipes(recipes);
110
+ admitDefinitions(queries);
110
111
  if (parsed.command === 'diff') {
111
112
  const lifecycle = deploymentLifecycle('Diff interrupted.');
112
113
  try {
@@ -1,17 +1,17 @@
1
1
  import ts from 'typescript';
2
2
  import type { SourceFile } from './index.js';
3
- /** The modules each recipe factory is exported from. */
4
- declare const RECIPE_MODULES: {
3
+ /** The modules each definition factory is exported from. */
4
+ declare const FACTORY_MODULES: {
5
5
  readonly defineQuery: Set<string>;
6
6
  readonly defineMutation: Set<string>;
7
7
  };
8
- /** The factories that define recipes: Query recipes, and Mutation recipes (D31). */
9
- export type RecipeFactory = keyof typeof RECIPE_MODULES;
8
+ /** The factories that define from an id: Queries v7, and Mutations (D31). */
9
+ export type DefinitionFactory = keyof typeof FACTORY_MODULES;
10
10
  /**
11
- * A recipe: `defineQuery<Schema>()` applied to an id and a spec `{ build, output? }`, or
11
+ * A definition from an id: `defineQuery<Schema>()` applied to an id and a spec `{ build, output? }`, or
12
12
  * `defineMutation<Schema>()` applied to an id and a spec `{ build, output?, reject? }`.
13
13
  */
14
- export interface RecipeDefinition {
14
+ export interface DefinitionCall {
15
15
  /** The application `(id, spec)`. */
16
16
  readonly call: ts.CallExpression;
17
17
  /** The factory, `defineQuery<Schema>()`, applied directly or through the const it is bound to. */
@@ -19,16 +19,16 @@ export interface RecipeDefinition {
19
19
  readonly origin: 'resolved' | 'ambiguous';
20
20
  }
21
21
  /**
22
- * The recipes a file defines with `name`. A recipe applies `defineQuery<Schema>()` (or
22
+ * The definitions a file makes with `name` from an id. Each applies `defineQuery<Schema>()` (or
23
23
  * `defineMutation<Schema>()`) to two values, its id and its spec, where a V6 Query (or a Mutation
24
24
  * of the closure form) applies it to one Domain projector. A const bound to the factory is followed
25
25
  * to its applications in the same file.
26
26
  */
27
- export declare function recipeDefinitions(file: SourceFile, name?: RecipeFactory): readonly RecipeDefinition[];
27
+ export declare function definitionCalls(file: SourceFile, name?: DefinitionFactory): readonly DefinitionCall[];
28
28
  /**
29
- * Whether a `defineQuery<Schema>()` (or `defineMutation<Schema>()`) call makes recipes: applied to
29
+ * Whether a `defineQuery<Schema>()` (or `defineMutation<Schema>()`) call defines from an id: applied to
30
30
  * an id and a spec, or bound to a const that no application in the file passes one Domain
31
31
  * projector.
32
32
  */
33
- export declare function isRecipeFactory(file: SourceFile, factory: ts.CallExpression): boolean;
33
+ export declare function isDefinitionFactory(file: SourceFile, factory: ts.CallExpression): boolean;
34
34
  export {};
@@ -1,18 +1,18 @@
1
1
  import ts from 'typescript';
2
2
  import { resolveImportedSymbol, unwrap, visit } from './syntax.js';
3
- /** The modules each recipe factory is exported from. */
4
- const RECIPE_MODULES = {
3
+ /** The modules each definition factory is exported from. */
4
+ const FACTORY_MODULES = {
5
5
  defineQuery: new Set(['@astrale-os/sdk', '@astrale-os/sdk/query']),
6
6
  defineMutation: new Set(['@astrale-os/sdk', '@astrale-os/sdk/mutation']),
7
7
  };
8
8
  /**
9
- * The recipes a file defines with `name`. A recipe applies `defineQuery<Schema>()` (or
9
+ * The definitions a file makes with `name` from an id. Each applies `defineQuery<Schema>()` (or
10
10
  * `defineMutation<Schema>()`) to two values, its id and its spec, where a V6 Query (or a Mutation
11
11
  * of the closure form) applies it to one Domain projector. A const bound to the factory is followed
12
12
  * to its applications in the same file.
13
13
  */
14
- export function recipeDefinitions(file, name = 'defineQuery') {
15
- const recipes = [];
14
+ export function definitionCalls(file, name = 'defineQuery') {
15
+ const definitions = [];
16
16
  visit(file.source, (node) => {
17
17
  if (!ts.isCallExpression(node) || node.arguments.length !== 2)
18
18
  return;
@@ -20,16 +20,16 @@ export function recipeDefinitions(file, name = 'defineQuery') {
20
20
  const factory = ts.isCallExpression(callee) ? callee : boundFactory(file, callee);
21
21
  const origin = factory && factoryOrigin(file, factory, name);
22
22
  if (factory && origin)
23
- recipes.push({ call: node, factory, origin });
23
+ definitions.push({ call: node, factory, origin });
24
24
  });
25
- return recipes;
25
+ return definitions;
26
26
  }
27
27
  /**
28
- * Whether a `defineQuery<Schema>()` (or `defineMutation<Schema>()`) call makes recipes: applied to
28
+ * Whether a `defineQuery<Schema>()` (or `defineMutation<Schema>()`) call defines from an id: applied to
29
29
  * an id and a spec, or bound to a const that no application in the file passes one Domain
30
30
  * projector.
31
31
  */
32
- export function isRecipeFactory(file, factory) {
32
+ export function isDefinitionFactory(file, factory) {
33
33
  const parent = factory.parent;
34
34
  if (ts.isCallExpression(parent) && unwrap(parent.expression) === factory)
35
35
  return parent.arguments.length === 2;
@@ -51,7 +51,7 @@ function factoryOrigin(file, factory, name) {
51
51
  return undefined;
52
52
  if (symbol.kind === 'ambiguous')
53
53
  return 'ambiguous';
54
- return RECIPE_MODULES[name].has(symbol.module) ? 'resolved' : undefined;
54
+ return FACTORY_MODULES[name].has(symbol.module) ? 'resolved' : undefined;
55
55
  }
56
56
  /** The factory a top-level const binds, when the callee names one. */
57
57
  function boundFactory(file, callee) {
@@ -5,7 +5,7 @@ export { bindingContains, importedSymbol, isLocallyDeclared, resolveImportedSymb
5
5
  export { assertSingleTypeUniverse } from './type-universe.js';
6
6
  export { observeQueryDefinitions } from './query-observation.js';
7
7
  export { queryCollectionKind } from './query-collection-type.js';
8
- export { isRecipeFactory, recipeDefinitions, type RecipeDefinition, type RecipeFactory, } from './recipe-definitions.js';
8
+ export { isDefinitionFactory, definitionCalls, type DefinitionCall, type DefinitionFactory, } from './definition-calls.js';
9
9
  export { declarationOf, expressionType, type ExpressionType } from './type-analysis.js';
10
10
  export { collectSuppressionDirectives } from './suppression-directives.js';
11
11
  import type ts from 'typescript';
@@ -5,6 +5,6 @@ export { bindingContains, importedSymbol, isLocallyDeclared, resolveImportedSymb
5
5
  export { assertSingleTypeUniverse } from './type-universe.js';
6
6
  export { observeQueryDefinitions } from './query-observation.js';
7
7
  export { queryCollectionKind } from './query-collection-type.js';
8
- export { isRecipeFactory, recipeDefinitions, } from './recipe-definitions.js';
8
+ export { isDefinitionFactory, definitionCalls, } from './definition-calls.js';
9
9
  export { declarationOf, expressionType } from './type-analysis.js';
10
10
  export { collectSuppressionDirectives } from './suppression-directives.js';
@@ -1,6 +1,6 @@
1
1
  import ts from 'typescript';
2
2
  import { ambiguous, known, unknown, } from '../../analysis/query/index.js';
3
- import { recipeDefinitions } from './recipe-definitions.js';
3
+ import { definitionCalls } from './definition-calls.js';
4
4
  import { location, resolveImportedSymbol, unwrap, visit } from './syntax.js';
5
5
  const SDK_MODULES = new Set(['@astrale-os/sdk', '@astrale-os/sdk/query']);
6
6
  const QUERY_MODULES = new Set([
@@ -14,9 +14,9 @@ export function observeQueryDefinitions(project) {
14
14
  .flatMap(observeFile));
15
15
  }
16
16
  function observeFile(file) {
17
- const recipes = recipeDefinitions(file);
18
- const applications = new Set(recipes.map(({ call }) => call));
19
- const observations = recipes.map((recipe) => recipeObservation(file, recipe));
17
+ const definitions = definitionCalls(file);
18
+ const applications = new Set(definitions.map(({ call }) => call));
19
+ const observations = definitions.map((definition) => definitionObservation(file, definition));
20
20
  visit(file.source, (node) => {
21
21
  if (!ts.isCallExpression(node) || applications.has(node))
22
22
  return;
@@ -79,10 +79,10 @@ function observeFile(file) {
79
79
  return observations;
80
80
  }
81
81
  /**
82
- * A v7 recipe is one single definition: its build returns reads built from the Domain's handles,
82
+ * A Query v7 is one single definition: its build returns reads built from the Domain's handles,
83
83
  * which lower to canonical Query JSON by construction, and it has no projection callback.
84
84
  */
85
- function recipeObservation(file, { call, factory, origin }) {
85
+ function definitionObservation(file, { call, factory, origin }) {
86
86
  const subjectId = `${file.path}#${call.getStart(file.source)}`;
87
87
  const sourceLocation = location(file, call);
88
88
  if (origin === 'ambiguous')
@@ -0,0 +1,2 @@
1
+ import type { SourceRuleVerifier } from './verifier.js';
2
+ export declare const definitionRules: readonly SourceRuleVerifier[];
@@ -1,37 +1,37 @@
1
1
  import ts from 'typescript';
2
- import { declarationOf, expressionType, isLocallyDeclared, recipeDefinitions, unwrap, visit, } from '../../adapters/typescript/index.js';
2
+ import { declarationOf, expressionType, isLocallyDeclared, definitionCalls, unwrap, visit, } from '../../adapters/typescript/index.js';
3
3
  import { production, propertyExpression, returnedExpressions, violation } from './shared.js';
4
- /** Rows of bound product past which a recipe is flagged: a tenth of what one call may read. */
4
+ /** Rows of bound product past which a Query is flagged: a tenth of what one call may read. */
5
5
  const ROWS = 10_000;
6
- export const recipeRules = [
6
+ export const definitionRules = [
7
7
  {
8
- id: 'QRY-RECIPE-CLOCK',
9
- ruleRevision: '9a5fd016eb166ca70830a30ca43cbf9796ccea5687c6e81a20b75e1775b82cb4',
8
+ id: 'QRY-CLOCK',
9
+ ruleRevision: '776cea7dd21460547625a1e6b7a74fcd80956bd7f4cfbdc6641e6458661095ee',
10
10
  evaluate(project) {
11
- return recipesOf(project).flatMap(({ file, recipe }) => clockEvidence(file, recipe));
11
+ return definitionsOf(project).flatMap(({ file, definition }) => clockEvidence(file, definition));
12
12
  },
13
13
  },
14
14
  {
15
- id: 'QRY-RECIPE-ROWS',
16
- ruleRevision: 'a2fbec742bc0c4a1e48acbb150b81f1dbafc81e291a47a2e2b16f60f89cc385d',
15
+ id: 'QRY-ROWS',
16
+ ruleRevision: '2b470871ff394e42f19b7fc1ddcfcd4e853ced9e65412e3dfe0d0c66e9caf4a2',
17
17
  evaluate(project) {
18
- return recipesOf(project).flatMap(({ file, recipe }) => rowsEvidence(project, file, recipe));
18
+ return definitionsOf(project).flatMap(({ file, definition }) => rowsEvidence(project, file, definition));
19
19
  },
20
20
  },
21
21
  {
22
- id: 'QRY-RECIPE-FALSY',
23
- ruleRevision: '972ad5ec32f46731a2652ae0328d486ed107c0c359a6c42d1d613b773b0ff478',
22
+ id: 'QRY-FALSY',
23
+ ruleRevision: '3041a35ba8209331f3c64d8aada93f6b7a8194802a23927f29d919a1e7354719',
24
24
  evaluate(project) {
25
- return recipesOf(project).flatMap(({ file, recipe }) => falsyFilterEvidence(project, file, recipe));
25
+ return definitionsOf(project).flatMap(({ file, definition }) => falsyFilterEvidence(project, file, definition));
26
26
  },
27
27
  },
28
28
  ];
29
- function recipesOf(project) {
30
- return production(project, 'queries').flatMap((file) => recipeDefinitions(file)
29
+ function definitionsOf(project) {
30
+ return production(project, 'queries').flatMap((file) => definitionCalls(file)
31
31
  .filter(({ origin }) => origin === 'resolved')
32
- .map((recipe) => ({ file, recipe })));
32
+ .map((definition) => ({ file, definition })));
33
33
  }
34
- /** A recipe's spec as written: its id, and its `build` and `output` written inline. */
34
+ /** A Query's spec as written: its id, and its `build` and `output` written inline. */
35
35
  function specOf(file, { call }) {
36
36
  const id = unwrap(call.arguments[0]);
37
37
  const spec = unwrap(call.arguments[1]);
@@ -57,8 +57,8 @@ const CLOCKS = [
57
57
  ['process', 'uptime'],
58
58
  ];
59
59
  /** Each clock read in `build` and `output`, their callbacks included: they all run in the call. */
60
- function clockEvidence(file, recipe) {
61
- const { name, build, output } = specOf(file, recipe);
60
+ function clockEvidence(file, definition) {
61
+ const { name, build, output } = specOf(file, definition);
62
62
  const evidence = [];
63
63
  const fields = [
64
64
  ...(build === undefined ? [] : [{ field: 'build', fn: build }]),
@@ -69,7 +69,7 @@ function clockEvidence(file, recipe) {
69
69
  const read = clockRead(node);
70
70
  if (read === undefined)
71
71
  return;
72
- evidence.push(violation(file, node, `Recipe ${name}'s ${field} reads the clock (${read}): no write moves time, so nothing would refresh the read. Take now in the recipe's input.`));
72
+ evidence.push(violation(file, node, `Query ${name}'s ${field} reads the clock (${read}): no write moves time, so nothing would refresh the read. Take now in the Query's input.`));
73
73
  });
74
74
  }
75
75
  return evidence;
@@ -105,12 +105,12 @@ function isGlobal(expression, path) {
105
105
  return ts.isIdentifier(current) && current.text === path[0] && !isLocallyDeclared(current);
106
106
  }
107
107
  /**
108
- * A recipe whose bounds multiply past `ROWS`, counted as a call counts them (S11): each verb's
108
+ * A Query whose bounds multiply past `ROWS`, counted as a call counts them (S11): each verb's
109
109
  * rows, `find` 2, `first(n)` n, `all` and `page` max + 1, times one plus what each row carries.
110
- * A bound that is not a constant counts nothing, so the count is the least the recipe may read.
110
+ * A bound that is not a constant counts nothing, so the count is the least the Query may read.
111
111
  */
112
- function rowsEvidence(project, file, recipe) {
113
- const { name, build } = specOf(file, recipe);
112
+ function rowsEvidence(project, file, definition) {
113
+ const { name, build } = specOf(file, definition);
114
114
  const handles = boundNames(build?.parameters[1]?.name);
115
115
  if (build === undefined || handles.size === 0)
116
116
  return [];
@@ -126,7 +126,7 @@ function rowsEvidence(project, file, recipe) {
126
126
  if (rows <= ROWS)
127
127
  return [];
128
128
  return [
129
- violation(file, recipe.call, `Recipe ${name} reads up to ${rows.toLocaleString('en-US')} rows, the product of its bounds, past ${ROWS.toLocaleString('en-US')}: lower a bound, or split the read.`),
129
+ violation(file, definition.call, `Query ${name} reads up to ${rows.toLocaleString('en-US')} rows, the product of its bounds, past ${ROWS.toLocaleString('en-US')}: lower a bound, or split the read.`),
130
130
  ];
131
131
  }
132
132
  /**
@@ -288,8 +288,8 @@ const COMBINATIONS = new Set(['and', 'or']);
288
288
  * number: the entry is then `false`, `0` or `undefined`, which is skipped, so the comparison is
289
289
  * dropped.
290
290
  */
291
- function falsyFilterEvidence(project, file, recipe) {
292
- const { name, build } = specOf(file, recipe);
291
+ function falsyFilterEvidence(project, file, definition) {
292
+ const { name, build } = specOf(file, definition);
293
293
  const evidence = [];
294
294
  if (build !== undefined)
295
295
  visit(build, (node) => {
@@ -306,7 +306,7 @@ function falsyFilterEvidence(project, file, recipe) {
306
306
  const explicit = admitted === 'number'
307
307
  ? `${value} !== undefined && ${value} !== 0 && …`
308
308
  : `${value} ? ….eq(true) : undefined`;
309
- evidence.push(violation(file, entry, `Recipe ${name} drops the condition on ${value} when ${value} is false or 0: the ${skipped.call} entry is then falsy, and ${skipped.call} skips it. To compare whenever ${value} is set, write ${value} !== undefined && …; if false or 0 means no filter, write that explicitly: ${explicit}.`));
309
+ evidence.push(violation(file, entry, `Query ${name} drops the condition on ${value} when ${value} is false or 0: the ${skipped.call} entry is then falsy, and ${skipped.call} skips it. To compare whenever ${value} is set, write ${value} !== undefined && …; if false or 0 means no filter, write that explicitly: ${explicit}.`));
310
310
  }
311
311
  });
312
312
  return evidence;
@@ -1,5 +1,5 @@
1
1
  import ts from 'typescript';
2
- import { RECIPE_ID } from '../../../../application/query/recipe/define.js';
2
+ import { DEFINITION_ID } from '../../../../application/query/defined/define.js';
3
3
  import { importedSymbol, resolveImportedSymbol, resolveProjectImport, unwrap, visit, } from '../../adapters/typescript/index.js';
4
4
  import { DSL_MODULES, SDK_MODULES, ambiguity, definitionOriginAmbiguity, definitionObjects, isDeepPackageImport, isForeignDomain, isLocallyBoundIdentifier, packageRoot, production, propertyExpression, violation, } from './shared.js';
5
5
  const CANONICAL_TYPES = new Set([
@@ -530,15 +530,17 @@ export const globalRules = [
530
530
  ts.isNoSubstitutionTemplateLiteral(idExpression))
531
531
  ? idExpression.text
532
532
  : undefined;
533
- // A v7 recipe id is the one `defineQuery` admits; any other keeps the stable form.
534
- const form = candidate.id ? RECIPE_ID : STABLE_DEFINITION_ID;
533
+ // A Query v7 or defined Mutation id is the one `defineQuery` admits; any other keeps the stable form.
534
+ const form = candidate.id ? DEFINITION_ID : STABLE_DEFINITION_ID;
535
535
  if (!idExpression || !id || !form.test(id)) {
536
536
  evidence.push(violation(file, idExpression ?? call, `${definition.name}${member ? `.${member}` : ''} ID must be a stable semantic literal.`));
537
537
  continue;
538
538
  }
539
- // An id is unique in its layer; Query and Mutation recipes also share one namespace,
540
- // the one the runtime admits them in.
541
- const scopes = candidate.id ? [definition.layer, 'recipe'] : [definition.layer];
539
+ // An id is unique in its layer; Queries and Mutations defined from an id also share one
540
+ // namespace, the one the runtime admits them in.
541
+ const scopes = candidate.id
542
+ ? [definition.layer, 'Query or Mutation']
543
+ : [definition.layer];
542
544
  const duplicated = scopes.find((scope) => owners.has(`${scope}\0${id}`));
543
545
  if (duplicated) {
544
546
  evidence.push(violation(file, idExpression, `${duplicated} definition ID ${id} is duplicated; first declared in ${owners.get(`${duplicated}\0${id}`).file.path}.`));
@@ -540,7 +540,7 @@ function mutationBuilderScopes(file) {
540
540
  continue;
541
541
  }
542
542
  for (const [imported, local] of sourceImport.bindings) {
543
- if (imported === 'RichMutationBuilder' || imported === 'RecipeMutationBuilder')
543
+ if (imported === 'RichMutationBuilder' || imported === 'DefinedMutationBuilder')
544
544
  richBuilderTypes.add(local);
545
545
  }
546
546
  }
@@ -663,7 +663,7 @@ function classOperationForBuilder(operation) {
663
663
  }
664
664
  }
665
665
  function dependencyClassTarget(expression, handles) {
666
- // A recipe names a dependency's Class by its handle, `d.<alias>.<Class>`.
666
+ // A defined Mutation names a dependency's Class by its handle, `d.<alias>.<Class>`.
667
667
  const path = handlePath(expression, handles);
668
668
  if (path !== undefined) {
669
669
  return path.length === 2 && !OWN_HANDLES.has(path[0])
@@ -721,7 +721,7 @@ function handleParameters(file) {
721
721
  return parameters;
722
722
  }
723
723
  /**
724
- * The handle a recipe's expression names, as its path from `d`: `d.Item` and a destructured
724
+ * The handle a defined Mutation's expression names, as its path from `d`: `d.Item` and a destructured
725
725
  * `{ Item }` are `['Item']`, `d.directory.Person` is `['directory', 'Person']`. Undefined for an
726
726
  * expression that does not start from the handles, or not statically.
727
727
  */
@@ -775,7 +775,7 @@ function bindingPath(binding, handles, seen) {
775
775
  ? path
776
776
  : undefined;
777
777
  }
778
- /** The builder a Mutation's `build` receives: second in the closure form, third in a recipe. */
778
+ /** The builder a Mutation's `build` receives: second in the closure form, third in a defined Mutation. */
779
779
  function builderParameter(definition, build) {
780
780
  return build.parameters[definition.id === undefined ? 1 : 2];
781
781
  }
@@ -1317,7 +1317,7 @@ function selectedClassNames(expression, handles, seen = new Set()) {
1317
1317
  const whenFalse = selectedClassNames(value.whenFalse, handles, seen);
1318
1318
  return whenTrue && whenFalse ? new Set([...whenTrue, ...whenFalse]) : undefined;
1319
1319
  }
1320
- // A recipe names its Class by its handle: the last segment of its path from `d`.
1320
+ // A defined Mutation names its Class by its handle: the last segment of its path from `d`.
1321
1321
  const path = handlePath(value, handles);
1322
1322
  if (path !== undefined)
1323
1323
  return path.length > 0 ? new Set([path.at(-1)]) : undefined;
@@ -7,7 +7,7 @@ export interface DefinitionObject {
7
7
  readonly call: ts.CallExpression;
8
8
  readonly object?: ts.ObjectLiteralExpression;
9
9
  readonly projector?: ts.FunctionLikeDeclaration;
10
- /** A recipe's id, its first argument: a recipe, Query or Mutation, has no Domain projector. */
10
+ /** A definition's id, its first argument: a Query v7 or a defined Mutation has no Domain projector. */
11
11
  readonly id?: ts.Expression;
12
12
  readonly origin: 'resolved' | 'ambiguous';
13
13
  }
@@ -23,7 +23,7 @@ export declare function memberCalls(file: SourceFile, importedName: string, memb
23
23
  export declare function definitionObjects(file: SourceFile, importedName: string, member?: string, modules?: Set<string>, argumentIndex?: number): DefinitionObject[];
24
24
  export declare function definitionOriginAmbiguity(file: SourceFile, definition: DefinitionObject, name: string): SourceRuleEvidence | undefined;
25
25
  /**
26
- * Prove the clean curried Domain projector shape for Query and Mutation definitions. A recipe,
26
+ * Prove the clean curried Domain projector shape for Query and Mutation definitions. A definition from an id,
27
27
  * `defineQuery<typeof Schema>()(id, { build })` or `defineMutation<typeof Schema>()(id, { build })`,
28
28
  * has no projector to prove.
29
29
  */
@@ -1,5 +1,5 @@
1
1
  import ts from 'typescript';
2
- import { bindingContains, importedSymbol, isRecipeFactory, location, objectProperty, propertyChain, recipeDefinitions, resolveImportedSymbol, resolveProjectImport, staticText, unwrap, visit, } from '../../adapters/typescript/index.js';
2
+ import { bindingContains, importedSymbol, isDefinitionFactory, location, objectProperty, propertyChain, definitionCalls, resolveImportedSymbol, resolveProjectImport, staticText, unwrap, visit, } from '../../adapters/typescript/index.js';
3
3
  export const SDK_MODULES = new Set([
4
4
  '@astrale-os/sdk',
5
5
  '@astrale-os/sdk/action',
@@ -59,10 +59,10 @@ export function memberCalls(file, importedName, member, modules = SDK_MODULES) {
59
59
  }
60
60
  export function definitionObjects(file, importedName, member, modules = SDK_MODULES, argumentIndex = 0) {
61
61
  if (!member && DOMAIN_BOUND_DEFINITIONS.has(importedName)) {
62
- const recipes = importedName === 'defineQuery' || importedName === 'defineMutation'
63
- ? recipeDefinitions(file, importedName)
62
+ const definitions = importedName === 'defineQuery' || importedName === 'defineMutation'
63
+ ? definitionCalls(file, importedName)
64
64
  : [];
65
- const applications = new Set(recipes.map(({ call }) => call));
65
+ const applications = new Set(definitions.map(({ call }) => call));
66
66
  return [
67
67
  ...curriedCalls(file, importedName, modules)
68
68
  .filter(({ call }) => !applications.has(call))
@@ -75,7 +75,7 @@ export function definitionObjects(file, importedName, member, modules = SDK_MODU
75
75
  object: projector && returnedObject(projector),
76
76
  };
77
77
  }),
78
- ...recipes.map(({ call, origin }) => ({
78
+ ...definitions.map(({ call, origin }) => ({
79
79
  call,
80
80
  origin,
81
81
  id: call.arguments[0],
@@ -122,7 +122,7 @@ export function definitionOriginAmbiguity(file, definition, name) {
122
122
  : undefined;
123
123
  }
124
124
  /**
125
- * Prove the clean curried Domain projector shape for Query and Mutation definitions. A recipe,
125
+ * Prove the clean curried Domain projector shape for Query and Mutation definitions. A definition from an id,
126
126
  * `defineQuery<typeof Schema>()(id, { build })` or `defineMutation<typeof Schema>()(id, { build })`,
127
127
  * has no projector to prove.
128
128
  */
@@ -132,7 +132,7 @@ export function domainProjectorEvidence(file, importedName, label) {
132
132
  if (candidate.origin === 'ambiguous')
133
133
  continue;
134
134
  if ((importedName === 'defineQuery' || importedName === 'defineMutation') &&
135
- isRecipeFactory(file, candidate.call))
135
+ isDefinitionFactory(file, candidate.call))
136
136
  continue;
137
137
  const application = candidate.call.parent;
138
138
  if (candidate.call.arguments.length !== 0 ||
@@ -1,4 +1,5 @@
1
1
  import { actionRules } from './actions.js';
2
+ import { definitionRules } from './definitions.js';
2
3
  import { dependencyRules } from './dependencies.js';
3
4
  import { globalRules } from './global.js';
4
5
  import { integrationRules } from './integrations.js';
@@ -6,7 +7,6 @@ import { mutationRules } from './mutations.js';
6
7
  import { policyEdgeRules } from './policy-edges.js';
7
8
  import { providerRules } from './providers.js';
8
9
  import { queryRules } from './queries.js';
9
- import { recipeRules } from './recipes.js';
10
10
  import { pureRuleRules } from './rules.js';
11
11
  import { schemaRules } from './schema.js';
12
12
  import { stateRules } from './states.js';
@@ -22,7 +22,7 @@ export const sourceRuleVerifiers = Object.freeze([
22
22
  ...stateRules,
23
23
  ...pureRuleRules,
24
24
  ...queryRules,
25
- ...recipeRules,
25
+ ...definitionRules,
26
26
  ...mutationRules,
27
27
  ...workflowRules,
28
28
  ...dependencyRules,