@reckona/mreact-next 0.0.66 → 0.0.68

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.
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EACL,+BAA+B,EAC/B,wBAAwB,GACzB,MAAM,YAAY,CAAC;AAEpB,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,MAAM,wBAAwB,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;AAE9D,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EACL,+BAA+B,EAC/B,wBAAwB,GACzB,MAAM,YAAY,CAAC;AAEpB,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,MAAM,wBAAwB,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;AAE9D,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\n\nimport { resolve } from \"node:path\";\nimport {\n formatGeneratedMreactComponents,\n generateMreactComponents,\n} from \"./index.js\";\n\nconst rootDir = resolve(process.argv[2] ?? \"app\");\nconst generated = await generateMreactComponents({ rootDir });\n\nconsole.log(formatGeneratedMreactComponents(generated, rootDir));\n"]}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { readdir, readFile, writeFile } from \"node:fs/promises\";\nimport { basename, dirname, join, relative } from \"node:path\";\nimport { transform } from \"@reckona/mreact-compiler\";\n\nexport interface GenerateMreactComponentsOptions {\n rootDir: string;\n}\n\nexport interface GeneratedMreactComponent {\n source: string;\n output: string;\n domOutput: string;\n}\n\nexport interface CompiledMreactComponentModule {\n wrapperCode: string;\n domCode: string;\n}\n\nexport async function generateMreactComponents(\n options: GenerateMreactComponentsOptions,\n): Promise<GeneratedMreactComponent[]> {\n const sources = await findMreactSources(options.rootDir);\n const generated: GeneratedMreactComponent[] = [];\n\n for (const source of sources) {\n const code = await readFile(source, \"utf8\");\n const output = outputPathForSource(source);\n const domOutput = domOutputPathForSource(source);\n const generatedCode = compileMreactComponentModule(code, source, {\n domImportPath: importPathForGeneratedModule(output, domOutput),\n });\n\n await writeFile(output, generatedCode.wrapperCode);\n await writeFile(domOutput, generatedCode.domCode);\n generated.push({ source, output, domOutput });\n }\n\n return generated;\n}\n\nexport interface CompileMreactComponentModuleOptions {\n domImportPath: string;\n}\n\nexport function compileMreactComponentModule(\n code: string,\n filename: string,\n options: CompileMreactComponentModuleOptions,\n): CompiledMreactComponentModule {\n const compiled = transform({\n code,\n filename,\n target: \"client\",\n dev: true,\n });\n\n if (compiled.metadata.components.length === 0) {\n throw new Error(`${filename} must export at least one mreact JSX component.`);\n }\n\n const components = compiled.metadata.components\n .filter((component) => hasCompiledExport(compiled.code, component.name, component.exportName))\n .map((component) => ({\n name: component.name,\n exportName: component.exportName,\n moduleAccess:\n component.exportName === \"default\" ? \"module.default\" : `module.${component.name}`,\n }));\n\n if (components.length === 0) {\n throw new Error(`${filename} must export at least one mreact JSX component.`);\n }\n const wrappers = components\n .map(\n (component) => `const ${component.name}$mounted = new WeakMap<Element, Node>();\nconst ${component.name}$mounting = new WeakSet<Element>();\n${emitExportFunction(component.exportName, component.name)}(props: Record<string, unknown>): never {\n return (\n <span\n data-mreact-component=${JSON.stringify(component.name)}\n ref={(node: Element | null) => {\n if (node === null || ${component.name}$mounted.has(node) || ${component.name}$mounting.has(node)) {\n return;\n }\n\n ${component.name}$mounting.add(node);\n void import(${JSON.stringify(options.domImportPath)}).then((module) => {\n const rendered = (${component.moduleAccess} as (props: Record<string, unknown>) => Node)(props);\n node.replaceChildren(rendered);\n ${component.name}$mounted.set(node, rendered);\n });\n }}\n />\n ) as never;\n}`,\n )\n .join(\"\\n\\n\");\n\n return {\n wrapperCode: `// @ts-nocheck\n\"use client\";\n${wrappers}\n`,\n domCode: `// @ts-nocheck\n${compiled.code}`,\n };\n}\n\nasync function findMreactSources(rootDir: string): Promise<string[]> {\n const entries = await readdir(rootDir, { withFileTypes: true });\n const sources: string[] = [];\n\n for (const entry of entries) {\n const path = join(rootDir, entry.name);\n\n if (entry.isDirectory()) {\n sources.push(...(await findMreactSources(path)));\n continue;\n }\n\n if (entry.isFile() && entry.name.endsWith(\".mreact.tsx\")) {\n sources.push(path);\n }\n }\n\n return sources.sort();\n}\n\nfunction outputPathForSource(source: string): string {\n return join(dirname(source), `${basename(source, \".mreact.tsx\")}.tsx`);\n}\n\nfunction domOutputPathForSource(source: string): string {\n return join(dirname(source), `${basename(source, \".mreact.tsx\")}.mreact-dom.ts`);\n}\n\nfunction importPathForGeneratedModule(from: string, to: string): string {\n const extensionless = relative(dirname(from), to).replace(/\\.ts$/, \"\");\n\n return extensionless.startsWith(\".\") ? extensionless : `./${extensionless}`;\n}\n\nfunction emitExportFunction(exportName: string, name: string): string {\n return exportName === \"default\" ? `export default function ${name}` : `export function ${name}`;\n}\n\nfunction hasCompiledExport(code: string, name: string, exportName: string): boolean {\n return code.includes(`${emitExportFunction(exportName, name)}(`);\n}\n\nexport function formatGeneratedMreactComponents(\n generated: readonly GeneratedMreactComponent[],\n rootDir: string,\n): string {\n if (generated.length === 0) {\n return \"No .mreact.tsx components found.\";\n }\n\n return generated\n .map(\n (item) =>\n `${relative(rootDir, item.source)} -> ${relative(rootDir, item.output)}, ${relative(rootDir, item.domOutput)}`,\n )\n .join(\"\\n\");\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reckona/mreact-next",
3
- "version": "0.0.66",
3
+ "version": "0.0.68",
4
4
  "description": "Experimental helpers for consuming compiled mreact components from Next.js.",
