@mayson-org/inject-script 1.0.1 → 1.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.
- package/.env.example +9 -0
- package/README.md +65 -23
- package/bin/cli.mjs +1 -283
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +104 -0
- package/dist/core/find-root-layout.d.ts +2 -0
- package/dist/core/find-root-layout.d.ts.map +1 -0
- package/dist/core/find-root-layout.js +61 -0
- package/dist/core/generators.d.ts +4 -0
- package/dist/core/generators.d.ts.map +1 -0
- package/dist/core/generators.js +37 -0
- package/dist/core/injector.d.ts +4 -0
- package/dist/core/injector.d.ts.map +1 -0
- package/dist/core/injector.js +76 -0
- package/dist/core/types.d.ts +48 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +1 -0
- package/dist/generators.d.ts.map +1 -1
- package/dist/generators.js +14 -27
- package/dist/index.d.ts +14 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +56 -9
- package/dist/plugins/ascii/index.d.ts +3 -0
- package/dist/plugins/ascii/index.d.ts.map +1 -0
- package/dist/plugins/ascii/index.js +25 -0
- package/dist/plugins/index.d.ts +7 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +9 -0
- package/dist/plugins/metadata/index.d.ts +3 -0
- package/dist/plugins/metadata/index.d.ts.map +1 -0
- package/dist/plugins/metadata/index.js +14 -0
- package/dist/plugins/watermark/index.d.ts +4 -0
- package/dist/plugins/watermark/index.d.ts.map +1 -0
- package/dist/plugins/watermark/index.js +7 -0
- package/dist/plugins/watermark/template.d.ts +9 -0
- package/dist/plugins/watermark/template.d.ts.map +1 -0
- package/dist/plugins/watermark/template.js +128 -0
- package/dist/shared/config.d.ts +13 -0
- package/dist/shared/config.d.ts.map +1 -0
- package/dist/shared/config.js +25 -0
- package/dist/shared/generated-app-metadata.d.ts +28 -0
- package/dist/shared/generated-app-metadata.d.ts.map +1 -0
- package/dist/shared/generated-app-metadata.js +103 -0
- package/dist/shared/remix-url.d.ts +13 -0
- package/dist/shared/remix-url.d.ts.map +1 -0
- package/dist/shared/remix-url.js +16 -0
- package/package.json +14 -9
- package/src/find-root-layout.ts +0 -75
- package/src/generators.ts +0 -176
- package/src/index.ts +0 -42
- 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 {};
|
package/dist/generators.d.ts.map
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/generators.js
CHANGED
|
@@ -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
|
-
███╗
|
|
67
|
-
████╗
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
██║ ╚═╝
|
|
71
|
-
|
|
65
|
+
const ASCII_ART = \`
|
|
66
|
+
███╗ ███╗█████╗ ██╗ ██╗███████╗██████╗ ██████╗
|
|
67
|
+
████╗ ████║██╔══██╗╚██╗ ██╔╝██╔════╝██╔═══██╗██╔══██╗
|
|
68
|
+
██╔████╔██║███████║ ╚████╔╝ ███████╗██║ ██║██║ ██║
|
|
69
|
+
██║╚██╔╝██║██╔══██║ ╚██╔╝ ╚════██║██║ ██║██║ ██║
|
|
70
|
+
██║ ╚═╝ ██║██║ ██║ ██║ ███████║╚██████╔╝██████╔╝
|
|
71
|
+
\`;
|
|
72
72
|
|
|
73
73
|
export function MaysonAscii() {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export {
|
|
5
|
-
export
|
|
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 type { ComponentType, GeneratedComponentInfo, ComponentGeneratorOptions, InjectorOptions, InjectorResult, MaysonPlugin, PluginGenerateContext, } from './core/types.js';
|
|
6
12
|
/**
|
|
7
|
-
*
|
|
13
|
+
* Auto-detect root layout, fetch watermark flags from generated-app-metadata when
|
|
14
|
+
* configured, generate component files, and inject them.
|
|
8
15
|
*/
|
|
9
|
-
export declare function runAutoInject(projectRoot?: string, types?: ComponentType[], dryRun?: boolean): InjectorResult
|
|
16
|
+
export declare function runAutoInject(projectRoot?: string, types?: ComponentType[], dryRun?: boolean): Promise<InjectorResult>;
|
|
10
17
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
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,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,EAAkB,EACtC,MAAM,GAAE,OAAe,GACtB,OAAO,CAAC,cAAc,CAAC,CA0DzB"}
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,34 @@
|
|
|
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
|
-
|
|
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
|
+
function filterTypesForConfig(types, showRemixPill) {
|
|
14
|
+
const messages = [];
|
|
15
|
+
const selected = types.includes('all')
|
|
16
|
+
? ['watermark', 'ascii', 'metadata']
|
|
17
|
+
: types;
|
|
18
|
+
if (selected.includes('watermark') && !showRemixPill) {
|
|
19
|
+
messages.push('watermark skipped — show_remix_pill is false (set via generated-app-metadata API)');
|
|
20
|
+
return {
|
|
21
|
+
types: selected.filter((t) => t !== 'watermark'),
|
|
22
|
+
messages,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
return { types: selected, messages };
|
|
26
|
+
}
|
|
6
27
|
/**
|
|
7
|
-
*
|
|
28
|
+
* Auto-detect root layout, fetch watermark flags from generated-app-metadata when
|
|
29
|
+
* configured, generate component files, and inject them.
|
|
8
30
|
*/
|
|
9
|
-
export function runAutoInject(projectRoot = process.cwd(), types = ['
|
|
31
|
+
export async function runAutoInject(projectRoot = process.cwd(), types = ['watermark'], dryRun = false) {
|
|
10
32
|
const layoutPath = findRootLayout(projectRoot);
|
|
11
33
|
if (!layoutPath) {
|
|
12
34
|
return {
|
|
@@ -17,15 +39,40 @@ export function runAutoInject(projectRoot = process.cwd(), types = ['badge'], dr
|
|
|
17
39
|
error: `Could not locate Next.js App Router root layout in ${projectRoot}`,
|
|
18
40
|
};
|
|
19
41
|
}
|
|
42
|
+
const config = await resolveMaysonConfig();
|
|
43
|
+
const { types: effectiveTypes, messages } = filterTypesForConfig(types, config.showRemixPill);
|
|
44
|
+
if (effectiveTypes.length === 0) {
|
|
45
|
+
return {
|
|
46
|
+
success: true,
|
|
47
|
+
filePath: layoutPath,
|
|
48
|
+
injectedComponents: [],
|
|
49
|
+
skippedComponents: [],
|
|
50
|
+
messages,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const context = {
|
|
54
|
+
watermark: {
|
|
55
|
+
showRemixPill: config.showRemixPill,
|
|
56
|
+
enableRemix: config.enableRemix,
|
|
57
|
+
appBaseUrl: config.appBaseUrl,
|
|
58
|
+
collectionId: config.collectionId,
|
|
59
|
+
},
|
|
60
|
+
};
|
|
20
61
|
const isTypeScript = layoutPath.endsWith('.tsx') || layoutPath.endsWith('.ts');
|
|
21
62
|
const targetDir = path.dirname(layoutPath);
|
|
22
|
-
const generatedComponents = generateComponents(
|
|
63
|
+
const generatedComponents = generateComponents(effectiveTypes, {
|
|
23
64
|
outputDir: targetDir,
|
|
24
65
|
isTypeScript,
|
|
66
|
+
dryRun,
|
|
67
|
+
context,
|
|
25
68
|
});
|
|
26
|
-
|
|
69
|
+
const result = injectComponentsIntoLayout({
|
|
27
70
|
filePath: layoutPath,
|
|
28
71
|
components: generatedComponents,
|
|
29
72
|
dryRun,
|
|
30
73
|
});
|
|
74
|
+
return {
|
|
75
|
+
...result,
|
|
76
|
+
messages: [...(result.messages ?? []), ...messages],
|
|
77
|
+
};
|
|
31
78
|
}
|
|
@@ -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;AAuBxD,eAAO,MAAM,WAAW,EAAE,YAIzB,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const ASCII_SOURCE = `'use client';
|
|
2
|
+
import React, { useEffect } from 'react';
|
|
3
|
+
|
|
4
|
+
const ASCII_ART = \`
|
|
5
|
+
███╗ ███╗█████╗ ██╗ ██╗███████╗██████╗ ██████╗
|
|
6
|
+
████╗ ████║██╔══██╗╚██╗ ██╔╝██╔════╝██╔═══██╗██╔══██╗
|
|
7
|
+
██╔████╔██║███████║ ╚████╔╝ ███████╗██║ ██║██║ ██║
|
|
8
|
+
██║╚██╔╝██║██╔══██║ ╚██╔╝ ╚════██║██║ ██║██║ ██║
|
|
9
|
+
██║ ╚═╝ ██║██║ ██║ ██║ ███████║╚██████╔╝██████╔╝
|
|
10
|
+
\`;
|
|
11
|
+
|
|
12
|
+
export function MaysonAscii() {
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
console.log('%c' + ASCII_ART, 'color: #6366f1; font-weight: bold;');
|
|
15
|
+
console.log('%c🚀 Powered by Mayson Platform', 'color: #10b981; font-weight: bold; font-size: 12px;');
|
|
16
|
+
}, []);
|
|
17
|
+
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
`;
|
|
21
|
+
export const asciiPlugin = {
|
|
22
|
+
type: 'ascii',
|
|
23
|
+
name: 'MaysonAscii',
|
|
24
|
+
generateSource: () => ASCII_SOURCE,
|
|
25
|
+
};
|
|
@@ -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 @@
|
|
|
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 @@
|
|
|
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
|
+
×
|
|
123
|
+
</button>
|
|
124
|
+
</div>
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
`;
|
|
128
|
+
}
|
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { MaysonEnvConfig } from './config.js';
|
|
2
|
+
export type GeneratedAppMetadataValue = {
|
|
3
|
+
show_remix_pill?: boolean | null;
|
|
4
|
+
enable_remix?: boolean | null;
|
|
5
|
+
};
|
|
6
|
+
export type GeneratedAppMetadataResponse = {
|
|
7
|
+
response_code?: number;
|
|
8
|
+
response_type?: string;
|
|
9
|
+
message?: string;
|
|
10
|
+
value?: GeneratedAppMetadataValue;
|
|
11
|
+
};
|
|
12
|
+
export type FetchGeneratedAppMetadataOptions = {
|
|
13
|
+
webToken?: string;
|
|
14
|
+
fetchImpl?: typeof fetch;
|
|
15
|
+
timeoutMs?: number;
|
|
16
|
+
};
|
|
17
|
+
/** When metadata record does not exist yet — show pill and allow remix. */
|
|
18
|
+
export declare const METADATA_NOT_FOUND_DEFAULTS: Pick<MaysonEnvConfig, 'showRemixPill' | 'enableRemix'>;
|
|
19
|
+
export declare function resolveGeneratedAppMetadataUrl(config: Pick<MaysonEnvConfig, 'apiBaseUrl' | 'workspaceId' | 'collectionId'>): string | null;
|
|
20
|
+
export declare function shouldFetchGeneratedAppMetadata(config: MaysonEnvConfig, webToken?: string): boolean;
|
|
21
|
+
export declare function mapGeneratedAppMetadataValue(value: GeneratedAppMetadataValue): Partial<Pick<MaysonEnvConfig, 'showRemixPill' | 'enableRemix'>>;
|
|
22
|
+
/** True when API indicates no metadata row exists yet (HTTP or body 404). */
|
|
23
|
+
export declare function isGeneratedAppMetadataNotFound(httpStatus: number, data: GeneratedAppMetadataResponse | null | undefined): boolean;
|
|
24
|
+
/** Fetch generated-app-metadata. Returns null on hard failure (network / non-404 errors). */
|
|
25
|
+
export declare function fetchGeneratedAppMetadata(config: MaysonEnvConfig, options?: FetchGeneratedAppMetadataOptions): Promise<Partial<Pick<MaysonEnvConfig, 'showRemixPill' | 'enableRemix'>> | null>;
|
|
26
|
+
/** Local env config merged with generated-app-metadata when credentials are set. */
|
|
27
|
+
export declare function resolveMaysonConfig(options?: FetchGeneratedAppMetadataOptions): Promise<MaysonEnvConfig>;
|
|
28
|
+
//# sourceMappingURL=generated-app-metadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generated-app-metadata.d.ts","sourceRoot":"","sources":["../../src/shared/generated-app-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGnD,MAAM,MAAM,yBAAyB,GAAG;IACtC,eAAe,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACjC,YAAY,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,yBAAyB,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,gCAAgC,GAAG;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,2EAA2E;AAC3E,eAAO,MAAM,2BAA2B,EAAE,IAAI,CAC5C,eAAe,EACf,eAAe,GAAG,aAAa,CAIhC,CAAC;AAEF,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,YAAY,GAAG,aAAa,GAAG,cAAc,CAAC,GAC3E,MAAM,GAAG,IAAI,CASf;AAED,wBAAgB,+BAA+B,CAC7C,MAAM,EAAE,eAAe,EACvB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAGT;AAED,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,yBAAyB,GAC/B,OAAO,CAAC,IAAI,CAAC,eAAe,EAAE,eAAe,GAAG,aAAa,CAAC,CAAC,CAWjE;AAED,6EAA6E;AAC7E,wBAAgB,8BAA8B,CAC5C,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,4BAA4B,GAAG,IAAI,GAAG,SAAS,GACpD,OAAO,CAiBT;AAYD,6FAA6F;AAC7F,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,eAAe,EACvB,OAAO,GAAE,gCAAqC,GAC7C,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,eAAe,EAAE,eAAe,GAAG,aAAa,CAAC,CAAC,GAAG,IAAI,CAAC,CAiDjF;AAED,oFAAoF;AACpF,wBAAsB,mBAAmB,CACvC,OAAO,GAAE,gCAAqC,GAC7C,OAAO,CAAC,eAAe,CAAC,CAa1B"}
|