@mayson-org/inject-script 1.0.1 → 1.0.4

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 (55) hide show
  1. package/.env.example +9 -0
  2. package/README.md +66 -23
  3. package/bin/cli.mjs +1 -283
  4. package/dist/cli.d.ts +3 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +104 -0
  7. package/dist/core/find-root-layout.d.ts +2 -0
  8. package/dist/core/find-root-layout.d.ts.map +1 -0
  9. package/dist/core/find-root-layout.js +61 -0
  10. package/dist/core/generators.d.ts +4 -0
  11. package/dist/core/generators.d.ts.map +1 -0
  12. package/dist/core/generators.js +37 -0
  13. package/dist/core/injector.d.ts +4 -0
  14. package/dist/core/injector.d.ts.map +1 -0
  15. package/dist/core/injector.js +76 -0
  16. package/dist/core/types.d.ts +48 -0
  17. package/dist/core/types.d.ts.map +1 -0
  18. package/dist/core/types.js +1 -0
  19. package/dist/generators.d.ts.map +1 -1
  20. package/dist/generators.js +14 -27
  21. package/dist/index.d.ts +16 -7
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +58 -9
  24. package/dist/plugins/ascii/index.d.ts +4 -0
  25. package/dist/plugins/ascii/index.d.ts.map +1 -0
  26. package/dist/plugins/ascii/index.js +7 -0
  27. package/dist/plugins/index.d.ts +7 -0
  28. package/dist/plugins/index.d.ts.map +1 -0
  29. package/dist/plugins/index.js +9 -0
  30. package/dist/plugins/metadata/index.d.ts +3 -0
  31. package/dist/plugins/metadata/index.d.ts.map +1 -0
  32. package/dist/plugins/metadata/index.js +14 -0
  33. package/dist/plugins/watermark/index.d.ts +4 -0
  34. package/dist/plugins/watermark/index.d.ts.map +1 -0
  35. package/dist/plugins/watermark/index.js +7 -0
  36. package/dist/plugins/watermark/template.d.ts +9 -0
  37. package/dist/plugins/watermark/template.d.ts.map +1 -0
  38. package/dist/plugins/watermark/template.js +128 -0
  39. package/dist/shared/ascii-art.d.ts +10 -0
  40. package/dist/shared/ascii-art.d.ts.map +1 -0
  41. package/dist/shared/ascii-art.js +44 -0
  42. package/dist/shared/config.d.ts +13 -0
  43. package/dist/shared/config.d.ts.map +1 -0
  44. package/dist/shared/config.js +25 -0
  45. package/dist/shared/generated-app-metadata.d.ts +28 -0
  46. package/dist/shared/generated-app-metadata.d.ts.map +1 -0
  47. package/dist/shared/generated-app-metadata.js +103 -0
  48. package/dist/shared/remix-url.d.ts +13 -0
  49. package/dist/shared/remix-url.d.ts.map +1 -0
  50. package/dist/shared/remix-url.js +16 -0
  51. package/package.json +14 -9
  52. package/src/find-root-layout.ts +0 -75
  53. package/src/generators.ts +0 -176
  54. package/src/index.ts +0 -42
  55. package/src/injector.ts +0 -108
