face-up 0.0.0 → 0.0.1

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 (46) hide show
  1. package/.gitmodules +3 -0
  2. package/.kiro/steering/project-context.md +17 -0
  3. package/.vscode/settings.json +3 -0
  4. package/FaceUp.js +305 -0
  5. package/README.md +165 -2
  6. package/imports.html +8 -0
  7. package/package.json +30 -20
  8. package/tests/test1.html +130 -0
  9. package/types/.kiro/specs/conversion-template/README.md +128 -0
  10. package/types/.kiro/specs/conversion-template/design.md +360 -0
  11. package/types/.kiro/specs/conversion-template/requirements.md +191 -0
  12. package/types/.kiro/specs/conversion-template/tasks.md +174 -0
  13. package/types/.kiro/steering/coding-standards.md +17 -0
  14. package/types/.kiro/steering/conversion-guide.md +103 -0
  15. package/types/.kiro/steering/declarative-configuration.md +108 -0
  16. package/types/.kiro/steering/emc-json-serializability.md +306 -0
  17. package/types/EnhancementConversionInstructions.md +1626 -0
  18. package/types/LICENSE +21 -0
  19. package/types/NewCustomElementFeature.md +672 -0
  20. package/types/NewEnhancementInstructions.md +395 -0
  21. package/types/README.md +2 -0
  22. package/types/agrace/types.d.ts +11 -0
  23. package/types/assign-gingerly/types.d.ts +328 -0
  24. package/types/be-a-beacon/types.d.ts +17 -0
  25. package/types/be-bound/types.d.ts +61 -0
  26. package/types/be-buttoned-up/types.d.ts +19 -0
  27. package/types/be-clonable/types.d.ts +36 -0
  28. package/types/be-committed/types.d.ts +22 -0
  29. package/types/be-decked-with/types.d.ts +26 -0
  30. package/types/be-delible/types.d.ts +25 -0
  31. package/types/be-reflective/types.d.ts +80 -0
  32. package/types/be-render-neutral/types.d.ts +29 -0
  33. package/types/be-typed/types.d.ts +31 -0
  34. package/types/do-inc/types.d.ts +56 -0
  35. package/types/do-invoke/types.d.ts +38 -0
  36. package/types/do-merge/types.d.ts +28 -0
  37. package/types/do-toggle/types.d.ts +31 -0
  38. package/types/face-up/types.d.ts +104 -0
  39. package/types/global.d.ts +29 -0
  40. package/types/id-generation/types.d.ts +26 -0
  41. package/types/inferencer/types.d.ts +46 -0
  42. package/types/mount-observer/types.d.ts +363 -0
  43. package/types/nested-regex-groups/types.d.ts +101 -0
  44. package/types/roundabout/types.d.ts +255 -0
  45. package/types/time-ticker/types.d.ts +66 -0
  46. package/types/truth-sourcer/types.d.ts +46 -0
