@akanjs/devkit 3.1.1 → 3.1.2-rc.1
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/akanConfig/akanConfig.test.ts +75 -0
- package/akanConfig/akanConfig.ts +11 -1
- package/akanMcpContract.test.ts +28 -1
- package/akanMcpContract.ts +51 -3
- package/applicationBuildRunner.test.ts +36 -0
- package/applicationBuildRunner.ts +4 -3
- package/artifact/implicitRootLayout.ts +4 -2
- package/cloud/globalConfig.test.ts +34 -0
- package/cloud/globalConfig.ts +2 -2
- package/codeAgent/agent/AkanCodeEnv.ts +26 -0
- package/codeAgent/agent/AkanCodeServices.ts +5 -2
- package/codeAgent/agent/CodeAgent.ts +7 -0
- package/codeAgent/agent/CodeAgentGate.ts +156 -10
- package/codeAgent/agent/CodeAgentProxy.ts +5 -4
- package/codeAgent/agent/CodeAgentRpcHost.ts +3 -0
- package/codeAgent/agent/CodeAgentRpcListener.ts +102 -16
- package/codeAgent/agent/WorkspaceTrust.ts +200 -0
- package/codeAgent/agent/akanCodePaths.ts +8 -1
- package/codeAgent/agent/akanSystemPrompt.ts +4 -0
- package/codeAgent/agent/codeAgentContract.test.ts +119 -0
- package/codeAgent/agent/codeAgentHosts.ts +30 -0
- package/codeAgent/agent/codeAgentProxy.test.ts +53 -1
- package/codeAgent/agent/codeAgentRpcListener.test.ts +115 -13
- package/codeAgent/agent/stringArg.ts +1 -1
- package/codeAgent/skills/akan-agent/SKILL.md +8 -1
- package/codeAgent/skills/akan-code/SKILL.md +37 -11
- package/codeAgent/skills/akan-debug/SKILL.md +2 -1
- package/codeAgent/skills/akan-err/SKILL.md +2 -1
- package/codeAgent/skills/akan-query/SKILL.md +3 -2
- package/codeAgent/skills/akan-runtime/SKILL.md +3 -0
- package/codeAgent/tools/McpServerConfig.ts +6 -4
- package/codeAgent/tools/McpSignIn.ts +7 -7
- package/codeAgent/tools/McpTokenStore.ts +63 -16
- package/codeAgent/tools/McpToolPack.ts +8 -1
- package/codeAgent/tools/WebToolPack.ts +50 -6
- package/codeAgent/tools/akanCodePlugins.test.ts +70 -2
- package/codeAgent/tools/mcpOAuth.test.ts +50 -14
- package/codeAgent/tools/mcpServerConfig.test.ts +130 -1
- package/commandDecorators/command.ts +4 -1
- package/createTunnel.test.ts +200 -2
- package/createTunnel.ts +80 -6
- package/envSeed.test.ts +90 -0
- package/envSeed.ts +68 -0
- package/executors.test.ts +19 -1
- package/executors.ts +41 -2
- package/fileSys.test.ts +30 -2
- package/fileSys.ts +14 -0
- package/formSetterScanner.test.ts +44 -1
- package/formSetterScanner.ts +53 -8
- package/frontendBuild/csrArtifactBuilder.ts +7 -0
- package/frontendBuild/mcpAppViewBuilder.test.ts +63 -0
- package/frontendBuild/mcpAppViewBuilder.ts +7 -1
- package/frontendBuild/optionalPeers.test.ts +132 -0
- package/integration/ssrMemoryProbe.ts +6 -0
- package/lint/no-unguarded-endpoint.grit +5 -5
- package/maintainabilityReport.ts +1 -1
- package/mobile/desktopServerStage.test.ts +1 -0
- package/mobile/desktopServerStage.ts +3 -1
- package/mobile/nativeApp.test.ts +20 -5
- package/mobile/nativeApp.ts +4 -1
- package/mobile/nativeConfig.test.ts +209 -5
- package/mobile/nativeConfig.ts +127 -6
- package/mobile/nativePublicEnv.test.ts +2 -0
- package/mobile/nativePublicEnv.ts +13 -0
- package/package.json +3 -2
- package/shellOnlyEnv.test.ts +65 -0
- package/shellOnlyEnv.ts +54 -0
- package/signalMutationIndex.ts +22 -81
- package/sshHostKeys.ts +59 -0
- package/storeSource.ts +9 -8
- package/subspace.test.ts +10 -0
- package/subspaceClone.ts +3 -1
- package/subspaceConfig.ts +6 -0
- package/transforms/barrelImportsPlugin.ts +10 -4
- package/transforms/mcpAppPageTrimmer.test.ts +8 -2
- package/transforms/mcpAppPageTrimmer.ts +5 -20
- package/transforms/pureLazyMarker.ts +1 -1
- package/workflow/mutationScaffold.ts +35 -21
- package/workflow/plan.ts +28 -0
- package/workflow/sourceAst.ts +10 -48
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { lowerlize } from "akanjs/common";
|
|
1
|
+
import { lowerlize, modelNames } from "akanjs/common";
|
|
2
2
|
import type { Sys } from "../commandDecorators";
|
|
3
3
|
import { GuardCatalog } from "./guardCatalog";
|
|
4
4
|
import { type MutationActingUser, type MutationCall, MutationSource } from "./mutationSource";
|
|
@@ -53,20 +53,34 @@ export class MutationScaffold {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
static reservedNamesOf(modelClassName: string) {
|
|
56
|
-
const
|
|
57
|
-
const prefixed = ["light", "create", "update", "remove", "view", "edit", "merge", "get", "load", "set", "reset"];
|
|
56
|
+
const names = modelNames(lowerlize(modelClassName));
|
|
58
57
|
return new Set([
|
|
59
|
-
model,
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
58
|
+
names.model,
|
|
59
|
+
names.lightModel,
|
|
60
|
+
names.createModel,
|
|
61
|
+
names.updateModel,
|
|
62
|
+
names.removeModel,
|
|
63
|
+
names.viewModel,
|
|
64
|
+
names.editModel,
|
|
65
|
+
names.mergeModel,
|
|
66
|
+
names.getModel,
|
|
67
|
+
names.loadModel,
|
|
68
|
+
names.setModel,
|
|
69
|
+
names.resetModel,
|
|
70
|
+
names.newModel,
|
|
71
|
+
names.submitModel,
|
|
72
|
+
names.invalidateModel,
|
|
73
|
+
names.createModelInForm,
|
|
74
|
+
names.updateModelInForm,
|
|
75
|
+
names.loadModelMany,
|
|
76
|
+
names.getModelView,
|
|
77
|
+
names.getModelEdit,
|
|
78
|
+
names.addModelFiles,
|
|
79
|
+
names.checkModelSubmitable,
|
|
80
|
+
names.writeOnModel,
|
|
81
|
+
names.loadModelFormDraft,
|
|
82
|
+
names.restoreModelFormDraft,
|
|
83
|
+
names.discardModelFormDraft,
|
|
70
84
|
]);
|
|
71
85
|
}
|
|
72
86
|
|
|
@@ -415,17 +429,17 @@ export class MutationScaffold {
|
|
|
415
429
|
#parametersOf(service: ServiceSource, ref: string, method: string) {
|
|
416
430
|
const declared = classMethodParameters(service.content, service.className, method);
|
|
417
431
|
if (declared) return declared;
|
|
418
|
-
const
|
|
432
|
+
const names = modelNames(lowerlize(moduleComponentName(ref)));
|
|
419
433
|
const generated: Record<string, { name: string; optional: boolean }[]> = {
|
|
420
|
-
[
|
|
421
|
-
[
|
|
422
|
-
[
|
|
423
|
-
[
|
|
424
|
-
[
|
|
434
|
+
[names.getModel]: [{ name: "id", optional: false }],
|
|
435
|
+
[names.loadModel]: [{ name: "id", optional: true }],
|
|
436
|
+
[names.loadModelMany]: [{ name: "ids", optional: false }],
|
|
437
|
+
[names.createModel]: [{ name: "data", optional: false }],
|
|
438
|
+
[names.updateModel]: [
|
|
425
439
|
{ name: "id", optional: false },
|
|
426
440
|
{ name: "data", optional: false },
|
|
427
441
|
],
|
|
428
|
-
[
|
|
442
|
+
[names.removeModel]: [{ name: "id", optional: false }],
|
|
429
443
|
};
|
|
430
444
|
return generated[method] ?? null;
|
|
431
445
|
}
|
package/workflow/plan.ts
CHANGED
|
@@ -19,6 +19,24 @@ import { addFieldUiPolicyForType } from "./uiPolicy";
|
|
|
19
19
|
|
|
20
20
|
const surfaceModes = new Set<WorkflowSurfaceMode>(["infer", "include", "skip"]);
|
|
21
21
|
|
|
22
|
+
const sysNamePattern = /^[a-z0-9][a-zA-Z0-9_-]*$/;
|
|
23
|
+
const identifierPattern = /^_{0,2}[a-zA-Z][a-zA-Z0-9_-]*$/;
|
|
24
|
+
//? These inputs become path segments, identifiers and command arguments, so none may carry a separator or a dot.
|
|
25
|
+
const nameInputPatterns: Record<string, RegExp> = {
|
|
26
|
+
app: sysNamePattern,
|
|
27
|
+
module: identifierPattern,
|
|
28
|
+
scalar: identifierPattern,
|
|
29
|
+
field: identifierPattern,
|
|
30
|
+
slice: identifierPattern,
|
|
31
|
+
mutation: identifierPattern,
|
|
32
|
+
interaction: identifierPattern,
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const isWorkflowSysName = (value: unknown): value is string =>
|
|
36
|
+
typeof value === "string" && sysNamePattern.test(value);
|
|
37
|
+
export const isWorkflowModuleName = (value: unknown): value is string =>
|
|
38
|
+
typeof value === "string" && identifierPattern.test(value);
|
|
39
|
+
|
|
22
40
|
const parseStringList = (value: unknown) => {
|
|
23
41
|
if (Array.isArray(value)) {
|
|
24
42
|
const values = value.filter((item): item is string => typeof item === "string" && item.trim().length > 0);
|
|
@@ -365,6 +383,16 @@ export const createWorkflowPlan = (spec: WorkflowSpec, rawInputs: Record<string,
|
|
|
365
383
|
});
|
|
366
384
|
continue;
|
|
367
385
|
}
|
|
386
|
+
const namePattern = nameInputPatterns[name];
|
|
387
|
+
if (namePattern && typeof value === "string" && !namePattern.test(value)) {
|
|
388
|
+
diagnostics.push({
|
|
389
|
+
severity: "error",
|
|
390
|
+
code: "workflow-input-invalid",
|
|
391
|
+
input: name,
|
|
392
|
+
message: `Workflow ${spec.name} input "${name}" must be a plain name without dots, slashes or spaces, not ${JSON.stringify(value)}.`,
|
|
393
|
+
});
|
|
394
|
+
continue;
|
|
395
|
+
}
|
|
368
396
|
if (inputSpec.allowedValues && typeof value === "string" && !inputSpec.allowedValues.includes(value)) {
|
|
369
397
|
diagnostics.push({
|
|
370
398
|
severity: "error",
|
package/workflow/sourceAst.ts
CHANGED
|
@@ -1,50 +1,12 @@
|
|
|
1
|
+
import { createAst } from "@akanjs/language";
|
|
1
2
|
import ts from "typescript";
|
|
2
3
|
|
|
3
|
-
export const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
export const propertyName = (node: ts.ObjectLiteralElementLike) =>
|
|
13
|
-
ts.isPropertyAssignment(node) || ts.isShorthandPropertyAssignment(node) || ts.isMethodDeclaration(node)
|
|
14
|
-
? nodeName(node.name)
|
|
15
|
-
: null;
|
|
16
|
-
|
|
17
|
-
export const expressionName = (expression: ts.Expression): string | null => {
|
|
18
|
-
if (ts.isIdentifier(expression)) return expression.text;
|
|
19
|
-
if (ts.isPropertyAccessExpression(expression)) return expression.name.text;
|
|
20
|
-
if (ts.isCallExpression(expression)) return expressionName(expression.expression);
|
|
21
|
-
if (ts.isAsExpression(expression)) return expressionName(expression.expression);
|
|
22
|
-
return null;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export const callExpressionName = (node: ts.CallExpression) =>
|
|
26
|
-
ts.isPropertyAccessExpression(node.expression) ? node.expression.name.text : expressionName(node.expression);
|
|
27
|
-
|
|
28
|
-
export const firstObjectReturnedByArrow = (node: ts.Node): ts.ObjectLiteralExpression | null => {
|
|
29
|
-
if (!ts.isArrowFunction(node) && !ts.isFunctionExpression(node)) return null;
|
|
30
|
-
if (ts.isObjectLiteralExpression(node.body)) return node.body;
|
|
31
|
-
if (ts.isParenthesizedExpression(node.body) && ts.isObjectLiteralExpression(node.body.expression)) {
|
|
32
|
-
return node.body.expression;
|
|
33
|
-
}
|
|
34
|
-
if (!ts.isBlock(node.body)) return null;
|
|
35
|
-
for (const statement of node.body.statements) {
|
|
36
|
-
if (ts.isReturnStatement(statement) && statement.expression && ts.isObjectLiteralExpression(statement.expression)) {
|
|
37
|
-
return statement.expression;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
return null;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
const isViaCall = (expression: ts.Expression) =>
|
|
44
|
-
ts.isCallExpression(expression) && expressionName(expression.expression) === "via";
|
|
45
|
-
|
|
46
|
-
export const heritageCall = (node: ts.ClassDeclaration) => {
|
|
47
|
-
const heritage = node.heritageClauses?.flatMap((clause) => [...clause.types]) ?? [];
|
|
48
|
-
const expression = heritage.find((clause) => isViaCall(clause.expression))?.expression;
|
|
49
|
-
return expression && ts.isCallExpression(expression) ? expression : null;
|
|
50
|
-
};
|
|
4
|
+
export const {
|
|
5
|
+
sourceFileFor,
|
|
6
|
+
nodeName,
|
|
7
|
+
propertyName,
|
|
8
|
+
expressionName,
|
|
9
|
+
callExpressionName,
|
|
10
|
+
firstObjectReturnedByArrow,
|
|
11
|
+
heritageCall,
|
|
12
|
+
} = createAst(ts);
|