@octanejs/cli 0.0.1 → 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.
@@ -55,9 +55,18 @@ export function integrationFor(bundler, mode) {
55
55
  return {
56
56
  specifier: target[mode].specifier,
57
57
  dependencies: ['octane', ...target[mode].packages],
58
- // The bundler itself is only ours to install when we are the ones
59
- // creating its config.
60
- devDependencies: ['@tsrx/typescript-plugin', ...(bundler === null ? ['vite'] : [])],
58
+ // TypeScript is absent from this list on purpose, but it does get
59
+ // installed: naming it here would take the newest major, which `tsrx-tsc`
60
+ // cannot start under, so it is installed afterwards at the range
61
+ // @tsrx/typescript-plugin declares as its peer. Nothing in the toolchain
62
+ // carries a compiler of its own. The bundler is only ours to install when
63
+ // we are the ones creating its config.
64
+ devDependencies: [
65
+ '@tsrx/typescript-plugin',
66
+ '@tsrx/prettier-plugin',
67
+ 'prettier',
68
+ ...(bundler === null ? ['vite'] : []),
69
+ ],
61
70
  };
62
71
  }
63
72
 
@@ -65,49 +74,161 @@ export function integrationFor(bundler, mode) {
65
74
  * @param {keyof typeof MODES} mode
66
75
  * @returns {string}
67
76
  */
68
- export const viteConfig = (mode) => `import { defineConfig } from 'vite';
69
- import { octane } from '${integrationFor('vite', mode).specifier}';
77
+ export const viteConfig = (mode) => `import { defineConfig } from "vite";
78
+ import { octane } from "${integrationFor('vite', mode).specifier}";
70
79
 
71
80
  export default defineConfig({
72
- \tplugins: [octane()],
73
- \tbuild: { target: 'esnext' },
81
+ plugins: [octane()],
82
+ build: { target: "esnext" },
74
83
  });
75
84
  `;
76
85
 
77
- export const octaneConfig = `import { defineConfig, RenderRoute } from '@octanejs/vite-plugin';
86
+ /** One route, naming its export so a typo fails loudly instead of rendering the wrong component. */
87
+ export const octaneConfig = `import { defineConfig, RenderRoute } from "@octanejs/vite-plugin";
78
88
 
79
89
  export default defineConfig({
80
- \trouter: {
81
- \t\troutes: [new RenderRoute({ path: '/', entry: ['App', '/src/App.tsrx'] })],
82
- \t},
90
+ router: {
91
+ routes: [new RenderRoute({ path: "/", entry: ["App", "/src/App.tsrx"] })],
92
+ },
83
93
  });
84
94
  `;
85
95
 
96
+ /** The component both templates start from. */
86
97
  export const appComponent = `export function App() @{
87
- \t<div class="app">
88
- \t\t<h1>{'Hello from Octane' as string}</h1>
89
- \t</div>
98
+ <main>
99
+ <h1>Hello from Octane</h1>
100
+ <p>Edit src/App.tsrx and save.</p>
101
+ </main>
90
102
  }
91
103
  `;
92
104
 
93
- export const tsconfig = {
94
- compilerOptions: {
95
- target: 'esnext',
96
- module: 'esnext',
97
- moduleResolution: 'bundler',
98
- lib: ['esnext', 'dom', 'dom.iterable'],
99
- strict: true,
100
- noEmit: true,
101
- allowImportingTsExtensions: true,
102
- isolatedModules: true,
103
- esModuleInterop: true,
104
- skipLibCheck: true,
105
- jsx: 'react-jsx',
106
- jsxImportSource: 'octane',
107
- plugins: [{ name: '@tsrx/typescript-plugin' }],
108
- },
109
- include: ['src/**/*', 'vite.config.ts'],
110
- };
105
+ const SPA_INDEX_HTML = `<!doctype html>
106
+ <html lang="en">
107
+ <head>
108
+ <meta charset="utf-8" />
109
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
110
+ <title>Octane app</title>
111
+ </head>
112
+ <body>
113
+ <div id="root"></div>
114
+ <script type="module" src="/src/main.ts"></script>
115
+ </body>
116
+ </html>
117
+ `;
118
+
119
+ const SSR_INDEX_HTML = `<!doctype html>
120
+ <html lang="en">
121
+ <head>
122
+ <meta charset="utf-8" />
123
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
124
+ <title>Octane app</title>
125
+ <!--ssr-head-->
126
+ </head>
127
+ <body>
128
+ <div id="root"><!--ssr-body--></div>
129
+ </body>
130
+ </html>
131
+ `;
132
+
133
+ /** The markers `validateSsrTemplate` requires of a fullstack index.html. */
134
+ export const SSR_MARKERS = ['<!--ssr-head-->', '<!--ssr-body-->'];
135
+
136
+ /**
137
+ * The HTML shell.
138
+ *
139
+ * `spa` is an ordinary Vite page, so it loads the client entry itself.
140
+ * `fullstack` loads nothing: the metaframework plugin owns the hydration entry,
141
+ * injecting the virtual module in dev and the hashed script at build. Its
142
+ * markers are a contract rather than decoration — `validateSsrTemplate` rejects
143
+ * a template that does not carry exactly one of each.
144
+ *
145
+ * @param {keyof typeof MODES} mode
146
+ * @returns {string}
147
+ */
148
+ export const indexHtml = (mode) => (mode === 'fullstack' ? SSR_INDEX_HTML : SPA_INDEX_HTML);
149
+
150
+ /**
151
+ * The client bootstrap, `spa` only. `render(App)` is the body-and-props
152
+ * overload, which keeps the entry plain TypeScript with no JSX pragma to carry.
153
+ */
154
+ export const clientEntry = `import { createRoot } from "octane";
155
+ import { App } from "./App.tsrx";
156
+
157
+ const root = createRoot(document.getElementById("root")!);
158
+ root.render(App);
159
+ `;
160
+
161
+ /**
162
+ * Prettier cannot parse `.tsrx` on its own, so a project that formats without
163
+ * this plugin either skips those files or mangles them.
164
+ */
165
+ export const prettierConfig = `{
166
+ "plugins": ["@tsrx/prettier-plugin"]
167
+ }
168
+ `;
169
+
170
+ /**
171
+ * The config filenames Prettier itself looks for, in the order it looks. A
172
+ * project that already has one owns its formatting, and this command states the
173
+ * edit instead of picking a fight with it.
174
+ *
175
+ * The order is load-bearing, not decorative: the first of these that exists is
176
+ * the one Prettier reads, so it is the one to inspect for the plugin and to
177
+ * name in an instruction. Note how little of it is alphabetical. The module
178
+ * variants interleave `.prettierrc.X` with `prettier.config.X` by type rather
179
+ * than grouping by prefix, and `.toml` sorts last rather than with the other
180
+ * data formats. Taken from prettier 3.9.6 and confirmed against it.
181
+ *
182
+ * `package.json` comes before all of these and is handled by its own check,
183
+ * since the file existing says nothing about whether it configures Prettier.
184
+ * `package.yaml`, which Prettier searches second, is not covered: telling one
185
+ * that configures Prettier from one that does not needs a YAML parser this
186
+ * package does not carry.
187
+ */
188
+ export const PRETTIER_CONFIG_FILES = [
189
+ '.prettierrc',
190
+ '.prettierrc.json',
191
+ '.prettierrc.yml',
192
+ '.prettierrc.yaml',
193
+ '.prettierrc.json5',
194
+ '.prettierrc.js',
195
+ 'prettier.config.js',
196
+ '.prettierrc.ts',
197
+ 'prettier.config.ts',
198
+ '.prettierrc.mjs',
199
+ 'prettier.config.mjs',
200
+ '.prettierrc.mts',
201
+ 'prettier.config.mts',
202
+ '.prettierrc.cjs',
203
+ 'prettier.config.cjs',
204
+ '.prettierrc.cts',
205
+ 'prettier.config.cts',
206
+ '.prettierrc.toml',
207
+ ];
208
+
209
+ export const tsconfig = `{
210
+ "compilerOptions": {
211
+ "target": "esnext",
212
+ "module": "esnext",
213
+ "moduleResolution": "bundler",
214
+ "lib": ["esnext", "dom", "dom.iterable"],
215
+ "strict": true,
216
+ "noEmit": true,
217
+ "allowImportingTsExtensions": true,
218
+ "isolatedModules": true,
219
+ "esModuleInterop": true,
220
+ "skipLibCheck": true,
221
+ "jsx": "react-jsx",
222
+ "jsxImportSource": "octane",
223
+ "plugins": [
224
+ {
225
+ "name": "@tsrx/typescript-plugin"
226
+ }
227
+ ]
228
+ },
229
+ "include": ["src/**/*", "vite.config.ts"]
230
+ }
231
+ `;
111
232
 
112
233
  /**
113
234
  * Scripts that are correct whatever the bundler is. `tsrx-tsc` is the only