@@ -0,0 +1,76 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ export function injectComponentsIntoLayout(options) {
4
+ const { filePath, components, dryRun = false } = options;
5
+ if (!fs.existsSync(filePath)) {
6
+ return {
7
+ success: false,
8
+ filePath,
9
+ injectedComponents: [],
10
+ skippedComponents: [],
11
+ error: `Layout file not found: ${filePath}`,
12
+ };
13
+ }
14
+ let content = fs.readFileSync(filePath, 'utf-8');
15
+ const injectedComponents = [];
16
+ const skippedComponents = [];
17
+ for (const comp of components) {
18
+ const importMarker = comp.name;
19
+ const jsxMarker = `<${comp.name}`;
20
+ // Skip if already injected
21
+ if (content.includes(importMarker) || content.includes(jsxMarker)) {
22
+ skippedComponents.push(comp.name);
23
+ continue;
24
+ }
25
+ // Determine component file import path relative to layout.tsx
26
+ const layoutDir = path.dirname(filePath);
27
+ const compDir = path.dirname(comp.filePath);
28
+ const compBaseName = path.basename(comp.filePath, path.extname(comp.filePath));
29
+ let relativeImportPath = path.relative(layoutDir, path.join(compDir, compBaseName));
30
+ if (!relativeImportPath.startsWith('.')) {
31
+ relativeImportPath = `./${relativeImportPath}`;
32
+ }
33
+ // Convert backslashes for Windows path consistency
34
+ relativeImportPath = relativeImportPath.replace(/\\/g, '/');
35
+ const importLine = `import { ${comp.name} } from '${relativeImportPath}';\n`;
36
+ // 1. Insert import statement
37
+ const importMatches = Array.from(content.matchAll(/import\s+.*?from\s+['"].*?['"];?/g));
38
+ if (importMatches.length > 0) {
39
+ const lastMatch = importMatches[importMatches.length - 1];
40
+ const insertPos = lastMatch.index + lastMatch[0].length;
41
+ content = content.slice(0, insertPos) + '\n' + importLine + content.slice(insertPos);
42
+ }
43
+ else {
44
+ content = importLine + content;
45
+ }
46
+ // 2. Insert JSX tag into return block
47
+ const jsxSnippet = `\n {/* @mayson-component-injected: ${comp.name} */}\n ${comp.jsxTag}`;
48
+ if (/<\/body>/i.test(content)) {
49
+ content = content.replace(/<\/body>/i, `${jsxSnippet}\n </body>`);
50
+ }
51
+ else if (/<\/html>/i.test(content)) {
52
+ content = content.replace(/<\/html>/i, `${jsxSnippet}\n </html>`);
53
+ }
54
+ else {
55
+ const lastClosingIndex = content.lastIndexOf('</');
56
+ if (lastClosingIndex !== -1) {
57
+ content =
58
+ content.slice(0, lastClosingIndex) +
59
+ jsxSnippet +
60
+ '\n ' +
61
+ content.slice(lastClosingIndex);
62
+ }
63
+ }
64
+ injectedComponents.push(comp.name);
65
+ }
66
+ if (injectedComponents.length > 0 && !dryRun) {
67
+ fs.writeFileSync(filePath, content, 'utf-8');
68
+ }
69
+ return {
70
+ success: true,
71
+ filePath,
72
+ injectedComponents,
73
+ skippedComponents,
74
+ modifiedContent: content,
75
+ };
76
+ }
@@ -0,0 +1,48 @@
1
+ export type ComponentType = 'watermark' | 'ascii' | 'metadata' | 'all';
2
+ export interface GeneratedComponentInfo {
3
+ name: string;
4
+ filePath: string;
5
+ importStatement: string;
6
+ jsxTag: string;
7
+ }
8
+ /** Context passed into plugin generateSource (e.g. watermark flags from API). */
9
+ export type PluginGenerateContext = {
10
+ watermark?: {
11
+ showRemixPill: boolean;
12
+ enableRemix: boolean;
13
+ appBaseUrl: string;
14
+ collectionId: string;
15
+ };
16
+ };
17
+ export interface ComponentGeneratorOptions {
18
+ outputDir: string;
19
+ isTypeScript?: boolean;
20
+ /** When true, return component info without writing files. */
21
+ dryRun?: boolean;
22
+ /** Plugin template context (API / env resolved flags). */
23
+ context?: PluginGenerateContext;
24
+ }
25
+ export interface InjectorOptions {
26
+ filePath: string;
27
+ components: GeneratedComponentInfo[];
28
+ dryRun?: boolean;
29
+ }
30
+ export interface InjectorResult {
31
+ success: boolean;
32
+ filePath: string;
33
+ injectedComponents: string[];
34
+ skippedComponents: string[];
35
+ modifiedContent?: string;
36
+ error?: string;
37
+ /** Extra notes (e.g. watermark skipped because show_remix_pill is false). */
38
+ messages?: string[];
39
+ }
40
+ /** Descriptor for a generate-and-inject plugin. */
41
+ export interface MaysonPlugin {
42
+ type: Exclude<ComponentType, 'all'>;
43
+ /** Exported React component name, e.g. MaysonWatermark */
44
+ name: string;
45
+ /** Source for the component file written next to the root layout */
46
+ generateSource: (context?: PluginGenerateContext) => string;
47
+ }
48
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,OAAO,GAAG,UAAU,GAAG,KAAK,CAAC;AAEvE,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,iFAAiF;AACjF,MAAM,MAAM,qBAAqB,GAAG;IAClC,SAAS,CAAC,EAAE;QACV,aAAa,EAAE,OAAO,CAAC;QACvB,WAAW,EAAE,OAAO,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;QACnB,YAAY,EAAE,MAAM,CAAC;KACtB,CAAC;CACH,CAAC;AAEF,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,0DAA0D;IAC1D,OAAO,CAAC,EAAE,qBAAqB,CAAC;CACjC;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,sBAAsB,EAAE,CAAC;IACrC,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,mDAAmD;AACnD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,OAAO,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;IACpC,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,cAAc,EAAE,CAAC,OAAO,CAAC,EAAE,qBAAqB,KAAK,MAAM,CAAC;CAC7D"}
@@ -0,0 +1 @@
1
+ export {};
@@ -1 +1 @@
1
- {"version":3,"file":"generators.d.ts","sourceRoot":"","sources":["../src/generators.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,WAAW,GAAG,OAAO,GAAG,UAAU,GAAG,KAAK,CAAC;AAEjF,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;CAChB;AA2GD,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,aAAa,EAAE,YAAY,EAClC,OAAO,EAAE,yBAAyB,GACjC,sBAAsB,EAAE,CAkD1B"}
1
+ {"version":3,"file":"generators.d.ts","sourceRoot":"","sources":["../src/generators.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,WAAW,GAAG,OAAO,GAAG,UAAU,GAAG,KAAK,CAAC;AAEjF,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;CAChB;AA8FD,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,aAAa,EAAE,YAAY,EAClC,OAAO,EAAE,yBAAyB,GACjC,sBAAsB,EAAE,CAkD1B"}
@@ -60,36 +60,23 @@ export function MaysonWatermark() {
60
60
  }
61
61
  `;
62
62
  const ASCII_TEMPLATE = `'use client';
63
- import React from 'react';
63
+ import React, { useEffect } from 'react';
64
64
 
65
- /*
66
- ███╗ ███╗██xA1██╗ ██╗███████╗██████╗ ██████╗
67
- ████╗ ████║██║██║ ██║██╔════╝██╔═══██╗██╔══██╗
68
- ██╔████╔██║██║██║ ██║███████╗██║ ██║██║ ██║
69
- ██║╚██╔╝██║██║██║ ██║╚════██║██║ ██║██║ ██║
70
- ██║ ╚═╝ ██║██║╚██████╔╝███████║╚██████╔╝██████╔╝
71
- */
65
+ const ASCII_ART = \`
66
+ ███╗ ███╗█████╗ ██╗ ██╗███████╗██████╗ ██████╗
67
+ ████╗ ████║██╔══██╗╚██╗ ██╔╝██╔════╝██╔═══██╗██╔══██╗
68
+ ██╔████╔██║███████║ ╚████╔╝ ███████╗██║ ██║██║ ██║
69
+ ██║╚██╔╝██║██╔══██║ ╚██╔╝ ╚════██║██║ ██║██║ ██║
70
+ ██║ ╚═╝ ██║██║ ██║ ██║ ███████║╚██████╔╝██████╔╝
71
+ \`;
72
72
 
73
73
  export function MaysonAscii() {
74
- return (
75
- <div
76
- style={{
77
- position: 'fixed',
78
- top: '8px',
79
- right: '12px',
80
- zIndex: 99999,
81
- fontSize: '10px',
82
- fontFamily: 'monospace',
83
- color: 'rgba(255, 255, 255, 0.6)',
84
- backgroundColor: 'rgba(0, 0, 0, 0.75)',
85
- padding: '4px 8px',
86
- borderRadius: '4px',
87
- pointerEvents: 'none',
88
- }}
89
- >
90
- MAYSON :: RUNTIME ACTIVE
91
- </div>
92
- );
74
+ useEffect(() => {
75
+ console.log('%c' + ASCII_ART, 'color: #6366f1; font-weight: bold;');
76
+ console.log('%c🚀 Powered by Mayson Platform', 'color: #10b981; font-weight: bold; font-size: 12px;');
77
+ }, []);
78
+
79
+ return null;
93
80
  }
94
81
  `;
95
82
  const METADATA_TEMPLATE = `'use client';
package/dist/index.d.ts CHANGED
@@ -1,10 +1,19 @@
1
- import { findRootLayout } from './find-root-layout.js';
2
- import { generateComponents, ComponentType, GeneratedComponentInfo } from './generators.js';
3
- import { injectComponentsIntoLayout, InjectorOptions, InjectorResult } from './injector.js';
4
- export { findRootLayout, generateComponents, injectComponentsIntoLayout };
5
- export type { ComponentType, GeneratedComponentInfo, InjectorOptions, InjectorResult };
1
+ import type { ComponentType, InjectorResult } from './core/types.js';
2
+ export { findRootLayout } from './core/find-root-layout.js';
3
+ export { generateComponents } from './core/generators.js';
4
+ export { injectComponentsIntoLayout } from './core/injector.js';
5
+ export { buildRemixRedirectUrl, BADGE_UTM_SOURCE } from './shared/remix-url.js';
6
+ export type { RemixUrlConfig } from './shared/remix-url.js';
7
+ export { loadMaysonEnvConfig } from './shared/config.js';
8
+ export type { MaysonEnvConfig } from './shared/config.js';
9
+ export { fetchGeneratedAppMetadata, resolveMaysonConfig, shouldFetchGeneratedAppMetadata, } from './shared/generated-app-metadata.js';
10
+ export { watermarkPlugin, buildMaysonWatermarkSource, } from './plugins/watermark/index.js';
11
+ export { asciiPlugin, buildMaysonAsciiSource, } from './plugins/ascii/index.js';
12
+ export { BUILD_WITH_LOVE_ASCII, MAYSON_LETTER_ASCII, } from './shared/ascii-art.js';
13
+ export type { ComponentType, GeneratedComponentInfo, ComponentGeneratorOptions, InjectorOptions, InjectorResult, MaysonPlugin, PluginGenerateContext, } from './core/types.js';
6
14
  /**
7
- * Convenience function to auto-detect Next.js App Router root layout, generate component files, and inject them.
15
+ * Auto-detect root layout, fetch watermark flags from generated-app-metadata when
16
+ * configured, generate component files, and inject them.
8
17
  */
9
- export declare function runAutoInject(projectRoot?: string, types?: ComponentType[], dryRun?: boolean): InjectorResult;
18
+ export declare function runAutoInject(projectRoot?: string, types?: ComponentType[], dryRun?: boolean): Promise<InjectorResult>;
10
19
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAC5F,OAAO,EAAE,0BAA0B,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE5F,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,0BAA0B,EAAE,CAAC;AAC1E,YAAY,EAAE,aAAa,EAAE,sBAAsB,EAAE,eAAe,EAAE,cAAc,EAAE,CAAC;AAEvF;;GAEG;AACH,wBAAgB,aAAa,CAC3B,WAAW,GAAE,MAAsB,EACnC,KAAK,GAAE,aAAa,EAAc,EAClC,MAAM,GAAE,OAAe,GACtB,cAAc,CA0BhB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,aAAa,EACb,cAAc,EAEf,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAChF,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EACL,yBAAyB,EACzB,mBAAmB,EACnB,+BAA+B,GAChC,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACL,eAAe,EACf,0BAA0B,GAC3B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,WAAW,EACX,sBAAsB,GACvB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,aAAa,EACb,sBAAsB,EACtB,yBAAyB,EACzB,eAAe,EACf,cAAc,EACd,YAAY,EACZ,qBAAqB,GACtB,MAAM,iBAAiB,CAAC;AAwBzB;;;GAGG;AACH,wBAAsB,aAAa,CACjC,WAAW,GAAE,MAAsB,EACnC,KAAK,GAAE,aAAa,EAA2B,EAC/C,MAAM,GAAE,OAAe,GACtB,OAAO,CAAC,cAAc,CAAC,CA0DzB"}
package/dist/index.js CHANGED
@@ -1,12 +1,36 @@
1
- import path from 'path';
2
- import { findRootLayout } from './find-root-layout.js';
3
- import { generateComponents } from './generators.js';
4
- import { injectComponentsIntoLayout } from './injector.js';
5
- export { findRootLayout, generateComponents, injectComponentsIntoLayout };
1
+ import path from 'node:path';
2
+ import { findRootLayout } from './core/find-root-layout.js';
3
+ import { generateComponents } from './core/generators.js';
4
+ import { injectComponentsIntoLayout } from './core/injector.js';
5
+ import { resolveMaysonConfig } from './shared/generated-app-metadata.js';
6
+ export { findRootLayout } from './core/find-root-layout.js';
7
+ export { generateComponents } from './core/generators.js';
8
+ export { injectComponentsIntoLayout } from './core/injector.js';
9
+ export { buildRemixRedirectUrl, BADGE_UTM_SOURCE } from './shared/remix-url.js';
10
+ export { loadMaysonEnvConfig } from './shared/config.js';
11
+ export { fetchGeneratedAppMetadata, resolveMaysonConfig, shouldFetchGeneratedAppMetadata, } from './shared/generated-app-metadata.js';
12
+ export { watermarkPlugin, buildMaysonWatermarkSource, } from './plugins/watermark/index.js';
13
+ export { asciiPlugin, buildMaysonAsciiSource, } from './plugins/ascii/index.js';
14
+ export { BUILD_WITH_LOVE_ASCII, MAYSON_LETTER_ASCII, } from './shared/ascii-art.js';
15
+ function filterTypesForConfig(types, showRemixPill) {
16
+ const messages = [];
17
+ const selected = types.includes('all')
18
+ ? ['watermark', 'ascii', 'metadata']
19
+ : types;
20
+ if (selected.includes('watermark') && !showRemixPill) {
21
+ messages.push('watermark skipped — show_remix_pill is false (set via generated-app-metadata API)');
22
+ return {
23
+ types: selected.filter((t) => t !== 'watermark'),
24
+ messages,
25
+ };
26
+ }
27
+ return { types: selected, messages };
28
+ }
6
29
  /**
7
- * Convenience function to auto-detect Next.js App Router root layout, generate component files, and inject them.
30
+ * Auto-detect root layout, fetch watermark flags from generated-app-metadata when
31
+ * configured, generate component files, and inject them.
8
32
  */
9
- export function runAutoInject(projectRoot = process.cwd(), types = ['badge'], dryRun = false) {
33
+ export async function runAutoInject(projectRoot = process.cwd(), types = ['watermark', 'ascii'], dryRun = false) {
10
34
  const layoutPath = findRootLayout(projectRoot);
11
35
  if (!layoutPath) {
12
36
  return {
@@ -17,15 +41,40 @@ export function runAutoInject(projectRoot = process.cwd(), types = ['badge'], dr
17
41
  error: `Could not locate Next.js App Router root layout in ${projectRoot}`,
18
42
  };
19
43
  }
44
+ const config = await resolveMaysonConfig();
45
+ const { types: effectiveTypes, messages } = filterTypesForConfig(types, config.showRemixPill);
46
+ if (effectiveTypes.length === 0) {
47
+ return {
48
+ success: true,
49
+ filePath: layoutPath,
50
+ injectedComponents: [],
51
+ skippedComponents: [],
52
+ messages,
53
+ };
54
+ }
55
+ const context = {
56
+ watermark: {
57
+ showRemixPill: config.showRemixPill,
58
+ enableRemix: config.enableRemix,
59
+ appBaseUrl: config.appBaseUrl,
60
+ collectionId: config.collectionId,
61
+ },
62
+ };
20
63
  const isTypeScript = layoutPath.endsWith('.tsx') || layoutPath.endsWith('.ts');
21
64
  const targetDir = path.dirname(layoutPath);
22
- const generatedComponents = generateComponents(types, {
65
+ const generatedComponents = generateComponents(effectiveTypes, {
23
66
  outputDir: targetDir,
24
67
  isTypeScript,
68
+ dryRun,
69
+ context,
25
70
  });
26
- return injectComponentsIntoLayout({
71
+ const result = injectComponentsIntoLayout({
27
72
  filePath: layoutPath,
28
73
  components: generatedComponents,
29
74
  dryRun,
30
75
  });
76
+ return {
77
+ ...result,
78
+ messages: [...(result.messages ?? []), ...messages],
79
+ };
31
80
  }
@@ -0,0 +1,4 @@
1
+ import type { MaysonPlugin } from '../../core/types.js';
2
+ export declare const asciiPlugin: MaysonPlugin;
3
+ export { buildMaysonAsciiSource } from '../../shared/ascii-art.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/ascii/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD,eAAO,MAAM,WAAW,EAAE,YAIzB,CAAC;AAEF,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { buildMaysonAsciiSource } from '../../shared/ascii-art.js';
2
+ export const asciiPlugin = {
3
+ type: 'ascii',
4
+ name: 'MaysonAscii',
5
+ generateSource: () => buildMaysonAsciiSource(),
6
+ };
7
+ export { buildMaysonAsciiSource } from '../../shared/ascii-art.js';
@@ -0,0 +1,7 @@
1
+ import type { MaysonPlugin } from '../core/types.js';
2
+ import { asciiPlugin } from './ascii/index.js';
3
+ import { metadataPlugin } from './metadata/index.js';
4
+ import { watermarkPlugin } from './watermark/index.js';
5
+ export declare const plugins: Record<Exclude<MaysonPlugin['type'], never>, MaysonPlugin>;
6
+ export { watermarkPlugin, asciiPlugin, metadataPlugin };
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugins/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,EAAE,YAAY,CAI9E,CAAC;AAEF,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC"}
@@ -0,0 +1,9 @@
1
+ import { asciiPlugin } from './ascii/index.js';
2
+ import { metadataPlugin } from './metadata/index.js';
3
+ import { watermarkPlugin } from './watermark/index.js';
4
+ export const plugins = {
5
+ watermark: watermarkPlugin,
6
+ ascii: asciiPlugin,
7
+ metadata: metadataPlugin,
8
+ };
9
+ export { watermarkPlugin, asciiPlugin, metadataPlugin };
@@ -0,0 +1,3 @@
1
+ import type { MaysonPlugin } from '../../core/types.js';
2
+ export declare const metadataPlugin: MaysonPlugin;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/metadata/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAYxD,eAAO,MAAM,cAAc,EAAE,YAI5B,CAAC"}
@@ -0,0 +1,14 @@
1
+ const METADATA_SOURCE = `'use client';
2
+ import React from 'react';
3
+
4
+ export function MaysonMetadata() {
5
+ return (
6
+ <meta name="mayson-generator" content="Mayson App Platform" />
7
+ );
8
+ }
9
+ `;
10
+ export const metadataPlugin = {
11
+ type: 'metadata',
12
+ name: 'MaysonMetadata',
13
+ generateSource: () => METADATA_SOURCE,
14
+ };
@@ -0,0 +1,4 @@
1
+ import type { MaysonPlugin } from '../../core/types.js';
2
+ export declare const watermarkPlugin: MaysonPlugin;
3
+ export { buildMaysonWatermarkSource } from './template.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/watermark/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD,eAAO,MAAM,eAAe,EAAE,YAI7B,CAAC;AAEF,OAAO,EAAE,0BAA0B,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { buildMaysonWatermarkSource } from './template.js';
2
+ export const watermarkPlugin = {
3
+ type: 'watermark',
4
+ name: 'MaysonWatermark',
5
+ generateSource: (context) => buildMaysonWatermarkSource(context),
6
+ };
7
+ export { buildMaysonWatermarkSource } from './template.js';
@@ -0,0 +1,9 @@
1
+ import type { PluginGenerateContext } from '../../core/types.js';
2
+ export type WatermarkTemplateOptions = {
3
+ enableRemix: boolean;
4
+ appBaseUrl: string;
5
+ collectionId: string;
6
+ };
7
+ /** Source for the consumer-app MaysonWatermark client component. */
8
+ export declare function buildMaysonWatermarkSource(context?: PluginGenerateContext): string;
9
+ //# sourceMappingURL=template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template.d.ts","sourceRoot":"","sources":["../../../src/plugins/watermark/template.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAIjE,MAAM,MAAM,wBAAwB,GAAG;IACrC,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAaF,oEAAoE;AACpE,wBAAgB,0BAA0B,CACxC,OAAO,CAAC,EAAE,qBAAqB,GAC9B,MAAM,CAqHR"}
@@ -0,0 +1,128 @@
1
+ import { buildRemixRedirectUrl } from '../../shared/remix-url.js';
2
+ const LOGO_URL = 'https://mayson.dev/logo/brand-logo-dark.png';
3
+ function resolveWatermarkOptions(context) {
4
+ const wm = context?.watermark;
5
+ return {
6
+ enableRemix: wm?.enableRemix ?? false,
7
+ appBaseUrl: wm?.appBaseUrl || 'https://mayson.dev',
8
+ collectionId: wm?.collectionId || '',
9
+ };
10
+ }
11
+ /** Source for the consumer-app MaysonWatermark client component. */
12
+ export function buildMaysonWatermarkSource(context) {
13
+ const options = resolveWatermarkOptions(context);
14
+ const remixUrl = buildRemixRedirectUrl({
15
+ appBaseUrl: options.appBaseUrl,
16
+ collectionId: options.collectionId,
17
+ enableRemix: options.enableRemix,
18
+ });
19
+ return `'use client';
20
+
21
+ import React, { useState } from 'react';
22
+
23
+ const LOGO_URL = ${JSON.stringify(LOGO_URL)};
24
+ const REMIX_URL = ${JSON.stringify(remixUrl)};
25
+
26
+ export function MaysonWatermark() {
27
+ const [dismissed, setDismissed] = useState(false);
28
+
29
+ if (dismissed) {
30
+ return null;
31
+ }
32
+
33
+ const handleRemix = (event: React.MouseEvent) => {
34
+ event.preventDefault();
35
+ event.stopPropagation();
36
+ window.location.href = REMIX_URL;
37
+ };
38
+
39
+ const handleDismiss = (event: React.MouseEvent) => {
40
+ event.preventDefault();
41
+ event.stopPropagation();
42
+ setDismissed(true);
43
+ };
44
+
45
+ return (
46
+ <div
47
+ role="group"
48
+ aria-label="Edit with Mayson"
49
+ style={{
50
+ position: 'fixed',
51
+ right: 16,
52
+ bottom: 16,
53
+ zIndex: 2147483647,
54
+ display: 'inline-flex',
55
+ alignItems: 'flex-end',
56
+ gap: 8,
57
+ padding: '4px 8px',
58
+ borderRadius: 6,
59
+ background: '#171718',
60
+ border: '0.6px solid #46454866',
61
+ boxShadow: '0px 8px 12px 6px #00000026',
62
+ fontFamily: '"Google Sans", system-ui, -apple-system, sans-serif',
63
+ textTransform: 'none',
64
+ }}
65
+ >
66
+ <button
67
+ type="button"
68
+ onClick={handleRemix}
69
+ style={{
70
+ display: 'inline-flex',
71
+ alignItems: 'center',
72
+ gap: 4,
73
+ color: '#9D9DA2',
74
+ textDecoration: 'none',
75
+ cursor: 'pointer',
76
+ outline: 'none',
77
+ border: 'none',
78
+ background: 'transparent',
79
+ padding: 0,
80
+ margin: 0,
81
+ fontFamily: 'inherit',
82
+ }}
83
+ >
84
+ <span
85
+ style={{
86
+ color: '#9D9DA2',
87
+ fontSize: 12,
88
+ fontWeight: 500,
89
+ lineHeight: '14px',
90
+ whiteSpace: 'nowrap',
91
+ }}
92
+ >
93
+ Edit with
94
+ </span>
95
+ <img
96
+ src={LOGO_URL}
97
+ alt="Mayson"
98
+ style={{ display: 'block', height: 16, width: 'auto' }}
99
+ />
100
+ </button>
101
+ <button
102
+ type="button"
103
+ aria-label="Dismiss Edit with Mayson"
104
+ onClick={handleDismiss}
105
+ style={{
106
+ display: 'inline-flex',
107
+ alignItems: 'center',
108
+ justifyContent: 'center',
109
+ width: 18,
110
+ height: 18,
111
+ padding: 0,
112
+ border: 'none',
113
+ background: 'transparent',
114
+ color: '#9D9DA2',
115
+ fontSize: 16,
116
+ lineHeight: 1,
117
+ cursor: 'pointer',
118
+ flexShrink: 0,
119
+ fontFamily: 'inherit',
120
+ }}
121
+ >
122
+ &times;
123
+ </button>
124
+ </div>
125
+ );
126
+ }
127
+ `;
128
+ }
@@ -0,0 +1,10 @@
1
+ /** Console love line from the legacy next-build-plugins package. */
2
+ export declare const BUILD_WITH_LOVE_ASCII = "Built with \uD83D\uDC9C";
3
+ /** Banner letter ASCII — "MAYSON". */
4
+ export declare const MAYSON_LETTER_ASCII: string;
5
+ /**
6
+ * Source for the consumer-app MaysonAscii client component.
7
+ * Matches the legacy console script: "Built with 💜" + MAYSON letter ASCII.
8
+ */
9
+ export declare function buildMaysonAsciiSource(): string;
10
+ //# sourceMappingURL=ascii-art.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ascii-art.d.ts","sourceRoot":"","sources":["../../src/shared/ascii-art.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,eAAO,MAAM,qBAAqB,4BAAkB,CAAC;AAErD,sCAAsC;AACtC,eAAO,MAAM,mBAAmB,QAQpB,CAAC;AAab;;;GAGG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAkB/C"}
@@ -0,0 +1,44 @@
1
+ /** Console love line from the legacy next-build-plugins package. */
2
+ export const BUILD_WITH_LOVE_ASCII = 'Built with 💜';
3
+ /** Banner letter ASCII — "MAYSON". */
4
+ export const MAYSON_LETTER_ASCII = [
5
+ '░███ ░███ ░███ ░██ ░██ ░██████ ░██████ ░███ ░██',
6
+ '░████ ░████ ░██░██ ░██ ░██ ░██ ░██ ░██ ░██ ░████ ░██',
7
+ '░██░██ ░██░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██░██ ░██',
8
+ '░██ ░████ ░██ ░█████████ ░████ ░████████ ░██ ░██ ░██ ░██ ░██',
9
+ '░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██░██',
10
+ '░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░██ ░████',
11
+ '░██ ░██ ░██ ░██ ░██ ░██████ ░██████ ░██ ░███',
12
+ ].join('\n');
13
+ const LOVE_STYLE = 'color:#A39FF9;font-family:monospace';
14
+ const ASCII_STYLE = [
15
+ 'font-family:monospace',
16
+ 'background:linear-gradient(90deg,#dbd0f8 0%,#a39ff9 16.24%,#8030f8 29.79%,#ae63ff 45.09%,#a828e8 59.87%,#a39ff9 79.85%,#450aa3 99.46%)',
17
+ '-webkit-background-clip:text',
18
+ 'background-clip:text',
19
+ 'color:transparent',
20
+ '-webkit-text-fill-color:transparent',
21
+ ].join(';');
22
+ /**
23
+ * Source for the consumer-app MaysonAscii client component.
24
+ * Matches the legacy console script: "Built with 💜" + MAYSON letter ASCII.
25
+ */
26
+ export function buildMaysonAsciiSource() {
27
+ return `'use client';
28
+
29
+ import React, { useEffect } from 'react';
30
+
31
+ const BUILD_WITH_LOVE = ${JSON.stringify(BUILD_WITH_LOVE_ASCII)};
32
+ const MAYSON_LETTER_ASCII = ${JSON.stringify(`\n${MAYSON_LETTER_ASCII}`)};
33
+ const LOVE_STYLE = ${JSON.stringify(LOVE_STYLE)};
34
+ const ASCII_STYLE = ${JSON.stringify(ASCII_STYLE)};
35
+
36
+ export function MaysonAscii() {
37
+ useEffect(() => {
38
+ console.log('%c' + BUILD_WITH_LOVE + '%c' + MAYSON_LETTER_ASCII, LOVE_STYLE, ASCII_STYLE);
39
+ }, []);
40
+
41
+ return null;
42
+ }
43
+ `;
44
+ }
@@ -0,0 +1,13 @@
1
+ export type MaysonEnvConfig = {
2
+ workspaceId: string;
3
+ collectionId: string;
4
+ apiBaseUrl: string;
5
+ appBaseUrl: string;
6
+ webToken: string;
7
+ /** Local defaults before API merge */
8
+ showRemixPill: boolean;
9
+ enableRemix: boolean;
10
+ };
11
+ /** Load Mayson platform env (inject-time / CLI). */
12
+ export declare function loadMaysonEnvConfig(): MaysonEnvConfig;
13
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/shared/config.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,sCAAsC;IACtC,aAAa,EAAE,OAAO,CAAC;IACvB,WAAW,EAAE,OAAO,CAAC;CACtB,CAAC;AAMF,oDAAoD;AACpD,wBAAgB,mBAAmB,IAAI,eAAe,CA0BrD"}
@@ -0,0 +1,25 @@
1
+ function readEnv(key) {
2
+ return process.env[key]?.trim() ?? '';
3
+ }
4
+ /** Load Mayson platform env (inject-time / CLI). */
5
+ export function loadMaysonEnvConfig() {
6
+ const workspaceId = readEnv('MAYSON_WORKSPACE_ID');
7
+ const collectionId = readEnv('MAYSON_COLLECTION_ID') || readEnv('NEXT_PUBLIC_MAYSON_COLLECTION_ID');
8
+ const apiBaseUrl = readEnv('MAYSON_API_BASE_URL');
9
+ const appBaseUrl = readEnv('MAYSON_APP_BASE_URL') ||
10
+ readEnv('NEXT_PUBLIC_MAYSON_APP_BASE_URL') ||
11
+ 'https://mayson.dev';
12
+ const webToken = readEnv('MAYSON_WEB_TOKEN');
13
+ if (!workspaceId && !collectionId && !apiBaseUrl) {
14
+ console.warn('[mayson] missing MAYSON_WORKSPACE_ID, MAYSON_COLLECTION_ID, or MAYSON_API_BASE_URL — metadata fetch may be skipped');
15
+ }
16
+ return {
17
+ workspaceId,
18
+ collectionId,
19
+ apiBaseUrl,
20
+ appBaseUrl,
21
+ webToken,
22
+ showRemixPill: false,
23
+ enableRemix: false,
24
+ };
25
+ }