apprun 3.38.0 → 6.0.0-rc.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 (113) hide show
  1. package/CHANGELOG.md +12 -1
  2. package/README.md +18 -10
  3. package/apprun.d.ts +67 -23
  4. package/dist/apprun-code.js +1 -1
  5. package/dist/apprun-code.js.map +1 -1
  6. package/dist/apprun-dev-tools.js +1 -1
  7. package/dist/apprun-dev-tools.js.map +1 -1
  8. package/dist/apprun-html.esm.js +7 -7
  9. package/dist/apprun-html.esm.js.map +1 -1
  10. package/dist/apprun-html.js +1 -1
  11. package/dist/apprun-html.js.map +1 -1
  12. package/dist/apprun-play.js +1 -1
  13. package/dist/apprun-play.js.map +1 -1
  14. package/dist/apprun.esm.js +1 -1
  15. package/dist/apprun.esm.js.map +1 -1
  16. package/dist/apprun.js +1 -1
  17. package/dist/apprun.js.map +1 -1
  18. package/esm/add-components.js +7 -7
  19. package/esm/add-components.js.map +1 -1
  20. package/esm/app.js +81 -32
  21. package/esm/app.js.map +1 -1
  22. package/esm/apprun-code.js +8 -2
  23. package/esm/apprun-code.js.map +1 -1
  24. package/esm/apprun-html.js +14 -9
  25. package/esm/apprun-html.js.map +1 -1
  26. package/esm/apprun-play.js +7 -1
  27. package/esm/apprun-play.js.map +1 -1
  28. package/esm/apprun.js +38 -19
  29. package/esm/apprun.js.map +1 -1
  30. package/esm/component.js +90 -37
  31. package/esm/component.js.map +1 -1
  32. package/esm/directive.js +1 -1
  33. package/esm/directive.js.map +1 -1
  34. package/esm/router.js +73 -19
  35. package/esm/router.js.map +1 -1
  36. package/esm/types.js +2 -1
  37. package/esm/types.js.map +1 -1
  38. package/esm/vdom-my.js +52 -52
  39. package/esm/vdom-my.js.map +1 -1
  40. package/esm/vdom-to-html.js +8 -1
  41. package/esm/vdom-to-html.js.map +1 -1
  42. package/esm/vdom.js +3 -3
  43. package/esm/vdom.js.map +1 -1
  44. package/esm/version.js +1 -1
  45. package/esm/version.js.map +1 -1
  46. package/esm/web-component.js +23 -6
  47. package/esm/web-component.js.map +1 -1
  48. package/jsx-runtime.js +1 -1
  49. package/jsx-runtime.js.map +1 -1
  50. package/package.json +62 -2
  51. package/.clinerules +0 -1
  52. package/.travis.yml +0 -10
  53. package/BACKERS.md +0 -8
  54. package/CNAME +0 -1
  55. package/WHATSNEW.md +0 -367
  56. package/ai/apprun-html.prompt.md +0 -290
  57. package/ai/apprun.prompt.md +0 -602
  58. package/apprun-book.jpg +0 -0
  59. package/dist/apprun-dev-tools-tests.js +0 -1
  60. package/dist/apprun-dev-tools.js.LICENSE.txt +0 -1
  61. package/dist/apprun-play-html.esm.js +0 -34
  62. package/dist/apprun-play-html.esm.js.map +0 -1
  63. package/error.log +0 -0
  64. package/esm/apprun-play-html.js +0 -210
  65. package/esm/apprun-play-html.js.map +0 -1
  66. package/esm/shadow.js +0 -8
  67. package/esm/shadow.js.map +0 -1
  68. package/esm/vdom-html.js +0 -22
  69. package/esm/vdom-html.js.map +0 -1
  70. package/esm/vdom-my-new.js +0 -327
  71. package/esm/vdom-my-new.js.map +0 -1
  72. package/esm/vdom-patch.js +0 -103
  73. package/esm/vdom-patch.js.map +0 -1
  74. package/index.html +0 -87
  75. package/jest.config.js +0 -57
  76. package/jest.setup.js +0 -73
  77. package/logo.png +0 -0
  78. package/react.js +0 -13
  79. package/rollup.config.js +0 -62
  80. package/src/add-components.ts +0 -103
  81. package/src/app.ts +0 -173
  82. package/src/apprun-code.tsx +0 -177
  83. package/src/apprun-dev-tools-tests.tsx +0 -101
  84. package/src/apprun-dev-tools.tsx +0 -307
  85. package/src/apprun-html.ts +0 -25
  86. package/src/apprun-play.tsx +0 -249
  87. package/src/apprun.ts +0 -238
  88. package/src/component.ts +0 -388
  89. package/src/createState.ts +0 -11
  90. package/src/decorator.ts +0 -98
  91. package/src/directive.ts +0 -303
  92. package/src/global.d.ts +0 -22
  93. package/src/router.ts +0 -311
  94. package/src/shadow.tsx +0 -8
  95. package/src/tsconfig.json +0 -16
  96. package/src/type-utils.ts +0 -130
  97. package/src/types.ts +0 -151
  98. package/src/vdom-html.ts_ +0 -20
  99. package/src/vdom-lit-html.ts +0 -67
  100. package/src/vdom-my-new.ts +0 -311
  101. package/src/vdom-my-prop-attr.ts +0 -241
  102. package/src/vdom-my.ts +0 -286
  103. package/src/vdom-patch.ts +0 -108
  104. package/src/vdom-to-html.tsx +0 -49
  105. package/src/vdom.ts +0 -28
  106. package/src/version.ts +0 -16
  107. package/src/web-component.ts +0 -154
  108. package/tsconfig.jest.json +0 -49
  109. package/tsconfig.json +0 -16
  110. package/tslint.json +0 -114
  111. package/typescriptreact.json +0 -87
  112. package/viewEngine.js +0 -54
  113. package/webpack.config.cjs +0 -41
