@supacloud/compiler 0.53.0 → 0.54.0
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.
- package/README.md +21 -12
- package/dist/cli.js +104 -20
- package/dist/index.js +103 -16
- package/dist/migration-app-version.d.ts +1 -1
- package/dist/migration-elysia-version.d.ts +1 -1
- package/dist/types.d.ts +20 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -3,22 +3,25 @@
|
|
|
3
3
|
## Enforced Database Governance
|
|
4
4
|
|
|
5
5
|
Existing compiler callers retain `off` as a compatibility migration exception.
|
|
6
|
-
Newly generated `command` starters
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
Newly generated `command` starters keep `databaseGovernance: { mode: "check",
|
|
7
|
+
moduleFile: "db/modules.ts" }` for ordinary compile/check/build. `check` runs
|
|
8
|
+
the existing `@supacloud/db` source-boundary and contract-freshness gate plus SQL
|
|
9
|
+
lint, without importing project modules or opening a database connection. The
|
|
10
|
+
generated integration dev profile switches the same configuration to `enforce`
|
|
11
|
+
and supplies a loopback database URL explicitly.
|
|
12
|
+
|
|
13
|
+
`enforce` adds live Catalog reconciliation on top of `check`, including on
|
|
10
14
|
incremental cache hits. Missing adoption files, stale contracts, SQL findings or
|
|
11
15
|
Catalog drift block generation even with `writeOnError`; checks never generate
|
|
12
|
-
contracts or migrations.
|
|
13
|
-
The minimal/http/edge starters remain database-free.
|
|
16
|
+
contracts or migrations. The minimal/http/edge starters remain database-free.
|
|
14
17
|
|
|
15
18
|
For an existing database project, adopt the governed path by declaring the real
|
|
16
|
-
database modules and
|
|
19
|
+
database modules and setting the following in `supacloud.config.ts`:
|
|
17
20
|
|
|
18
21
|
```ts
|
|
19
22
|
export default {
|
|
20
23
|
databaseGovernance: {
|
|
21
|
-
mode: "
|
|
24
|
+
mode: "check",
|
|
22
25
|
projectRoot: ".",
|
|
23
26
|
moduleFile: "db/modules.ts",
|
|
24
27
|
databaseUrlEnv: "SUPACLOUD_CHECK_DATABASE_URL",
|
|
@@ -27,11 +30,17 @@ export default {
|
|
|
27
30
|
};
|
|
28
31
|
```
|
|
29
32
|
|
|
33
|
+
Keep `check` in committed project configuration so local builds and CI remain
|
|
34
|
+
hermetic. Run `enforce` only in an explicit release/deployment gate where the
|
|
35
|
+
platform injects a read-only PostgreSQL connection, or run the separate
|
|
36
|
+
`supacloud db module_check` command through the same controlled environment.
|
|
37
|
+
Application code and committed configuration must not contain a production
|
|
38
|
+
connection URL.
|
|
39
|
+
|
|
30
40
|
`projectRoot` is relative to the configuration directory (or `rootDir` when
|
|
31
|
-
calling `compileProject` / `checkProject` directly).
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
generate migrations, repair contracts, or apply SQL. Setting `mode: "off"` is
|
|
41
|
+
calling `compileProject` / `checkProject` directly). The compiler does not load
|
|
42
|
+
`.env` files for this worker, generate migrations, repair contracts, or apply
|
|
43
|
+
SQL. Never use a migration/owner role for this check. Setting `mode: "off"` is
|
|
35
44
|
reserved for an explicit migration exception and should not be used in a new
|
|
36
45
|
database starter.
|
|
37
46
|
|
package/dist/cli.js
CHANGED
|
@@ -1475,6 +1475,9 @@ var init_validate = __esm(() => {
|
|
|
1475
1475
|
"effect-direct-runtime-execution": { code: "SC3045", docsUrl: "https://supacloud.dev/errors/SC3045" },
|
|
1476
1476
|
"effect-direct-throw": { code: "SC3046", docsUrl: "https://supacloud.dev/errors/SC3046" },
|
|
1477
1477
|
"effect-promise-return": { code: "SC3047", docsUrl: "https://supacloud.dev/errors/SC3047" },
|
|
1478
|
+
"effect-retry-target-required": { code: "SC3048", docsUrl: "https://supacloud.dev/errors/SC3048" },
|
|
1479
|
+
"effect-retryable-invalid": { code: "SC3049", docsUrl: "https://supacloud.dev/errors/SC3049" },
|
|
1480
|
+
"effect-retry-required": { code: "SC3050", docsUrl: "https://supacloud.dev/errors/SC3050" },
|
|
1478
1481
|
"invalid-route-response-map": { code: "SC3024", docsUrl: "https://supacloud.dev/errors/SC3024" },
|
|
1479
1482
|
"invalid-route-response-selector": { code: "SC3025", docsUrl: "https://supacloud.dev/errors/SC3025" },
|
|
1480
1483
|
"conflicting-route-response-schema": { code: "SC3026", docsUrl: "https://supacloud.dev/errors/SC3026" },
|
|
@@ -19105,7 +19108,8 @@ var DEFAULT_EFFECT_ANALYSIS_OPTIONS = {
|
|
|
19105
19108
|
requireExactDependencyTypes: true,
|
|
19106
19109
|
requireTimeoutForDependencies: true,
|
|
19107
19110
|
forbidDirectRuntimeExecution: true,
|
|
19108
|
-
forbidDirectThrows: true
|
|
19111
|
+
forbidDirectThrows: true,
|
|
19112
|
+
requireRetryPolicy: true
|
|
19109
19113
|
};
|
|
19110
19114
|
function nodeText(node) {
|
|
19111
19115
|
return node.getText(node.getSourceFile());
|
|
@@ -19178,7 +19182,8 @@ async function analyzeProject(rootDir, include, cache, changedPaths, effectOptio
|
|
|
19178
19182
|
requireExactDependencyTypes: effectOptions.requireExactDependencyTypes ?? DEFAULT_EFFECT_ANALYSIS_OPTIONS.requireExactDependencyTypes,
|
|
19179
19183
|
requireTimeoutForDependencies: effectOptions.requireTimeoutForDependencies ?? DEFAULT_EFFECT_ANALYSIS_OPTIONS.requireTimeoutForDependencies,
|
|
19180
19184
|
forbidDirectRuntimeExecution: effectOptions.forbidDirectRuntimeExecution ?? DEFAULT_EFFECT_ANALYSIS_OPTIONS.forbidDirectRuntimeExecution,
|
|
19181
|
-
forbidDirectThrows: effectOptions.forbidDirectThrows ?? DEFAULT_EFFECT_ANALYSIS_OPTIONS.forbidDirectThrows
|
|
19185
|
+
forbidDirectThrows: effectOptions.forbidDirectThrows ?? DEFAULT_EFFECT_ANALYSIS_OPTIONS.forbidDirectThrows,
|
|
19186
|
+
requireRetryPolicy: effectOptions.requireRetryPolicy ?? DEFAULT_EFFECT_ANALYSIS_OPTIONS.requireRetryPolicy
|
|
19182
19187
|
}
|
|
19183
19188
|
};
|
|
19184
19189
|
if (ctx.effectOptions.forbidDirectRuntimeExecution) {
|
|
@@ -20001,6 +20006,21 @@ function resolveStaticObjectLiteral(input, ctx, seen = new Set) {
|
|
|
20001
20006
|
}
|
|
20002
20007
|
return ts7.isObjectLiteralExpression(input) ? input : undefined;
|
|
20003
20008
|
}
|
|
20009
|
+
function resolveStaticArrayLiteral(input, ctx, seen = new Set) {
|
|
20010
|
+
if (!input || seen.has(input))
|
|
20011
|
+
return;
|
|
20012
|
+
seen.add(input);
|
|
20013
|
+
if (ts7.isAsExpression(input) || ts7.isSatisfiesExpression(input) || ts7.isParenthesizedExpression(input)) {
|
|
20014
|
+
return resolveStaticArrayLiteral(input.expression, ctx, seen);
|
|
20015
|
+
}
|
|
20016
|
+
if (ts7.isIdentifier(input)) {
|
|
20017
|
+
const declaration = resolveDeclaration(input, ctx).find(ts7.isVariableDeclaration);
|
|
20018
|
+
const list = declaration?.parent;
|
|
20019
|
+
const isConst = Boolean(list && ts7.isVariableDeclarationList(list) && (list.flags & ts7.NodeFlags.Const) !== 0);
|
|
20020
|
+
return isConst && declaration?.initializer ? resolveStaticArrayLiteral(declaration.initializer, ctx, seen) : undefined;
|
|
20021
|
+
}
|
|
20022
|
+
return ts7.isArrayLiteralExpression(input) ? input : undefined;
|
|
20023
|
+
}
|
|
20004
20024
|
function routePolicyProperty(object, name, ctx, seen = new Set) {
|
|
20005
20025
|
if (seen.has(object))
|
|
20006
20026
|
return { unresolved: true };
|
|
@@ -20961,7 +20981,7 @@ function parseController(input, ctx) {
|
|
|
20961
20981
|
file,
|
|
20962
20982
|
line: lineOf(effectExpr),
|
|
20963
20983
|
message: `Route ${route.handler} effect must be a statically resolvable object literal.`,
|
|
20964
|
-
suggestion:
|
|
20984
|
+
suggestion: 'Use effect: { required: true, errors: [...], dependencies: [...], retry: "none" }.'
|
|
20965
20985
|
});
|
|
20966
20986
|
} else {
|
|
20967
20987
|
const effect = { required: true };
|
|
@@ -20992,6 +21012,8 @@ function parseController(input, ctx) {
|
|
|
20992
21012
|
} else {
|
|
20993
21013
|
effect.retry = retry;
|
|
20994
21014
|
}
|
|
21015
|
+
} else if (ctx.effectOptions.requireRetryPolicy === false) {
|
|
21016
|
+
effect.retry = "none";
|
|
20995
21017
|
}
|
|
20996
21018
|
const maxAttemptsExpr = getProp(effectObject, "maxAttempts");
|
|
20997
21019
|
if (maxAttemptsExpr !== undefined) {
|
|
@@ -21040,7 +21062,8 @@ function parseController(input, ctx) {
|
|
|
21040
21062
|
}
|
|
21041
21063
|
const dependenciesExpr = getProp(effectObject, "dependencies");
|
|
21042
21064
|
if (dependenciesExpr !== undefined) {
|
|
21043
|
-
|
|
21065
|
+
const dependenciesArray = resolveStaticArrayLiteral(dependenciesExpr, ctx);
|
|
21066
|
+
if (!dependenciesArray || dependenciesArray.elements.some((element) => !ts7.isStringLiteral(element) || element.text.trim().length === 0)) {
|
|
21044
21067
|
ctx.diagnostics.push({
|
|
21045
21068
|
severity: "error",
|
|
21046
21069
|
code: "invalid-effect-dependencies",
|
|
@@ -21048,10 +21071,10 @@ function parseController(input, ctx) {
|
|
|
21048
21071
|
docsUrl: "https://supacloud.dev/errors/SC3033",
|
|
21049
21072
|
file,
|
|
21050
21073
|
line: lineOf(dependenciesExpr),
|
|
21051
|
-
message: `Route ${route.handler} effect.dependencies must be
|
|
21074
|
+
message: `Route ${route.handler} effect.dependencies must be a string array or a const initialized with one.`
|
|
21052
21075
|
});
|
|
21053
21076
|
} else {
|
|
21054
|
-
effect.dependencies =
|
|
21077
|
+
effect.dependencies = dependenciesArray.elements.map((element) => element.text);
|
|
21055
21078
|
if (new Set(effect.dependencies).size !== effect.dependencies.length) {
|
|
21056
21079
|
ctx.diagnostics.push({
|
|
21057
21080
|
severity: "error",
|
|
@@ -21068,7 +21091,8 @@ function parseController(input, ctx) {
|
|
|
21068
21091
|
}
|
|
21069
21092
|
const errorsExpr = getProp(effectObject, "errors");
|
|
21070
21093
|
if (errorsExpr !== undefined) {
|
|
21071
|
-
|
|
21094
|
+
const errorsArray = resolveStaticArrayLiteral(errorsExpr, ctx);
|
|
21095
|
+
if (!errorsArray) {
|
|
21072
21096
|
ctx.diagnostics.push({
|
|
21073
21097
|
severity: "error",
|
|
21074
21098
|
code: "invalid-effect-errors",
|
|
@@ -21076,11 +21100,11 @@ function parseController(input, ctx) {
|
|
|
21076
21100
|
docsUrl: "https://supacloud.dev/errors/SC3034",
|
|
21077
21101
|
file,
|
|
21078
21102
|
line: lineOf(errorsExpr),
|
|
21079
|
-
message: `Route ${route.handler} effect.errors must be an
|
|
21103
|
+
message: `Route ${route.handler} effect.errors must be an object array or a const initialized with one.`
|
|
21080
21104
|
});
|
|
21081
21105
|
} else {
|
|
21082
21106
|
const errors = [];
|
|
21083
|
-
for (const errorExpr of
|
|
21107
|
+
for (const errorExpr of errorsArray.elements) {
|
|
21084
21108
|
if (!ts7.isObjectLiteralExpression(errorExpr)) {
|
|
21085
21109
|
ctx.diagnostics.push({
|
|
21086
21110
|
severity: "error",
|
|
@@ -21097,6 +21121,23 @@ function parseController(input, ctx) {
|
|
|
21097
21121
|
const code = stringLiteralProp(errorExpr, "code");
|
|
21098
21122
|
const status = numberLiteralProp(errorExpr, "status");
|
|
21099
21123
|
const message = stringLiteralProp(errorExpr, "message");
|
|
21124
|
+
const codeFromError = booleanLiteralProp(errorExpr, "codeFromError");
|
|
21125
|
+
const messageFromError = booleanLiteralProp(errorExpr, "messageFromError");
|
|
21126
|
+
const statusFromError = booleanLiteralProp(errorExpr, "statusFromError");
|
|
21127
|
+
const retryable = booleanLiteralProp(errorExpr, "retryable");
|
|
21128
|
+
const outcomeUnknown = booleanLiteralProp(errorExpr, "outcomeUnknown");
|
|
21129
|
+
if (invalidBooleanProp(errorExpr, "codeFromError") || invalidBooleanProp(errorExpr, "messageFromError") || invalidBooleanProp(errorExpr, "statusFromError") || invalidBooleanProp(errorExpr, "retryable") || invalidBooleanProp(errorExpr, "outcomeUnknown")) {
|
|
21130
|
+
ctx.diagnostics.push({
|
|
21131
|
+
severity: "error",
|
|
21132
|
+
code: "invalid-effect-errors",
|
|
21133
|
+
errorCode: "SC3034",
|
|
21134
|
+
docsUrl: "https://supacloud.dev/errors/SC3034",
|
|
21135
|
+
file,
|
|
21136
|
+
line: lineOf(errorExpr),
|
|
21137
|
+
message: `Route ${route.handler} effect.errors instance flags must be boolean literals.`
|
|
21138
|
+
});
|
|
21139
|
+
continue;
|
|
21140
|
+
}
|
|
21100
21141
|
if (!tag || !code || status === undefined || !Number.isInteger(status) || status < 400 || status > 599) {
|
|
21101
21142
|
ctx.diagnostics.push({
|
|
21102
21143
|
severity: "error",
|
|
@@ -21109,7 +21150,17 @@ function parseController(input, ctx) {
|
|
|
21109
21150
|
});
|
|
21110
21151
|
continue;
|
|
21111
21152
|
}
|
|
21112
|
-
errors.push({
|
|
21153
|
+
errors.push({
|
|
21154
|
+
tag,
|
|
21155
|
+
code,
|
|
21156
|
+
status,
|
|
21157
|
+
...message === undefined ? {} : { message },
|
|
21158
|
+
...codeFromError === undefined ? {} : { codeFromError },
|
|
21159
|
+
...messageFromError === undefined ? {} : { messageFromError },
|
|
21160
|
+
...statusFromError === undefined ? {} : { statusFromError },
|
|
21161
|
+
...retryable === undefined ? {} : { retryable },
|
|
21162
|
+
...outcomeUnknown === undefined ? {} : { outcomeUnknown }
|
|
21163
|
+
});
|
|
21113
21164
|
}
|
|
21114
21165
|
effect.errors = errors;
|
|
21115
21166
|
if (new Set(errors.map((entry) => entry.tag)).size !== errors.length) {
|
|
@@ -21837,6 +21888,19 @@ function numberLiteralProp(obj, name) {
|
|
|
21837
21888
|
const value = Number(expr.text);
|
|
21838
21889
|
return Number.isFinite(value) ? value : undefined;
|
|
21839
21890
|
}
|
|
21891
|
+
function booleanLiteralProp(obj, name) {
|
|
21892
|
+
const expr = getProp(obj, name);
|
|
21893
|
+
if (!expr || !isBooleanLiteral(expr))
|
|
21894
|
+
return;
|
|
21895
|
+
return expr.kind === ts7.SyntaxKind.TrueKeyword;
|
|
21896
|
+
}
|
|
21897
|
+
function isBooleanLiteral(expr) {
|
|
21898
|
+
return expr.kind === ts7.SyntaxKind.TrueKeyword || expr.kind === ts7.SyntaxKind.FalseKeyword;
|
|
21899
|
+
}
|
|
21900
|
+
function invalidBooleanProp(obj, name) {
|
|
21901
|
+
const expr = getProp(obj, name);
|
|
21902
|
+
return expr !== undefined && !isBooleanLiteral(expr);
|
|
21903
|
+
}
|
|
21840
21904
|
function arrayProp(obj, name) {
|
|
21841
21905
|
const expr = getProp(obj, name);
|
|
21842
21906
|
return expr && ts7.isArrayLiteralExpression(expr) ? [...expr.elements] : [];
|
|
@@ -22777,6 +22841,9 @@ function validateEffectPolicies(graph, options = {}) {
|
|
|
22777
22841
|
if (options.requireDependencies && effect.dependencies === undefined) {
|
|
22778
22842
|
diagnostics.push(diagnostic("effect-dependencies-required", `Route ${label} declares an Effect contract without dependencies.`, controller.file, "Declare the logical services required by the Effect environment."));
|
|
22779
22843
|
}
|
|
22844
|
+
if (effect.retry === undefined && options.requireRetryPolicy !== false) {
|
|
22845
|
+
diagnostics.push(diagnostic("effect-retry-required", `Route ${label} declares an Effect contract but does not declare retry.`, controller.file, 'Set effect.retry to "none". That is the required default; use "explicit" only with maxAttempts and a retryable 5xx allow-list.'));
|
|
22846
|
+
}
|
|
22780
22847
|
if (effect.retry === "explicit" && effect.maxAttempts === undefined) {
|
|
22781
22848
|
diagnostics.push(diagnostic("invalid-effect-retry", `Route ${label} enables explicit Effect retry without maxAttempts.`, controller.file, "Declare a positive maxAttempts value including the initial attempt."));
|
|
22782
22849
|
}
|
|
@@ -22787,6 +22854,18 @@ function validateEffectPolicies(graph, options = {}) {
|
|
|
22787
22854
|
if (command && command.idempotency !== "required") {
|
|
22788
22855
|
diagnostics.push(diagnostic("effect-command-retry-forbidden", `Route ${label} enables explicit Effect retry for non-idempotent command "${command.name}".`, controller.file, 'Set command idempotency to "required" or use effect.retry: "none".'));
|
|
22789
22856
|
}
|
|
22857
|
+
const retryable = (effect.errors ?? []).filter((entry) => entry.retryable === true);
|
|
22858
|
+
if (retryable.length === 0) {
|
|
22859
|
+
diagnostics.push(diagnostic("effect-retry-target-required", `Route ${label} enables explicit Effect retry without a transient failure allow-list.`, controller.file, 'Mark only 5xx failures that did not commit with retryable: true, or use effect.retry: "none".'));
|
|
22860
|
+
}
|
|
22861
|
+
}
|
|
22862
|
+
for (const entry of effect.errors ?? []) {
|
|
22863
|
+
if (entry.retryable !== true)
|
|
22864
|
+
continue;
|
|
22865
|
+
const transient = effect.retry === "explicit" && entry.outcomeUnknown !== true && entry.statusFromError !== true && entry.status >= 500 && entry.status <= 599;
|
|
22866
|
+
if (!transient) {
|
|
22867
|
+
diagnostics.push(diagnostic("effect-retryable-invalid", `Route ${label} marks "${entry.tag}" retryable, but in-process retry is only for declared 5xx failures that are not outcome-unknown.`, controller.file, 'Remove retryable, or keep it on a 5xx mapping with retry: "explicit" and without outcomeUnknown or statusFromError.'));
|
|
22868
|
+
}
|
|
22790
22869
|
}
|
|
22791
22870
|
}
|
|
22792
22871
|
}
|
|
@@ -23787,7 +23866,9 @@ var DEFAULT_SUPACLOUD_CONFIG = {
|
|
|
23787
23866
|
requireExactDependencyTypes: true,
|
|
23788
23867
|
requireTimeoutForDependencies: true,
|
|
23789
23868
|
forbidDirectRuntimeExecution: true,
|
|
23790
|
-
forbidDirectThrows: true
|
|
23869
|
+
forbidDirectThrows: true,
|
|
23870
|
+
requireRetryPolicy: true,
|
|
23871
|
+
defaultRetry: "none"
|
|
23791
23872
|
}
|
|
23792
23873
|
};
|
|
23793
23874
|
function defineSupacloudConfig(config = {}) {
|
|
@@ -23869,7 +23950,9 @@ function validateGovernanceConfig(config) {
|
|
|
23869
23950
|
"requireExactDependencyTypes",
|
|
23870
23951
|
"requireTimeoutForDependencies",
|
|
23871
23952
|
"forbidDirectRuntimeExecution",
|
|
23872
|
-
"forbidDirectThrows"
|
|
23953
|
+
"forbidDirectThrows",
|
|
23954
|
+
"requireRetryPolicy",
|
|
23955
|
+
"defaultRetry"
|
|
23873
23956
|
].includes(key))) {
|
|
23874
23957
|
throw new Error("effect contains an unsupported governance option.");
|
|
23875
23958
|
}
|
|
@@ -23881,12 +23964,16 @@ function validateGovernanceConfig(config) {
|
|
|
23881
23964
|
"requireExactDependencyTypes",
|
|
23882
23965
|
"requireTimeoutForDependencies",
|
|
23883
23966
|
"forbidDirectRuntimeExecution",
|
|
23884
|
-
"forbidDirectThrows"
|
|
23967
|
+
"forbidDirectThrows",
|
|
23968
|
+
"requireRetryPolicy"
|
|
23885
23969
|
]) {
|
|
23886
23970
|
if (config.effect[key] !== undefined && typeof config.effect[key] !== "boolean") {
|
|
23887
23971
|
throw new Error(`effect.${key} must be boolean.`);
|
|
23888
23972
|
}
|
|
23889
23973
|
}
|
|
23974
|
+
if (config.effect["defaultRetry"] !== undefined && config.effect["defaultRetry"] !== "none") {
|
|
23975
|
+
throw new Error('effect.defaultRetry must be "none". explicit can only be written on a route, with maxAttempts and a retryable 5xx allow-list.');
|
|
23976
|
+
}
|
|
23890
23977
|
}
|
|
23891
23978
|
}
|
|
23892
23979
|
function resolveSupacloudConfig(config = {}, cwd = process.cwd()) {
|
|
@@ -23985,10 +24072,7 @@ async function realDirectory(path) {
|
|
|
23985
24072
|
}
|
|
23986
24073
|
if (!stat.isDirectory() || stat.isSymbolicLink())
|
|
23987
24074
|
return fail("PREVIEW_FIX_ROOT_UNSUPPORTED");
|
|
23988
|
-
|
|
23989
|
-
if (real !== resolved)
|
|
23990
|
-
return fail("PREVIEW_FIX_ROOT_UNSUPPORTED");
|
|
23991
|
-
return real;
|
|
24075
|
+
return realpath4(resolved);
|
|
23992
24076
|
}
|
|
23993
24077
|
async function treeDigest(root) {
|
|
23994
24078
|
const files = [];
|
|
@@ -25734,10 +25818,10 @@ import { readFileSync as readFileSync4 } from "node:fs";
|
|
|
25734
25818
|
import { resolve as resolve19 } from "node:path";
|
|
25735
25819
|
|
|
25736
25820
|
// src/migration-app-version.ts
|
|
25737
|
-
var MIGRATION_APP_VERSION = "0.
|
|
25821
|
+
var MIGRATION_APP_VERSION = "0.36.0";
|
|
25738
25822
|
|
|
25739
25823
|
// src/migration-elysia-version.ts
|
|
25740
|
-
var MIGRATION_ELYSIA_VERSION = "0.
|
|
25824
|
+
var MIGRATION_ELYSIA_VERSION = "0.38.0";
|
|
25741
25825
|
|
|
25742
25826
|
// src/migration-policy.ts
|
|
25743
25827
|
var cachedCompilerVersion;
|
|
@@ -25756,7 +25840,7 @@ function migrationDependencies() {
|
|
|
25756
25840
|
"@supacloud/app": MIGRATION_APP_VERSION,
|
|
25757
25841
|
"@supacloud/compiler": compilerVersion(),
|
|
25758
25842
|
"@supacloud/elysia": MIGRATION_ELYSIA_VERSION,
|
|
25759
|
-
elysia: "2.0.0-rc.
|
|
25843
|
+
elysia: "2.0.0-rc.1",
|
|
25760
25844
|
typescript: "7.0.2"
|
|
25761
25845
|
};
|
|
25762
25846
|
}
|
package/dist/index.js
CHANGED
|
@@ -1474,6 +1474,9 @@ var init_validate = __esm(() => {
|
|
|
1474
1474
|
"effect-direct-runtime-execution": { code: "SC3045", docsUrl: "https://supacloud.dev/errors/SC3045" },
|
|
1475
1475
|
"effect-direct-throw": { code: "SC3046", docsUrl: "https://supacloud.dev/errors/SC3046" },
|
|
1476
1476
|
"effect-promise-return": { code: "SC3047", docsUrl: "https://supacloud.dev/errors/SC3047" },
|
|
1477
|
+
"effect-retry-target-required": { code: "SC3048", docsUrl: "https://supacloud.dev/errors/SC3048" },
|
|
1478
|
+
"effect-retryable-invalid": { code: "SC3049", docsUrl: "https://supacloud.dev/errors/SC3049" },
|
|
1479
|
+
"effect-retry-required": { code: "SC3050", docsUrl: "https://supacloud.dev/errors/SC3050" },
|
|
1477
1480
|
"invalid-route-response-map": { code: "SC3024", docsUrl: "https://supacloud.dev/errors/SC3024" },
|
|
1478
1481
|
"invalid-route-response-selector": { code: "SC3025", docsUrl: "https://supacloud.dev/errors/SC3025" },
|
|
1479
1482
|
"conflicting-route-response-schema": { code: "SC3026", docsUrl: "https://supacloud.dev/errors/SC3026" },
|
|
@@ -19064,7 +19067,8 @@ var DEFAULT_EFFECT_ANALYSIS_OPTIONS = {
|
|
|
19064
19067
|
requireExactDependencyTypes: true,
|
|
19065
19068
|
requireTimeoutForDependencies: true,
|
|
19066
19069
|
forbidDirectRuntimeExecution: true,
|
|
19067
|
-
forbidDirectThrows: true
|
|
19070
|
+
forbidDirectThrows: true,
|
|
19071
|
+
requireRetryPolicy: true
|
|
19068
19072
|
};
|
|
19069
19073
|
function nodeText(node) {
|
|
19070
19074
|
return node.getText(node.getSourceFile());
|
|
@@ -19137,7 +19141,8 @@ async function analyzeProject(rootDir, include, cache, changedPaths, effectOptio
|
|
|
19137
19141
|
requireExactDependencyTypes: effectOptions.requireExactDependencyTypes ?? DEFAULT_EFFECT_ANALYSIS_OPTIONS.requireExactDependencyTypes,
|
|
19138
19142
|
requireTimeoutForDependencies: effectOptions.requireTimeoutForDependencies ?? DEFAULT_EFFECT_ANALYSIS_OPTIONS.requireTimeoutForDependencies,
|
|
19139
19143
|
forbidDirectRuntimeExecution: effectOptions.forbidDirectRuntimeExecution ?? DEFAULT_EFFECT_ANALYSIS_OPTIONS.forbidDirectRuntimeExecution,
|
|
19140
|
-
forbidDirectThrows: effectOptions.forbidDirectThrows ?? DEFAULT_EFFECT_ANALYSIS_OPTIONS.forbidDirectThrows
|
|
19144
|
+
forbidDirectThrows: effectOptions.forbidDirectThrows ?? DEFAULT_EFFECT_ANALYSIS_OPTIONS.forbidDirectThrows,
|
|
19145
|
+
requireRetryPolicy: effectOptions.requireRetryPolicy ?? DEFAULT_EFFECT_ANALYSIS_OPTIONS.requireRetryPolicy
|
|
19141
19146
|
}
|
|
19142
19147
|
};
|
|
19143
19148
|
if (ctx.effectOptions.forbidDirectRuntimeExecution) {
|
|
@@ -19960,6 +19965,21 @@ function resolveStaticObjectLiteral(input, ctx, seen = new Set) {
|
|
|
19960
19965
|
}
|
|
19961
19966
|
return ts7.isObjectLiteralExpression(input) ? input : undefined;
|
|
19962
19967
|
}
|
|
19968
|
+
function resolveStaticArrayLiteral(input, ctx, seen = new Set) {
|
|
19969
|
+
if (!input || seen.has(input))
|
|
19970
|
+
return;
|
|
19971
|
+
seen.add(input);
|
|
19972
|
+
if (ts7.isAsExpression(input) || ts7.isSatisfiesExpression(input) || ts7.isParenthesizedExpression(input)) {
|
|
19973
|
+
return resolveStaticArrayLiteral(input.expression, ctx, seen);
|
|
19974
|
+
}
|
|
19975
|
+
if (ts7.isIdentifier(input)) {
|
|
19976
|
+
const declaration = resolveDeclaration(input, ctx).find(ts7.isVariableDeclaration);
|
|
19977
|
+
const list = declaration?.parent;
|
|
19978
|
+
const isConst = Boolean(list && ts7.isVariableDeclarationList(list) && (list.flags & ts7.NodeFlags.Const) !== 0);
|
|
19979
|
+
return isConst && declaration?.initializer ? resolveStaticArrayLiteral(declaration.initializer, ctx, seen) : undefined;
|
|
19980
|
+
}
|
|
19981
|
+
return ts7.isArrayLiteralExpression(input) ? input : undefined;
|
|
19982
|
+
}
|
|
19963
19983
|
function routePolicyProperty(object, name, ctx, seen = new Set) {
|
|
19964
19984
|
if (seen.has(object))
|
|
19965
19985
|
return { unresolved: true };
|
|
@@ -20920,7 +20940,7 @@ function parseController(input, ctx) {
|
|
|
20920
20940
|
file,
|
|
20921
20941
|
line: lineOf(effectExpr),
|
|
20922
20942
|
message: `Route ${route.handler} effect must be a statically resolvable object literal.`,
|
|
20923
|
-
suggestion:
|
|
20943
|
+
suggestion: 'Use effect: { required: true, errors: [...], dependencies: [...], retry: "none" }.'
|
|
20924
20944
|
});
|
|
20925
20945
|
} else {
|
|
20926
20946
|
const effect = { required: true };
|
|
@@ -20951,6 +20971,8 @@ function parseController(input, ctx) {
|
|
|
20951
20971
|
} else {
|
|
20952
20972
|
effect.retry = retry;
|
|
20953
20973
|
}
|
|
20974
|
+
} else if (ctx.effectOptions.requireRetryPolicy === false) {
|
|
20975
|
+
effect.retry = "none";
|
|
20954
20976
|
}
|
|
20955
20977
|
const maxAttemptsExpr = getProp(effectObject, "maxAttempts");
|
|
20956
20978
|
if (maxAttemptsExpr !== undefined) {
|
|
@@ -20999,7 +21021,8 @@ function parseController(input, ctx) {
|
|
|
20999
21021
|
}
|
|
21000
21022
|
const dependenciesExpr = getProp(effectObject, "dependencies");
|
|
21001
21023
|
if (dependenciesExpr !== undefined) {
|
|
21002
|
-
|
|
21024
|
+
const dependenciesArray = resolveStaticArrayLiteral(dependenciesExpr, ctx);
|
|
21025
|
+
if (!dependenciesArray || dependenciesArray.elements.some((element) => !ts7.isStringLiteral(element) || element.text.trim().length === 0)) {
|
|
21003
21026
|
ctx.diagnostics.push({
|
|
21004
21027
|
severity: "error",
|
|
21005
21028
|
code: "invalid-effect-dependencies",
|
|
@@ -21007,10 +21030,10 @@ function parseController(input, ctx) {
|
|
|
21007
21030
|
docsUrl: "https://supacloud.dev/errors/SC3033",
|
|
21008
21031
|
file,
|
|
21009
21032
|
line: lineOf(dependenciesExpr),
|
|
21010
|
-
message: `Route ${route.handler} effect.dependencies must be
|
|
21033
|
+
message: `Route ${route.handler} effect.dependencies must be a string array or a const initialized with one.`
|
|
21011
21034
|
});
|
|
21012
21035
|
} else {
|
|
21013
|
-
effect.dependencies =
|
|
21036
|
+
effect.dependencies = dependenciesArray.elements.map((element) => element.text);
|
|
21014
21037
|
if (new Set(effect.dependencies).size !== effect.dependencies.length) {
|
|
21015
21038
|
ctx.diagnostics.push({
|
|
21016
21039
|
severity: "error",
|
|
@@ -21027,7 +21050,8 @@ function parseController(input, ctx) {
|
|
|
21027
21050
|
}
|
|
21028
21051
|
const errorsExpr = getProp(effectObject, "errors");
|
|
21029
21052
|
if (errorsExpr !== undefined) {
|
|
21030
|
-
|
|
21053
|
+
const errorsArray = resolveStaticArrayLiteral(errorsExpr, ctx);
|
|
21054
|
+
if (!errorsArray) {
|
|
21031
21055
|
ctx.diagnostics.push({
|
|
21032
21056
|
severity: "error",
|
|
21033
21057
|
code: "invalid-effect-errors",
|
|
@@ -21035,11 +21059,11 @@ function parseController(input, ctx) {
|
|
|
21035
21059
|
docsUrl: "https://supacloud.dev/errors/SC3034",
|
|
21036
21060
|
file,
|
|
21037
21061
|
line: lineOf(errorsExpr),
|
|
21038
|
-
message: `Route ${route.handler} effect.errors must be an
|
|
21062
|
+
message: `Route ${route.handler} effect.errors must be an object array or a const initialized with one.`
|
|
21039
21063
|
});
|
|
21040
21064
|
} else {
|
|
21041
21065
|
const errors = [];
|
|
21042
|
-
for (const errorExpr of
|
|
21066
|
+
for (const errorExpr of errorsArray.elements) {
|
|
21043
21067
|
if (!ts7.isObjectLiteralExpression(errorExpr)) {
|
|
21044
21068
|
ctx.diagnostics.push({
|
|
21045
21069
|
severity: "error",
|
|
@@ -21056,6 +21080,23 @@ function parseController(input, ctx) {
|
|
|
21056
21080
|
const code = stringLiteralProp(errorExpr, "code");
|
|
21057
21081
|
const status = numberLiteralProp(errorExpr, "status");
|
|
21058
21082
|
const message = stringLiteralProp(errorExpr, "message");
|
|
21083
|
+
const codeFromError = booleanLiteralProp(errorExpr, "codeFromError");
|
|
21084
|
+
const messageFromError = booleanLiteralProp(errorExpr, "messageFromError");
|
|
21085
|
+
const statusFromError = booleanLiteralProp(errorExpr, "statusFromError");
|
|
21086
|
+
const retryable = booleanLiteralProp(errorExpr, "retryable");
|
|
21087
|
+
const outcomeUnknown = booleanLiteralProp(errorExpr, "outcomeUnknown");
|
|
21088
|
+
if (invalidBooleanProp(errorExpr, "codeFromError") || invalidBooleanProp(errorExpr, "messageFromError") || invalidBooleanProp(errorExpr, "statusFromError") || invalidBooleanProp(errorExpr, "retryable") || invalidBooleanProp(errorExpr, "outcomeUnknown")) {
|
|
21089
|
+
ctx.diagnostics.push({
|
|
21090
|
+
severity: "error",
|
|
21091
|
+
code: "invalid-effect-errors",
|
|
21092
|
+
errorCode: "SC3034",
|
|
21093
|
+
docsUrl: "https://supacloud.dev/errors/SC3034",
|
|
21094
|
+
file,
|
|
21095
|
+
line: lineOf(errorExpr),
|
|
21096
|
+
message: `Route ${route.handler} effect.errors instance flags must be boolean literals.`
|
|
21097
|
+
});
|
|
21098
|
+
continue;
|
|
21099
|
+
}
|
|
21059
21100
|
if (!tag || !code || status === undefined || !Number.isInteger(status) || status < 400 || status > 599) {
|
|
21060
21101
|
ctx.diagnostics.push({
|
|
21061
21102
|
severity: "error",
|
|
@@ -21068,7 +21109,17 @@ function parseController(input, ctx) {
|
|
|
21068
21109
|
});
|
|
21069
21110
|
continue;
|
|
21070
21111
|
}
|
|
21071
|
-
errors.push({
|
|
21112
|
+
errors.push({
|
|
21113
|
+
tag,
|
|
21114
|
+
code,
|
|
21115
|
+
status,
|
|
21116
|
+
...message === undefined ? {} : { message },
|
|
21117
|
+
...codeFromError === undefined ? {} : { codeFromError },
|
|
21118
|
+
...messageFromError === undefined ? {} : { messageFromError },
|
|
21119
|
+
...statusFromError === undefined ? {} : { statusFromError },
|
|
21120
|
+
...retryable === undefined ? {} : { retryable },
|
|
21121
|
+
...outcomeUnknown === undefined ? {} : { outcomeUnknown }
|
|
21122
|
+
});
|
|
21072
21123
|
}
|
|
21073
21124
|
effect.errors = errors;
|
|
21074
21125
|
if (new Set(errors.map((entry) => entry.tag)).size !== errors.length) {
|
|
@@ -21796,6 +21847,19 @@ function numberLiteralProp(obj, name) {
|
|
|
21796
21847
|
const value = Number(expr.text);
|
|
21797
21848
|
return Number.isFinite(value) ? value : undefined;
|
|
21798
21849
|
}
|
|
21850
|
+
function booleanLiteralProp(obj, name) {
|
|
21851
|
+
const expr = getProp(obj, name);
|
|
21852
|
+
if (!expr || !isBooleanLiteral(expr))
|
|
21853
|
+
return;
|
|
21854
|
+
return expr.kind === ts7.SyntaxKind.TrueKeyword;
|
|
21855
|
+
}
|
|
21856
|
+
function isBooleanLiteral(expr) {
|
|
21857
|
+
return expr.kind === ts7.SyntaxKind.TrueKeyword || expr.kind === ts7.SyntaxKind.FalseKeyword;
|
|
21858
|
+
}
|
|
21859
|
+
function invalidBooleanProp(obj, name) {
|
|
21860
|
+
const expr = getProp(obj, name);
|
|
21861
|
+
return expr !== undefined && !isBooleanLiteral(expr);
|
|
21862
|
+
}
|
|
21799
21863
|
function arrayProp(obj, name) {
|
|
21800
21864
|
const expr = getProp(obj, name);
|
|
21801
21865
|
return expr && ts7.isArrayLiteralExpression(expr) ? [...expr.elements] : [];
|
|
@@ -22738,6 +22802,9 @@ function validateEffectPolicies(graph, options = {}) {
|
|
|
22738
22802
|
if (options.requireDependencies && effect.dependencies === undefined) {
|
|
22739
22803
|
diagnostics.push(diagnostic("effect-dependencies-required", `Route ${label} declares an Effect contract without dependencies.`, controller.file, "Declare the logical services required by the Effect environment."));
|
|
22740
22804
|
}
|
|
22805
|
+
if (effect.retry === undefined && options.requireRetryPolicy !== false) {
|
|
22806
|
+
diagnostics.push(diagnostic("effect-retry-required", `Route ${label} declares an Effect contract but does not declare retry.`, controller.file, 'Set effect.retry to "none". That is the required default; use "explicit" only with maxAttempts and a retryable 5xx allow-list.'));
|
|
22807
|
+
}
|
|
22741
22808
|
if (effect.retry === "explicit" && effect.maxAttempts === undefined) {
|
|
22742
22809
|
diagnostics.push(diagnostic("invalid-effect-retry", `Route ${label} enables explicit Effect retry without maxAttempts.`, controller.file, "Declare a positive maxAttempts value including the initial attempt."));
|
|
22743
22810
|
}
|
|
@@ -22748,6 +22815,18 @@ function validateEffectPolicies(graph, options = {}) {
|
|
|
22748
22815
|
if (command && command.idempotency !== "required") {
|
|
22749
22816
|
diagnostics.push(diagnostic("effect-command-retry-forbidden", `Route ${label} enables explicit Effect retry for non-idempotent command "${command.name}".`, controller.file, 'Set command idempotency to "required" or use effect.retry: "none".'));
|
|
22750
22817
|
}
|
|
22818
|
+
const retryable = (effect.errors ?? []).filter((entry) => entry.retryable === true);
|
|
22819
|
+
if (retryable.length === 0) {
|
|
22820
|
+
diagnostics.push(diagnostic("effect-retry-target-required", `Route ${label} enables explicit Effect retry without a transient failure allow-list.`, controller.file, 'Mark only 5xx failures that did not commit with retryable: true, or use effect.retry: "none".'));
|
|
22821
|
+
}
|
|
22822
|
+
}
|
|
22823
|
+
for (const entry of effect.errors ?? []) {
|
|
22824
|
+
if (entry.retryable !== true)
|
|
22825
|
+
continue;
|
|
22826
|
+
const transient = effect.retry === "explicit" && entry.outcomeUnknown !== true && entry.statusFromError !== true && entry.status >= 500 && entry.status <= 599;
|
|
22827
|
+
if (!transient) {
|
|
22828
|
+
diagnostics.push(diagnostic("effect-retryable-invalid", `Route ${label} marks "${entry.tag}" retryable, but in-process retry is only for declared 5xx failures that are not outcome-unknown.`, controller.file, 'Remove retryable, or keep it on a 5xx mapping with retry: "explicit" and without outcomeUnknown or statusFromError.'));
|
|
22829
|
+
}
|
|
22751
22830
|
}
|
|
22752
22831
|
}
|
|
22753
22832
|
}
|
|
@@ -24991,10 +25070,10 @@ import { readFileSync as readFileSync4 } from "node:fs";
|
|
|
24991
25070
|
import { resolve as resolve17 } from "node:path";
|
|
24992
25071
|
|
|
24993
25072
|
// src/migration-app-version.ts
|
|
24994
|
-
var MIGRATION_APP_VERSION = "0.
|
|
25073
|
+
var MIGRATION_APP_VERSION = "0.36.0";
|
|
24995
25074
|
|
|
24996
25075
|
// src/migration-elysia-version.ts
|
|
24997
|
-
var MIGRATION_ELYSIA_VERSION = "0.
|
|
25076
|
+
var MIGRATION_ELYSIA_VERSION = "0.38.0";
|
|
24998
25077
|
|
|
24999
25078
|
// src/migration-policy.ts
|
|
25000
25079
|
var cachedCompilerVersion;
|
|
@@ -25013,7 +25092,7 @@ function migrationDependencies() {
|
|
|
25013
25092
|
"@supacloud/app": MIGRATION_APP_VERSION,
|
|
25014
25093
|
"@supacloud/compiler": compilerVersion(),
|
|
25015
25094
|
"@supacloud/elysia": MIGRATION_ELYSIA_VERSION,
|
|
25016
|
-
elysia: "2.0.0-rc.
|
|
25095
|
+
elysia: "2.0.0-rc.1",
|
|
25017
25096
|
typescript: "7.0.2"
|
|
25018
25097
|
};
|
|
25019
25098
|
}
|
|
@@ -26357,7 +26436,9 @@ var DEFAULT_SUPACLOUD_CONFIG = {
|
|
|
26357
26436
|
requireExactDependencyTypes: true,
|
|
26358
26437
|
requireTimeoutForDependencies: true,
|
|
26359
26438
|
forbidDirectRuntimeExecution: true,
|
|
26360
|
-
forbidDirectThrows: true
|
|
26439
|
+
forbidDirectThrows: true,
|
|
26440
|
+
requireRetryPolicy: true,
|
|
26441
|
+
defaultRetry: "none"
|
|
26361
26442
|
}
|
|
26362
26443
|
};
|
|
26363
26444
|
function defineSupacloudConfig(config = {}) {
|
|
@@ -26439,7 +26520,9 @@ function validateGovernanceConfig(config) {
|
|
|
26439
26520
|
"requireExactDependencyTypes",
|
|
26440
26521
|
"requireTimeoutForDependencies",
|
|
26441
26522
|
"forbidDirectRuntimeExecution",
|
|
26442
|
-
"forbidDirectThrows"
|
|
26523
|
+
"forbidDirectThrows",
|
|
26524
|
+
"requireRetryPolicy",
|
|
26525
|
+
"defaultRetry"
|
|
26443
26526
|
].includes(key))) {
|
|
26444
26527
|
throw new Error("effect contains an unsupported governance option.");
|
|
26445
26528
|
}
|
|
@@ -26451,12 +26534,16 @@ function validateGovernanceConfig(config) {
|
|
|
26451
26534
|
"requireExactDependencyTypes",
|
|
26452
26535
|
"requireTimeoutForDependencies",
|
|
26453
26536
|
"forbidDirectRuntimeExecution",
|
|
26454
|
-
"forbidDirectThrows"
|
|
26537
|
+
"forbidDirectThrows",
|
|
26538
|
+
"requireRetryPolicy"
|
|
26455
26539
|
]) {
|
|
26456
26540
|
if (config.effect[key] !== undefined && typeof config.effect[key] !== "boolean") {
|
|
26457
26541
|
throw new Error(`effect.${key} must be boolean.`);
|
|
26458
26542
|
}
|
|
26459
26543
|
}
|
|
26544
|
+
if (config.effect["defaultRetry"] !== undefined && config.effect["defaultRetry"] !== "none") {
|
|
26545
|
+
throw new Error('effect.defaultRetry must be "none". explicit can only be written on a route, with maxAttempts and a retryable 5xx allow-list.');
|
|
26546
|
+
}
|
|
26460
26547
|
}
|
|
26461
26548
|
}
|
|
26462
26549
|
function resolveSupacloudConfig(config = {}, cwd = process.cwd()) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const MIGRATION_APP_VERSION = "0.
|
|
1
|
+
export declare const MIGRATION_APP_VERSION = "0.36.0";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const MIGRATION_ELYSIA_VERSION = "0.
|
|
1
|
+
export declare const MIGRATION_ELYSIA_VERSION = "0.38.0";
|
package/dist/types.d.ts
CHANGED
|
@@ -191,6 +191,19 @@ export interface EffectErrorMappingNode {
|
|
|
191
191
|
status: number;
|
|
192
192
|
code: string;
|
|
193
193
|
message?: string;
|
|
194
|
+
/** Use the failure value's own `code` string when it is non-empty and bounded. */
|
|
195
|
+
codeFromError?: boolean;
|
|
196
|
+
/** Use the failure value's own `message` string when it is non-empty and bounded. */
|
|
197
|
+
messageFromError?: boolean;
|
|
198
|
+
/** Use the failure value's own HTTP status when it is an integer from 400 to 599. */
|
|
199
|
+
statusFromError?: boolean;
|
|
200
|
+
/**
|
|
201
|
+
* In-process retry allow-list. Only a declared 5xx failure that did not
|
|
202
|
+
* commit may be retried by the framework adapter.
|
|
203
|
+
*/
|
|
204
|
+
retryable?: boolean;
|
|
205
|
+
/** The write may already have happened. The framework adapter must not retry it. */
|
|
206
|
+
outcomeUnknown?: boolean;
|
|
194
207
|
}
|
|
195
208
|
export interface EffectRouteNode {
|
|
196
209
|
required: true;
|
|
@@ -511,6 +524,13 @@ export interface EffectCompilerOptions {
|
|
|
511
524
|
forbidDirectRuntimeExecution?: boolean;
|
|
512
525
|
/** Reject direct throw statements inside governed route handlers. */
|
|
513
526
|
forbidDirectThrows?: boolean;
|
|
527
|
+
/** Require every route that declares an Effect contract to write an explicit retry policy. */
|
|
528
|
+
requireRetryPolicy?: boolean;
|
|
529
|
+
/**
|
|
530
|
+
* Materialize an omitted retry policy when requireRetryPolicy is disabled.
|
|
531
|
+
* The only project-level default is "none"; "explicit" stays route-local.
|
|
532
|
+
*/
|
|
533
|
+
defaultRetry?: "none";
|
|
514
534
|
}
|
|
515
535
|
export interface GraphqlOptions {
|
|
516
536
|
/** Additionally emit standard TypedDocumentNode artifacts for GraphQL ecosystem clients. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@supacloud/compiler",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.54.0",
|
|
4
4
|
"description": "Static compiler for @supacloud/app metadata: builds the application graph from AST, validates it, and generates reflection-free factory code",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"directory": "packages/compiler"
|
|
58
58
|
},
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"@supacloud/db": "0.20.
|
|
60
|
+
"@supacloud/db": "0.20.4",
|
|
61
61
|
"@supacloud/delivery": "0.24.0",
|
|
62
62
|
"typebox": "1.4.3",
|
|
63
63
|
"@graphql-codegen/core": "^6.2.2",
|