proteum 2.2.6 → 2.2.8
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/AGENTS.md +1 -1
- package/README.md +4 -4
- package/agents/project/AGENTS.md +2 -1
- package/agents/project/app-root/AGENTS.md +1 -1
- package/agents/project/diagnostics.md +1 -1
- package/agents/project/root/AGENTS.md +2 -1
- package/cli/commands/configure.ts +14 -35
- package/cli/commands/dev.ts +105 -52
- package/cli/compiler/artifacts/controllers.ts +30 -4
- package/cli/compiler/artifacts/manifest.ts +1 -5
- package/cli/compiler/artifacts/services.ts +67 -29
- package/cli/presentation/commands.ts +9 -9
- package/cli/presentation/help.ts +1 -1
- package/cli/scaffold/index.ts +2 -5
- package/cli/scaffold/templates.ts +3 -10
- package/cli/utils/agents.ts +281 -199
- package/client/dev/profiler/ApexChart.tsx +4 -3
- package/common/dev/serverHotReload.ts +26 -25
- package/package.json +1 -1
- package/server/app/commands.ts +11 -16
- package/server/app/commandsManager.ts +5 -1
- package/server/app/controller/index.ts +68 -16
- package/server/app/devCommands.ts +3 -3
- package/server/app/devDiagnostics.ts +2 -2
- package/server/app/index.ts +19 -8
- package/server/app/service/container.ts +22 -19
- package/server/app/service/index.ts +33 -13
- package/server/app.tsconfig.json +0 -1
- package/server/services/auth/index.ts +12 -6
- package/server/services/auth/router/index.ts +12 -14
- package/server/services/auth/router/request.ts +34 -13
- package/server/services/disks/driver.ts +1 -1
- package/server/services/disks/index.ts +11 -8
- package/server/services/email/index.ts +1 -1
- package/server/services/prisma/Facet.ts +6 -5
- package/server/services/router/index.ts +8 -7
- package/server/services/router/request/validation/zod.ts +2 -0
- package/server/services/router/response/index.ts +9 -9
- package/server/services/router/service.ts +12 -8
- package/tests/agents-utils.test.cjs +207 -0
- package/tests/dev-transpile-watch.test.cjs +513 -0
- package/types/global/vendors.d.ts +70 -0
|
@@ -711,6 +711,68 @@ ${classMembers.join('\n')}
|
|
|
711
711
|
};
|
|
712
712
|
};
|
|
713
713
|
|
|
714
|
+
const isNamespaceImportDeclaration = (statement: ts.ImportDeclaration) =>
|
|
715
|
+
statement.importClause?.namedBindings !== undefined && ts.isNamespaceImport(statement.importClause.namedBindings);
|
|
716
|
+
|
|
717
|
+
const isClientServerStubSupportStatement = (statement: ts.Statement, appClassIdentifier: string) => {
|
|
718
|
+
if (ts.isTypeAliasDeclaration(statement)) {
|
|
719
|
+
return !new Set([
|
|
720
|
+
`${appClassIdentifier}Disks`,
|
|
721
|
+
`${appClassIdentifier}Router`,
|
|
722
|
+
`${appClassIdentifier}RouterPlugins`,
|
|
723
|
+
]).has(statement.name.text);
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
return ts.isInterfaceDeclaration(statement) || ts.isModuleDeclaration(statement);
|
|
727
|
+
};
|
|
728
|
+
|
|
729
|
+
const createClientServerIndexDeclaration = (rootServices: TParsedService[]) => {
|
|
730
|
+
const sourceFile = createSourceFile(getAppServerEntryFilepath());
|
|
731
|
+
const appClass = getDefaultExportClassDeclaration(sourceFile);
|
|
732
|
+
const serviceTypesByRegisteredName = new Map(
|
|
733
|
+
rootServices.map((service) => [service.registeredName, `import("${service.importPath}").default`] as const),
|
|
734
|
+
);
|
|
735
|
+
|
|
736
|
+
const imports = sourceFile.statements
|
|
737
|
+
.filter((statement): statement is ts.ImportDeclaration => ts.isImportDeclaration(statement))
|
|
738
|
+
.filter((statement) => !isNamespaceImportDeclaration(statement))
|
|
739
|
+
.map((statement) => statement.getText(sourceFile));
|
|
740
|
+
const supportStatements = sourceFile.statements
|
|
741
|
+
.slice(0, sourceFile.statements.indexOf(appClass))
|
|
742
|
+
.filter((statement) => isClientServerStubSupportStatement(statement, app.identity.identifier))
|
|
743
|
+
.map((statement) => statement.getText(sourceFile));
|
|
744
|
+
const heritageClauses = appClass.heritageClauses?.map((clause) => clause.getText(sourceFile)).join(' ');
|
|
745
|
+
const properties = appClass.members
|
|
746
|
+
.filter((member): member is ts.PropertyDeclaration => ts.isPropertyDeclaration(member))
|
|
747
|
+
.filter((member) => !isPrivateOrProtectedInstanceMember(member))
|
|
748
|
+
.map((property) => {
|
|
749
|
+
const propertyName = getPropertyNameText(property.name);
|
|
750
|
+
if (!propertyName) return undefined;
|
|
751
|
+
|
|
752
|
+
const propertyType =
|
|
753
|
+
propertyName === 'Disks'
|
|
754
|
+
? 'object'
|
|
755
|
+
: propertyName === 'Router'
|
|
756
|
+
? `${app.identity.identifier}Router`
|
|
757
|
+
: property.type?.getText(sourceFile) || serviceTypesByRegisteredName.get(propertyName);
|
|
758
|
+
if (!propertyType) return undefined;
|
|
759
|
+
|
|
760
|
+
return ` public ${propertyName}: ${propertyType};`;
|
|
761
|
+
})
|
|
762
|
+
.filter((property): property is string => property !== undefined);
|
|
763
|
+
|
|
764
|
+
return `${imports.join('\n')}
|
|
765
|
+
|
|
766
|
+
${supportStatements.join('\n\n')}
|
|
767
|
+
|
|
768
|
+
type ${app.identity.identifier}Router = Router<${app.identity.identifier}>;
|
|
769
|
+
|
|
770
|
+
export default class ${app.identity.identifier}${heritageClauses ? ` ${heritageClauses}` : ''} {
|
|
771
|
+
${properties.join('\n')}
|
|
772
|
+
}
|
|
773
|
+
`;
|
|
774
|
+
};
|
|
775
|
+
|
|
714
776
|
const resolveManifestService = (service: TParsedService, parent: string): TProteumManifestService => ({
|
|
715
777
|
kind: 'service',
|
|
716
778
|
registeredName: service.registeredName,
|
|
@@ -730,6 +792,11 @@ export const generateServiceArtifacts = () => {
|
|
|
730
792
|
const routerPluginServices = routerPlugins.map((service) => resolveManifestService(service, 'Router.plugins'));
|
|
731
793
|
const commandServiceStubs = createCommandServiceStubDeclarations(rootServices);
|
|
732
794
|
|
|
795
|
+
writeIfChanged(
|
|
796
|
+
path.join(app.paths.client.generated, 'server-index.d.ts'),
|
|
797
|
+
createClientServerIndexDeclaration(rootServices),
|
|
798
|
+
);
|
|
799
|
+
|
|
733
800
|
writeIfChanged(
|
|
734
801
|
path.join(app.paths.client.generated, 'services.d.ts'),
|
|
735
802
|
`declare type ${appClassIdentifier} = import("@/server/index").default;
|
|
@@ -737,18 +804,9 @@ export const generateServiceArtifacts = () => {
|
|
|
737
804
|
declare module "@app" {
|
|
738
805
|
|
|
739
806
|
import { ${appClassIdentifier} as ${appClassIdentifier}Client } from "@/client";
|
|
740
|
-
import ${appClassIdentifier}Server from "@/server/index";
|
|
741
807
|
|
|
742
808
|
export const Router: ${appClassIdentifier}Client['Router'];
|
|
743
809
|
|
|
744
|
-
${rootServices
|
|
745
|
-
.map((service) =>
|
|
746
|
-
service.registeredName !== 'Router'
|
|
747
|
-
? `export const ${service.registeredName}: ${appClassIdentifier}Server["${service.registeredName}"];`
|
|
748
|
-
: '',
|
|
749
|
-
)
|
|
750
|
-
.join('\n')}
|
|
751
|
-
|
|
752
810
|
}
|
|
753
811
|
|
|
754
812
|
declare module '@models/types' {
|
|
@@ -894,26 +952,6 @@ declare module "@app" {
|
|
|
894
952
|
export = ServerServices
|
|
895
953
|
}
|
|
896
954
|
|
|
897
|
-
declare module '@server/app' {
|
|
898
|
-
|
|
899
|
-
import { Application } from "@server/app";
|
|
900
|
-
import { Environment } from "@server/app";
|
|
901
|
-
import { ServicesContainer } from "@server/app/service/container";
|
|
902
|
-
|
|
903
|
-
abstract class ApplicationWithServices extends Application<
|
|
904
|
-
ServicesContainer<InstalledServices>
|
|
905
|
-
> {}
|
|
906
|
-
|
|
907
|
-
export interface Exported {
|
|
908
|
-
Application: typeof ApplicationWithServices,
|
|
909
|
-
Environment: Environment,
|
|
910
|
-
}
|
|
911
|
-
|
|
912
|
-
const foo: Exported;
|
|
913
|
-
|
|
914
|
-
export = foo;
|
|
915
|
-
}
|
|
916
|
-
|
|
917
955
|
declare module '@common/errors' {
|
|
918
956
|
|
|
919
957
|
export * from '@common/errors/index';
|
|
@@ -113,22 +113,22 @@ export const proteumCommands: Record<TProteumCommandName, TProteumCommandDoc> =
|
|
|
113
113
|
configure: {
|
|
114
114
|
name: 'configure',
|
|
115
115
|
category: 'Project scaffolding',
|
|
116
|
-
summary: 'Interactively configure Proteum
|
|
116
|
+
summary: 'Interactively configure tracked Proteum instruction files for a standalone app or monorepo app root.',
|
|
117
117
|
usage: 'proteum configure agents',
|
|
118
118
|
bestFor:
|
|
119
|
-
'Creating or switching the
|
|
119
|
+
'Creating or switching the tracked instruction layout intentionally while keeping Proteum-owned instructions embedded in managed sections.',
|
|
120
120
|
examples: [
|
|
121
121
|
{
|
|
122
|
-
description: 'Configure instruction
|
|
122
|
+
description: 'Configure instruction files for the current standalone app',
|
|
123
123
|
command: 'proteum configure agents',
|
|
124
124
|
},
|
|
125
125
|
],
|
|
126
126
|
notes: [
|
|
127
|
-
'This command is interactive. It asks whether the current Proteum app belongs to a monorepo and, if so, which ancestor path should receive the reusable root `AGENTS.md`
|
|
128
|
-
'Standalone mode writes
|
|
129
|
-
'Monorepo mode writes the reusable root `AGENTS.md` into the chosen monorepo root and
|
|
130
|
-
'
|
|
131
|
-
'
|
|
127
|
+
'This command is interactive. It asks whether the current Proteum app belongs to a monorepo and, if so, which ancestor path should receive the reusable root `AGENTS.md` file.',
|
|
128
|
+
'Standalone mode writes tracked instruction files into the current Proteum app root.',
|
|
129
|
+
'Monorepo mode writes the reusable root `AGENTS.md` into the chosen monorepo root and the app-root instruction files into the current Proteum app root.',
|
|
130
|
+
'Every managed instruction file contains a `# Proteum Instructions` section with the full embedded Proteum project instruction corpus.',
|
|
131
|
+
'Existing content outside `# Proteum Instructions` is preserved. Directories and foreign symlinks are replaced only after confirmation.',
|
|
132
132
|
],
|
|
133
133
|
status: 'experimental',
|
|
134
134
|
},
|
|
@@ -191,7 +191,7 @@ export const proteumCommands: Record<TProteumCommandName, TProteumCommandDoc> =
|
|
|
191
191
|
notes: [
|
|
192
192
|
'Use `--cwd` when the target Proteum app lives in another worktree or checkout and you do not want to `cd` first.',
|
|
193
193
|
'Proteum writes a machine-readable dev session file under `var/run/proteum/dev/<port>.json` by default; override it with `--session-file` when an agent needs a stable path.',
|
|
194
|
-
'Before the
|
|
194
|
+
'Before the dev loop starts, Proteum ensures tracked instruction files contain the current managed `# Proteum Instructions` section.',
|
|
195
195
|
'Use `--replace-existing` when retries should stop the previously tracked matching session before starting a new one.',
|
|
196
196
|
'`proteum dev list` inspects tracked sessions for the current app root. Add `--stale` to show only orphaned or dead sessions.',
|
|
197
197
|
'`proteum dev stop` targets the current session file by default. Add `--all` to stop every tracked session for the current app root.',
|
package/cli/presentation/help.ts
CHANGED
|
@@ -139,7 +139,7 @@ export const renderCliOverview = async ({
|
|
|
139
139
|
indent: ' ',
|
|
140
140
|
nextIndent: ' ',
|
|
141
141
|
}),
|
|
142
|
-
wrapText('
|
|
142
|
+
wrapText('Before the dev loop starts, `proteum dev` ensures tracked instruction files contain the current managed `# Proteum Instructions` section.', {
|
|
143
143
|
indent: ' ',
|
|
144
144
|
nextIndent: ' ',
|
|
145
145
|
}),
|
package/cli/scaffold/index.ts
CHANGED
|
@@ -5,7 +5,6 @@ import { UsageError } from 'clipanion';
|
|
|
5
5
|
|
|
6
6
|
import cli from '..';
|
|
7
7
|
import { loadApplicationIdentityConfig } from '../../common/applicationConfigLoader';
|
|
8
|
-
import { renderProjectInstructionGitignoreBlock } from '../utils/agents';
|
|
9
8
|
import { runProcess } from '../utils/runProcess';
|
|
10
9
|
import {
|
|
11
10
|
createClientTsconfigTemplate,
|
|
@@ -656,9 +655,7 @@ const createInitFilePlans = ({ appRoot, config }: { appRoot: string; config: TSc
|
|
|
656
655
|
},
|
|
657
656
|
{
|
|
658
657
|
relativePath: '.gitignore',
|
|
659
|
-
content: createGitignoreTemplate(
|
|
660
|
-
projectInstructionGitignoreBlock: renderProjectInstructionGitignoreBlock({ coreRoot: cli.paths.core.root }),
|
|
661
|
-
}),
|
|
658
|
+
content: createGitignoreTemplate(),
|
|
662
659
|
},
|
|
663
660
|
{
|
|
664
661
|
relativePath: 'eslint.config.mjs',
|
|
@@ -727,7 +724,7 @@ export const runInitScaffold = async () => {
|
|
|
727
724
|
? 'Run `npm run dev` in the new app directory.'
|
|
728
725
|
: 'Run `npm install`, then `npm run dev` in the new app directory.',
|
|
729
726
|
);
|
|
730
|
-
result.nextSteps.push('Run `proteum configure agents` when you want Proteum
|
|
727
|
+
result.nextSteps.push('Run `proteum configure agents` when you want tracked Proteum instruction files.');
|
|
731
728
|
result.nextSteps.push('Use `proteum create page|controller|command|route|service ...` to add app artifacts.');
|
|
732
729
|
|
|
733
730
|
printResult(result, createInitSummary(result, config));
|
|
@@ -191,6 +191,7 @@ export const createClientTsconfigTemplate = (paths: TTsconfigTemplatePaths) => `
|
|
|
191
191
|
"@server/*": [${JSON.stringify(paths.frameworkServer)}],
|
|
192
192
|
|
|
193
193
|
"@/client/context": ["./.proteum/client/context.ts"],
|
|
194
|
+
"@/server/index": ["./.proteum/client/server-index.d.ts"],
|
|
194
195
|
"@generated/client/*": ["./.proteum/client/*"],
|
|
195
196
|
"@generated/common/*": ["./.proteum/common/*"],
|
|
196
197
|
"@generated/server/*": ["./.proteum/server/*"],
|
|
@@ -207,8 +208,7 @@ export const createClientTsconfigTemplate = (paths: TTsconfigTemplatePaths) => `
|
|
|
207
208
|
".",
|
|
208
209
|
"../var/typings",
|
|
209
210
|
${JSON.stringify(paths.frameworkTypesGlobal)},
|
|
210
|
-
"../.proteum/client/services.d.ts"
|
|
211
|
-
"../server/index.ts"
|
|
211
|
+
"../.proteum/client/services.d.ts"
|
|
212
212
|
]
|
|
213
213
|
}
|
|
214
214
|
`;
|
|
@@ -228,7 +228,6 @@ export const createServerTsconfigTemplate = (paths: TTsconfigTemplatePaths) => `
|
|
|
228
228
|
"@common/*": [${JSON.stringify(paths.frameworkCommon)}],
|
|
229
229
|
"@server/*": [${JSON.stringify(paths.frameworkServer)}],
|
|
230
230
|
|
|
231
|
-
"@/client/context": ["./.proteum/client/context.ts"],
|
|
232
231
|
"@generated/client/*": ["./.proteum/client/*"],
|
|
233
232
|
"@generated/common/*": ["./.proteum/common/*"],
|
|
234
233
|
"@generated/server/*": ["./.proteum/server/*"],
|
|
@@ -253,11 +252,7 @@ export const createServerTsconfigTemplate = (paths: TTsconfigTemplatePaths) => `
|
|
|
253
252
|
}
|
|
254
253
|
`;
|
|
255
254
|
|
|
256
|
-
export const createGitignoreTemplate = (
|
|
257
|
-
projectInstructionGitignoreBlock,
|
|
258
|
-
}: {
|
|
259
|
-
projectInstructionGitignoreBlock: string;
|
|
260
|
-
}) => `node_modules
|
|
255
|
+
export const createGitignoreTemplate = () => `node_modules
|
|
261
256
|
/.proteum
|
|
262
257
|
/.cache
|
|
263
258
|
/bin
|
|
@@ -265,8 +260,6 @@ export const createGitignoreTemplate = ({
|
|
|
265
260
|
/var
|
|
266
261
|
/proteum.connected.json
|
|
267
262
|
.env
|
|
268
|
-
|
|
269
|
-
${projectInstructionGitignoreBlock}
|
|
270
263
|
`;
|
|
271
264
|
|
|
272
265
|
export const createEnvTemplate = ({ port, url }: { port: number; url: string }) => `ENV_NAME=local
|