@yousxlfs/next-arch 0.1.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.
Files changed (52) hide show
  1. package/dist/index.d.ts +2 -0
  2. package/dist/index.js +255 -0
  3. package/dist/index.js.map +1 -0
  4. package/package.json +58 -0
  5. package/templates/app/AGENTS.md +5 -0
  6. package/templates/app/CLAUDE.md +1 -0
  7. package/templates/app/README.md +36 -0
  8. package/templates/app/components.json +25 -0
  9. package/templates/app/eslint.config.mjs +33 -0
  10. package/templates/app/next-env.d.ts +6 -0
  11. package/templates/app/next.config.ts +7 -0
  12. package/templates/app/package.json +37 -0
  13. package/templates/app/postcss.config.mjs +7 -0
  14. package/templates/app/public/file.svg +1 -0
  15. package/templates/app/public/globe.svg +1 -0
  16. package/templates/app/public/next.svg +1 -0
  17. package/templates/app/public/vercel.svg +1 -0
  18. package/templates/app/public/window.svg +1 -0
  19. package/templates/app/src/app/favicon.ico +0 -0
  20. package/templates/app/src/app/globals.css +130 -0
  21. package/templates/app/src/app/layout.tsx +33 -0
  22. package/templates/app/src/app/page.tsx +6 -0
  23. package/templates/app/src/components/ui/button.tsx +67 -0
  24. package/templates/app/src/features/demo/actions/submitDemo.ts +5 -0
  25. package/templates/app/src/features/demo/api/fetchDemo.ts +3 -0
  26. package/templates/app/src/features/demo/index.ts +4 -0
  27. package/templates/app/src/features/demo/lib/formatDemo.ts +3 -0
  28. package/templates/app/src/features/demo/model/index.ts +2 -0
  29. package/templates/app/src/features/demo/model/types.ts +7 -0
  30. package/templates/app/src/features/demo/ui/FeatureDemo.tsx +18 -0
  31. package/templates/app/src/lib/utils.ts +1 -0
  32. package/templates/app/src/shared/lib/utils.ts +6 -0
  33. package/templates/app/src/shared/ui/index.ts +2 -0
  34. package/templates/app/src/views/HomeView/index.tsx +21 -0
  35. package/templates/app/tsconfig.json +40 -0
  36. package/templates/entity/index.ts +1 -0
  37. package/templates/entity/model/types.ts +3 -0
  38. package/templates/entity/ui/{{Name}}Card.tsx +8 -0
  39. package/templates/feature/actions/submit{{Name}}.ts +5 -0
  40. package/templates/feature/api/fetch{{Name}}.ts +3 -0
  41. package/templates/feature/index.ts +4 -0
  42. package/templates/feature/lib/format{{Name}}.ts +3 -0
  43. package/templates/feature/model/index.ts +5 -0
  44. package/templates/feature/model/types.ts +7 -0
  45. package/templates/feature/ui/{{Name}}.tsx +10 -0
  46. package/templates/view/index.tsx +12 -0
  47. package/templates/widget/index.ts +1 -0
  48. package/templates/widget/ui/{{Name}}.tsx +9 -0
  49. package/vendor/eslint-plugin-next-arch/dist/index.d.ts +50 -0
  50. package/vendor/eslint-plugin-next-arch/dist/index.js +386 -0
  51. package/vendor/eslint-plugin-next-arch/dist/index.js.map +1 -0
  52. package/vendor/eslint-plugin-next-arch/package.json +55 -0
