proteum 1.0.3 → 2.0.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/AGENTS.md +92 -0
- package/agents/codex/AGENTS.md +95 -0
- package/agents/codex/CODING_STYLE.md +71 -0
- package/agents/codex/agents.md.zip +0 -0
- package/agents/codex/client/AGENTS.md +102 -0
- package/agents/codex/client/pages/AGENTS.md +35 -0
- package/agents/codex/server/routes/AGENTS.md +12 -0
- package/agents/codex/server/services/AGENTS.md +137 -0
- package/agents/codex/tests/AGENTS.md +8 -0
- package/cli/app/config.ts +12 -17
- package/cli/app/index.ts +59 -99
- package/cli/bin.js +1 -1
- package/cli/commands/build.ts +23 -12
- package/cli/commands/check.ts +19 -0
- package/cli/commands/deploy/app.ts +4 -8
- package/cli/commands/deploy/web.ts +16 -20
- package/cli/commands/dev.ts +185 -75
- package/cli/commands/devEvents.ts +106 -0
- package/cli/commands/init.ts +63 -57
- package/cli/commands/lint.ts +21 -0
- package/cli/commands/refresh.ts +6 -6
- package/cli/commands/typecheck.ts +18 -0
- package/cli/compiler/client/identite.ts +79 -49
- package/cli/compiler/client/index.ts +132 -214
- package/cli/compiler/common/bundleAnalysis.ts +94 -0
- package/cli/compiler/common/clientManifest.ts +67 -0
- package/cli/compiler/common/controllers.ts +288 -0
- package/cli/compiler/common/files/autres.ts +7 -18
- package/cli/compiler/common/files/images.ts +40 -37
- package/cli/compiler/common/files/style.ts +12 -25
- package/cli/compiler/common/generatedRouteModules.ts +368 -0
- package/cli/compiler/common/index.ts +29 -68
- package/cli/compiler/common/loaders/forbid-ssr-import.js +13 -0
- package/cli/compiler/common/rspackAliases.ts +13 -0
- package/cli/compiler/common/scripts.ts +37 -0
- package/cli/compiler/index.ts +764 -234
- package/cli/compiler/server/index.ts +52 -77
- package/cli/compiler/writeIfChanged.ts +21 -0
- package/cli/index.ts +65 -90
- package/cli/paths.ts +51 -57
- package/cli/print.ts +17 -11
- package/cli/tsconfig.json +5 -4
- package/cli/utils/agents.ts +100 -0
- package/cli/utils/check.ts +71 -0
- package/cli/utils/index.ts +1 -3
- package/cli/utils/keyboard.ts +8 -25
- package/cli/utils/runProcess.ts +30 -0
- package/client/app/component.tsx +29 -29
- package/client/app/index.ts +36 -57
- package/client/app/service.ts +7 -12
- package/client/app.tsconfig.json +2 -2
- package/client/components/Dialog/Manager.ssr.tsx +40 -0
- package/client/components/Dialog/Manager.tsx +119 -150
- package/client/components/Dialog/status.tsx +3 -3
- package/client/components/index.ts +1 -1
- package/client/components/types.d.ts +1 -3
- package/client/dev/hmr.ts +65 -0
- package/client/global.d.ts +2 -2
- package/client/hooks.ts +6 -9
- package/client/index.ts +2 -1
- package/client/islands/index.ts +7 -0
- package/client/islands/useDeferredModule.ts +199 -0
- package/client/pages/_layout/index.tsx +4 -12
- package/client/pages/useHeader.tsx +14 -21
- package/client/router.ts +27 -0
- package/client/services/router/components/Link.tsx +34 -27
- package/client/services/router/components/Page.tsx +6 -14
- package/client/services/router/components/router.ssr.tsx +36 -0
- package/client/services/router/components/router.tsx +63 -83
- package/client/services/router/index.tsx +185 -220
- package/client/services/router/request/api.ts +97 -119
- package/client/services/router/request/history.ts +2 -2
- package/client/services/router/request/index.ts +13 -12
- package/client/services/router/request/multipart.ts +72 -62
- package/client/services/router/response/index.tsx +68 -61
- package/client/services/router/response/page.ts +28 -32
- package/client/utils/dom.ts +17 -33
- package/common/app/index.ts +3 -3
- package/common/data/chaines/index.ts +22 -23
- package/common/data/dates.ts +35 -70
- package/common/data/markdown.ts +42 -39
- package/common/dev/serverHotReload.ts +26 -0
- package/common/errors/index.tsx +110 -142
- package/common/router/contracts.ts +29 -0
- package/common/router/index.ts +89 -108
- package/common/router/layouts.ts +34 -47
- package/common/router/pageSetup.ts +50 -0
- package/common/router/register.ts +53 -24
- package/common/router/request/api.ts +30 -36
- package/common/router/request/index.ts +2 -8
- package/common/router/response/index.ts +8 -15
- package/common/router/response/page.ts +70 -58
- package/common/utils.ts +1 -1
- package/eslint.js +62 -0
- package/package.json +12 -45
- package/prettier.config.cjs +9 -0
- package/scripts/cleanup-generated-controllers.ts +62 -0
- package/scripts/fix-reference-app-typing.ts +490 -0
- package/scripts/refactor-client-app-imports.ts +244 -0
- package/scripts/refactor-client-pages.ts +587 -0
- package/scripts/refactor-server-controllers.ts +470 -0
- package/scripts/refactor-server-runtime-aliases.ts +360 -0
- package/scripts/restore-client-app-import-files.ts +41 -0
- package/scripts/restore-files-from-git-head.ts +20 -0
- package/scripts/update-codex-agents.ts +35 -0
- package/server/app/commands.ts +35 -64
- package/server/app/container/config.ts +39 -69
- package/server/app/container/console/index.ts +202 -248
- package/server/app/container/index.ts +33 -71
- package/server/app/controller/index.ts +61 -0
- package/server/app/index.ts +39 -105
- package/server/app/service/container.ts +41 -42
- package/server/app/service/index.ts +120 -147
- package/server/context.ts +1 -1
- package/server/index.ts +25 -1
- package/server/services/auth/index.ts +75 -115
- package/server/services/auth/router/index.ts +31 -32
- package/server/services/auth/router/request.ts +14 -16
- package/server/services/cron/CronTask.ts +13 -26
- package/server/services/cron/index.ts +14 -36
- package/server/services/disks/driver.ts +40 -58
- package/server/services/disks/drivers/local/index.ts +79 -90
- package/server/services/disks/drivers/s3/index.ts +116 -163
- package/server/services/disks/index.ts +23 -38
- package/server/services/email/index.ts +45 -104
- package/server/services/email/utils.ts +14 -27
- package/server/services/fetch/index.ts +53 -85
- package/server/services/prisma/Facet.ts +39 -91
- package/server/services/prisma/index.ts +74 -110
- package/server/services/router/generatedRuntime.ts +29 -0
- package/server/services/router/http/index.ts +77 -72
- package/server/services/router/http/multipart.ts +19 -42
- package/server/services/router/index.ts +378 -365
- package/server/services/router/request/api.ts +26 -25
- package/server/services/router/request/index.ts +44 -51
- package/server/services/router/request/service.ts +7 -11
- package/server/services/router/request/validation/zod.ts +111 -148
- package/server/services/router/response/index.ts +110 -125
- package/server/services/router/response/mask/Filter.ts +31 -72
- package/server/services/router/response/mask/index.ts +8 -15
- package/server/services/router/response/mask/selecteurs.ts +11 -25
- package/server/services/router/response/page/clientManifest.ts +25 -0
- package/server/services/router/response/page/document.tsx +199 -127
- package/server/services/router/response/page/index.tsx +89 -94
- package/server/services/router/service.ts +13 -15
- package/server/services/schema/index.ts +17 -26
- package/server/services/schema/request.ts +19 -33
- package/server/services/schema/router/index.ts +8 -11
- package/server/services/security/encrypt/aes/index.ts +15 -35
- package/server/utils/slug.ts +29 -32
- package/skills/clean-project-code/SKILL.md +63 -0
- package/skills/clean-project-code/agents/openai.yaml +4 -0
- package/tsconfig.common.json +4 -3
- package/tsconfig.json +4 -1
- package/types/aliases.d.ts +17 -21
- package/types/controller-input.test.ts +48 -0
- package/types/express-extra.d.ts +6 -0
- package/types/global/constants.d.ts +1 -0
- package/types/global/express-extra.d.ts +6 -0
- package/types/global/modules.d.ts +13 -16
- package/types/global/utils.d.ts +17 -49
- package/types/global/vendors.d.ts +62 -0
- package/types/icons.d.ts +65 -1
- package/types/uuid.d.ts +3 -0
- package/types/vendors.d.ts +62 -0
- package/cli/compiler/common/babel/index.ts +0 -173
- package/cli/compiler/common/babel/plugins/index.ts +0 -0
- package/cli/compiler/common/babel/plugins/services.ts +0 -586
- package/cli/compiler/common/babel/routes/imports.ts +0 -127
- package/cli/compiler/common/babel/routes/routes.ts +0 -1170
- package/client/services/captcha/index.ts +0 -67
- package/client/services/socket/index.ts +0 -147
- package/common/data/rte/nodes.ts +0 -83
- package/common/data/stats.ts +0 -90
- package/common/utils/rte.ts +0 -183
- package/server/services/auth/old.ts +0 -277
- package/server/services/cache/commands.ts +0 -41
- package/server/services/cache/index.ts +0 -297
- package/server/services/cache/service.json +0 -6
- package/server/services/socket/index.ts +0 -162
- package/server/services/socket/scope.ts +0 -226
- package/server/services/socket/service.json +0 -6
- package/server/services_old/SocketClient.ts +0 -92
- package/server/services_old/Token.old.ts +0 -97
package/cli/paths.ts
CHANGED
|
@@ -7,7 +7,6 @@ import fs from 'fs';
|
|
|
7
7
|
import path from 'path';
|
|
8
8
|
import TsAlias from 'ts-alias';
|
|
9
9
|
import moduleAlias from 'module-alias';
|
|
10
|
-
import { filenameToImportName } from 'babel-plugin-glob-import';
|
|
11
10
|
|
|
12
11
|
// Core
|
|
13
12
|
|
|
@@ -19,23 +18,22 @@ import type { App } from './app';
|
|
|
19
18
|
import type { TAppSide } from './app';
|
|
20
19
|
|
|
21
20
|
export type TPathInfosOptions = {
|
|
22
|
-
basePath?: string
|
|
23
|
-
shortenExtensions: string[]
|
|
21
|
+
basePath?: string;
|
|
22
|
+
shortenExtensions: string[];
|
|
24
23
|
// Indexed will be trimed only when the extension can be shorten
|
|
25
|
-
trimIndex: boolean
|
|
26
|
-
}
|
|
24
|
+
trimIndex: boolean;
|
|
25
|
+
};
|
|
27
26
|
|
|
28
27
|
export type TPathInfos = {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
relative: string,
|
|
28
|
+
original: string;
|
|
29
|
+
absolute: string;
|
|
30
|
+
relative: string;
|
|
33
31
|
//forImport: string,
|
|
34
32
|
|
|
35
|
-
name: string
|
|
36
|
-
extension: string
|
|
37
|
-
isIndex: boolean
|
|
38
|
-
}
|
|
33
|
+
name: string;
|
|
34
|
+
extension: string;
|
|
35
|
+
isIndex: boolean;
|
|
36
|
+
};
|
|
39
37
|
|
|
40
38
|
/*----------------------------------
|
|
41
39
|
- CONFIG
|
|
@@ -43,10 +41,7 @@ export type TPathInfos = {
|
|
|
43
41
|
|
|
44
42
|
export const staticAssetName = /*isDebug ? '[name].[ext].[hash:8]' :*/ '[hash:8][ext]';
|
|
45
43
|
|
|
46
|
-
const pathInfosDefaultOpts = {
|
|
47
|
-
shortenExtensions: ['ts', 'js', 'tsx', 'jsx'],
|
|
48
|
-
trimIndex: true,
|
|
49
|
-
}
|
|
44
|
+
const pathInfosDefaultOpts = { shortenExtensions: ['ts', 'js', 'tsx', 'jsx'], trimIndex: true };
|
|
50
45
|
|
|
51
46
|
const resolveCoreRoot = (appRoot: string) => {
|
|
52
47
|
const localInstall = path.join(appRoot, 'node_modules', 'proteum');
|
|
@@ -55,66 +50,62 @@ const resolveCoreRoot = (appRoot: string) => {
|
|
|
55
50
|
// When running `npx`/global installs, there may be no local `node_modules/proteum` yet.
|
|
56
51
|
// Fall back to the installed package root (this file lives in `<root>/cli`).
|
|
57
52
|
return path.resolve(__dirname, '..');
|
|
58
|
-
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const normalizeImportPath = (value: string) => value.replace(/\\/g, '/');
|
|
56
|
+
|
|
57
|
+
const filenameToImportName = (value: string) =>
|
|
58
|
+
normalizeImportPath(value).replace(/[^A-Za-z0-9_]+/g, '_');
|
|
59
59
|
|
|
60
60
|
/*----------------------------------
|
|
61
61
|
- LIB
|
|
62
62
|
----------------------------------*/
|
|
63
63
|
export default class Paths {
|
|
64
|
-
|
|
65
64
|
/*----------------------------------
|
|
66
65
|
- LISTE
|
|
67
66
|
----------------------------------*/
|
|
68
67
|
|
|
69
|
-
public constructor(
|
|
68
|
+
public constructor(
|
|
70
69
|
public appRoot: string,
|
|
71
|
-
public coreRoot = resolveCoreRoot(appRoot)
|
|
72
|
-
) {
|
|
73
|
-
|
|
74
|
-
}
|
|
70
|
+
public coreRoot = resolveCoreRoot(appRoot),
|
|
71
|
+
) {}
|
|
75
72
|
|
|
76
|
-
public core = {
|
|
77
|
-
cli: path.resolve(__dirname, '.'),
|
|
78
|
-
root: this.coreRoot,
|
|
79
|
-
pages: this.coreRoot + '/client/pages',
|
|
80
|
-
}
|
|
73
|
+
public core = { cli: path.resolve(__dirname, '.'), root: this.coreRoot, pages: this.coreRoot + '/client/pages' };
|
|
81
74
|
|
|
82
75
|
/*----------------------------------
|
|
83
76
|
- EXTRACTION
|
|
84
77
|
----------------------------------*/
|
|
85
78
|
|
|
86
79
|
public infos(filename: string, givenOpts: Partial<TPathInfosOptions> = {}): TPathInfos {
|
|
87
|
-
|
|
88
|
-
const opts: TPathInfosOptions = { ...pathInfosDefaultOpts, ...givenOpts }
|
|
80
|
+
const opts: TPathInfosOptions = { ...pathInfosDefaultOpts, ...givenOpts };
|
|
89
81
|
|
|
90
82
|
// Extraction élements du chemin
|
|
91
|
-
const decomp = filename.split('/')
|
|
92
|
-
|
|
83
|
+
const decomp = filename.split('/');
|
|
84
|
+
const nomComplet = decomp.pop() as string;
|
|
85
|
+
const lastDotIndex = nomComplet.lastIndexOf('.');
|
|
86
|
+
const nomFichier = lastDotIndex === -1 ? nomComplet : nomComplet.substring(0, lastDotIndex);
|
|
87
|
+
const extension = lastDotIndex === -1 ? '' : nomComplet.substring(lastDotIndex + 1);
|
|
93
88
|
const shortenExtension = opts.shortenExtensions && opts.shortenExtensions.includes(extension);
|
|
94
89
|
|
|
95
90
|
// Vire l'index
|
|
96
|
-
const isIndex = nomFichier === 'index'
|
|
91
|
+
const isIndex = nomFichier === 'index';
|
|
97
92
|
let cheminAbsolu: string;
|
|
98
93
|
let nomReel: string;
|
|
99
94
|
if (isIndex && shortenExtension && opts.trimIndex) {
|
|
100
95
|
cheminAbsolu = decomp.join('/');
|
|
101
96
|
nomReel = decomp.pop() as string;
|
|
102
97
|
} else {
|
|
103
|
-
cheminAbsolu = [...decomp, nomFichier].join('/')
|
|
104
|
-
nomReel = nomFichier
|
|
98
|
+
cheminAbsolu = [...decomp, nomFichier].join('/');
|
|
99
|
+
nomReel = nomFichier;
|
|
105
100
|
}
|
|
106
101
|
|
|
107
102
|
// Conserve l'extension si nécessaire
|
|
108
|
-
if (!shortenExtension)
|
|
109
|
-
cheminAbsolu += '.' + extension;
|
|
103
|
+
if (!shortenExtension) cheminAbsolu += '.' + extension;
|
|
110
104
|
|
|
111
|
-
const relative = opts.basePath === undefined
|
|
112
|
-
? ''
|
|
113
|
-
: cheminAbsolu.substring( opts.basePath.length + 1 )
|
|
105
|
+
const relative = opts.basePath === undefined ? '' : cheminAbsolu.substring(opts.basePath.length + 1);
|
|
114
106
|
|
|
115
107
|
// Retour
|
|
116
108
|
const retour = {
|
|
117
|
-
|
|
118
109
|
original: filename,
|
|
119
110
|
absolute: cheminAbsolu,
|
|
120
111
|
relative,
|
|
@@ -124,16 +115,15 @@ export default class Paths {
|
|
|
124
115
|
|
|
125
116
|
name: nomReel,
|
|
126
117
|
extension,
|
|
127
|
-
isIndex
|
|
128
|
-
}
|
|
118
|
+
isIndex,
|
|
119
|
+
};
|
|
129
120
|
|
|
130
121
|
return retour;
|
|
131
122
|
}
|
|
132
123
|
|
|
133
|
-
public getPageChunk(
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
basePath: file.startsWith( app.paths.pages ) ? app.paths.pages : this.core.pages,
|
|
124
|
+
public getPageChunk(app: App, file: string) {
|
|
125
|
+
const infos = this.infos(file, {
|
|
126
|
+
basePath: file.startsWith(app.paths.pages) ? app.paths.pages : this.core.pages,
|
|
137
127
|
// Avoid potential conflicts between /landing.tsx and /landing/index.tsx
|
|
138
128
|
trimIndex: false,
|
|
139
129
|
});
|
|
@@ -145,21 +135,25 @@ export default class Paths {
|
|
|
145
135
|
let chunkId = filenameToImportName(filepath);
|
|
146
136
|
|
|
147
137
|
// nsure it's non-empty
|
|
148
|
-
if (chunkId.length === 0)
|
|
149
|
-
|
|
138
|
+
if (chunkId.length === 0)
|
|
139
|
+
// = /index.tsx
|
|
140
|
+
chunkId = 'main';
|
|
150
141
|
|
|
151
|
-
return { filepath, chunkId }
|
|
142
|
+
return { filepath, chunkId };
|
|
143
|
+
}
|
|
152
144
|
|
|
145
|
+
public getLayoutChunk(app: App, file: string) {
|
|
146
|
+
const layoutDir = path.dirname(path.dirname(file));
|
|
147
|
+
const relativeLayoutDir = path.relative(app.paths.pages, layoutDir);
|
|
148
|
+
const filepath = relativeLayoutDir === '' ? '' : normalizeImportPath(relativeLayoutDir);
|
|
149
|
+
|
|
150
|
+
return { filepath, chunkId: filenameToImportName(filepath) };
|
|
153
151
|
}
|
|
154
152
|
|
|
155
153
|
public applyAliases() {
|
|
156
|
-
|
|
157
|
-
const aliases = new TsAlias({
|
|
158
|
-
rootDir: this.core.cli
|
|
159
|
-
});
|
|
154
|
+
const aliases = new TsAlias({ rootDir: this.core.cli });
|
|
160
155
|
|
|
161
156
|
//console.log('Applying Aliases ...', aliases.forModuleAlias());
|
|
162
|
-
moduleAlias.addAliases(
|
|
163
|
-
|
|
157
|
+
moduleAlias.addAliases(aliases.forModuleAlias());
|
|
164
158
|
}
|
|
165
159
|
}
|
package/cli/print.ts
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
export const h1 = (titre: string) =>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
)
|
|
1
|
+
export const h1 = (titre: string) =>
|
|
2
|
+
console.log(
|
|
3
|
+
'\n' +
|
|
4
|
+
'######################################################\n' +
|
|
5
|
+
'# ' +
|
|
6
|
+
titre.toUpperCase() +
|
|
7
|
+
'\n' +
|
|
8
|
+
'######################################################',
|
|
9
|
+
);
|
|
7
10
|
|
|
8
|
-
export const h2 = (titre: string) =>
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
)
|
|
11
|
+
export const h2 = (titre: string) =>
|
|
12
|
+
console.log(
|
|
13
|
+
'------------------------------------------------------\n' +
|
|
14
|
+
'> ' +
|
|
15
|
+
titre.toUpperCase() +
|
|
16
|
+
'\n' +
|
|
17
|
+
'------------------------------------------------------',
|
|
18
|
+
);
|
package/cli/tsconfig.json
CHANGED
|
@@ -10,13 +10,14 @@
|
|
|
10
10
|
"skipLibCheck": true,
|
|
11
11
|
"allowJs": true,
|
|
12
12
|
"strict": false,
|
|
13
|
+
"noImplicitAny": true,
|
|
14
|
+
"noImplicitThis": true,
|
|
15
|
+
"strictBindCallApply": true,
|
|
16
|
+
"useUnknownInCatchVariables": true,
|
|
13
17
|
"downlevelIteration": true,
|
|
14
18
|
|
|
15
|
-
//
|
|
19
|
+
// Keep symlinked package paths stable for local framework development.
|
|
16
20
|
"preserveSymlinks": true,
|
|
17
|
-
// Décorateurs
|
|
18
|
-
"experimentalDecorators": true,
|
|
19
|
-
|
|
20
21
|
// React
|
|
21
22
|
"jsx": "react-jsx",
|
|
22
23
|
"jsxImportSource": "preact",
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/*----------------------------------
|
|
2
|
+
- DEPENDANCES
|
|
3
|
+
----------------------------------*/
|
|
4
|
+
|
|
5
|
+
// Npm
|
|
6
|
+
import fs from 'fs-extra';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
|
|
9
|
+
/*----------------------------------
|
|
10
|
+
- TYPES
|
|
11
|
+
----------------------------------*/
|
|
12
|
+
|
|
13
|
+
type TEnsureProjectAgentSymlinksArgs = { appRoot: string; coreRoot: string };
|
|
14
|
+
|
|
15
|
+
type TAgentLinkDefinition = { projectPath: string; sourcePath: string; ensureParentDir?: boolean };
|
|
16
|
+
|
|
17
|
+
/*----------------------------------
|
|
18
|
+
- CONSTANTS
|
|
19
|
+
----------------------------------*/
|
|
20
|
+
|
|
21
|
+
// Project-local AGENTS entrypoints mapped to their framework-owned source files.
|
|
22
|
+
const codexAgentLinkDefinitions: TAgentLinkDefinition[] = [
|
|
23
|
+
{ projectPath: 'AGENTS.md', sourcePath: 'AGENTS.md' },
|
|
24
|
+
{ projectPath: 'CODING_STYLE.md', sourcePath: 'CODING_STYLE.md' },
|
|
25
|
+
{ projectPath: path.join('client', 'AGENTS.md'), sourcePath: path.join('client', 'AGENTS.md') },
|
|
26
|
+
{ projectPath: path.join('client', 'pages', 'AGENTS.md'), sourcePath: path.join('client', 'pages', 'AGENTS.md') },
|
|
27
|
+
{
|
|
28
|
+
projectPath: path.join('server', 'services', 'AGENTS.md'),
|
|
29
|
+
sourcePath: path.join('server', 'services', 'AGENTS.md'),
|
|
30
|
+
},
|
|
31
|
+
{ projectPath: path.join('server', 'routes', 'AGENTS.md'), sourcePath: path.join('server', 'routes', 'AGENTS.md') },
|
|
32
|
+
{ projectPath: path.join('tests', 'e2e', 'AGENTS.md'), sourcePath: path.join('tests', 'AGENTS.md') },
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
/*----------------------------------
|
|
36
|
+
- PUBLIC API
|
|
37
|
+
----------------------------------*/
|
|
38
|
+
|
|
39
|
+
export function ensureProjectAgentSymlinks({ appRoot, coreRoot }: TEnsureProjectAgentSymlinksArgs) {
|
|
40
|
+
const agentSourceRoot = path.join(coreRoot, 'agents', 'codex');
|
|
41
|
+
const agentLinks = codexAgentLinkDefinitions.map((linkDefinition) => ({
|
|
42
|
+
...linkDefinition,
|
|
43
|
+
sourcePath: path.join(agentSourceRoot, linkDefinition.sourcePath),
|
|
44
|
+
}));
|
|
45
|
+
|
|
46
|
+
ensureSymlinks(appRoot, agentLinks, '[agents]');
|
|
47
|
+
ensureProjectSkillSymlinks({ appRoot, coreRoot });
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/*----------------------------------
|
|
51
|
+
- HELPERS
|
|
52
|
+
----------------------------------*/
|
|
53
|
+
|
|
54
|
+
function ensureProjectSkillSymlinks({ appRoot, coreRoot }: TEnsureProjectAgentSymlinksArgs) {
|
|
55
|
+
const frameworkSkillsRoot = path.join(coreRoot, 'skills');
|
|
56
|
+
if (!fs.existsSync(frameworkSkillsRoot)) return;
|
|
57
|
+
|
|
58
|
+
const skillLinks: TAgentLinkDefinition[] = fs
|
|
59
|
+
.readdirSync(frameworkSkillsRoot, { withFileTypes: true })
|
|
60
|
+
.filter((dirent) => dirent.isDirectory())
|
|
61
|
+
.map((dirent) => ({
|
|
62
|
+
projectPath: path.join('skills', dirent.name),
|
|
63
|
+
sourcePath: path.join(frameworkSkillsRoot, dirent.name),
|
|
64
|
+
ensureParentDir: true,
|
|
65
|
+
}))
|
|
66
|
+
.filter((linkDefinition) => pathEntryExists(path.join(linkDefinition.sourcePath, 'SKILL.md')));
|
|
67
|
+
|
|
68
|
+
ensureSymlinks(appRoot, skillLinks, '[skills]');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function ensureSymlinks(appRoot: string, linkDefinitions: TAgentLinkDefinition[], logPrefix: string) {
|
|
72
|
+
for (const linkDefinition of linkDefinitions) {
|
|
73
|
+
const projectFilepath = path.join(appRoot, linkDefinition.projectPath);
|
|
74
|
+
const projectParentDir = path.dirname(projectFilepath);
|
|
75
|
+
|
|
76
|
+
if (linkDefinition.ensureParentDir) fs.ensureDirSync(projectParentDir);
|
|
77
|
+
else if (!fs.existsSync(projectParentDir)) continue;
|
|
78
|
+
|
|
79
|
+
if (pathEntryExists(projectFilepath)) continue;
|
|
80
|
+
|
|
81
|
+
const sourceFilepath = linkDefinition.sourcePath;
|
|
82
|
+
if (!fs.existsSync(sourceFilepath)) {
|
|
83
|
+
throw new Error(`Missing framework asset: ${sourceFilepath}`);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const symlinkTarget = path.relative(projectParentDir, sourceFilepath);
|
|
87
|
+
fs.symlinkSync(symlinkTarget, projectFilepath);
|
|
88
|
+
|
|
89
|
+
console.info(`${logPrefix} Created ${path.relative(appRoot, projectFilepath) || '.'} -> ${symlinkTarget}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function pathEntryExists(filepath: string) {
|
|
94
|
+
try {
|
|
95
|
+
fs.lstatSync(filepath);
|
|
96
|
+
return true;
|
|
97
|
+
} catch {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
import cli from '..';
|
|
5
|
+
import Compiler from '../compiler';
|
|
6
|
+
import { runProcess } from './runProcess';
|
|
7
|
+
|
|
8
|
+
const tsconfigPaths = ['client/tsconfig.json', 'server/tsconfig.json'];
|
|
9
|
+
const eslintConfigPaths = ['eslint.config.mjs', 'eslint.config.js', 'eslint.config.cjs'];
|
|
10
|
+
|
|
11
|
+
const resolveInstalledBinary = (name: string) => {
|
|
12
|
+
const binary = path.join(cli.paths.core.root, 'node_modules', '.bin', name);
|
|
13
|
+
|
|
14
|
+
if (!fs.existsSync(binary)) throw new Error(`Missing required binary "${name}" in Proteum dependencies.`);
|
|
15
|
+
|
|
16
|
+
return binary;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const resolveExistingAppPaths = (paths: string[]) =>
|
|
20
|
+
paths
|
|
21
|
+
.map((relativePath) => ({ relativePath, absolutePath: path.join(cli.paths.appRoot, relativePath) }))
|
|
22
|
+
.filter(({ absolutePath }) => fs.existsSync(absolutePath));
|
|
23
|
+
|
|
24
|
+
const getTypecheckEnv = () => {
|
|
25
|
+
const existingNodeOptions = process.env.NODE_OPTIONS ?? '';
|
|
26
|
+
|
|
27
|
+
if (existingNodeOptions.includes('max-old-space-size')) return {};
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
NODE_OPTIONS: [existingNodeOptions, '--max-old-space-size=8192'].filter(Boolean).join(' '),
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const refreshGeneratedTypings = async () => {
|
|
35
|
+
const compiler = new Compiler('dev');
|
|
36
|
+
|
|
37
|
+
await compiler.refreshGeneratedTypings();
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const runAppTypecheck = async () => {
|
|
41
|
+
const existingProjects = resolveExistingAppPaths(tsconfigPaths);
|
|
42
|
+
|
|
43
|
+
if (existingProjects.length === 0)
|
|
44
|
+
throw new Error(`No TypeScript app projects found. Expected one of: ${tsconfigPaths.join(', ')}.`);
|
|
45
|
+
|
|
46
|
+
const tsc = resolveInstalledBinary('tsc');
|
|
47
|
+
|
|
48
|
+
for (const { relativePath } of existingProjects)
|
|
49
|
+
await runProcess(tsc, ['-p', relativePath, '--noEmit', '--pretty', 'false'], {
|
|
50
|
+
cwd: cli.paths.appRoot,
|
|
51
|
+
env: getTypecheckEnv(),
|
|
52
|
+
});
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const runAppLint = async ({ fix = false } = {}) => {
|
|
56
|
+
const [config] = resolveExistingAppPaths(eslintConfigPaths);
|
|
57
|
+
|
|
58
|
+
if (!config)
|
|
59
|
+
throw new Error(
|
|
60
|
+
`No ESLint config found. Expected one of: ${eslintConfigPaths
|
|
61
|
+
.map((relativePath) => path.join(cli.paths.appRoot, relativePath))
|
|
62
|
+
.join(', ')}.`,
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
const eslint = resolveInstalledBinary('eslint');
|
|
66
|
+
const args = ['.', '--config', config.absolutePath, '--no-config-lookup'];
|
|
67
|
+
|
|
68
|
+
if (fix) args.push('--fix');
|
|
69
|
+
|
|
70
|
+
await runProcess(eslint, args, { cwd: cli.paths.appRoot });
|
|
71
|
+
};
|
package/cli/utils/index.ts
CHANGED
|
@@ -6,12 +6,10 @@
|
|
|
6
6
|
import fs from 'fs-extra';
|
|
7
7
|
import path from 'path';
|
|
8
8
|
|
|
9
|
-
|
|
10
9
|
/*----------------------------------
|
|
11
10
|
- TYPES
|
|
12
11
|
----------------------------------*/
|
|
13
12
|
|
|
14
|
-
|
|
15
13
|
/*----------------------------------
|
|
16
14
|
- UTILS
|
|
17
15
|
----------------------------------*/
|
|
@@ -19,4 +17,4 @@ import path from 'path';
|
|
|
19
17
|
export const api = (method: string, path: string, data: object, local: boolean = false) =>
|
|
20
18
|
`curl -X ${method} ${local ? 'http://localhost:3010' : 'https://dopamyn.io'}${path} ` +
|
|
21
19
|
`-H 'Content-Type: application/json' -H 'Accept: application/json' ` +
|
|
22
|
-
`-d '${JSON.stringify(data)}';`;
|
|
20
|
+
`-d '${JSON.stringify(data)}';`;
|
package/cli/utils/keyboard.ts
CHANGED
|
@@ -9,28 +9,22 @@ import readline, { Key } from 'readline';
|
|
|
9
9
|
- TYPES
|
|
10
10
|
----------------------------------*/
|
|
11
11
|
|
|
12
|
-
type TKeyboardCommand = {
|
|
13
|
-
remove?: boolean,
|
|
14
|
-
run: (str: string, chunk: string, key: Key) => void
|
|
15
|
-
}
|
|
12
|
+
type TKeyboardCommand = { remove?: boolean; run: (str: string, chunk: string, key: Key) => void };
|
|
16
13
|
|
|
17
14
|
/*----------------------------------
|
|
18
15
|
- METHODS
|
|
19
16
|
----------------------------------*/
|
|
20
17
|
class KeyboardCommands {
|
|
21
|
-
|
|
22
|
-
private commands: { [input: string]: TKeyboardCommand } = {}
|
|
18
|
+
private commands: { [input: string]: TKeyboardCommand } = {};
|
|
23
19
|
|
|
24
20
|
public constructor() {
|
|
25
21
|
this.listen();
|
|
26
22
|
}
|
|
27
23
|
|
|
28
24
|
private listen() {
|
|
29
|
-
|
|
30
25
|
readline.emitKeypressEvents(process.stdin);
|
|
31
26
|
process.stdin.setRawMode(true);
|
|
32
27
|
process.stdin.on('keypress', async (chunk: string, key: Key) => {
|
|
33
|
-
|
|
34
28
|
let str = key.name;
|
|
35
29
|
if (!str) return;
|
|
36
30
|
if (str === 'return') str = 'enter';
|
|
@@ -41,38 +35,27 @@ class KeyboardCommands {
|
|
|
41
35
|
|
|
42
36
|
const kCommand = this.commands[str] || this.commands.fallback;
|
|
43
37
|
if (kCommand) {
|
|
44
|
-
|
|
45
38
|
kCommand.run(str, chunk, key);
|
|
46
39
|
|
|
47
|
-
if (kCommand.remove)
|
|
48
|
-
delete this.commands[str];
|
|
40
|
+
if (kCommand.remove) delete this.commands[str];
|
|
49
41
|
}
|
|
50
42
|
|
|
51
43
|
if (str === 'ctrl+c') {
|
|
52
|
-
|
|
53
44
|
console.log(`Exiting ...`);
|
|
54
45
|
process.exit(0);
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
|
|
46
|
+
}
|
|
59
47
|
});
|
|
60
48
|
}
|
|
61
49
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
this.commands[str] = { run, ...options }
|
|
50
|
+
public input(str: string, run: TKeyboardCommand['run'], options: Omit<TKeyboardCommand, 'run'> = {}) {
|
|
51
|
+
this.commands[str] = { run, ...options };
|
|
65
52
|
}
|
|
66
53
|
|
|
67
54
|
public waitForInput(str: string): Promise<void> {
|
|
68
55
|
return new Promise((resolve) => {
|
|
69
|
-
this.commands[str] = {
|
|
70
|
-
run: () => resolve(),
|
|
71
|
-
remove: true
|
|
72
|
-
}
|
|
56
|
+
this.commands[str] = { run: () => resolve(), remove: true };
|
|
73
57
|
});
|
|
74
58
|
}
|
|
75
|
-
|
|
76
59
|
}
|
|
77
60
|
|
|
78
|
-
export default new KeyboardCommands
|
|
61
|
+
export default new KeyboardCommands();
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import cp from 'child_process';
|
|
2
|
+
|
|
3
|
+
type TRunProcessOptions = {
|
|
4
|
+
cwd?: string;
|
|
5
|
+
env?: NodeJS.ProcessEnv;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const runProcess = (command: string, args: string[] = [], options: TRunProcessOptions = {}) =>
|
|
9
|
+
new Promise<void>((resolve, reject) => {
|
|
10
|
+
const child = cp.spawn(command, args, {
|
|
11
|
+
cwd: options.cwd,
|
|
12
|
+
env: { ...process.env, ...options.env },
|
|
13
|
+
stdio: 'inherit',
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
child.on('error', reject);
|
|
17
|
+
child.on('exit', (code, signal) => {
|
|
18
|
+
if (signal) {
|
|
19
|
+
reject(new Error(`Command "${command}" was interrupted by signal ${signal}.`));
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (code === 0) {
|
|
24
|
+
resolve();
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
reject(new Error(`Command "${command}" exited with code ${code ?? 'unknown'}.`));
|
|
29
|
+
});
|
|
30
|
+
});
|
package/client/app/component.tsx
CHANGED
|
@@ -7,48 +7,48 @@ import React from 'react';
|
|
|
7
7
|
|
|
8
8
|
// Core
|
|
9
9
|
import type { Layout } from '@common/router';
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
10
|
+
import type { LayoutProps } from '@common/router/layouts';
|
|
11
|
+
import { ReactClientContext, type ClientContext } from '@/client/context';
|
|
12
|
+
import DialogManager from '@client/components/Dialog/Manager';
|
|
12
13
|
|
|
13
14
|
// Core components
|
|
14
15
|
import RouterComponent from '@client/services/router/components/router';
|
|
15
|
-
import type { TClientOrServerContextForPage } from '@common/router';
|
|
16
16
|
|
|
17
17
|
/*----------------------------------
|
|
18
18
|
- COMPOSANT
|
|
19
19
|
----------------------------------*/
|
|
20
|
-
export default function App({ context }: {
|
|
21
|
-
context: TClientOrServerContextForPage,
|
|
22
|
-
}) {
|
|
23
|
-
|
|
20
|
+
export default function App({ context }: { context: ClientContext }) {
|
|
24
21
|
const curLayout = context.page?.layout;
|
|
25
22
|
const [layout, setLayout] = React.useState<Layout | false | undefined>(curLayout);
|
|
26
23
|
const [apiData, setApiData] = React.useState<{ [k: string]: any } | null>(context.page?.data || {});
|
|
27
24
|
|
|
28
25
|
// TODO: context.page is always provided in the context on the client side
|
|
29
|
-
if (context.app.side ===
|
|
30
|
-
|
|
26
|
+
if (context.app.side === 'client') context.app.setLayout = setLayout;
|
|
27
|
+
|
|
28
|
+
const layoutProps: LayoutProps = {
|
|
29
|
+
...context,
|
|
30
|
+
context,
|
|
31
|
+
data: { ...apiData, ...context.request.data },
|
|
32
|
+
menu: undefined,
|
|
33
|
+
children: undefined,
|
|
34
|
+
};
|
|
31
35
|
|
|
32
36
|
return (
|
|
33
37
|
<ReactClientContext.Provider value={context}>
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
{
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}}
|
|
49
|
-
/>
|
|
50
|
-
</>}
|
|
51
|
-
|
|
38
|
+
<DialogManager />
|
|
39
|
+
|
|
40
|
+
{!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
|
+
</>
|
|
45
|
+
) : (
|
|
46
|
+
<>
|
|
47
|
+
{' '}
|
|
48
|
+
{/* Same as router/components/Page.tsx */}
|
|
49
|
+
<layout.Component {...layoutProps} />
|
|
50
|
+
</>
|
|
51
|
+
)}
|
|
52
52
|
</ReactClientContext.Provider>
|
|
53
|
-
)
|
|
54
|
-
}
|
|
53
|
+
);
|
|
54
|
+
}
|