@@ -0,0 +1,306 @@
1
+ # EMC Configuration JSON Serializability
2
+
3
+ ## Core Principle
4
+
5
+ **All content in `emc.mjs` files MUST be JSON-serializable without loss of information.**
6
+
7
+ The `render()` function at the bottom of every `emc.mjs` file exports the configuration as JSON via `JSON.stringify()`. This JSON is what gets loaded at runtime by enhancement classes and the be-hive system.
8
+
9
+ ## Why This Matters
10
+
11
+ 1. **Runtime Loading**: Enhancement classes import `emc.json` (not `emc.mjs`) using JSON import assertions
12
+ 2. **Declarative Configuration**: The JSON file is the source of truth for how enhancements are configured
13
+ 3. **Portability**: JSON files can be loaded by any JavaScript environment without executing code
14
+ 4. **Security**: JSON is safer than executing arbitrary JavaScript
15
+ 5. **Tooling**: JSON can be validated, transformed, and analyzed by standard tools
16
+
17
+ ## What IS JSON-Serializable
18
+
19
+ ✅ **Allowed in emc.mjs:**
20
+ - Strings: `"hello"`
21
+ - Numbers: `42`, `3.14`
22
+ - Booleans: `true`, `false`
23
+ - null: `null`
24
+ - Arrays: `[1, 2, 3]`
25
+ - Plain objects: `{ key: "value" }`
26
+ - Nested structures: `{ items: [{ id: 1 }, { id: 2 }] }`
27
+
28
+ ## What is NOT JSON-Serializable
29
+
30
+ ❌ **NOT allowed in emc.mjs:**
31
+ - **Functions**: `parser: (v) => v.split(',')` ❌
32
+ - **Class constructors**: `spawn: MyClass` ❌
33
+ - **Symbols**: `Symbol('key')` ❌
34
+ - **undefined**: `value: undefined` ❌ (becomes `null` or omitted)
35
+ - **Regular expressions**: `/pattern/` ❌ (becomes `{}`)
36
+ - **Dates**: `new Date()` ❌ (becomes string)
37
+ - **WeakMap/WeakSet**: Not serializable
38
+ - **Circular references**: Will throw error
39
+
40
+ ## How to Handle Non-Serializable Values
41
+
42
+ ### Functions (Parsers, Handlers)
43
+
44
+ **❌ WRONG:**
45
+ ```javascript
46
+ // emc.mjs
47
+ function myParser(value) {
48
+ return value.split(',');
49
+ }
50
+
51
+ export const emc = {
52
+ enhConfig: {
53
+ withAttrs: {
54
+ _base: {
55
+ parser: myParser // ❌ Function reference - not JSON serializable
56
+ }
57
+ }
58
+ }
59
+ };
60
+ ```
61
+
62
+ **✅ CORRECT:**
63
+ ```javascript
64
+ // emc.mjs
65
+ export const emc = {
66
+ enhConfig: {
67
+ withAttrs: {
68
+ _base: {
69
+ parser: 'myParser' // ✅ String reference - JSON serializable
70
+ }
71
+ }
72
+ }
73
+ };
74
+
75
+ // Separate parser file: parser.js
76
+ export default function myParser(value) {
77
+ return value.split(',');
78
+ }
79
+
80
+ // HTML: Load parser separately
81
+ <script type="emc-parser" src="./parser.js" parser-name="myParser"></script>
82
+ ```
83
+
84
+ ### Class Constructors (spawn)
85
+
86
+ **❌ WRONG:**
87
+ ```javascript
88
+ // emc.mjs
89
+ import { MyEnhancement } from './my-enhancement.js';
90
+
91
+ export const emc = {
92
+ enhConfig: {
93
+ spawn: MyEnhancement // ❌ Class reference - not JSON serializable
94
+ }
95
+ };
96
+ ```
97
+
98
+ **✅ CORRECT:**
99
+ ```javascript
100
+ // emc.mjs
101
+ export const emc = {
102
+ enhConfig: {
103
+ spawn: 'my-enhancement/my-enhancement.js' // ✅ Module path string
104
+ }
105
+ };
106
+ ```
107
+
108
+ ### Regular Expressions
109
+
110
+ **❌ WRONG:**
111
+ ```javascript
112
+ export const emc = {
113
+ enhConfig: {
114
+ withAttrs: {
115
+ pattern: /^test-/ // ❌ RegExp - becomes {}
116
+ }
117
+ }
118
+ };
119
+ ```
120
+
121
+ **✅ CORRECT:**
122
+ ```javascript
123
+ export const emc = {
124
+ enhConfig: {
125
+ withAttrs: {
126
+ pattern: '^test-' // ✅ String - can be converted to RegExp at runtime
127
+ }
128
+ }
129
+ };
130
+ ```
131
+
132
+ ## Validation
133
+
134
+ Every `emc.mjs` file should end with:
135
+
136
+ ```javascript
137
+ export function render() {
138
+ return JSON.stringify(emc, null, 4);
139
+ }
140
+
141
+ console.log(render());
142
+ ```
143
+
144
+ **Test your configuration:**
145
+ ```bash
146
+ node emc.mjs
147
+ ```
148
+
149
+ If this command:
150
+ - ✅ Outputs valid JSON → Configuration is serializable
151
+ - ❌ Throws an error → You have non-serializable values
152
+ - ❌ Outputs `{}` or `null` for a property → You have a non-serializable value that was silently dropped
153
+
154
+ ## Common Mistakes
155
+
156
+ ### Mistake 1: Inline Parser Functions
157
+
158
+ ```javascript
159
+ // ❌ WRONG
160
+ export const emc = {
161
+ enhConfig: {
162
+ withAttrs: {
163
+ _base: {
164
+ parser: (v) => v.split(',') // Lost in JSON.stringify()
165
+ }
166
+ }
167
+ }
168
+ };
169
+ ```
170
+
171
+ **Result:** The `parser` property becomes `{}` in the JSON output.
172
+
173
+ ### Mistake 2: Importing Classes
174
+
175
+ ```javascript
176
+ // ❌ WRONG
177
+ import { MyClass } from './my-class.js';
178
+
179
+ export const emc = {
180
+ customData: {
181
+ helperClass: MyClass // Lost in JSON.stringify()
182
+ }
183
+ };
184
+ ```
185
+
186
+ **Result:** The `helperClass` property becomes `{}` in the JSON output.
187
+
188
+ ### Mistake 3: Using undefined
189
+
190
+ ```javascript
191
+ // ❌ WRONG
192
+ export const emc = {
193
+ customData: {
194
+ optionalValue: undefined // Omitted in JSON.stringify()
195
+ }
196
+ };
197
+ ```
198
+
199
+ **Result:** The `optionalValue` property is completely omitted from the JSON output.
200
+
201
+ ## Best Practices
202
+
203
+ 1. **Always test serialization**: Run `node emc.mjs` to verify output
204
+ 2. **Use string references**: For parsers, use string names that resolve at runtime
205
+ 3. **Use module paths**: For `spawn`, use string paths to modules
206
+ 4. **Document external dependencies**: If your config references parsers by name, document which parser files are required
207
+ 5. **Avoid undefined**: Use `null` instead if you need to represent "no value"
208
+ 6. **Keep it simple**: The simpler your config, the easier it is to serialize
209
+
210
+ ## Example: Complete Valid emc.mjs
211
+
212
+ ```javascript
213
+ // @ts-check
214
+
215
+ /** @import {EMC} from './types/mount-observer/types' */;
216
+ /** @import {AllProps, Actions} from './types/my-enhancement/types' */
217
+ /** @import {RAConfig} from './types/roundabout/types' */
218
+
219
+ /**
220
+ * @type {EMC<any, AllProps, Element, RAConfig<AllProps, Actions> >}
221
+ */
222
+ export const emc = {
223
+ enhConfig: {
224
+ enhKey: 'MyEnhancement',
225
+ spawn: 'my-enhancement/my-enhancement.js', // ✅ String path
226
+ withAttrs: {
227
+ base: 'my-enhancement',
228
+ value: '${base}-value',
229
+ _value: {
230
+ parser: 'myParser' // ✅ String reference
231
+ }
232
+ }
233
+ },
234
+ customData: {
235
+ weakRef: {
236
+ properties: ['enhancedElement']
237
+ },
238
+ actions: {
239
+ hydrate: {
240
+ ifAllOf: ['value', 'enhancedElement']
241
+ }
242
+ },
243
+ defaultPropVals: {
244
+ enabled: true,
245
+ count: 0
246
+ }
247
+ }
248
+ };
249
+
250
+ export function render() {
251
+ return JSON.stringify(emc, null, 4);
252
+ }
253
+
254
+ console.log(render());
255
+ ```
256
+
257
+ ## Enforcement
258
+
259
+ This principle should be enforced by:
260
+
261
+ 1. **Code review**: Check that all `emc.mjs` files only contain JSON-serializable values
262
+ 2. **Testing**: Run `node emc.mjs` as part of the build process
263
+ 3. **Documentation**: Reference this principle in conversion guides
264
+ 4. **Linting**: Consider adding a custom lint rule to detect non-serializable values
265
+
266
+ ## Dependency Version Management
267
+
268
+ **Always use specific point versions** in `package.json`, not version ranges:
269
+
270
+ ✅ **CORRECT:**
271
+ ```json
272
+ {
273
+ "dependencies": {
274
+ "be-hive": "0.1.9",
275
+ "mount-observer": "0.0.16",
276
+ "roundabout-lib": "0.0.2"
277
+ }
278
+ }
279
+ ```
280
+
281
+ ❌ **WRONG:**
282
+ ```json
283
+ {
284
+ "dependencies": {
285
+ "be-hive": "^0.1.9", // ❌ Caret allows minor/patch updates
286
+ "mount-observer": "~0.0.16", // ❌ Tilde allows patch updates
287
+ "roundabout-lib": "*" // ❌ Wildcard allows any version
288
+ }
289
+ }
290
+ ```
291
+
292
+ **Why specific versions?**
293
+ - **Reproducible builds**: Same versions across all environments
294
+ - **No surprises**: Prevents automatic breaking changes
295
+ - **Explicit control**: You decide when to update
296
+ - **Easier debugging**: Know exactly which version caused an issue
297
+ - **Consistent testing**: CI/CD uses same versions as development
298
+
299
+ **When to update:**
300
+ Use `npm run update` (which runs `ncu -u && npm install`) to explicitly update all dependencies to their latest versions. Review the changes and test thoroughly before committing.
301
+
302
+ ## Related Documentation
303
+
304
+ - [Scoped Parser Registry](https://github.com/bahrus/mount-observer#scoped-parser-registry-for-emc-scripts)
305
+ - [EMC Scripts](https://github.com/bahrus/mount-observer#element-mount-configuration-emc-scripts)
306
+ - [Conversion Instructions](../ConversionInstructions.md)