@@ -0,0 +1,130 @@
1
+ @import "tailwindcss";
2
+ @import "tw-animate-css";
3
+ @import "shadcn/tailwind.css";
4
+
5
+ @custom-variant dark (&:is(.dark *));
6
+
7
+ @theme inline {
8
+ --color-background: var(--background);
9
+ --color-foreground: var(--foreground);
10
+ --font-sans: var(--font-sans);
11
+ --font-mono: var(--font-geist-mono);
12
+ --font-heading: var(--font-sans);
13
+ --color-sidebar-ring: var(--sidebar-ring);
14
+ --color-sidebar-border: var(--sidebar-border);
15
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
16
+ --color-sidebar-accent: var(--sidebar-accent);
17
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
18
+ --color-sidebar-primary: var(--sidebar-primary);
19
+ --color-sidebar-foreground: var(--sidebar-foreground);
20
+ --color-sidebar: var(--sidebar);
21
+ --color-chart-5: var(--chart-5);
22
+ --color-chart-4: var(--chart-4);
23
+ --color-chart-3: var(--chart-3);
24
+ --color-chart-2: var(--chart-2);
25
+ --color-chart-1: var(--chart-1);
26
+ --color-ring: var(--ring);
27
+ --color-input: var(--input);
28
+ --color-border: var(--border);
29
+ --color-destructive: var(--destructive);
30
+ --color-accent-foreground: var(--accent-foreground);
31
+ --color-accent: var(--accent);
32
+ --color-muted-foreground: var(--muted-foreground);
33
+ --color-muted: var(--muted);
34
+ --color-secondary-foreground: var(--secondary-foreground);
35
+ --color-secondary: var(--secondary);
36
+ --color-primary-foreground: var(--primary-foreground);
37
+ --color-primary: var(--primary);
38
+ --color-popover-foreground: var(--popover-foreground);
39
+ --color-popover: var(--popover);
40
+ --color-card-foreground: var(--card-foreground);
41
+ --color-card: var(--card);
42
+ --radius-sm: calc(var(--radius) * 0.6);
43
+ --radius-md: calc(var(--radius) * 0.8);
44
+ --radius-lg: var(--radius);
45
+ --radius-xl: calc(var(--radius) * 1.4);
46
+ --radius-2xl: calc(var(--radius) * 1.8);
47
+ --radius-3xl: calc(var(--radius) * 2.2);
48
+ --radius-4xl: calc(var(--radius) * 2.6);
49
+ }
50
+
51
+ :root {
52
+ --background: oklch(1 0 0);
53
+ --foreground: oklch(0.145 0 0);
54
+ --card: oklch(1 0 0);
55
+ --card-foreground: oklch(0.145 0 0);
56
+ --popover: oklch(1 0 0);
57
+ --popover-foreground: oklch(0.145 0 0);
58
+ --primary: oklch(0.205 0 0);
59
+ --primary-foreground: oklch(0.985 0 0);
60
+ --secondary: oklch(0.97 0 0);
61
+ --secondary-foreground: oklch(0.205 0 0);
62
+ --muted: oklch(0.97 0 0);
63
+ --muted-foreground: oklch(0.556 0 0);
64
+ --accent: oklch(0.97 0 0);
65
+ --accent-foreground: oklch(0.205 0 0);
66
+ --destructive: oklch(0.577 0.245 27.325);
67
+ --border: oklch(0.922 0 0);
68
+ --input: oklch(0.922 0 0);
69
+ --ring: oklch(0.708 0 0);
70
+ --chart-1: oklch(0.87 0 0);
71
+ --chart-2: oklch(0.556 0 0);
72
+ --chart-3: oklch(0.439 0 0);
73
+ --chart-4: oklch(0.371 0 0);
74
+ --chart-5: oklch(0.269 0 0);
75
+ --radius: 0.625rem;
76
+ --sidebar: oklch(0.985 0 0);
77
+ --sidebar-foreground: oklch(0.145 0 0);
78
+ --sidebar-primary: oklch(0.205 0 0);
79
+ --sidebar-primary-foreground: oklch(0.985 0 0);
80
+ --sidebar-accent: oklch(0.97 0 0);
81
+ --sidebar-accent-foreground: oklch(0.205 0 0);
82
+ --sidebar-border: oklch(0.922 0 0);
83
+ --sidebar-ring: oklch(0.708 0 0);
84
+ }
85
+
86
+ .dark {
87
+ --background: oklch(0.145 0 0);
88
+ --foreground: oklch(0.985 0 0);
89
+ --card: oklch(0.205 0 0);
90
+ --card-foreground: oklch(0.985 0 0);
91
+ --popover: oklch(0.205 0 0);
92
+ --popover-foreground: oklch(0.985 0 0);
93
+ --primary: oklch(0.922 0 0);
94
+ --primary-foreground: oklch(0.205 0 0);
95
+ --secondary: oklch(0.269 0 0);
96
+ --secondary-foreground: oklch(0.985 0 0);
97
+ --muted: oklch(0.269 0 0);
98
+ --muted-foreground: oklch(0.708 0 0);
99
+ --accent: oklch(0.269 0 0);
100
+ --accent-foreground: oklch(0.985 0 0);
101
+ --destructive: oklch(0.704 0.191 22.216);
102
+ --border: oklch(1 0 0 / 10%);
103
+ --input: oklch(1 0 0 / 15%);
104
+ --ring: oklch(0.556 0 0);
105
+ --chart-1: oklch(0.87 0 0);
106
+ --chart-2: oklch(0.556 0 0);
107
+ --chart-3: oklch(0.439 0 0);
108
+ --chart-4: oklch(0.371 0 0);
109
+ --chart-5: oklch(0.269 0 0);
110
+ --sidebar: oklch(0.205 0 0);
111
+ --sidebar-foreground: oklch(0.985 0 0);
112
+ --sidebar-primary: oklch(0.488 0.243 264.376);
113
+ --sidebar-primary-foreground: oklch(0.985 0 0);
114
+ --sidebar-accent: oklch(0.269 0 0);
115
+ --sidebar-accent-foreground: oklch(0.985 0 0);
116
+ --sidebar-border: oklch(1 0 0 / 10%);
117
+ --sidebar-ring: oklch(0.556 0 0);
118
+ }
119
+
120
+ @layer base {
121
+ * {
122
+ @apply border-border outline-ring/50;
123
+ }
124
+ body {
125
+ @apply bg-background text-foreground;
126
+ }
127
+ html {
128
+ @apply font-sans;
129
+ }
130
+ }
@@ -0,0 +1,33 @@
1
+ import type { Metadata } from "next";
2
+ import { Geist, Geist_Mono } from "next/font/google";
3
+ import "./globals.css";
4
+
5
+ const geistSans = Geist({
6
+ variable: "--font-geist-sans",
7
+ subsets: ["latin"],
8
+ });
9
+
10
+ const geistMono = Geist_Mono({
11
+ variable: "--font-geist-mono",
12
+ subsets: ["latin"],
13
+ });
14
+
15
+ export const metadata: Metadata = {
16
+ title: "Create Next App",
17
+ description: "Generated by create next app",
18
+ };
19
+
20
+ export default function RootLayout({
21
+ children,
22
+ }: Readonly<{
23
+ children: React.ReactNode;
24
+ }>) {
25
+ return (
26
+ <html
27
+ lang="en"
28
+ className={`${geistSans.variable} ${geistMono.variable} h-full antialiased`}
29
+ >
30
+ <body className="min-h-full flex flex-col">{children}</body>
31
+ </html>
32
+ );
33
+ }
@@ -0,0 +1,6 @@
1
+ // src/app/page.tsx
2
+ import { HomeView } from '@/views/HomeView';
3
+
4
+ export default function HomePage() {
5
+ return <HomeView />;
6
+ }
@@ -0,0 +1,67 @@
1
+ import * as React from "react"
2
+ import { cva, type VariantProps } from "class-variance-authority"
3
+ import { Slot } from "radix-ui"
4
+
5
+ import { cn } from "@/lib/utils"
6
+
7
+ const buttonVariants = cva(
8
+ "group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default: "bg-primary text-primary-foreground hover:bg-primary/80",
13
+ outline:
14
+ "border-border bg-background hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
15
+ secondary:
16
+ "bg-secondary text-secondary-foreground hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
17
+ ghost:
18
+ "hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
19
+ destructive:
20
+ "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
21
+ link: "text-primary underline-offset-4 hover:underline",
22
+ },
23
+ size: {
24
+ default:
25
+ "h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
26
+ xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
27
+ sm: "h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
28
+ lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
29
+ icon: "size-8",
30
+ "icon-xs":
31
+ "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
32
+ "icon-sm":
33
+ "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
34
+ "icon-lg": "size-9",
35
+ },
36
+ },
37
+ defaultVariants: {
38
+ variant: "default",
39
+ size: "default",
40
+ },
41
+ }
42
+ )
43
+
44
+ function Button({
45
+ className,
46
+ variant = "default",
47
+ size = "default",
48
+ asChild = false,
49
+ ...props
50
+ }: React.ComponentProps<"button"> &
51
+ VariantProps<typeof buttonVariants> & {
52
+ asChild?: boolean
53
+ }) {
54
+ const Comp = asChild ? Slot.Root : "button"
55
+
56
+ return (
57
+ <Comp
58
+ data-slot="button"
59
+ data-variant={variant}
60
+ data-size={size}
61
+ className={cn(buttonVariants({ variant, size, className }))}
62
+ {...props}
63
+ />
64
+ )
65
+ }
66
+
67
+ export { Button, buttonVariants }
@@ -0,0 +1,5 @@
1
+ 'use server';
2
+
3
+ export async function submitDemo(payload: { count: number }) {
4
+ return payload;
5
+ }
@@ -0,0 +1,3 @@
1
+ export async function fetchDemo() {
2
+ return { ok: true };
3
+ }
@@ -0,0 +1,4 @@
1
+ export { FeatureDemo } from './ui/FeatureDemo';
2
+ export type { DemoState } from './model/types';
3
+ export { fetchDemo } from './api/fetchDemo';
4
+ export { submitDemo } from './actions/submitDemo';
@@ -0,0 +1,3 @@
1
+ export function formatDemoLabel(value: string) {
2
+ return value.trim();
3
+ }
@@ -0,0 +1,2 @@
1
+ export type { DemoState } from './types';
2
+ export { initialDemoState } from './types';
@@ -0,0 +1,7 @@
1
+ export type DemoState = {
2
+ count: number;
3
+ };
4
+
5
+ export const initialDemoState: DemoState = {
6
+ count: 0,
7
+ };
@@ -0,0 +1,18 @@
1
+ 'use client';
2
+
3
+ import { Button } from '@/shared/ui';
4
+ import { useState } from 'react';
5
+
6
+ export function FeatureDemo() {
7
+ const [count, setCount] = useState(0);
8
+
9
+ return (
10
+ <div className="p-6 border rounded-xl bg-card">
11
+ <h2 className="text-2xl font-semibold mb-4">Demo Feature</h2>
12
+ <p className="mb-4">Счётчик: {count}</p>
13
+ <Button onClick={() => setCount(count + 1)}>
14
+ Увеличить
15
+ </Button>
16
+ </div>
17
+ );
18
+ }
@@ -0,0 +1 @@
1
+ export { cn } from '@/shared/lib/utils';
@@ -0,0 +1,6 @@
1
+ import { type ClassValue, clsx } from "clsx";
2
+ import { twMerge } from "tailwind-merge";
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs));
6
+ }
@@ -0,0 +1,2 @@
1
+ export { Button } from '@/components/ui/button';
2
+ // Добавляй сюда другие компоненты shadcn
@@ -0,0 +1,21 @@
1
+ 'use client';
2
+
3
+ import { FeatureDemo } from '@/features/demo';
4
+
5
+ export function HomeView() {
6
+ return (
7
+ <main className="min-h-screen p-8">
8
+ <div className="max-w-4xl mx-auto">
9
+ <h1 className="text-4xl font-bold mb-8">
10
+ Next Architecture
11
+ </h1>
12
+
13
+ <p className="text-xl text-muted-foreground mb-8">
14
+ Профессиональная структура для Next.js 16
15
+ </p>
16
+
17
+ <FeatureDemo />
18
+ </div>
19
+ </main>
20
+ );
21
+ }
@@ -0,0 +1,40 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2017",
4
+ "lib": ["dom", "dom.iterable", "esnext"],
5
+ "allowJs": true,
6
+ "skipLibCheck": true,
7
+ "strict": true,
8
+ "noEmit": true,
9
+ "esModuleInterop": true,
10
+ "module": "esnext",
11
+ "moduleResolution": "bundler",
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true,
14
+ "jsx": "react-jsx",
15
+ "incremental": true,
16
+ "plugins": [
17
+ {
18
+ "name": "next"
19
+ }
20
+ ],
21
+ "paths": {
22
+ "@/*": ["./src/*"],
23
+ "@app/*": ["./src/app/*"],
24
+ "@views/*": ["./src/views/*"],
25
+ "@features/*": ["./src/features/*"],
26
+ "@widgets/*": ["./src/widgets/*"],
27
+ "@entities/*": ["./src/entities/*"],
28
+ "@shared/*": ["./src/shared/*"]
29
+ }
30
+ },
31
+ "include": [
32
+ "next-env.d.ts",
33
+ "**/*.ts",
34
+ "**/*.tsx",
35
+ ".next/types/**/*.ts",
36
+ ".next/dev/types/**/*.ts",
37
+ "**/*.mts"
38
+ ],
39
+ "exclude": ["node_modules"]
40
+ }
@@ -0,0 +1 @@
1
+ export type { {{Name}} } from '../model/types';
@@ -0,0 +1,3 @@
1
+ export type {{Name}} = {
2
+ id: string;
3
+ };
@@ -0,0 +1,8 @@
1
+ export function {{Name}}Card({ item }: { item: { id: string } }) {
2
+ return (
3
+ <article className="rounded-lg border p-4">
4
+ <p className="text-sm text-muted-foreground">Entity: {{name}}</p>
5
+ <p className="font-medium">{item.id}</p>
6
+ </article>
7
+ );
8
+ }
@@ -0,0 +1,5 @@
1
+ 'use server';
2
+
3
+ export async function submit{{Name}}(payload: { id: string }) {
4
+ return payload;
5
+ }
@@ -0,0 +1,3 @@
1
+ export async function fetch{{Name}}() {
2
+ return { id: '{{name}}' };
3
+ }
@@ -0,0 +1,4 @@
1
+ export { {{Name}} } from './ui/{{Name}}';
2
+ export type { {{Name}}State } from './model/types';
3
+ export { fetch{{Name}} } from './api/fetch{{Name}}';
4
+ export { submit{{Name}} } from './actions/submit{{Name}}';
@@ -0,0 +1,3 @@
1
+ export function format{{Name}}Label(value: string) {
2
+ return value.trim();
3
+ }
@@ -0,0 +1,5 @@
1
+ export type { {{Name}}State } from '../model/types';
2
+ export { initial{{Name}}State } from '../model/types';
3
+ export { fetch{{Name}} } from '../api/fetch{{Name}}';
4
+ export { format{{Name}}Label } from '../lib/format{{Name}}';
5
+ export { submit{{Name}} } from '../actions/submit{{Name}}';
@@ -0,0 +1,7 @@
1
+ export type {{Name}}State = {
2
+ id: string;
3
+ };
4
+
5
+ export const initial{{Name}}State: {{Name}}State = {
6
+ id: '{{name}}',
7
+ };
@@ -0,0 +1,10 @@
1
+ 'use client';
2
+
3
+ export function {{Name}}() {
4
+ return (
5
+ <section className="rounded-xl border bg-card p-6">
6
+ <h2 className="text-2xl font-semibold">{{Name}}</h2>
7
+ <p className="mt-2 text-muted-foreground">Feature slice: {{name}}</p>
8
+ </section>
9
+ );
10
+ }
@@ -0,0 +1,12 @@
1
+ 'use client';
2
+
3
+ export function {{Name}}() {
4
+ return (
5
+ <main className="min-h-screen p-8">
6
+ <div className="mx-auto max-w-4xl">
7
+ <h1 className="text-4xl font-bold">{{Name}}</h1>
8
+ <p className="mt-4 text-muted-foreground">View slice: {{name}}</p>
9
+ </div>
10
+ </main>
11
+ );
12
+ }
@@ -0,0 +1 @@
1
+ export { {{Name}} } from './ui/{{Name}}';
@@ -0,0 +1,9 @@
1
+ export function {{Name}}() {
2
+ return (
3
+ <header className="border-b bg-background px-6 py-4">
4
+ <div className="mx-auto flex max-w-6xl items-center justify-between">
5
+ <span className="font-semibold">{{Name}}</span>
6
+ </div>
7
+ </header>
8
+ );
9
+ }
@@ -0,0 +1,50 @@
1
+ import * as eslint from 'eslint';
2
+ import { Rule } from 'eslint';
3
+
4
+ declare const noCrossFeatureImports: Rule.RuleModule;
5
+
6
+ declare const noDeepImports: Rule.RuleModule;
7
+
8
+ declare const noServerInClient: Rule.RuleModule;
9
+
10
+ declare const noUpwardImports: Rule.RuleModule;
11
+
12
+ declare const plugin: {
13
+ meta: {
14
+ name: string;
15
+ version: string;
16
+ };
17
+ rules: {
18
+ 'no-cross-feature-imports': eslint.Rule.RuleModule;
19
+ 'no-deep-imports': eslint.Rule.RuleModule;
20
+ 'no-server-in-client': eslint.Rule.RuleModule;
21
+ 'no-upward-imports': eslint.Rule.RuleModule;
22
+ };
23
+ };
24
+
25
+ declare const configs: {
26
+ recommended: {
27
+ plugins: {
28
+ 'next-arch': {
29
+ meta: {
30
+ name: string;
31
+ version: string;
32
+ };
33
+ rules: {
34
+ 'no-cross-feature-imports': eslint.Rule.RuleModule;
35
+ 'no-deep-imports': eslint.Rule.RuleModule;
36
+ 'no-server-in-client': eslint.Rule.RuleModule;
37
+ 'no-upward-imports': eslint.Rule.RuleModule;
38
+ };
39
+ };
40
+ };
41
+ rules: {
42
+ 'next-arch/no-cross-feature-imports': "error";
43
+ 'next-arch/no-deep-imports': "error";
44
+ 'next-arch/no-server-in-client': "error";
45
+ 'next-arch/no-upward-imports': "error";
46
+ };
47
+ };
48
+ };
49
+
50
+ export { configs, plugin as default, noCrossFeatureImports, noDeepImports, noServerInClient, noUpwardImports };