archicat 0.0.3
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/LICENSE +21 -0
- package/README.md +104 -0
- package/bin/archicat.mjs +11 -0
- package/dist/cli/index.mjs +30 -0
- package/dist/src/index.cjs +1 -0
- package/dist/src/index.d.cts +32 -0
- package/dist/src/index.d.mts +32 -0
- package/dist/src/index.mjs +1 -0
- package/package.json +60 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Simon Rastislav Kovačič
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# ArchiCat
|
|
2
|
+
|
|
3
|
+
**M²: Modular Mirroring.**
|
|
4
|
+
|
|
5
|
+
The generative architecture framework for clean architecture.
|
|
6
|
+
|
|
7
|
+
ArchiCat generates a module mirror from your source code. Public APIs become aliases. Implementations stay private. The mirror is the boundary.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm i -D archicat
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Why
|
|
14
|
+
|
|
15
|
+
Architecture should be enforceable.
|
|
16
|
+
|
|
17
|
+
Your code stays yours.
|
|
18
|
+
|
|
19
|
+
## M²
|
|
20
|
+
|
|
21
|
+
**M²** means **Modular Mirroring**.
|
|
22
|
+
|
|
23
|
+
```txt
|
|
24
|
+
source modules
|
|
25
|
+
-> module definitions
|
|
26
|
+
-> generated mirror
|
|
27
|
+
-> checked boundaries
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
You define the module:
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import { defineModule } from 'archicat';
|
|
34
|
+
|
|
35
|
+
export default defineModule({
|
|
36
|
+
id: 'account',
|
|
37
|
+
api: './api',
|
|
38
|
+
impl: './impl',
|
|
39
|
+
dependencies: ['media'],
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
ArchiCat mirrors it:
|
|
44
|
+
|
|
45
|
+
```txt
|
|
46
|
+
.archicat/modules/account/
|
|
47
|
+
api/
|
|
48
|
+
impl/
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
You import the mirror:
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
import { AccountReader } from '@account';
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Not the machinery:
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
import { AccountRepository } from '@account/impl'; // does not exist
|
|
61
|
+
import { AccountRepository } from '../../account/impl/repository'; // blocked
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Config
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
import { defineArchicatConfig } from 'archicat';
|
|
68
|
+
|
|
69
|
+
export default defineArchicatConfig({
|
|
70
|
+
root: '.',
|
|
71
|
+
outDir: './.archicat',
|
|
72
|
+
modules: {
|
|
73
|
+
include: ['./src/modules/*/archicat.module.ts'],
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Output
|
|
79
|
+
|
|
80
|
+
```txt
|
|
81
|
+
.archicat/
|
|
82
|
+
tsconfig.json
|
|
83
|
+
manifest.json
|
|
84
|
+
modules/
|
|
85
|
+
generated/
|
|
86
|
+
report/
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Extend the generated config:
|
|
90
|
+
|
|
91
|
+
```json
|
|
92
|
+
{
|
|
93
|
+
"extends": "./.archicat/tsconfig.json"
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Commands
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
archicat generate
|
|
101
|
+
archicat check
|
|
102
|
+
archicat graph
|
|
103
|
+
archicat doctor
|
|
104
|
+
```
|
package/bin/archicat.mjs
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import e from"node:path";import t from"node:fs";import{createJiti as n}from"jiti";import r from"typescript";async function i(n=`archicat.config.ts`){let r=process.cwd(),i=e.resolve(r,n);if(!t.existsSync(i))throw Error(`ArchiCat config was not found: ${i}`);let a=await o(i,r);return s(a,i),{configFilePath:i,rootDir:e.resolve(r,a.root),outDir:e.resolve(r,a.outDir),config:a}}async function a(t){let n=await o(t,e.dirname(t));return c(n,t),{contractFilePath:t,moduleDir:e.dirname(t),contract:n}}async function o(e,t){return await n(t,{interopDefault:!0,extensions:[`.js`,`.cjs`,`.mjs`,`.ts`,`.cts`,`.mts`,`.json`]}).import(e,{default:!0})}function s(e,t){if(typeof e!=`object`||!e)throw Error(`Invalid ArchiCat config: ${t}`);let n=e;if(typeof n.root!=`string`||n.root.trim()===``)throw Error(`ArchiCat config must define a non-empty root string: ${t}`);if(typeof n.outDir!=`string`||n.outDir.trim()===``)throw Error(`ArchiCat config must define a non-empty outDir string: ${t}`);if(!n.modules||!Array.isArray(n.modules.include))throw Error(`ArchiCat config must define modules.include: ${t}`)}function c(e,t){if(typeof e!=`object`||!e)throw Error(`Invalid ArchiCat module contract: ${t}`);let n=e;if(typeof n.id!=`string`||n.id.trim()===``)throw Error(`ArchiCat module must define a non-empty id: ${t}`);if(n.api!==void 0&&typeof n.api!=`string`)throw Error(`ArchiCat module api must be a string when defined: ${t}`);if(n.impl!==void 0&&typeof n.impl!=`string`)throw Error(`ArchiCat module impl must be a string when defined: ${t}`);if(!Array.isArray(n.dependencies))throw Error(`ArchiCat module dependencies must be an array: ${t}`)}function l(e,t){let n=t.flatMap(t=>u(e,t));return Array.from(new Set(n)).sort((e,t)=>e.localeCompare(t))}function u(n,r){let i=e.resolve(n,r);if(!i.includes(`*`))return t.existsSync(i)?[i]:[];let a=i.split(e.sep);if(a.filter(e=>e.includes(`*`)).length!==1)throw Error(`ArchiCat V1 supports exactly one wildcard segment per include pattern: ${r}`);let o=a.findIndex(e=>e.includes(`*`)),s=a.slice(0,o).join(e.sep)||e.sep,c=a[o]??`*`,l=a.slice(o+1),u=d(c);return t.existsSync(s)?t.readdirSync(s,{withFileTypes:!0}).filter(e=>e.isDirectory()).filter(e=>u.test(e.name)).map(t=>e.join(s,t.name,...l)).filter(e=>t.existsSync(e)&&t.statSync(e).isFile()):[]}function d(e){let t=e.replace(/[.+?^${}()|[\]\\]/gu,`\\$&`).replace(/\*/gu,`.*`);return RegExp(`^${t}$`,`u`)}function f(e,t){let n=t.map(t=>p(e.outDir,t));return g(n),ee(n),{rootDir:e.rootDir,outDir:e.outDir,configFilePath:e.configFilePath,modules:n}}function p(t,n){let{contract:r,contractFilePath:i,moduleDir:a}=n;h(r.id,i);let o=r.api?m(a,r.api,`api`,r.id):void 0,s=r.impl?m(a,r.impl,`impl`,r.id):void 0;return{id:r.id,alias:`@${r.id}`,dependencies:[...r.dependencies],contractFilePath:i,moduleDir:a,apiRootPath:o,implRootPath:s,mirrorApiRootPath:e.join(t,`modules`,r.id,`api`),mirrorImplRootPath:e.join(t,`modules`,r.id,`impl`)}}function m(n,r,i,a){let o=e.resolve(n,r);if(!t.existsSync(o))throw Error(`Module "${a}" declares ${i} root that does not exist: ${o}`);if(!t.statSync(o).isDirectory())throw Error(`Module "${a}" declares ${i} root that is not a directory: ${o}`);return o}function h(e,t){if(!/^[a-z][a-z0-9-]*$/u.test(e))throw Error(`Invalid ArchiCat module id "${e}" in ${t}. Use ^[a-z][a-z0-9-]*$`)}function g(e){let t=new Map;for(let n of e){let e=t.get(n.id);if(e)throw Error(`Duplicate ArchiCat module id "${n.id}" in ${e} and ${n.contractFilePath}`);t.set(n.id,n.contractFilePath)}}function ee(e){let t=new Set(e.map(e=>e.id));for(let n of e)for(let e of n.dependencies){if(e===n.id)throw Error(`Module "${n.id}" cannot depend on itself.`);if(!t.has(e))throw Error(`Module "${n.id}" declares unknown dependency "${e}".`)}}async function _(e){let t=await i(e),n=l(t.rootDir,t.config.modules.include);if(n.length===0)throw Error(`No ArchiCat module contracts matched modules.include.`);return f(t,await Promise.all(n.map(e=>a(e))))}function v(t){return t.split(e.sep).join(`/`)}function y(t,n){let r=e.dirname(t),i=e.parse(n),a=e.join(i.dir,i.name),o=v(e.relative(r,a));return o.startsWith(`.`)||(o=`./${o}`),`${o}.js`}function b(t,n){let r=e.relative(n,t);return r===``||!!r&&!r.startsWith(`..`)&&!e.isAbsolute(r)}function x(e){return e.replace(/\.(?:js|mjs|cjs|ts|mts|cts|tsx)$/u,``)}function S(t,n){return v(e.relative(t,n))}function C(e){return t.existsSync(e)?t.statSync(e).isFile()?w(e)?[e]:[]:T(e).filter(w).sort((e,t)=>e.localeCompare(t)):[]}function w(e){return/\.(?:ts|mts|cts|tsx)$/u.test(e)&&!/\.d\.(?:ts|mts|cts)$/u.test(e)}function T(n){let r=[],i=t.readdirSync(n,{withFileTypes:!0});for(let t of i){let i=e.join(n,t.name);if(t.isDirectory()){r.push(...T(i));continue}t.isFile()&&r.push(i)}return r}function E(e){let n=r.createSourceFile(e,t.readFileSync(e,`utf8`),r.ScriptTarget.Latest,!0),i=[],a=e=>{if(r.isImportDeclaration(e)&&r.isStringLiteral(e.moduleSpecifier)&&i.push({moduleSpecifier:e.moduleSpecifier.text,kind:`import`}),r.isExportDeclaration(e)&&e.moduleSpecifier&&r.isStringLiteral(e.moduleSpecifier)&&i.push({moduleSpecifier:e.moduleSpecifier.text,kind:`export`}),r.isCallExpression(e)&&e.expression.kind===r.SyntaxKind.ImportKeyword){let[t]=e.arguments;t&&r.isStringLiteral(t)&&i.push({moduleSpecifier:t.text,kind:`dynamic-import`})}r.forEachChild(e,a)};return a(n),i}function te(e){let n=r.createSourceFile(e,t.readFileSync(e,`utf8`),r.ScriptTarget.Latest,!0),i=!1,a=e=>{if(!i){if(r.isExportAssignment(e)&&!e.isExportEquals){i=!0;return}if(ne(e)){i=!0;return}if(r.isExportDeclaration(e)&&e.exportClause&&r.isNamedExports(e.exportClause))for(let t of e.exportClause.elements){let e=t.name.text,n=t.propertyName?.text;if(e==="default"||n==="default"){i=!0;return}}r.forEachChild(e,a)}};return a(n),i}function ne(e){let t=r.canHaveModifiers(e)?r.getModifiers(e):void 0;if(!t)return!1;let n=t.some(e=>e.kind===r.SyntaxKind.ExportKeyword),i=t.some(e=>e.kind===r.SyntaxKind.DefaultKeyword);return n&&i}async function re(e){let t=await _(e);return[...ie(t),...M(t)]}function ie(e){let t=[],n=e.modules.flatMap(e=>ae(e));for(let r of n){let n=A(e.modules,r);if(n)for(let i of E(r)){let a=D(e,n,r,i.moduleSpecifier);a&&t.push(a)}}return t}function ae(e){return[...e.apiRootPath?C(e.apiRootPath):[],...e.implRootPath?C(e.implRootPath):[]]}function D(e,t,n,r){let i=j(e.modules,r);if(i)return i.id===t.id||t.dependencies.includes(i.id)?void 0:N(e,n,r,`Module "${t.id}" imports "${i.id}" but does not declare it in dependencies.`);if(!r.startsWith(`#archicat/`)&&(r.startsWith(`.`)||r.startsWith(`/`)))return O(e,t,n,r)}function O(e,t,n,r){let i=k(n,r),a=A(e.modules,i);if(!(!a||a.id===t.id))return N(e,n,r,`Module "${t.id}" imports module "${a.id}" through a source path. Use "${a.alias}" instead.`)}function k(t,n){return x(n.startsWith(`/`)?n:e.resolve(e.dirname(t),n))}function A(e,t){let n=x(t);return e.find(e=>[e.apiRootPath,e.implRootPath,e.moduleDir].filter(e=>!!e).some(e=>b(n,x(e))))}function j(e,t){return e.find(e=>t===e.alias||t.startsWith(`${e.alias}/`))}function M(e){let t=[],n=new Map(e.modules.map(e=>[e.id,e])),r=new Set,i=new Set,a=(o,s)=>{if(!i.has(o.id)){if(r.has(o.id)){t.push({filePath:S(e.rootDir,o.contractFilePath),importPath:o.id,message:`Cyclic ArchiCat module dependency detected: ${[...s,o.id].join(` -> `)}`});return}r.add(o.id);for(let e of o.dependencies){let t=n.get(e);t&&a(t,[...s,o.id])}r.delete(o.id),i.add(o.id)}};for(let t of e.modules)a(t,[]);return t}function N(e,t,n,r){return{filePath:S(e.rootDir,t),importPath:n,message:r}}async function P(e){let t=await _(e);return[...F(t),...I(t),...L(t)]}function F(n){let r=e.join(n.outDir,`tsconfig.json`);return t.existsSync(r)?[]:[{severity:`warning`,message:`Generated tsconfig does not exist yet: ${r}. Run archicat generate.`}]}function I(n){let r=e.join(n.rootDir,`tsconfig.json`);if(!t.existsSync(r))return[{severity:`warning`,message:`Root tsconfig.json was not found: ${r}`}];try{let e=JSON.parse(t.readFileSync(r,`utf8`)),n=[];return e.extends!==`./.archicat/tsconfig.json`&&e.extends!==`.archicat/tsconfig.json`&&n.push({severity:`warning`,message:`Root tsconfig.json should extend ./.archicat/tsconfig.json for ArchiCat aliases to work like Nuxt.`}),(e.compilerOptions?.rootDir===`src`||e.compilerOptions?.rootDir===`./src`)&&n.push({severity:`warning`,message:`compilerOptions.rootDir is set to src. Generated .archicat files live outside src and may break tsc.`}),n}catch(e){return[{severity:`warning`,message:`Failed to parse root tsconfig.json: ${e}`}]}}function L(n){let r=[];for(let i of n.modules){let n=e.join(i.moduleDir,`api`),a=e.join(i.moduleDir,`impl`);!i.apiRootPath&&t.existsSync(n)&&r.push({severity:`warning`,message:`Module "${i.id}" has a physical api directory but its contract omits api. ArchiCat treats the public API as empty.`}),!i.implRootPath&&t.existsSync(a)&&r.push({severity:`warning`,message:`Module "${i.id}" has a physical impl directory but its contract omits impl. ArchiCat treats the implementation as no-op.`})}return r}function R(e){t.existsSync(e)&&t.rmSync(e,{recursive:!0,force:!0}),t.mkdirSync(e,{recursive:!0})}function z(n,r){t.mkdirSync(e.dirname(n),{recursive:!0}),t.writeFileSync(n,r,`utf8`)}function B(e,t){z(e,`${JSON.stringify(t,null,2)}\n`)}function V(t){let n={modules:t.modules.map(e=>({id:e.id,dependencies:e.dependencies}))};B(e.join(t.outDir,`report`,`module-graph.json`),n),z(e.join(t.outDir,`report`,`module-graph.mmd`),oe(t))}function oe(e){let t=[`graph TD`];for(let n of e.modules){t.push(` ${H(n.id)}[${n.id}]`);for(let e of n.dependencies)t.push(` ${H(n.id)} --> ${H(e)}`)}return`${t.join(`
|
|
2
|
+
`)}\n`}function H(e){return e.replace(/[^a-zA-Z0-9_]/gu,`_`)}function U(e){W(e),G(e)}function W(t){let n=`// Generated by ArchiCat. Do not edit.
|
|
3
|
+
${t.modules.map(e=>`import * as ${K(e.id)} from '../modules/${e.id}/impl/index.js';`).join(`
|
|
4
|
+
`)}
|
|
5
|
+
|
|
6
|
+
export const ArchicatModules = [
|
|
7
|
+
${t.modules.map(e=>` { id: '${e.id}', implementation: ${K(e.id)} },`).join(`
|
|
8
|
+
`)}
|
|
9
|
+
] as const;
|
|
10
|
+
`;z(e.join(t.outDir,`generated`,`modules.ts`),n)}function G(t){z(e.join(t.outDir,`generated`,`composition.ts`),`// Generated by ArchiCat. Do not edit.
|
|
11
|
+
import { ArchicatModules } from './modules.js';
|
|
12
|
+
|
|
13
|
+
export { ArchicatModules };
|
|
14
|
+
|
|
15
|
+
export function getArchicatModules() {
|
|
16
|
+
return ArchicatModules;
|
|
17
|
+
}
|
|
18
|
+
`)}function K(e){return`${e.replace(/-([a-z0-9])/gu,(e,t)=>t.toUpperCase())}Implementation`}function q(t){let n={generatedBy:`archicat`,version:1,rootDir:t.rootDir,outDir:t.outDir,modules:t.modules.map(e=>({id:e.id,alias:e.alias,dependencies:e.dependencies,contractFilePath:S(t.rootDir,e.contractFilePath),moduleDir:S(t.rootDir,e.moduleDir),...e.apiRootPath?{apiRootPath:S(t.rootDir,e.apiRootPath)}:{},...e.implRootPath?{implRootPath:S(t.rootDir,e.implRootPath)}:{},mirrorApiRootPath:S(t.rootDir,e.mirrorApiRootPath),mirrorImplRootPath:S(t.rootDir,e.mirrorImplRootPath)}))};return B(e.join(t.outDir,`manifest.json`),n),n}function se(e){for(let t of e)ce(t),le(t)}function ce(t){if(!t.apiRootPath){z(e.join(t.mirrorApiRootPath,`index.ts`),`${Y(`empty api`)}export {};\n`);return}let n=C(t.apiRootPath),r=new Set;for(let i of n){let n=v(e.relative(t.apiRootPath,i));r.add(n),J(e.join(t.mirrorApiRootPath,n),i)}r.has(`index.ts`)||z(e.join(t.mirrorApiRootPath,`index.ts`),`${Y(`empty api index`)}export {};\n`)}function le(t){let n=t.implRootPath?ue(t.implRootPath):void 0;if(!n){let n=`${Y(`empty impl`)}
|
|
19
|
+
export const ArchicatModuleImplementation = {
|
|
20
|
+
id: '${t.id}',
|
|
21
|
+
assemblies: [],
|
|
22
|
+
schemas: [],
|
|
23
|
+
routes: [],
|
|
24
|
+
} as const;
|
|
25
|
+
|
|
26
|
+
export default ArchicatModuleImplementation;
|
|
27
|
+
`;z(e.join(t.mirrorImplRootPath,`index.ts`),n);return}J(e.join(t.mirrorImplRootPath,`index.ts`),n)}function J(e,t){let n=y(e,t),r=te(t)?`export { default } from '${n}';\n`:``;z(e,`${Y(`mirror`)}
|
|
28
|
+
export * from '${n}';
|
|
29
|
+
${r}`)}function ue(t){for(let n of[`index.ts`,`index.mts`,`index.cts`,`index.tsx`]){let r=e.join(t,n);if(C(r).length>0)return r}}function Y(e){return`// Generated by ArchiCat (${e}). Do not edit.\n`}function de(n){let r={"#archicat/*":[`.archicat/generated/*`]};for(let t of n.modules)r[t.alias]=[v(e.relative(n.rootDir,e.join(t.mirrorApiRootPath,`index.ts`)))],r[`${t.alias}/*`]=[v(e.relative(n.rootDir,e.join(t.mirrorApiRootPath,`*`)))];let i=e.join(n.rootDir,`tsconfig.base.json`),a=t.existsSync(i)?`../tsconfig.base.json`:void 0,o={...a?{extends:a}:{},compilerOptions:{baseUrl:`..`,paths:r},include:[`../src/**/*.ts`,`./**/*.ts`],exclude:[`../node_modules`,`../dist`]};B(e.join(n.outDir,`tsconfig.json`),o)}async function X(t){let n=await _(t);if(e.resolve(n.outDir)===e.resolve(n.rootDir))throw Error(`ArchiCat outDir cannot be the project root.`);return R(n.outDir),se(n.modules),de(n),q(n),U(n),V(n),n}async function fe(e=process.argv.slice(2)){let[t,...n]=e,r=pe(n);try{switch(t){case`generate`:{let e=await X(r.config);Q(`Generated ${e.modules.length} module(s) into ${e.outDir}`);return}case`check`:{let e=await re(r.config);if(e.length===0){Q(`Architecture check passed.`);return}for(let t of e)$(`${t.filePath}\n import: ${t.importPath}\n ${t.message}`);process.exitCode=1;return}case`graph`:Q(`Generated graph for ${(await X(r.config)).modules.length} module(s).`);return;case`doctor`:{let e=await P(r.config);if(e.length===0){Q(`Doctor found no issues.`);return}for(let t of e){if(t.severity===`error`){$(t.message);continue}me(t.message)}return}case`help`:case`--help`:case`-h`:case void 0:Z();return;default:$(`Unknown command: ${t}`),Z(),process.exitCode=1}}catch(e){$(e instanceof Error?e.message:String(e)),process.exitCode=1}}function pe(e){let t={};for(let n=0;n<e.length;n+=1){let r=e[n];if(r===`--config`||r===`-c`){let i=e[n+1];if(!i)throw Error(`${r} requires a value.`);t.config=i,n+=1}}return t}function Z(){console.log([`ArchiCat`,``,`Usage:`,` archicat generate [--config archicat.config.ts]`,` archicat check [--config archicat.config.ts]`,` archicat graph [--config archicat.config.ts]`,` archicat doctor [--config archicat.config.ts]`,``].join(`
|
|
30
|
+
`))}function Q(e){console.log(`✓ ${e}`)}function me(e){console.warn(`! ${e}`)}function $(e){console.error(`✗ ${e}`)}export{fe as runMain};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});function e(e){return Object.freeze({root:e.root,outDir:e.outDir,modules:Object.freeze({include:Object.freeze([...e.modules.include])})})}function t(e){return Object.freeze({id:e.id,...e.api===void 0?{}:{api:e.api},...e.impl===void 0?{}:{impl:e.impl},dependencies:Object.freeze([...e.dependencies??[]])})}exports.defineArchicatConfig=e,exports.defineModule=t;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//#region src/definition.d.ts
|
|
2
|
+
interface ArchicatModuleRootConfig {
|
|
3
|
+
include: readonly string[];
|
|
4
|
+
}
|
|
5
|
+
interface ArchicatConfigInput {
|
|
6
|
+
root: string;
|
|
7
|
+
outDir: string;
|
|
8
|
+
modules: ArchicatModuleRootConfig;
|
|
9
|
+
}
|
|
10
|
+
type ArchicatConfig = Readonly<{
|
|
11
|
+
root: string;
|
|
12
|
+
outDir: string;
|
|
13
|
+
modules: Readonly<{
|
|
14
|
+
include: readonly string[];
|
|
15
|
+
}>;
|
|
16
|
+
}>;
|
|
17
|
+
interface ArchicatModuleInput {
|
|
18
|
+
id: string;
|
|
19
|
+
api?: string;
|
|
20
|
+
impl?: string;
|
|
21
|
+
dependencies?: readonly string[];
|
|
22
|
+
}
|
|
23
|
+
type ArchicatModuleContract = Readonly<{
|
|
24
|
+
id: string;
|
|
25
|
+
api?: string;
|
|
26
|
+
impl?: string;
|
|
27
|
+
dependencies: readonly string[];
|
|
28
|
+
}>;
|
|
29
|
+
declare function defineArchicatConfig(config: ArchicatConfigInput): ArchicatConfig;
|
|
30
|
+
declare function defineModule(module: ArchicatModuleInput): ArchicatModuleContract;
|
|
31
|
+
//#endregion
|
|
32
|
+
export { type ArchicatConfig, type ArchicatConfigInput, type ArchicatModuleContract, type ArchicatModuleInput, type ArchicatModuleRootConfig, defineArchicatConfig, defineModule };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//#region src/definition.d.ts
|
|
2
|
+
interface ArchicatModuleRootConfig {
|
|
3
|
+
include: readonly string[];
|
|
4
|
+
}
|
|
5
|
+
interface ArchicatConfigInput {
|
|
6
|
+
root: string;
|
|
7
|
+
outDir: string;
|
|
8
|
+
modules: ArchicatModuleRootConfig;
|
|
9
|
+
}
|
|
10
|
+
type ArchicatConfig = Readonly<{
|
|
11
|
+
root: string;
|
|
12
|
+
outDir: string;
|
|
13
|
+
modules: Readonly<{
|
|
14
|
+
include: readonly string[];
|
|
15
|
+
}>;
|
|
16
|
+
}>;
|
|
17
|
+
interface ArchicatModuleInput {
|
|
18
|
+
id: string;
|
|
19
|
+
api?: string;
|
|
20
|
+
impl?: string;
|
|
21
|
+
dependencies?: readonly string[];
|
|
22
|
+
}
|
|
23
|
+
type ArchicatModuleContract = Readonly<{
|
|
24
|
+
id: string;
|
|
25
|
+
api?: string;
|
|
26
|
+
impl?: string;
|
|
27
|
+
dependencies: readonly string[];
|
|
28
|
+
}>;
|
|
29
|
+
declare function defineArchicatConfig(config: ArchicatConfigInput): ArchicatConfig;
|
|
30
|
+
declare function defineModule(module: ArchicatModuleInput): ArchicatModuleContract;
|
|
31
|
+
//#endregion
|
|
32
|
+
export { type ArchicatConfig, type ArchicatConfigInput, type ArchicatModuleContract, type ArchicatModuleInput, type ArchicatModuleRootConfig, defineArchicatConfig, defineModule };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function e(e){return Object.freeze({root:e.root,outDir:e.outDir,modules:Object.freeze({include:Object.freeze([...e.modules.include])})})}function t(e){return Object.freeze({id:e.id,...e.api===void 0?{}:{api:e.api},...e.impl===void 0?{}:{impl:e.impl},dependencies:Object.freeze([...e.dependencies??[]])})}export{e as defineArchicatConfig,t as defineModule};
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "archicat",
|
|
3
|
+
"version": "0.0.3",
|
|
4
|
+
"description": "M²: modular mirroring for clean architecture.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"m2",
|
|
7
|
+
"modular-mirroring",
|
|
8
|
+
"module-system",
|
|
9
|
+
"clean-architecture",
|
|
10
|
+
"architecture"
|
|
11
|
+
],
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"author": "Simon Rastislav Kovačič",
|
|
14
|
+
"type": "module",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"import": {
|
|
18
|
+
"types": "./dist/src/index.d.mts",
|
|
19
|
+
"default": "./dist/src/index.mjs"
|
|
20
|
+
},
|
|
21
|
+
"require": {
|
|
22
|
+
"types": "./dist/src/index.d.cts",
|
|
23
|
+
"default": "./dist/src/index.cjs"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"bin": {
|
|
28
|
+
"archicat": "bin/archicat.mjs"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"bin",
|
|
32
|
+
"dist",
|
|
33
|
+
"README.md",
|
|
34
|
+
"LICENSE"
|
|
35
|
+
],
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsdown --config tsdown.config.cli.ts --config-loader unrun && tsdown --config tsdown.config.src.ts --config-loader unrun",
|
|
38
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"jiti": "2.7.0",
|
|
42
|
+
"typescript": "6.0.3"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/node": "26.0.0"
|
|
46
|
+
},
|
|
47
|
+
"repository": {
|
|
48
|
+
"type": "git",
|
|
49
|
+
"url": "git+https://github.com/MeawKit/ArchiCat.git",
|
|
50
|
+
"directory": "packages/archicat"
|
|
51
|
+
},
|
|
52
|
+
"bugs": {
|
|
53
|
+
"url": "https://github.com/MeawKit/ArchiCat/issues"
|
|
54
|
+
},
|
|
55
|
+
"homepage": "https://github.com/MeawKit/ArchiCat#readme",
|
|
56
|
+
"publishConfig": {
|
|
57
|
+
"registry": "https://registry.npmjs.org/"
|
|
58
|
+
},
|
|
59
|
+
"gitHead": "4a6db6ef9c4a76049f668acc206a01f924c548e7"
|
|
60
|
+
}
|