proteum 2.1.0 → 2.1.2

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 (95) hide show
  1. package/AGENTS.md +44 -98
  2. package/README.md +143 -10
  3. package/agents/framework/AGENTS.md +146 -886
  4. package/agents/project/AGENTS.md +73 -127
  5. package/agents/project/client/AGENTS.md +22 -93
  6. package/agents/project/client/pages/AGENTS.md +24 -26
  7. package/agents/project/server/routes/AGENTS.md +10 -8
  8. package/agents/project/server/services/AGENTS.md +22 -159
  9. package/agents/project/tests/AGENTS.md +11 -8
  10. package/cli/app/config.ts +7 -20
  11. package/cli/bin.js +8 -0
  12. package/cli/commands/command.ts +243 -0
  13. package/cli/commands/commandLocalRunner.js +198 -0
  14. package/cli/commands/create.ts +5 -0
  15. package/cli/commands/deploy/web.ts +1 -2
  16. package/cli/commands/dev.ts +98 -2
  17. package/cli/commands/doctor.ts +8 -74
  18. package/cli/commands/explain.ts +8 -186
  19. package/cli/commands/init.ts +2 -94
  20. package/cli/commands/trace.ts +228 -0
  21. package/cli/compiler/artifacts/commands.ts +217 -0
  22. package/cli/compiler/artifacts/manifest.ts +35 -21
  23. package/cli/compiler/artifacts/services.ts +300 -1
  24. package/cli/compiler/client/index.ts +43 -8
  25. package/cli/compiler/common/commands.ts +175 -0
  26. package/cli/compiler/common/index.ts +1 -1
  27. package/cli/compiler/common/proteumManifest.ts +15 -114
  28. package/cli/compiler/index.ts +25 -2
  29. package/cli/compiler/server/index.ts +31 -6
  30. package/cli/index.ts +1 -4
  31. package/cli/paths.ts +16 -1
  32. package/cli/presentation/commands.ts +104 -14
  33. package/cli/presentation/devSession.ts +22 -3
  34. package/cli/presentation/proteum_logo_400x400_square_icon.txt +400 -0
  35. package/cli/runtime/commands.ts +121 -4
  36. package/cli/scaffold/index.ts +720 -0
  37. package/cli/scaffold/templates.ts +344 -0
  38. package/cli/scaffold/types.ts +26 -0
  39. package/cli/tsconfig.json +4 -1
  40. package/cli/utils/check.ts +1 -1
  41. package/client/app/component.tsx +13 -9
  42. package/client/dev/profiler/index.tsx +2511 -0
  43. package/client/dev/profiler/noop.tsx +5 -0
  44. package/client/dev/profiler/runtime.noop.ts +116 -0
  45. package/client/dev/profiler/runtime.ts +840 -0
  46. package/client/services/router/components/router.tsx +30 -2
  47. package/client/services/router/index.tsx +27 -3
  48. package/client/services/router/request/api.ts +133 -17
  49. package/commands/proteum/diagnostics.ts +11 -0
  50. package/common/dev/commands.ts +50 -0
  51. package/common/dev/diagnostics.ts +298 -0
  52. package/common/dev/profiler.ts +92 -0
  53. package/common/dev/proteumManifest.ts +135 -0
  54. package/common/dev/requestTrace.ts +115 -0
  55. package/common/env/proteumEnv.ts +284 -0
  56. package/common/router/index.ts +4 -22
  57. package/docs/dev-commands.md +93 -0
  58. package/docs/diagnostics.md +88 -0
  59. package/docs/request-tracing.md +132 -0
  60. package/eslint.js +11 -6
  61. package/package.json +3 -3
  62. package/server/app/commands.ts +35 -370
  63. package/server/app/commandsManager.ts +393 -0
  64. package/server/app/container/config.ts +11 -49
  65. package/server/app/container/console/index.ts +2 -3
  66. package/server/app/container/index.ts +5 -2
  67. package/server/app/container/trace/index.ts +364 -0
  68. package/server/app/devCommands.ts +192 -0
  69. package/server/app/devDiagnostics.ts +53 -0
  70. package/server/app/index.ts +29 -6
  71. package/server/index.ts +0 -1
  72. package/server/services/auth/index.ts +525 -61
  73. package/server/services/auth/router/index.ts +106 -7
  74. package/server/services/cron/CronTask.ts +73 -5
  75. package/server/services/cron/index.ts +34 -11
  76. package/server/services/fetch/index.ts +3 -10
  77. package/server/services/prisma/index.ts +66 -4
  78. package/server/services/router/http/index.ts +173 -6
  79. package/server/services/router/index.ts +200 -12
  80. package/server/services/router/request/api.ts +30 -1
  81. package/server/services/router/response/index.ts +83 -10
  82. package/server/services/router/response/page/document.tsx +16 -0
  83. package/server/services/router/response/page/index.tsx +27 -1
  84. package/skills/clean-project-code/SKILL.md +7 -2
  85. package/test-results/.last-run.json +4 -0
  86. package/types/aliases.d.ts +6 -0
  87. package/types/global/utils.d.ts +7 -14
  88. package/Rte.zip +0 -0
  89. package/agents/project/agents.md.zip +0 -0
  90. package/doc/TODO.md +0 -71
  91. package/doc/front/router.md +0 -27
  92. package/doc/workspace/workspace.png +0 -0
  93. package/doc/workspace/workspace2.png +0 -0
  94. package/doc/workspace/workspace_26.01.22.png +0 -0
  95. package/server/services/router/http/session.ts.old +0 -40