package/src/app.ts DELETED
@@ -1,173 +0,0 @@
1
- /**
2
- * Core AppRun application class and singleton instance
3
- *
4
- * This file provides:
5
- * 1. App class - The core event system implementation with pub/sub capabilities
6
- * - on(): Subscribe to events with options (once, delay, global)
7
- * - off(): Unsubscribe from events with proper cleanup
8
- * - run(): Publish events synchronously with error handling
9
- * - runAsync(): Publish events asynchronously with Promise support, returns handler values
10
- * - query(): Deprecated alias for runAsync() - use runAsync() instead
11
- *
12
- * 2. Default app singleton - Global event bus instance
13
- * - Created once and reused across the application
14
- * - Stored in global scope (window/global) with version tracking
15
- * - Prevents duplicate instances across different versions
16
- *
17
- * Features:
18
- * - Event wildcards support (events ending with '*')
19
- * - Delayed event execution with timeout management
20
- * - Once-only event subscriptions
21
- * - Async event handling with Promise.all
22
- * - Global event bus shared across components
23
- * - Memory leak prevention with proper cleanup
24
- *
25
- * Type Safety Improvements (v3.35.1):
26
- * - Added validation for event handler functions
27
- * - Enhanced error handling in event execution
28
- * - Improved null checks in delayed event handling
29
- * - Better error reporting for invalid handlers
30
- *
31
- * Usage:
32
- * ```ts
33
- * // Subscribe to events
34
- * app.on('event-name', (state, ...args) => {
35
- * // Handle event
36
- * });
37
- *
38
- * // Publish events (fire-and-forget)
39
- * app.run('event-name', ...args);
40
- *
41
- * // Get return values from event handlers
42
- * app.runAsync('event-name', data).then(results => {
43
- * // Handle results array
44
- * });
45
- * ```
46
- */
47
-
48
- import { EventOptions } from './types'
49
- import { APPRUN_VERSION_GLOBAL } from './version'
50
-
51
- export class App {
52
-
53
- _events: { [key: string]: Array<{ fn: (...args: any[]) => any, options: EventOptions }> };
54
-
55
- constructor() {
56
- this._events = {} as { [key: string]: Array<{ fn: (...args: any[]) => any, options: EventOptions }> };
57
- }
58
-
59
- on(name: string, fn: (...args: any[]) => any, options: EventOptions = {}): void {
60
- this._events[name] = this._events[name] || [];
61
- this._events[name].push({ fn, options });
62
- }
63
-
64
- off(name: string, fn: (...args: any[]) => any): void {
65
- const subscribers = this._events[name] || [];
66
-
67
- this._events[name] = subscribers.filter((sub) => sub.fn !== fn);
68
- }
69
-
70
- find(name: string): any {
71
- return this._events[name];
72
- }
73
-
74
- run(name: string, ...args: any[]): number {
75
- const subscribers = this.getSubscribers(name, this._events);
76
- console.assert(subscribers && subscribers.length > 0, 'No subscriber for event: ' + name);
77
- subscribers.forEach((sub) => {
78
- const { fn, options } = sub;
79
- if (!fn || typeof fn !== 'function') {
80
- console.error(`AppRun event handler for '${name}' is not a function:`, fn);
81
- return false;
82
- }
83
- if (options.delay) {
84
- this.delay(name, fn, args, options);
85
- } else {
86
- try {
87
- Object.keys(options).length > 0 ? fn.apply(this, [...args, options]) : fn.apply(this, args);
88
- } catch (error) {
89
- console.error(`Error in event handler for '${name}':`, error);
90
- }
91
- }
92
- return !sub.options.once;
93
- });
94
-
95
- return subscribers.length;
96
- }
97
-
98
- once(name: string, fn: (...args: any[]) => any, options: EventOptions = {}): void {
99
- this.on(name, fn, { ...options, once: true });
100
- }
101
-
102
- private delay(name: string, fn: (...args: any[]) => any, args: any[], options: EventOptions): void {
103
- if (options._t) clearTimeout(options._t);
104
- options._t = setTimeout(() => {
105
- clearTimeout(options._t);
106
- try {
107
- Object.keys(options).length > 0 ? fn.apply(this, [...args, options]) : fn.apply(this, args);
108
- } catch (error) {
109
- console.error(`Error in delayed event handler for '${name}':`, error);
110
- }
111
- }, options.delay);
112
- }
113
-
114
- runAsync(name: string, ...args: any[]): Promise<any[]> {
115
- const subscribers = this.getSubscribers(name, this._events);
116
- console.assert(subscribers && subscribers.length > 0, 'No subscriber for event: ' + name);
117
- const promises = subscribers.map(sub => {
118
- const { fn, options } = sub;
119
- if (!fn || typeof fn !== 'function') {
120
- console.error(`AppRun async event handler for '${name}' is not a function:`, fn);
121
- return Promise.resolve(null);
122
- }
123
- try {
124
- return Object.keys(options).length > 0 ? fn.apply(this, [...args, options]) : fn.apply(this, args);
125
- } catch (error) {
126
- console.error(`Error in async event handler for '${name}':`, error);
127
- return Promise.reject(error);
128
- }
129
- });
130
- return Promise.all(promises);
131
- }
132
-
133
- /**
134
- * @deprecated Use runAsync() instead. app.query() will be removed in a future version.
135
- */
136
- query(name: string, ...args: any[]): Promise<any[]> {
137
- console.warn('app.query() is deprecated. Use app.runAsync() instead.');
138
- return this.runAsync(name, ...args);
139
- }
140
-
141
- private getSubscribers(name: string, events: { [key: string]: Array<{ fn: (...args: any[]) => any, options: EventOptions }> }): Array<{ fn: (...args: any[]) => any, options: EventOptions }> {
142
- const subscribers = events[name] || [];
143
-
144
- // Update the list of subscribers by pulling out those which will run once.
145
- // We must do this update prior to running any of the events in case they
146
- // cause additional events to be turned off or on.
147
- events[name] = subscribers.filter((sub) => {
148
- return !sub.options.once;
149
- });
150
- Object.keys(events).filter(evt => evt.endsWith('*') && name.startsWith(evt.replace('*', '')))
151
- .sort((a, b) => b.length - a.length)
152
- .forEach(evt => subscribers.push(...events[evt].map(sub => ({
153
- ...sub,
154
- options: { ...sub.options, event: name }
155
- }))));
156
- return subscribers;
157
- }
158
- }
159
-
160
- const AppRunVersions = APPRUN_VERSION_GLOBAL;
161
- let _app: App;
162
- const root = (typeof window !== 'undefined' ? window :
163
- typeof global !== 'undefined' ? global :
164
- typeof self !== 'undefined' ? self : {}) as any;
165
-
166
- if (root.app && root._AppRunVersions) {
167
- _app = root.app;
168
- } else {
169
- _app = new App();
170
- root.app = _app;
171
- root._AppRunVersions = AppRunVersions;
172
- }
173
- export default _app;
@@ -1,177 +0,0 @@
1
- import { app, Component } from './apprun';
2
-
3
- declare var CodeMirror;
4
-
5
- const styles = `
6
- .CodeMirror, .apprun-play iframe {
7
- height: 100%;
8
- border: dotted gray 1px;
9
- }
10
-
11
- .apprun-play {
12
- height: 100%;
13
- display: flex;
14
- font-size: 1.1rem;
15
- }
16
-
17
- .apprun-play .col {
18
- margin: 2px;
19
- }
20
-
21
- .apprun-play .editor, .apprun-play .preview {
22
- width: 100%;
23
- height: 100%;
24
- }
25
- `;
26
-
27
- const encodeHTML = code => {
28
- return code.replace(/&/g, '&amp;')
29
- .replace(/</g, '&lt;')
30
- .replace(/>/g, '&gt;')
31
- .replace(/"/g, '&quot;')
32
- .replace(/'/g, '&#039;');
33
- }
34
-
35
- const code_html = code => `<!DOCTYPE html>
36
- <html lang="en">
37
- <head>
38
- <meta charset="UTF-8">
39
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
40
- <meta http-equiv="X-UA-Compatible" content="ie=edge">
41
- <title>AppRun Playground</title>
42
- <style>
43
- body {
44
- font-family: "Benton Sans", "Helvetica Neue", helvetica, arial, sans-serif;
45
- margin: 2em;
46
- }
47
- </style>
48
- <script src="https://cdn.jsdelivr.net/npm/typescript@latest"></script>
49
- <script src="dist/apprun-html.js"></script>
50
- </head>
51
- <body>
52
- <pre id="code" style="display:none">${encodeHTML(code)}</pre>
53
- <script type="module">
54
- const code = document.getElementById('code').innerText;
55
- const compiled = ts.transpileModule(code, {
56
- compilerOptions: {
57
- "jsx": "react",
58
- "jsxFactory": "app.h",
59
- "jsxFragmentFactory": "app.Fragment",
60
- "target": "es2020",
61
- "module": "esnext",
62
- },
63
- reportDiagnostics: true,
64
- });
65
-
66
- if (compiled.diagnostics && compiled.diagnostics.length) {
67
- const pre = document.createElement('pre');
68
- pre.style = 'font-size: 10px;';
69
- pre.innerText = compiled.diagnostics.map(d => {
70
- const start = d.start;
71
- const end = d.start + d.length;
72
- const line = code.substring(0, end).split('\\n').length;
73
- const column = code.substring(0, end).split('\\n').pop().length;
74
- return \`Line: \${line}, Column: \${column}, \${d.messageText}\`;
75
- }).join('\\n');
76
- document.body.appendChild(pre);
77
- } else {
78
- window.onerror = function () {
79
- const pre = document.createElement('pre');
80
- pre.style = 'font-size: 10px;';
81
- pre.innerText = compiled.outputText;;
82
- document.body.appendChild(pre);
83
- };
84
- const script = document.createElement('script');
85
- script.type = 'module';
86
- script.text = compiled.outputText;
87
- document.body.appendChild(script);
88
- }
89
- </script>
90
- </body>
91
- </html>`;
92
-
93
-
94
- class Play extends Component {
95
- view = ({ code, hide_code }) => {
96
- return <>
97
- <style>{styles}</style>
98
- {hide_code ?
99
- <div class="apprun-play">
100
- <iframe class="preview" />
101
- </div>
102
- :
103
- <div class="apprun-play">
104
- <div class="col" style="width:75%" >
105
- <textarea class="editor">{code}</textarea>
106
- </div>
107
- <div class="col" style="flex:1" >
108
- <iframe class="preview" />
109
- </div>
110
- </div>}
111
- </>;
112
- }
113
-
114
- mounted = props => {
115
- const element = this['element'];
116
- const code_id = props['code-id'];
117
- const hide_code = props['hide-code'];
118
- const code_width = props['code-width'];
119
-
120
- let code_area;
121
- if (code_id) {
122
- code_area = document.getElementById(code_id);
123
- } else {
124
- code_area = element.previousElementSibling ||
125
- element.parentElement.previousElementSibling;
126
- }
127
-
128
- const code = code_area?.innerText // from div
129
- || code_area?.value // from textarea
130
- || element.textContent // from child node
131
-
132
- if (code_area) code_area.style.display = 'none';
133
-
134
- return { code, hide_code, code_width };
135
- }
136
-
137
-
138
- rendered = ({ code, hide_code, code_width }) => {
139
- const element = this['element'];
140
-
141
- const textarea = element.querySelector(".apprun-play .editor") as any;
142
- let iframe = element.querySelector('.apprun-play .preview');
143
- if (!iframe || !textarea) return;
144
-
145
- const run_code = code => {
146
- const iframe_clone = iframe.cloneNode();
147
- iframe.parentNode?.replaceChild(iframe_clone, iframe);
148
- iframe = iframe_clone;
149
- const doc = iframe.contentWindow?.document;
150
- if (!doc) return;
151
- doc.open();
152
- if (code.indexOf('<html') >= 0)
153
- doc.write(code);
154
- else
155
- doc.write(code_html(code));
156
- doc.close();
157
- }
158
-
159
- if (code) run_code(code);
160
- if (hide_code || !textarea) return;
161
-
162
- if (code_width) textarea.parentElement.style.width = code_width;
163
-
164
- if (typeof CodeMirror === 'undefined') {
165
- textarea.onkeyup = () => run_code(textarea.value);
166
- } else {
167
- const editor = CodeMirror.fromTextArea(textarea, {
168
- lineNumbers: true,
169
- mode: 'jsx'
170
- });
171
- editor.setValue(code);
172
- editor.on('change', (cm) => run_code(cm.getValue()));
173
- }
174
- }
175
- }
176
-
177
- app.webComponent('apprun-code', Play);
@@ -1,101 +0,0 @@
1
- declare var app;
2
- let win;
3
- app['debug'] = true;
4
-
5
- function openWin(name) {
6
- win = window.open('', name);
7
- win.document.write(`<html>
8
- <title>AppRun Analyzer | ${document.location.href}</title>
9
- <style>
10
- body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI" }
11
- </style>
12
- <body><pre>`);
13
- }
14
-
15
- function write(text) {
16
- win.document.write(text + '\n');
17
- }
18
-
19
- function closeWin() {
20
- win.document.write(`</pre>
21
- </body>
22
- </html>`);
23
- win.document.close();
24
- }
25
-
26
- const print_component_test = component => {
27
- write(`import ${component.constructor.name} from '../src/${component.constructor.name}'`);
28
- write(`describe('${component.constructor.name}', ()=>{`);
29
- component._actions.forEach(action => {
30
- if (action.name !== '.') {
31
- write(` it ('should handle event: ${action.name}', (done)=>{`);
32
- write(` const component = new ${component.constructor.name}().mount();`);
33
- write(` component.run('${action.name}');`);
34
- write(` setTimeout(() => {`);
35
- write(` \/\/expect(?).toHaveBeenCalled();`);
36
- write(` \/\/expect(component.state).toBe(?);`);
37
- write(` done();`);
38
- write(` })`);
39
- }
40
- });
41
- write(`});`);
42
- };
43
- export const _createEventTests = () => {
44
- const o = { components: {} };
45
- app.run('get-components', o);
46
- const { components } = o;
47
- openWin('');
48
- if (components instanceof Map) {
49
- for (let [key, comps] of components) {
50
- comps.forEach(print_component_test);
51
- }
52
- } else {
53
- Object.keys(components).forEach(el => {
54
- components[el].forEach(print_component_test);
55
- });
56
- }
57
- closeWin();
58
- }
59
-
60
- let recording = false;
61
- let events = [];
62
-
63
- app.on('debug', p => {
64
- if (recording && p.vdom) {
65
- events.push(p);
66
- console.log(`* ${events.length} state(s) recorded.`);
67
- }
68
- });
69
-
70
- export const _createStateTests = (s) => {
71
-
72
- const printTests = () => {
73
- if (events.length === 0) {
74
- console.log('* No state recorded.');
75
- return;
76
- }
77
- openWin('');
78
- events.forEach((event, idx) => {
79
- write(` it ('view snapshot: #${idx + 1}', ()=>{`);
80
- write(` const component = new ${event.component.constructor.name}()`);
81
- write(` const state = ${JSON.stringify(event.state, undefined, 2)};`);
82
- write(` const vdom = component['view'](state);`);
83
- write(` expect(JSON.stringify(vdom)).toMatchSnapshot();`);
84
- write(` })`);
85
- });
86
- closeWin();
87
- }
88
-
89
- if (s === 'start') {
90
- events = [];
91
- recording = true;
92
- console.log('* State logging started.');
93
- } else if (s === 'stop') {
94
- printTests();
95
- recording = false;
96
- events = [];
97
- console.log('* State logging stopped.');
98
- } else {
99
- console.log('create-state-tests <start|stop>');
100
- }
101
- }