create-appraisejs 0.2.0-alpha.2 → 0.2.0-alpha.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.
- package/package.json +9 -5
- package/templates/default/.appraise-template-meta.json +2 -2
- package/templates/default/prisma/dev.db +0 -0
- package/templates/default/scripts/sync-environments.ts +7 -3
- package/templates/default/src/config/db-config.ts +67 -6
- package/templates/default/src/lib/environment-file-utils.ts +39 -43
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-appraisejs",
|
|
3
|
-
"version": "0.2.0-alpha.
|
|
3
|
+
"version": "0.2.0-alpha.4",
|
|
4
4
|
"description": "Scaffold a new AppraiseJS app in your directory",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Hasnat Jamil",
|
|
@@ -44,10 +44,14 @@
|
|
|
44
44
|
"sync-templates": "tsx scripts/sync-templates.ts",
|
|
45
45
|
"test": "vitest run",
|
|
46
46
|
"test:e2e": "vitest run --config vitest.e2e.config.ts",
|
|
47
|
-
"publish": "npm
|
|
48
|
-
"publish:
|
|
49
|
-
"
|
|
50
|
-
"bump:
|
|
47
|
+
"publish:alpha": "npm publish --tag alpha",
|
|
48
|
+
"publish:beta": "npm publish --tag beta",
|
|
49
|
+
"bump:alpha": "npm version prerelease --preid alpha",
|
|
50
|
+
"bump:beta": "npm version prerelease --preid beta",
|
|
51
|
+
"bump:release": "npm version patch",
|
|
52
|
+
"bump:major": "npm version major",
|
|
53
|
+
"bump:minor": "npm version minor",
|
|
54
|
+
"bump:patch": "npm version patch"
|
|
51
55
|
},
|
|
52
56
|
"dependencies": {
|
|
53
57
|
"@inquirer/prompts": "^7.2.0",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"preparedAt": "2026-03-
|
|
3
|
-
"inputHash": "
|
|
2
|
+
"preparedAt": "2026-03-24T10:58:54.969Z",
|
|
3
|
+
"inputHash": "596a28d2c5dc408d39926068711127354f3752a92c086cd0df27e8cf85eb5990",
|
|
4
4
|
"databasePath": "prisma/dev.db"
|
|
5
5
|
}
|
|
Binary file
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import { promises as fs } from 'fs'
|
|
12
|
+
import path from 'path'
|
|
12
13
|
import prisma from '../src/config/db-config'
|
|
13
14
|
import { ensureAutomationWorkspaceReady, getAutomationEnvironmentsDir } from '../src/lib/automation/paths'
|
|
14
15
|
|
|
@@ -40,16 +41,20 @@ interface SyncResult {
|
|
|
40
41
|
skippedEnvironments: string[]
|
|
41
42
|
}
|
|
42
43
|
|
|
44
|
+
const EMPTY_ENVIRONMENTS_FILE_CONTENT = '{}\n'
|
|
45
|
+
|
|
43
46
|
/**
|
|
44
47
|
* Reads and parses the environments.json file
|
|
45
48
|
*/
|
|
46
49
|
async function readEnvironmentsFromFile(): Promise<Record<string, EnvironmentConfig>> {
|
|
47
|
-
const filePath =
|
|
50
|
+
const filePath = path.join(getAutomationEnvironmentsDir(), 'environments.json')
|
|
48
51
|
|
|
49
52
|
try {
|
|
50
53
|
await fs.access(filePath)
|
|
51
54
|
} catch {
|
|
52
|
-
|
|
55
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true })
|
|
56
|
+
await fs.writeFile(filePath, EMPTY_ENVIRONMENTS_FILE_CONTENT, 'utf-8')
|
|
57
|
+
return {}
|
|
53
58
|
}
|
|
54
59
|
|
|
55
60
|
try {
|
|
@@ -342,4 +347,3 @@ async function main() {
|
|
|
342
347
|
main()
|
|
343
348
|
|
|
344
349
|
|
|
345
|
-
|
|
@@ -1,9 +1,70 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import { createRequire } from 'module'
|
|
3
|
+
import path from 'path'
|
|
4
|
+
|
|
5
|
+
function readProjectDatabaseUrl(): string | null {
|
|
6
|
+
const envPath = path.join(process.cwd(), '.env')
|
|
7
|
+
if (!fs.existsSync(envPath)) {
|
|
8
|
+
return null
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const envContent = fs.readFileSync(envPath, 'utf8')
|
|
12
|
+
const match = envContent.match(/^\s*DATABASE_URL\s*=\s*(?:"([^"]*)"|'([^']*)'|([^#\r\n]+))\s*$/m)
|
|
13
|
+
const rawValue = match?.[1] ?? match?.[2] ?? match?.[3]
|
|
14
|
+
const normalizedValue = rawValue?.trim()
|
|
15
|
+
|
|
16
|
+
return normalizedValue ? normalizedValue : null
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function normalizeDatabaseUrl(databaseUrl: string): string {
|
|
20
|
+
if (!databaseUrl.startsWith('file:')) {
|
|
21
|
+
return databaseUrl
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const sqlitePathWithQuery = databaseUrl.slice('file:'.length)
|
|
25
|
+
if (!sqlitePathWithQuery || sqlitePathWithQuery === ':memory:') {
|
|
26
|
+
return databaseUrl
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const queryStartIndex = sqlitePathWithQuery.indexOf('?')
|
|
30
|
+
const sqlitePath = queryStartIndex >= 0 ? sqlitePathWithQuery.slice(0, queryStartIndex) : sqlitePathWithQuery
|
|
31
|
+
const query = queryStartIndex >= 0 ? sqlitePathWithQuery.slice(queryStartIndex) : ''
|
|
32
|
+
|
|
33
|
+
if (path.isAbsolute(sqlitePath)) {
|
|
34
|
+
return databaseUrl
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Prisma resolves relative SQLite paths from the schema directory. The app's schema
|
|
38
|
+
// lives in `<project>/prisma`, so normalize local file URLs to that location.
|
|
39
|
+
const absolutePath = path.resolve(process.cwd(), 'prisma', sqlitePath)
|
|
40
|
+
return `file:${absolutePath}${query}`
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function ensureProjectDatabaseUrl(): void {
|
|
44
|
+
if (process.env.DATABASE_URL) {
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const projectDatabaseUrl = readProjectDatabaseUrl()
|
|
49
|
+
if (!projectDatabaseUrl) {
|
|
50
|
+
return
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
process.env.DATABASE_URL = normalizeDatabaseUrl(projectDatabaseUrl)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
ensureProjectDatabaseUrl()
|
|
57
|
+
|
|
58
|
+
type PrismaClientInstance = import('@prisma/client').PrismaClient
|
|
59
|
+
const require = createRequire(import.meta.url)
|
|
60
|
+
const { PrismaClient } = require('@prisma/client') as {
|
|
61
|
+
PrismaClient: new () => PrismaClientInstance
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const globalForPrisma = global as unknown as {
|
|
65
|
+
prisma: PrismaClientInstance | undefined
|
|
66
|
+
}
|
|
67
|
+
const prisma = globalForPrisma.prisma ?? new PrismaClient()
|
|
7
68
|
|
|
8
69
|
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
|
|
9
70
|
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import { promises as fs } from 'fs'
|
|
2
|
-
import * as path from 'path'
|
|
3
|
-
import prisma from '@/config/db-config'
|
|
4
|
-
import { ensureAutomationWorkspaceReady, getAutomationEnvironmentsDir } from '@/lib/automation/paths'
|
|
5
|
-
|
|
6
|
-
interface EnvironmentConfig {
|
|
7
|
-
baseUrl: string
|
|
8
|
-
apiBaseUrl: string
|
|
9
|
-
email: string
|
|
10
|
-
password: string
|
|
11
|
-
}
|
|
1
|
+
import { promises as fs } from 'fs'
|
|
2
|
+
import * as path from 'path'
|
|
3
|
+
import prisma from '@/config/db-config'
|
|
4
|
+
import { ensureAutomationWorkspaceReady, getAutomationEnvironmentsDir } from '@/lib/automation/paths'
|
|
5
|
+
|
|
6
|
+
interface EnvironmentConfig {
|
|
7
|
+
baseUrl: string
|
|
8
|
+
apiBaseUrl: string
|
|
9
|
+
email: string
|
|
10
|
+
password: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const EMPTY_ENVIRONMENTS_FILE_CONTENT = '{}\n'
|
|
12
14
|
|
|
13
15
|
export function getEnvironmentsFilePath(): string {
|
|
14
16
|
return path.join(getAutomationEnvironmentsDir(), 'environments.json')
|
|
@@ -44,44 +46,38 @@ export async function generateEnvironmentsContent(): Promise<Record<string, Envi
|
|
|
44
46
|
}
|
|
45
47
|
}
|
|
46
48
|
|
|
47
|
-
export async function createOrUpdateEnvironmentsFile(): Promise<boolean> {
|
|
48
|
-
try {
|
|
49
|
-
await ensureAutomationWorkspaceReady()
|
|
50
|
-
const filePath = getEnvironmentsFilePath()
|
|
51
|
-
await ensureConfigDirectoryExists()
|
|
52
|
-
|
|
53
|
-
const content = await generateEnvironmentsContent()
|
|
54
|
-
|
|
55
|
-
if (Object.keys(content).length === 0) {
|
|
56
|
-
await
|
|
57
|
-
return true
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
await fs.writeFile(filePath, JSON.stringify(content, null, 2))
|
|
61
|
-
return true
|
|
49
|
+
export async function createOrUpdateEnvironmentsFile(): Promise<boolean> {
|
|
50
|
+
try {
|
|
51
|
+
await ensureAutomationWorkspaceReady()
|
|
52
|
+
const filePath = getEnvironmentsFilePath()
|
|
53
|
+
await ensureConfigDirectoryExists()
|
|
54
|
+
|
|
55
|
+
const content = await generateEnvironmentsContent()
|
|
56
|
+
|
|
57
|
+
if (Object.keys(content).length === 0) {
|
|
58
|
+
await fs.writeFile(filePath, EMPTY_ENVIRONMENTS_FILE_CONTENT)
|
|
59
|
+
return true
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
await fs.writeFile(filePath, JSON.stringify(content, null, 2))
|
|
63
|
+
return true
|
|
62
64
|
} catch (error) {
|
|
63
65
|
console.error('Error creating/updating environments file:', error)
|
|
64
66
|
return false
|
|
65
67
|
}
|
|
66
68
|
}
|
|
67
69
|
|
|
68
|
-
export async function deleteEnvironmentsFile(): Promise<boolean> {
|
|
69
|
-
try {
|
|
70
|
-
await ensureAutomationWorkspaceReady()
|
|
71
|
-
const filePath = getEnvironmentsFilePath()
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
await fs.unlink(filePath)
|
|
80
|
-
return true
|
|
81
|
-
} catch (error) {
|
|
82
|
-
console.error('Error deleting environments file:', error)
|
|
83
|
-
return false
|
|
84
|
-
}
|
|
70
|
+
export async function deleteEnvironmentsFile(): Promise<boolean> {
|
|
71
|
+
try {
|
|
72
|
+
await ensureAutomationWorkspaceReady()
|
|
73
|
+
const filePath = getEnvironmentsFilePath()
|
|
74
|
+
await ensureConfigDirectoryExists()
|
|
75
|
+
await fs.writeFile(filePath, EMPTY_ENVIRONMENTS_FILE_CONTENT)
|
|
76
|
+
return true
|
|
77
|
+
} catch (error) {
|
|
78
|
+
console.error('Error deleting environments file:', error)
|
|
79
|
+
return false
|
|
80
|
+
}
|
|
85
81
|
}
|
|
86
82
|
|
|
87
83
|
export async function readEnvironmentsFile(): Promise<{
|