@@ -0,0 +1,344 @@
1
+ import type { TScaffoldInitConfig, TScaffoldResult } from './types';
2
+
3
+ const renderJson = (value: unknown) => JSON.stringify(value, null, 4);
4
+
5
+ export const createPageTemplate = ({
6
+ routePath,
7
+ heading,
8
+ message,
9
+ }: {
10
+ routePath: string;
11
+ heading: string;
12
+ message: string;
13
+ }) => `import Router from '@/client/router';
14
+
15
+ Router.page(
16
+ ${JSON.stringify(routePath)},
17
+ () => ({
18
+ _auth: false,
19
+ _layout: false,
20
+ heading: ${JSON.stringify(heading)},
21
+ message: ${JSON.stringify(message)},
22
+ }),
23
+ ({ heading, message }) => {
24
+ return (
25
+ <main>
26
+ <h1>{heading}</h1>
27
+ <p>{message}</p>
28
+ </main>
29
+ );
30
+ },
31
+ );
32
+ `;
33
+
34
+ export const createControllerTemplate = ({
35
+ appIdentifier,
36
+ className,
37
+ methodName,
38
+ }: {
39
+ appIdentifier: string;
40
+ className: string;
41
+ methodName: string;
42
+ }) => `import Controller from '@server/app/controller';
43
+
44
+ export default class ${className} extends Controller<${appIdentifier}> {
45
+ public async ${methodName}() {
46
+ return {
47
+ ok: true,
48
+ };
49
+ }
50
+ }
51
+ `;
52
+
53
+ export const createCommandTemplate = ({
54
+ className,
55
+ methodName,
56
+ }: {
57
+ className: string;
58
+ methodName: string;
59
+ }) => `import { Commands } from '@server/app/commands';
60
+ import type App from '@/server/index';
61
+
62
+ export default class ${className} extends Commands<App> {
63
+ public async ${methodName}() {
64
+ return {
65
+ ok: true,
66
+ app: this.app.identity.identifier,
67
+ };
68
+ }
69
+ }
70
+ `;
71
+
72
+ export const createRouteTemplate = ({
73
+ httpMethod,
74
+ routePath,
75
+ }: {
76
+ httpMethod: string;
77
+ routePath: string;
78
+ }) => `import { Router } from '@app';
79
+
80
+ Router.${httpMethod}(${JSON.stringify(routePath)}, {}, async () => {
81
+ return {
82
+ ok: true,
83
+ };
84
+ });
85
+ `;
86
+
87
+ export const createServiceTemplate = ({
88
+ appIdentifier,
89
+ className,
90
+ }: {
91
+ appIdentifier: string;
92
+ className: string;
93
+ }) => `import Service from '@server/app/service';
94
+
95
+ export type Config = {
96
+ debug?: boolean;
97
+ };
98
+
99
+ export default class ${className} extends Service<Config, {}, ${appIdentifier}, ${appIdentifier}> {
100
+ public async health() {
101
+ return {
102
+ ok: true,
103
+ };
104
+ }
105
+ }
106
+ `;
107
+
108
+ export const createServiceConfigTemplate = ({
109
+ configExportName,
110
+ serviceImportPath,
111
+ serviceImportName,
112
+ }: {
113
+ configExportName: string;
114
+ serviceImportPath: string;
115
+ serviceImportName: string;
116
+ }) => `import { Services } from '@server/app';
117
+ import ${serviceImportName} from ${JSON.stringify(serviceImportPath)};
118
+
119
+ export const ${configExportName} = Services.config(${serviceImportName}, {});
120
+ `;
121
+
122
+ export const createRouterConfigTemplate = () => `import { type ServiceConfig } from '@server/app';
123
+ import AppContainer from '@server/app/container';
124
+ import Router from '@server/services/router';
125
+
126
+ type RouterBaseConfig = Omit<ServiceConfig<typeof Router>, 'plugins'>;
127
+
128
+ const currentDomain = AppContainer.Environment.router.currentDomain;
129
+ const currentUrl = new URL(currentDomain);
130
+
131
+ export const routerBaseConfig = {
132
+ currentDomain,
133
+ http: {
134
+ domain: currentUrl.hostname,
135
+ port: AppContainer.Environment.router.port,
136
+ ssl: currentUrl.protocol === 'https:',
137
+ upload: {
138
+ maxSize: '10mb',
139
+ },
140
+ },
141
+ context: () => ({}),
142
+ } satisfies RouterBaseConfig;
143
+ `;
144
+
145
+ export const createServerIndexTemplate = ({ appIdentifier }: { appIdentifier: string }) => `import { Application } from '@server/app';
146
+ import Router from '@server/services/router';
147
+ import SchemaRouter from '@server/services/schema/router';
148
+
149
+ import * as appConfig from '@/server/config/app';
150
+
151
+ export default class ${appIdentifier} extends Application {
152
+ public Router = new Router(
153
+ this,
154
+ {
155
+ ...appConfig.routerBaseConfig,
156
+ plugins: {
157
+ schema: new SchemaRouter({}, this),
158
+ },
159
+ },
160
+ this,
161
+ );
162
+ }
163
+ `;
164
+
165
+ export const createClientTsconfigTemplate = () => `{
166
+ "extends": "../node_modules/proteum/tsconfig.common.json",
167
+ "compilerOptions": {
168
+ "rootDir": "..",
169
+ "baseUrl": "..",
170
+ "noImplicitAny": true,
171
+ "noImplicitThis": true,
172
+ "strictBindCallApply": true,
173
+ "useUnknownInCatchVariables": true,
174
+ "paths": {
175
+ "@client/*": ["./node_modules/proteum/client/*"],
176
+ "@common/*": ["./node_modules/proteum/common/*"],
177
+ "@server/*": ["./node_modules/proteum/server/*"],
178
+
179
+ "@/client/context": ["./.proteum/client/context.ts"],
180
+ "@generated/client/*": ["./.proteum/client/*"],
181
+ "@generated/common/*": ["./.proteum/common/*"],
182
+ "@generated/server/*": ["./.proteum/server/*"],
183
+ "@/*": ["./*"],
184
+
185
+ "react": ["./node_modules/preact/compat"],
186
+ "react-dom/test-utils": ["./node_modules/preact/test-utils"],
187
+ "react-dom": ["./node_modules/preact/compat"],
188
+ "react/jsx-runtime": ["./node_modules/preact/jsx-runtime"]
189
+ }
190
+ },
191
+ "include": [
192
+ ".",
193
+ "../var/typings",
194
+ "../node_modules/proteum/types/global",
195
+ "../.proteum/client/services.d.ts",
196
+ "../server/index.ts"
197
+ ]
198
+ }
199
+ `;
200
+
201
+ export const createServerTsconfigTemplate = () => `{
202
+ "extends": "../node_modules/proteum/tsconfig.common.json",
203
+ "compilerOptions": {
204
+ "rootDir": "..",
205
+ "baseUrl": "..",
206
+ "noImplicitAny": true,
207
+ "noImplicitThis": true,
208
+ "strictBindCallApply": true,
209
+ "useUnknownInCatchVariables": true,
210
+ "moduleSuffixes": [".ssr", ""],
211
+ "paths": {
212
+ "@client/*": ["./node_modules/proteum/client/*"],
213
+ "@common/*": ["./node_modules/proteum/common/*"],
214
+ "@server/*": ["./node_modules/proteum/server/*"],
215
+
216
+ "@/client/context": ["./.proteum/client/context.ts"],
217
+ "@generated/client/*": ["./.proteum/client/*"],
218
+ "@generated/common/*": ["./.proteum/common/*"],
219
+ "@generated/server/*": ["./.proteum/server/*"],
220
+ "@/*": ["./*"],
221
+
222
+ "react": ["./node_modules/preact/compat"],
223
+ "react-dom/test-utils": ["./node_modules/preact/test-utils"],
224
+ "react-dom": ["./node_modules/preact/compat"],
225
+ "react/jsx-runtime": ["./node_modules/preact/jsx-runtime"]
226
+ }
227
+ },
228
+ "include": [
229
+ ".",
230
+ "../var/typings",
231
+ "../node_modules/proteum/types/global",
232
+ "../.proteum/server/services.d.ts",
233
+ "../server/index.ts"
234
+ ]
235
+ }
236
+ `;
237
+
238
+ export const createGitignoreTemplate = () => `node_modules
239
+ .proteum
240
+ .cache
241
+ bin
242
+ dev
243
+ var
244
+ .env
245
+ `;
246
+
247
+ export const createEnvTemplate = ({ port, url }: { port: number; url: string }) => `ENV_NAME=local
248
+ ENV_PROFILE=dev
249
+ PORT=${port}
250
+ URL=${url}
251
+
252
+ # Optional trace settings
253
+ # TRACE_ENABLE=true
254
+ # TRACE_CAPTURE=resolve
255
+ # TRACE_PERSIST_ON_ERROR=true
256
+ `;
257
+
258
+ export const createEslintConfigTemplate = () => `import proteumEslint from 'proteum/eslint.js';
259
+
260
+ const { createProteumEslintConfig } = proteumEslint;
261
+
262
+ export default createProteumEslintConfig();
263
+ `;
264
+
265
+ export const createPackageJsonTemplate = ({
266
+ packageName,
267
+ appDescription,
268
+ proteumDependency,
269
+ preactDependency,
270
+ }: {
271
+ packageName: string;
272
+ appDescription: string;
273
+ proteumDependency: string;
274
+ preactDependency: string;
275
+ }) =>
276
+ `${renderJson({
277
+ name: packageName,
278
+ version: '0.0.1',
279
+ private: true,
280
+ engines: {
281
+ node: '>=20.19.0',
282
+ npm: '>=3.10.10',
283
+ },
284
+ browserslist: ['>1%', 'not dead', 'not op_mini all'],
285
+ scripts: {
286
+ dev: 'NODE_ENV=development proteum dev',
287
+ refresh: 'npx proteum refresh',
288
+ typecheck: 'npx proteum typecheck',
289
+ lint: 'npx proteum lint',
290
+ check: 'npx proteum check',
291
+ build: 'npx proteum build --prod',
292
+ start: 'NODE_ENV=production node ./bin/server.js',
293
+ },
294
+ description: appDescription,
295
+ dependencies: {
296
+ preact: preactDependency,
297
+ proteum: proteumDependency,
298
+ },
299
+ })}\n`;
300
+
301
+ export const createIdentityTemplate = ({
302
+ appName,
303
+ appIdentifier,
304
+ appDescription,
305
+ }: {
306
+ appName: string;
307
+ appIdentifier: string;
308
+ appDescription: string;
309
+ }) => `name: ${appName}
310
+ identifier: ${appIdentifier}
311
+ description: ${JSON.stringify(appDescription)}
312
+
313
+ author:
314
+ name: ${appName}
315
+ url: localhost
316
+ email: team@example.com
317
+
318
+ social:
319
+
320
+ language: en
321
+ locale: en-US
322
+ maincolor: white
323
+ iconsPack: light
324
+
325
+ web:
326
+ title: ${JSON.stringify(appName)}
327
+ titleSuffix: ${JSON.stringify(appName)}
328
+ fullTitle: ${JSON.stringify(appName)}
329
+ description: ${JSON.stringify(appDescription)}
330
+ version: 0.0.1
331
+ `;
332
+
333
+ export const createInitSummary = (result: TScaffoldResult, config: TScaffoldInitConfig) => ({
334
+ ...result,
335
+ project: {
336
+ directory: config.directory,
337
+ name: config.name,
338
+ identifier: config.identifier,
339
+ port: config.port,
340
+ url: config.url,
341
+ proteumDependency: config.proteumDependency,
342
+ install: config.install,
343
+ },
344
+ });
@@ -0,0 +1,26 @@
1
+ export type TScaffoldKind = 'page' | 'controller' | 'command' | 'route' | 'service';
2
+
3
+ export type TScaffoldFilePlan = {
4
+ relativePath: string;
5
+ content: string;
6
+ };
7
+
8
+ export type TScaffoldResult = {
9
+ dryRun: boolean;
10
+ created: string[];
11
+ updated: string[];
12
+ skipped: string[];
13
+ notes: string[];
14
+ nextSteps: string[];
15
+ };
16
+
17
+ export type TScaffoldInitConfig = {
18
+ directory: string;
19
+ name: string;
20
+ identifier: string;
21
+ description: string;
22
+ port: number;
23
+ url: string;
24
+ install: boolean;
25
+ proteumDependency: string;
26
+ };
package/cli/tsconfig.json CHANGED
@@ -29,9 +29,12 @@
29
29
  "outDir": "./bin",
