|
1 | 1 | # Build Architecture |
2 | 2 |
|
3 | | -## External Dependencies |
| 3 | +## Overview |
4 | 4 |
|
5 | | -### Overview |
| 5 | +Socket Lib uses a specialized architecture for dependencies to optimize bundle size and ensure clean separation between bundled and external code. |
6 | 6 |
|
7 | | -The registry uses a specialized architecture for managing dependencies to optimize bundle size and ensure clean separation between bundled and external code. |
| 7 | +## Key Concepts |
8 | 8 |
|
9 | | -### Dependency Types |
| 9 | +**Vendored Dependencies**: Source code copied into `src/external/` and bundled |
| 10 | +**External Dependencies**: Listed in `dependencies` and used at runtime |
| 11 | +**Validation**: Automated checking via `node scripts/validate-external.mjs` |
10 | 12 |
|
11 | | -#### dependencies (Runtime) |
| 13 | +## Dependency Types |
12 | 14 |
|
13 | | -The following package is a **runtime dependency** because it's a separate package: |
| 15 | +### Runtime Dependencies |
14 | 16 |
|
15 | 17 | ```json |
16 | 18 | "@socketregistry/packageurl-js": "1.3.0" |
17 | 19 | ``` |
18 | 20 |
|
19 | | -This package: |
20 | | -- Is a separate package that depends on registry |
| 21 | +Separate packages that: |
21 | 22 | - Can be re-exported from `src/external/` |
22 | | -- Is listed in ALLOWED_EXTERNAL_PACKAGES |
| 23 | +- Listed in ALLOWED_EXTERNAL_PACKAGES |
| 24 | +- Required at runtime |
23 | 25 |
|
24 | | -#### devDependencies (Build-time, Vendored) |
| 26 | +### Vendored Dependencies (Build-time) |
25 | 27 |
|
26 | | -Other @socketregistry and @socketsecurity packages are **vendored** into `src/external/`: |
27 | | -- The source code is copied directly into external files |
28 | | -- They do NOT need to be listed in any dependencies |
29 | | -- They are standalone, bundled code |
| 28 | +Other @socketregistry and @socketsecurity packages: |
| 29 | +- Source code copied into `src/external/` |
| 30 | +- NOT listed in dependencies |
| 31 | +- Bundled at build time |
30 | 32 |
|
31 | | -### The src/external/ Layer |
| 33 | +## Import Rules |
32 | 34 |
|
33 | | -#### Purpose |
34 | | - |
35 | | -`src/external/` contains **vendored/bundled source code** from dependencies. |
36 | | - |
37 | | -#### Import Rules |
38 | | - |
39 | | -**Inside src/external/**: Files must contain bundled/vendored code |
| 35 | +**Inside `src/external/`**: Must contain bundled/vendored code |
40 | 36 | ```javascript |
41 | 37 | // src/external/@socketregistry/is-unicode-supported.js |
42 | | -// Contains the full source code, not a re-export |
43 | 38 | module.exports = function isUnicodeSupported() { |
44 | 39 | // ... implementation ... |
45 | 40 | } |
46 | 41 | ``` |
47 | 42 |
|
48 | | -**Outside src/external/**: Must use relative paths |
| 43 | +**Outside `src/external/`**: Use relative paths |
49 | 44 | ```javascript |
50 | | -// src/lib/logger.ts - CORRECT |
51 | | -require('../external/@socketregistry/is-unicode-supported')() |
| 45 | +// ✅ CORRECT |
| 46 | +require('../external/@socketregistry/is-unicode-supported') |
52 | 47 |
|
53 | | -// src/lib/logger.ts - INCORRECT |
| 48 | +// ❌ WRONG |
54 | 49 | require('@socketregistry/is-unicode-supported') |
55 | 50 | ``` |
56 | 51 |
|
57 | | -### Validation |
58 | | - |
59 | | -The `scripts/validate-external.mjs` script enforces these rules: |
| 52 | +## Validation |
60 | 53 |
|
61 | | -- Scans all files in `src/external/` |
62 | | -- Detects re-exports of `@socketregistry/*` and `@socketsecurity/*` packages (except allowed) |
63 | | -- Ensures external files contain bundled code, not `require('@package')` re-exports |
64 | | - |
65 | | -Run validation: |
| 54 | +Run validation before build: |
66 | 55 | ```bash |
67 | 56 | node scripts/validate-external.mjs |
68 | 57 | ``` |
69 | 58 |
|
70 | | -Forbidden patterns in `src/external/` (except ALLOWED_EXTERNAL_PACKAGES): |
| 59 | +Detects forbidden patterns in `src/external/` (except ALLOWED_EXTERNAL_PACKAGES): |
71 | 60 | - `require('@socketregistry/package-name')` |
72 | | -- `from '@socketregistry/package-name'` |
73 | 61 | - `require('@socketsecurity/package-name')` |
| 62 | +- `from '@socketregistry/package-name'` |
74 | 63 | - `from '@socketsecurity/package-name'` |
75 | 64 |
|
76 | | -Allowed: |
77 | | -- `@socketregistry/packageurl-js` - separate package, listed in dependencies |
78 | | - |
79 | | -### Build Process |
80 | | - |
81 | | -#### src/external/ Files |
| 65 | +## Build Process |
82 | 66 |
|
83 | | -Files in `src/external/`: |
84 | | -1. Are validated before build (must be bundled code) |
85 | | -2. Copied to `dist/external/` by `scripts/rollup/build-external.mjs` |
86 | | -3. The bundled code is included in the dist output |
| 67 | +1. Validate external files (must be bundled code) |
| 68 | +2. Copy `src/external/` to `dist/external/` |
| 69 | +3. Rollup externalizes Node.js built-ins, node_modules, and `/external/` paths |
87 | 70 |
|
88 | | -#### Rollup Configuration |
89 | | - |
90 | | -The main rollup config (`.config/rollup.dist.config.mjs`) externalizes: |
91 | | -- Node.js built-ins |
92 | | -- `node_modules` dependencies |
93 | | -- Paths containing `/external/` |
94 | | - |
95 | | -### Why This Architecture? |
96 | | - |
97 | | -1. **No Runtime Dependencies**: Vendored code means no external dependencies needed |
98 | | -2. **Clear Boundaries**: `src/external/` contains only bundled/vendored code |
99 | | -3. **Build-time Validation**: Automatic detection of accidental re-exports |
100 | | -4. **Smaller Bundles**: Only include what's actually used |
101 | | -5. **Maintainability**: Clear rules about what external files can contain |
102 | | - |
103 | | -### Common Mistakes |
104 | | - |
105 | | -❌ **Re-exporting from npm in src/external/** |
106 | | -```javascript |
107 | | -// src/external/@socketregistry/yocto-spinner.js - WRONG |
108 | | -module.exports = require('@socketregistry/yocto-spinner') |
109 | | -``` |
110 | | - |
111 | | -❌ **Adding vendored packages to devDependencies** |
112 | | -```json |
113 | | -"devDependencies": { |
114 | | - "@socketregistry/yocto-spinner": "1.0.24" // WRONG - it's vendored |
115 | | -} |
116 | | -``` |
| 71 | +## Common Patterns |
117 | 72 |
|
118 | | -❌ **Bare imports outside src/external/** |
119 | | -```javascript |
120 | | -// src/lib/logger.ts - WRONG |
121 | | -require('@socketregistry/is-unicode-supported') |
122 | | -``` |
| 73 | +### ✅ Correct |
123 | 74 |
|
124 | | -✅ **Correct patterns** |
| 75 | +**Vendored code:** |
125 | 76 | ```javascript |
126 | | -// src/external/@socketregistry/yocto-spinner.js - CORRECT |
| 77 | +// src/external/@socketregistry/yocto-spinner.js |
127 | 78 | module.exports = function yoctoSpinner(options) { |
128 | 79 | // ... full bundled implementation ... |
129 | 80 | } |
130 | 81 | ``` |
131 | 82 |
|
| 83 | +**Relative import:** |
132 | 84 | ```javascript |
133 | | -// src/lib/logger.ts - CORRECT |
| 85 | +// src/lib/logger.ts |
134 | 86 | require('../external/@socketregistry/is-unicode-supported') |
135 | 87 | ``` |
136 | 88 |
|
| 89 | +**Runtime dependency:** |
137 | 90 | ```json |
138 | | -// package.json - CORRECT |
139 | 91 | "dependencies": { |
140 | 92 | "@socketregistry/packageurl-js": "1.3.0" |
141 | 93 | } |
142 | 94 | ``` |
143 | 95 |
|
144 | | -### Troubleshooting |
| 96 | +### ❌ Wrong |
| 97 | + |
| 98 | +**Re-exporting in external:** |
| 99 | +```javascript |
| 100 | +// src/external/@socketregistry/yocto-spinner.js |
| 101 | +module.exports = require('@socketregistry/yocto-spinner') // WRONG |
| 102 | +``` |
| 103 | + |
| 104 | +**Vendored package in devDependencies:** |
| 105 | +```json |
| 106 | +"devDependencies": { |
| 107 | + "@socketregistry/yocto-spinner": "1.0.24" // WRONG - it's vendored |
| 108 | +} |
| 109 | +``` |
145 | 110 |
|
146 | | -**"Cannot find module '@socketregistry/package-name'" at runtime** |
| 111 | +**Bare import outside external:** |
| 112 | +```javascript |
| 113 | +// src/lib/logger.ts |
| 114 | +require('@socketregistry/is-unicode-supported') // WRONG |
| 115 | +``` |
147 | 116 |
|
148 | | -This means a package is being required directly but isn't in dependencies. Check if: |
149 | | -1. It should be vendored into `src/external/` as bundled code |
150 | | -2. It should be added to `dependencies` and ALLOWED_EXTERNAL_PACKAGES |
| 117 | +## Troubleshooting |
151 | 118 |
|
152 | | -**Validation fails for external file** |
| 119 | +**"Cannot find module '@socketregistry/package-name'"** |
| 120 | +- Should it be vendored into `src/external/` as bundled code? |
| 121 | +- Should it be added to `dependencies` and ALLOWED_EXTERNAL_PACKAGES? |
153 | 122 |
|
154 | | -The external file contains a re-export instead of bundled code. Either: |
155 | | -1. Vendor the source code directly into the file |
156 | | -2. Add the package to ALLOWED_EXTERNAL_PACKAGES and `dependencies` if it's meant to be a runtime dependency |
| 123 | +**Validation fails** |
| 124 | +- File contains re-export instead of bundled code |
| 125 | +- Either vendor the source directly or add to ALLOWED_EXTERNAL_PACKAGES |
157 | 126 |
|
158 | 127 | **How to vendor a new dependency** |
159 | | - |
160 | | -1. Copy the source code into `src/external/@scope/package-name.js` |
| 128 | +1. Copy source into `src/external/@scope/package-name.js` |
161 | 129 | 2. Ensure it doesn't `require()` the npm package |
162 | | -3. Run `pnpm run validate:external` to verify |
163 | | -4. The code will be bundled during build |
| 130 | +3. Run `pnpm run validate:external` |
| 131 | +4. Code will bundle during build |
| 132 | + |
| 133 | +## Why This Architecture? |
| 134 | + |
| 135 | +1. **No Runtime Dependencies**: Vendored code eliminates external dependencies |
| 136 | +2. **Clear Boundaries**: `src/external/` contains only bundled code |
| 137 | +3. **Build-time Validation**: Automatic detection of re-exports |
| 138 | +4. **Smaller Bundles**: Include only what's used |
| 139 | +5. **Maintainability**: Clear rules for external files |
0 commit comments