5
5
  "keywords": [
6
6
  "compiler",
@@ -24,7 +24,8 @@
24
24
  "dist/**/*.js",
25
25
  "dist/**/*.js.map",
26
26
  "dist/**/*.d.ts",
27
- "dist/**/*.d.ts.map"
27
+ "dist/**/*.d.ts.map",
28
+ "src/**/*"
28
29
  ],
29
30
  "type": "module",
30
31
  "sideEffects": false,
@@ -39,6 +40,6 @@
39
40
  "access": "public"
40
41
  },
41
42
  "dependencies": {
42
- "@reckona/mreact-compiler": "0.0.66"
43
+ "@reckona/mreact-compiler": "0.0.68"
43
44
  }
44
45
  }
package/src/cli.ts ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { resolve } from "node:path";
4
+ import {
5
+ formatGeneratedMreactComponents,
6
+ generateMreactComponents,
7
+ } from "./index.js";
8
+
9
+ const rootDir = resolve(process.argv[2] ?? "app");
10
+ const generated = await generateMreactComponents({ rootDir });
11
+
12
+ console.log(formatGeneratedMreactComponents(generated, rootDir));
package/src/index.ts ADDED
@@ -0,0 +1,166 @@
1
+ import { readdir, readFile, writeFile } from "node:fs/promises";
2
+ import { basename, dirname, join, relative } from "node:path";
3
+ import { transform } from "@reckona/mreact-compiler";
4
+
5
+ export interface GenerateMreactComponentsOptions {
6
+ rootDir: string;
7
+ }
8
+
9
+ export interface GeneratedMreactComponent {
10
+ source: string;
11
+ output: string;
12
+ domOutput: string;
13
+ }
14
+
15
+ export interface CompiledMreactComponentModule {
16
+ wrapperCode: string;
17
+ domCode: string;
18
+ }
19
+
20
+ export async function generateMreactComponents(
21
+ options: GenerateMreactComponentsOptions,
22
+ ): Promise<GeneratedMreactComponent[]> {
23
+ const sources = await findMreactSources(options.rootDir);
24
+ const generated: GeneratedMreactComponent[] = [];
25
+
26
+ for (const source of sources) {
27
+ const code = await readFile(source, "utf8");
28
+ const output = outputPathForSource(source);
29
+ const domOutput = domOutputPathForSource(source);
30
+ const generatedCode = compileMreactComponentModule(code, source, {
31
+ domImportPath: importPathForGeneratedModule(output, domOutput),
32
+ });
33
+
34
+ await writeFile(output, generatedCode.wrapperCode);
35
+ await writeFile(domOutput, generatedCode.domCode);
36
+ generated.push({ source, output, domOutput });
37
+ }
38
+
39
+ return generated;
40
+ }
41
+
42
+ export interface CompileMreactComponentModuleOptions {
43
+ domImportPath: string;
44
+ }
45
+
46
+ export function compileMreactComponentModule(
47
+ code: string,
48
+ filename: string,
49
+ options: CompileMreactComponentModuleOptions,
50
+ ): CompiledMreactComponentModule {
51
+ const compiled = transform({
52
+ code,
53
+ filename,
54
+ target: "client",
55
+ dev: true,
56
+ });
57
+
58
+ if (compiled.metadata.components.length === 0) {
59
+ throw new Error(`${filename} must export at least one mreact JSX component.`);
60
+ }
61
+
62
+ const components = compiled.metadata.components
63
+ .filter((component) => hasCompiledExport(compiled.code, component.name, component.exportName))
64
+ .map((component) => ({
65
+ name: component.name,
66
+ exportName: component.exportName,
67
+ moduleAccess:
68
+ component.exportName === "default" ? "module.default" : `module.${component.name}`,
69
+ }));
70
+
71
+ if (components.length === 0) {
72
+ throw new Error(`${filename} must export at least one mreact JSX component.`);
73
+ }
74
+ const wrappers = components
75
+ .map(
76
+ (component) => `const ${component.name}$mounted = new WeakMap<Element, Node>();
77
+ const ${component.name}$mounting = new WeakSet<Element>();
78
+ ${emitExportFunction(component.exportName, component.name)}(props: Record<string, unknown>): never {
79
+ return (
80
+ <span
81
+ data-mreact-component=${JSON.stringify(component.name)}
82
+ ref={(node: Element | null) => {
83
+ if (node === null || ${component.name}$mounted.has(node) || ${component.name}$mounting.has(node)) {
84
+ return;
85
+ }
86
+
87
+ ${component.name}$mounting.add(node);
88
+ void import(${JSON.stringify(options.domImportPath)}).then((module) => {
89
+ const rendered = (${component.moduleAccess} as (props: Record<string, unknown>) => Node)(props);
90
+ node.replaceChildren(rendered);
91
+ ${component.name}$mounted.set(node, rendered);
92
+ });
93
+ }}
94
+ />
95
+ ) as never;
96
+ }`,
97
+ )
98
+ .join("\n\n");
99
+
100
+ return {
101
+ wrapperCode: `// @ts-nocheck
102
+ "use client";
103
+ ${wrappers}
104
+ `,
105
+ domCode: `// @ts-nocheck
106
+ ${compiled.code}`,
107
+ };
108
+ }
109
+
110
+ async function findMreactSources(rootDir: string): Promise<string[]> {
111
+ const entries = await readdir(rootDir, { withFileTypes: true });
112
+ const sources: string[] = [];
113
+
114
+ for (const entry of entries) {
115
+ const path = join(rootDir, entry.name);
116
+
117
+ if (entry.isDirectory()) {
118
+ sources.push(...(await findMreactSources(path)));
119
+ continue;
120
+ }
121
+
122
+ if (entry.isFile() && entry.name.endsWith(".mreact.tsx")) {
123
+ sources.push(path);
124
+ }
125
+ }
126
+
127
+ return sources.sort();
128
+ }
129
+
130
+ function outputPathForSource(source: string): string {
131
+ return join(dirname(source), `${basename(source, ".mreact.tsx")}.tsx`);
132
+ }
133
+
134
+ function domOutputPathForSource(source: string): string {
135
+ return join(dirname(source), `${basename(source, ".mreact.tsx")}.mreact-dom.ts`);
136
+ }
137
+
138
+ function importPathForGeneratedModule(from: string, to: string): string {
139
+ const extensionless = relative(dirname(from), to).replace(/\.ts$/, "");
140
+
141
+ return extensionless.startsWith(".") ? extensionless : `./${extensionless}`;
142
+ }
143
+
144
+ function emitExportFunction(exportName: string, name: string): string {
145
+ return exportName === "default" ? `export default function ${name}` : `export function ${name}`;
146
+ }
147
+
148
+ function hasCompiledExport(code: string, name: string, exportName: string): boolean {
149
+ return code.includes(`${emitExportFunction(exportName, name)}(`);
150
+ }
151
+
152
+ export function formatGeneratedMreactComponents(
153
+ generated: readonly GeneratedMreactComponent[],
154
+ rootDir: string,
155
+ ): string {
156
+ if (generated.length === 0) {
157
+ return "No .mreact.tsx components found.";
158
+ }
159
+
160
+ return generated
161
+ .map(
162
+ (item) =>
163
+ `${relative(rootDir, item.source)} -> ${relative(rootDir, item.output)}, ${relative(rootDir, item.domOutput)}`,
164
+ )
165
+ .join("\n");
166
+ }