30
30
 
31
31
  "paths": {
32
+ "@client/*": [ "../client/*" ],
32
33
  "@cli/*": [ "./*" ],
33
34
  "@cli/app": [ "./app" ],
34
- "@cli": [ "./" ]
35
+ "@cli": [ "./" ],
36
+ "@common/*": [ "../common/*" ],
37
+ "@server/*": [ "../server/*" ]
35
38
  },
36
39
  },
37
40
 
@@ -5,7 +5,7 @@ import cli from '..';
5
5
  import Compiler from '../compiler';
6
6
  import { runProcess } from './runProcess';
7
7
 
8
- const tsconfigPaths = ['client/tsconfig.json', 'server/tsconfig.json'];
8
+ const tsconfigPaths = ['client/tsconfig.json', 'server/tsconfig.json', 'commands/tsconfig.json'];
9
9
  const eslintConfigPaths = ['eslint.config.mjs', 'eslint.config.js', 'eslint.config.cjs'];
10
10
 
11
11
  const resolveInstalledBinary = (name: string) => {
@@ -21,10 +21,17 @@ export default function App({ context }: { context: ClientContext }) {
21
21
  const curLayout = context.page?.layout;
22
22
  const [layout, setLayout] = React.useState<Layout | false | undefined>(curLayout);
23
23
  const [apiData, setApiData] = React.useState<{ [k: string]: any } | null>(context.page?.data || {});
24
+ const shouldEnableDevProfiler = __DEV__ && typeof window !== 'undefined' && window.dev;
25
+ const [isDevProfilerMounted, setDevProfilerMounted] = React.useState(false);
24
26
 
25
27
  // TODO: context.page is always provided in the context on the client side
26
28
  if (context.app.side === 'client') context.app.setLayout = setLayout;
27
29
 
30
+ React.useEffect(() => {
31
+ if (!shouldEnableDevProfiler) return;
32
+ setDevProfilerMounted(true);
33
+ }, [shouldEnableDevProfiler]);
34
+
28
35
  const layoutProps: LayoutProps = {
29
36
  ...context,
30
37
  context,
@@ -32,22 +39,19 @@ export default function App({ context }: { context: ClientContext }) {
32
39
  menu: undefined,
33
40
  children: undefined,
34
41
  };
42
+ const DevProfiler = shouldEnableDevProfiler
43
+ ? ((require('@client/dev/profiler') as typeof import('@client/dev/profiler')).default as React.ComponentType)
44
+ : null;
35
45
 
36
46
  return (
37
47
  <ReactClientContext.Provider value={context}>
38
48
  <DialogManager />
49
+ {DevProfiler && isDevProfilerMounted ? <DevProfiler /> : null}
39
50
 
40
51
  {!layout ? (
41
- <>
42
- {/* TODO: move to app, because here, we're not aware that the router service has been defined */}
43
- <RouterComponent service={context.Router} />
44
- </>
52
+ <RouterComponent service={context.Router} />
45
53
  ) : (
46
- <>
47
- {' '}
48
- {/* Same as router/components/Page.tsx */}
49
- <layout.Component {...layoutProps} />
50
- </>
54
+ <layout.Component {...layoutProps} />
51
55
  )}
52
56
  </ReactClientContext.Provider>
53
57
  );