@open-mercato/shared 0.4.11-develop.1916.be37b7bcbb → 0.4.11-develop.1917.b6098e78cb
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/lib/bootstrap/appResolver.js +26 -8
- package/dist/lib/bootstrap/appResolver.js.map +2 -2
- package/dist/lib/version.js +1 -1
- package/dist/lib/version.js.map +1 -1
- package/package.json +1 -1
- package/src/lib/bootstrap/__tests__/appResolver.test.ts +24 -0
- package/src/lib/bootstrap/appResolver.ts +31 -14
|
@@ -1,12 +1,27 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import fs from "node:fs";
|
|
3
|
+
const nextConfigNames = [
|
|
4
|
+
"next.config.ts",
|
|
5
|
+
"next.config.js",
|
|
6
|
+
"next.config.mjs"
|
|
7
|
+
];
|
|
8
|
+
function hasNextConfigFile(appDir) {
|
|
9
|
+
return nextConfigNames.some((configName) => {
|
|
10
|
+
const configPath = path.join(appDir, configName);
|
|
11
|
+
if (!fs.existsSync(configPath)) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
try {
|
|
15
|
+
return fs.statSync(configPath).isFile();
|
|
16
|
+
} catch {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
3
21
|
function findAppRoot(startDir = process.cwd()) {
|
|
4
22
|
let current = startDir;
|
|
5
|
-
while (
|
|
6
|
-
|
|
7
|
-
const configJs = path.join(current, "next.config.js");
|
|
8
|
-
const configMjs = path.join(current, "next.config.mjs");
|
|
9
|
-
if (fs.existsSync(configTs) || fs.existsSync(configJs) || fs.existsSync(configMjs)) {
|
|
23
|
+
while (true) {
|
|
24
|
+
if (hasNextConfigFile(current)) {
|
|
10
25
|
const mercatoDir = path.join(current, ".mercato");
|
|
11
26
|
const generatedDir = path.join(mercatoDir, "generated");
|
|
12
27
|
if (fs.existsSync(generatedDir)) {
|
|
@@ -14,7 +29,11 @@ function findAppRoot(startDir = process.cwd()) {
|
|
|
14
29
|
}
|
|
15
30
|
return { appDir: current, mercatoDir, generatedDir };
|
|
16
31
|
}
|
|
17
|
-
|
|
32
|
+
const parent = path.dirname(current);
|
|
33
|
+
if (parent === current) {
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
current = parent;
|
|
18
37
|
}
|
|
19
38
|
return null;
|
|
20
39
|
}
|
|
@@ -26,8 +45,7 @@ function findAllApps(rootDir) {
|
|
|
26
45
|
for (const entry of entries) {
|
|
27
46
|
if (!entry.isDirectory()) continue;
|
|
28
47
|
const appDir = path.join(appsDir, entry.name);
|
|
29
|
-
|
|
30
|
-
if (!hasNextConfig) continue;
|
|
48
|
+
if (!hasNextConfigFile(appDir)) continue;
|
|
31
49
|
const mercatoDir = path.join(appDir, ".mercato");
|
|
32
50
|
const generatedDir = path.join(mercatoDir, "generated");
|
|
33
51
|
if (fs.existsSync(generatedDir)) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/bootstrap/appResolver.ts"],
|
|
4
|
-
"sourcesContent": ["import path from 'node:path'\nimport fs from 'node:fs'\n\nexport interface AppRoot {\n appDir: string\n mercatoDir: string\n generatedDir: string\n}\n\n/**\n * Find the Next.js app root by searching for next.config.ts/js/mjs.\n *\n * Starts from the given directory (defaults to cwd) and walks up the\n * directory tree until it finds a Next.js config file with a .mercato/generated\n * directory.\n *\n * @param startDir - Directory to start searching from (defaults to process.cwd())\n * @returns The resolved app root paths, or null if not found\n */\nexport function findAppRoot(startDir: string = process.cwd()): AppRoot | null {\n let current = startDir\n\n while (
|
|
5
|
-
"mappings": "AAAA,OAAO,UAAU;AACjB,OAAO,QAAQ;
|
|
4
|
+
"sourcesContent": ["import path from 'node:path'\nimport fs from 'node:fs'\n\nexport interface AppRoot {\n appDir: string\n mercatoDir: string\n generatedDir: string\n}\n\nconst nextConfigNames = [\n 'next.config.ts',\n 'next.config.js',\n 'next.config.mjs',\n] as const\n\nfunction hasNextConfigFile(appDir: string): boolean {\n return nextConfigNames.some((configName) => {\n const configPath = path.join(appDir, configName)\n\n if (!fs.existsSync(configPath)) {\n return false\n }\n\n try {\n return fs.statSync(configPath).isFile()\n } catch {\n return false\n }\n })\n}\n\n/**\n * Find the Next.js app root by searching for next.config.ts/js/mjs.\n *\n * Starts from the given directory (defaults to cwd) and walks up the\n * directory tree until it finds a Next.js config file with a .mercato/generated\n * directory.\n *\n * @param startDir - Directory to start searching from (defaults to process.cwd())\n * @returns The resolved app root paths, or null if not found\n */\nexport function findAppRoot(startDir: string = process.cwd()): AppRoot | null {\n let current = startDir\n\n while (true) {\n if (hasNextConfigFile(current)) {\n const mercatoDir = path.join(current, '.mercato')\n const generatedDir = path.join(mercatoDir, 'generated')\n\n // Only return if .mercato/generated exists\n if (fs.existsSync(generatedDir)) {\n return { appDir: current, mercatoDir, generatedDir }\n }\n\n // Found Next.js config but no .mercato/generated - return anyway for generate command\n // The caller can decide whether to create the directory\n return { appDir: current, mercatoDir, generatedDir }\n }\n\n const parent = path.dirname(current)\n if (parent === current) {\n break\n }\n\n current = parent\n }\n\n return null\n}\n\n/**\n * Find all apps with .mercato directories in a monorepo.\n *\n * Scans the apps/ directory for Next.js apps with .mercato/generated directories.\n *\n * @param rootDir - The monorepo root directory\n * @returns Array of app root paths\n */\nexport function findAllApps(rootDir: string): AppRoot[] {\n const appsDir = path.join(rootDir, 'apps')\n if (!fs.existsSync(appsDir)) return []\n\n const apps: AppRoot[] = []\n const entries = fs.readdirSync(appsDir, { withFileTypes: true })\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue\n\n const appDir = path.join(appsDir, entry.name)\n\n if (!hasNextConfigFile(appDir)) continue\n\n const mercatoDir = path.join(appDir, '.mercato')\n const generatedDir = path.join(mercatoDir, 'generated')\n\n if (fs.existsSync(generatedDir)) {\n apps.push({ appDir, mercatoDir, generatedDir })\n }\n }\n\n return apps\n}\n"],
|
|
5
|
+
"mappings": "AAAA,OAAO,UAAU;AACjB,OAAO,QAAQ;AAQf,MAAM,kBAAkB;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAAS,kBAAkB,QAAyB;AAClD,SAAO,gBAAgB,KAAK,CAAC,eAAe;AAC1C,UAAM,aAAa,KAAK,KAAK,QAAQ,UAAU;AAE/C,QAAI,CAAC,GAAG,WAAW,UAAU,GAAG;AAC9B,aAAO;AAAA,IACT;AAEA,QAAI;AACF,aAAO,GAAG,SAAS,UAAU,EAAE,OAAO;AAAA,IACxC,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AACH;AAYO,SAAS,YAAY,WAAmB,QAAQ,IAAI,GAAmB;AAC5E,MAAI,UAAU;AAEd,SAAO,MAAM;AACX,QAAI,kBAAkB,OAAO,GAAG;AAC9B,YAAM,aAAa,KAAK,KAAK,SAAS,UAAU;AAChD,YAAM,eAAe,KAAK,KAAK,YAAY,WAAW;AAGtD,UAAI,GAAG,WAAW,YAAY,GAAG;AAC/B,eAAO,EAAE,QAAQ,SAAS,YAAY,aAAa;AAAA,MACrD;AAIA,aAAO,EAAE,QAAQ,SAAS,YAAY,aAAa;AAAA,IACrD;AAEA,UAAM,SAAS,KAAK,QAAQ,OAAO;AACnC,QAAI,WAAW,SAAS;AACtB;AAAA,IACF;AAEA,cAAU;AAAA,EACZ;AAEA,SAAO;AACT;AAUO,SAAS,YAAY,SAA4B;AACtD,QAAM,UAAU,KAAK,KAAK,SAAS,MAAM;AACzC,MAAI,CAAC,GAAG,WAAW,OAAO,EAAG,QAAO,CAAC;AAErC,QAAM,OAAkB,CAAC;AACzB,QAAM,UAAU,GAAG,YAAY,SAAS,EAAE,eAAe,KAAK,CAAC;AAE/D,aAAW,SAAS,SAAS;AAC3B,QAAI,CAAC,MAAM,YAAY,EAAG;AAE1B,UAAM,SAAS,KAAK,KAAK,SAAS,MAAM,IAAI;AAE5C,QAAI,CAAC,kBAAkB,MAAM,EAAG;AAEhC,UAAM,aAAa,KAAK,KAAK,QAAQ,UAAU;AAC/C,UAAM,eAAe,KAAK,KAAK,YAAY,WAAW;AAEtD,QAAI,GAAG,WAAW,YAAY,GAAG;AAC/B,WAAK,KAAK,EAAE,QAAQ,YAAY,aAAa,CAAC;AAAA,IAChD;AAAA,EACF;AAEA,SAAO;AACT;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/lib/version.js
CHANGED
package/dist/lib/version.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/version.ts"],
|
|
4
|
-
"sourcesContent": ["// Build-time generated version\nexport const APP_VERSION = '0.4.11-develop.
|
|
4
|
+
"sourcesContent": ["// Build-time generated version\nexport const APP_VERSION = '0.4.11-develop.1917.b6098e78cb'\nexport const appVersion = APP_VERSION\n"],
|
|
5
5
|
"mappings": "AACO,MAAM,cAAc;AACpB,MAAM,aAAa;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -21,6 +21,17 @@ function createApp(rootDir: string, relativeAppDir: string, configName: NextConf
|
|
|
21
21
|
return { appDir, mercatoDir, generatedDir }
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
function createInvalidConfigDirectory(rootDir: string, relativeAppDir: string, configName: NextConfigName): AppRoot {
|
|
25
|
+
const appDir = path.join(rootDir, relativeAppDir)
|
|
26
|
+
const mercatoDir = path.join(appDir, '.mercato')
|
|
27
|
+
const generatedDir = path.join(mercatoDir, 'generated')
|
|
28
|
+
|
|
29
|
+
fs.mkdirSync(path.join(appDir, configName), { recursive: true })
|
|
30
|
+
fs.mkdirSync(generatedDir, { recursive: true })
|
|
31
|
+
|
|
32
|
+
return { appDir, mercatoDir, generatedDir }
|
|
33
|
+
}
|
|
34
|
+
|
|
24
35
|
describe('appResolver', () => {
|
|
25
36
|
let tempDir: string
|
|
26
37
|
|
|
@@ -61,6 +72,16 @@ describe('appResolver', () => {
|
|
|
61
72
|
expect(findAppRoot(nestedDir)).toEqual(innerApp)
|
|
62
73
|
})
|
|
63
74
|
|
|
75
|
+
it('ignores directories masquerading as Next.js config files', () => {
|
|
76
|
+
const outerApp = createApp(tempDir, 'apps/outer', 'next.config.ts')
|
|
77
|
+
const invalidInnerApp = createInvalidConfigDirectory(outerApp.appDir, 'examples/inner', 'next.config.js')
|
|
78
|
+
const nestedDir = path.join(invalidInnerApp.appDir, 'src')
|
|
79
|
+
|
|
80
|
+
fs.mkdirSync(nestedDir, { recursive: true })
|
|
81
|
+
|
|
82
|
+
expect(findAppRoot(nestedDir)).toEqual(outerApp)
|
|
83
|
+
})
|
|
84
|
+
|
|
64
85
|
it('returns null when no Next.js app can be found', () => {
|
|
65
86
|
const nestedDir = path.join(tempDir, 'packages', 'shared', 'src')
|
|
66
87
|
|
|
@@ -80,6 +101,9 @@ describe('appResolver', () => {
|
|
|
80
101
|
createApp(tempDir, 'apps/docs', 'next.config.js')
|
|
81
102
|
createApp(tempDir, 'apps/admin', 'next.config.mjs')
|
|
82
103
|
createApp(tempDir, 'apps/incomplete', 'next.config.ts', false)
|
|
104
|
+
createInvalidConfigDirectory(tempDir, 'apps/not-really-an-app', 'next.config.ts')
|
|
105
|
+
|
|
106
|
+
fs.mkdirSync(path.join(tempDir, 'apps', 'folder-without-next-config'), { recursive: true })
|
|
83
107
|
|
|
84
108
|
fs.writeFileSync(path.join(tempDir, 'apps', 'README.md'), 'not an app')
|
|
85
109
|
|
|
@@ -7,6 +7,28 @@ export interface AppRoot {
|
|
|
7
7
|
generatedDir: string
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
+
const nextConfigNames = [
|
|
11
|
+
'next.config.ts',
|
|
12
|
+
'next.config.js',
|
|
13
|
+
'next.config.mjs',
|
|
14
|
+
] as const
|
|
15
|
+
|
|
16
|
+
function hasNextConfigFile(appDir: string): boolean {
|
|
17
|
+
return nextConfigNames.some((configName) => {
|
|
18
|
+
const configPath = path.join(appDir, configName)
|
|
19
|
+
|
|
20
|
+
if (!fs.existsSync(configPath)) {
|
|
21
|
+
return false
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
return fs.statSync(configPath).isFile()
|
|
26
|
+
} catch {
|
|
27
|
+
return false
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
|
|
10
32
|
/**
|
|
11
33
|
* Find the Next.js app root by searching for next.config.ts/js/mjs.
|
|
12
34
|
*
|
|
@@ -20,12 +42,8 @@ export interface AppRoot {
|
|
|
20
42
|
export function findAppRoot(startDir: string = process.cwd()): AppRoot | null {
|
|
21
43
|
let current = startDir
|
|
22
44
|
|
|
23
|
-
while (
|
|
24
|
-
|
|
25
|
-
const configJs = path.join(current, 'next.config.js')
|
|
26
|
-
const configMjs = path.join(current, 'next.config.mjs')
|
|
27
|
-
|
|
28
|
-
if (fs.existsSync(configTs) || fs.existsSync(configJs) || fs.existsSync(configMjs)) {
|
|
45
|
+
while (true) {
|
|
46
|
+
if (hasNextConfigFile(current)) {
|
|
29
47
|
const mercatoDir = path.join(current, '.mercato')
|
|
30
48
|
const generatedDir = path.join(mercatoDir, 'generated')
|
|
31
49
|
|
|
@@ -39,7 +57,12 @@ export function findAppRoot(startDir: string = process.cwd()): AppRoot | null {
|
|
|
39
57
|
return { appDir: current, mercatoDir, generatedDir }
|
|
40
58
|
}
|
|
41
59
|
|
|
42
|
-
|
|
60
|
+
const parent = path.dirname(current)
|
|
61
|
+
if (parent === current) {
|
|
62
|
+
break
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
current = parent
|
|
43
66
|
}
|
|
44
67
|
|
|
45
68
|
return null
|
|
@@ -65,13 +88,7 @@ export function findAllApps(rootDir: string): AppRoot[] {
|
|
|
65
88
|
|
|
66
89
|
const appDir = path.join(appsDir, entry.name)
|
|
67
90
|
|
|
68
|
-
|
|
69
|
-
const hasNextConfig =
|
|
70
|
-
fs.existsSync(path.join(appDir, 'next.config.ts')) ||
|
|
71
|
-
fs.existsSync(path.join(appDir, 'next.config.js')) ||
|
|
72
|
-
fs.existsSync(path.join(appDir, 'next.config.mjs'))
|
|
73
|
-
|
|
74
|
-
if (!hasNextConfig) continue
|
|
91
|
+
if (!hasNextConfigFile(appDir)) continue
|
|
75
92
|
|
|
76
93
|
const mercatoDir = path.join(appDir, '.mercato')
|
|
77
94
|
const generatedDir = path.join(mercatoDir, 'generated')
|