astro-tractstack 2.0.0-rc.0 → 2.0.0-rc.1
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/bin/create-tractstack.js
CHANGED
|
@@ -28,6 +28,56 @@ function detectPackageManager() {
|
|
|
28
28
|
return 'pnpm';
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
// Parse existing .env file
|
|
32
|
+
function parseExistingEnv() {
|
|
33
|
+
const defaults = {
|
|
34
|
+
goBackend: 'http://localhost:8080',
|
|
35
|
+
tenantId: 'default',
|
|
36
|
+
goBackendPath: `${homedir()}/t8k-go-server/`,
|
|
37
|
+
enableMultiTenant: false,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
if (!existsSync('.env')) {
|
|
41
|
+
return defaults;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
const envContent = readFileSync('.env', 'utf-8');
|
|
46
|
+
const envVars = {};
|
|
47
|
+
|
|
48
|
+
envContent.split('\n').forEach((line) => {
|
|
49
|
+
line = line.trim();
|
|
50
|
+
if (line && !line.startsWith('#')) {
|
|
51
|
+
const [key, ...valueParts] = line.split('=');
|
|
52
|
+
if (key && valueParts.length > 0) {
|
|
53
|
+
// Remove surrounding quotes and trim
|
|
54
|
+
let value = valueParts.join('=').trim();
|
|
55
|
+
if (
|
|
56
|
+
(value.startsWith('"') && value.endsWith('"')) ||
|
|
57
|
+
(value.startsWith("'") && value.endsWith("'"))
|
|
58
|
+
) {
|
|
59
|
+
value = value.slice(1, -1);
|
|
60
|
+
}
|
|
61
|
+
envVars[key.trim()] = value;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
goBackend: envVars.PUBLIC_GO_BACKEND || defaults.goBackend,
|
|
68
|
+
tenantId: envVars.PUBLIC_TENANTID || defaults.tenantId,
|
|
69
|
+
goBackendPath: envVars.PRIVATE_GO_BACKEND_PATH || defaults.goBackendPath,
|
|
70
|
+
enableMultiTenant:
|
|
71
|
+
envVars.ENABLE_MULTI_TENANT === 'true' || defaults.enableMultiTenant,
|
|
72
|
+
};
|
|
73
|
+
} catch (error) {
|
|
74
|
+
console.log(
|
|
75
|
+
kleur.yellow('⚠️ Found .env file but could not parse it, using defaults')
|
|
76
|
+
);
|
|
77
|
+
return defaults;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
31
81
|
async function main() {
|
|
32
82
|
// ASCII art
|
|
33
83
|
console.log(
|
|
@@ -89,13 +139,25 @@ ${kleur.bold('Examples:')}
|
|
|
89
139
|
process.exit(1);
|
|
90
140
|
}
|
|
91
141
|
|
|
92
|
-
//
|
|
142
|
+
// Parse existing .env values
|
|
143
|
+
const envDefaults = parseExistingEnv();
|
|
144
|
+
const hasExistingEnv = existsSync('.env');
|
|
145
|
+
|
|
146
|
+
if (hasExistingEnv) {
|
|
147
|
+
console.log(
|
|
148
|
+
kleur.yellow(
|
|
149
|
+
'📁 Found existing .env file, using current values as defaults\n'
|
|
150
|
+
)
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Prompt for configuration with existing values as defaults
|
|
93
155
|
const responses = await prompts([
|
|
94
156
|
{
|
|
95
157
|
type: 'text',
|
|
96
158
|
name: 'goBackend',
|
|
97
159
|
message: 'TractStack Go backend URL:',
|
|
98
|
-
initial:
|
|
160
|
+
initial: envDefaults.goBackend,
|
|
99
161
|
validate: (value) => {
|
|
100
162
|
try {
|
|
101
163
|
new URL(value);
|
|
@@ -106,22 +168,27 @@ ${kleur.bold('Examples:')}
|
|
|
106
168
|
},
|
|
107
169
|
},
|
|
108
170
|
{
|
|
109
|
-
type: '
|
|
171
|
+
type: 'confirm',
|
|
172
|
+
name: 'enableMultiTenant',
|
|
173
|
+
message: 'Enable multi-tenant functionality?',
|
|
174
|
+
initial: enableMultiTenant || envDefaults.enableMultiTenant,
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
type: (prev, values) => (values.enableMultiTenant ? 'text' : null),
|
|
110
178
|
name: 'tenantId',
|
|
111
179
|
message: 'Tenant ID:',
|
|
112
|
-
initial:
|
|
180
|
+
initial: envDefaults.tenantId,
|
|
113
181
|
validate: (value) => value.length > 0 || 'Tenant ID is required',
|
|
114
182
|
},
|
|
115
183
|
{
|
|
116
184
|
type: 'text',
|
|
117
185
|
name: 'goBackendPath',
|
|
118
186
|
message: 'TractStack Go backend path:',
|
|
119
|
-
initial:
|
|
187
|
+
initial: envDefaults.goBackendPath,
|
|
120
188
|
validate: (value) => {
|
|
121
189
|
if (!value || value.trim().length === 0) {
|
|
122
190
|
return 'Backend path is required';
|
|
123
191
|
}
|
|
124
|
-
// Ensure it ends with trailing slash for consistency
|
|
125
192
|
return true;
|
|
126
193
|
},
|
|
127
194
|
},
|
|
@@ -132,29 +199,38 @@ ${kleur.bold('Examples:')}
|
|
|
132
199
|
'Include CodeHook examples? (custom components, collections route)',
|
|
133
200
|
initial: includeExamples,
|
|
134
201
|
},
|
|
135
|
-
{
|
|
136
|
-
type: 'confirm',
|
|
137
|
-
name: 'enableMultiTenant',
|
|
138
|
-
message: 'Enable multi-tenant functionality?',
|
|
139
|
-
initial: enableMultiTenant,
|
|
140
|
-
},
|
|
141
202
|
]);
|
|
142
203
|
|
|
143
|
-
if (!responses.goBackend
|
|
204
|
+
if (!responses.goBackend) {
|
|
144
205
|
console.log(kleur.red('\n❌ Setup cancelled.'));
|
|
145
206
|
process.exit(1);
|
|
146
207
|
}
|
|
147
208
|
|
|
209
|
+
// Use existing tenantId if multi-tenant is disabled
|
|
210
|
+
const finalTenantId = responses.enableMultiTenant
|
|
211
|
+
? responses.tenantId
|
|
212
|
+
: envDefaults.tenantId;
|
|
213
|
+
|
|
214
|
+
if (!finalTenantId) {
|
|
215
|
+
console.log(kleur.red('\n❌ Setup cancelled - Tenant ID is required.'));
|
|
216
|
+
process.exit(1);
|
|
217
|
+
}
|
|
218
|
+
|
|
148
219
|
// Create .env file
|
|
149
220
|
const envContent = `# TractStack Configuration
|
|
150
221
|
PUBLIC_GO_BACKEND="${responses.goBackend}"
|
|
151
|
-
PUBLIC_TENANTID="${
|
|
222
|
+
PUBLIC_TENANTID="${finalTenantId}"
|
|
152
223
|
PRIVATE_GO_BACKEND_PATH="${responses.goBackendPath.endsWith('/') ? responses.goBackendPath : responses.goBackendPath + '/'}"
|
|
224
|
+
${responses.enableMultiTenant ? 'ENABLE_MULTI_TENANT="true"' : ''}
|
|
153
225
|
`;
|
|
154
226
|
|
|
155
227
|
try {
|
|
156
228
|
writeFileSync('.env', envContent);
|
|
157
|
-
|
|
229
|
+
if (hasExistingEnv) {
|
|
230
|
+
console.log(kleur.green('✅ Updated .env file with new configuration'));
|
|
231
|
+
} else {
|
|
232
|
+
console.log(kleur.green('✅ Created .env file'));
|
|
233
|
+
}
|
|
158
234
|
} catch (error) {
|
|
159
235
|
console.log(kleur.red('❌ Failed to create .env file:', error.message));
|
|
160
236
|
process.exit(1);
|
package/package.json
CHANGED
|
@@ -154,7 +154,11 @@ const createdDate = created ? new Date(created) : new Date();
|
|
|
154
154
|
class="text-myblue xs:flex-row my-2 flex flex-col items-center justify-center"
|
|
155
155
|
>
|
|
156
156
|
<div class="px-12 text-center text-2xl">
|
|
157
|
-
Copyright © {createdDate.getFullYear()}
|
|
157
|
+
Copyright © {createdDate.getFullYear()}{
|
|
158
|
+
createdDate.getFullYear() !== new Date().getFullYear()
|
|
159
|
+
? `-${new Date().getFullYear()}`
|
|
160
|
+
: ''
|
|
161
|
+
}
|
|
158
162
|
|
|
|
159
163
|
{footer}
|
|
160
164
|
</div>
|
|
@@ -33,23 +33,8 @@ export const POST: APIRoute = async ({ request }) => {
|
|
|
33
33
|
const goBackend =
|
|
34
34
|
import.meta.env.PUBLIC_GO_BACKEND || 'http://localhost:8080';
|
|
35
35
|
|
|
36
|
-
//
|
|
37
|
-
const
|
|
38
|
-
method: 'POST',
|
|
39
|
-
headers: {
|
|
40
|
-
'Content-Type': 'application/json',
|
|
41
|
-
'X-Tenant-ID': tenantId,
|
|
42
|
-
},
|
|
43
|
-
body: JSON.stringify({
|
|
44
|
-
password: import.meta.env.ADMIN_PASSWORD || 'letmein',
|
|
45
|
-
}),
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
if (!authResponse.ok) {
|
|
49
|
-
throw new Error('Failed to authenticate with Go backend');
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const { token } = await authResponse.json();
|
|
36
|
+
// Forward authentication cookies to the backend
|
|
37
|
+
const cookieHeader = request.headers.get('cookie') || '';
|
|
53
38
|
|
|
54
39
|
// Get classes from Go backend (includes whitelist + clean panes)
|
|
55
40
|
const classesResponse = await fetch(
|
|
@@ -58,7 +43,7 @@ export const POST: APIRoute = async ({ request }) => {
|
|
|
58
43
|
method: 'POST',
|
|
59
44
|
headers: {
|
|
60
45
|
'Content-Type': 'application/json',
|
|
61
|
-
|
|
46
|
+
Cookie: cookieHeader,
|
|
62
47
|
'X-Tenant-ID': tenantId,
|
|
63
48
|
},
|
|
64
49
|
body: JSON.stringify({ excludePaneIds: dirtyPaneIds || [] }),
|
|
@@ -86,14 +71,13 @@ export const POST: APIRoute = async ({ request }) => {
|
|
|
86
71
|
htmlContent
|
|
87
72
|
);
|
|
88
73
|
|
|
89
|
-
// Return result (SaveModal will handle the update call logging)
|
|
90
74
|
return new Response(
|
|
91
75
|
JSON.stringify({
|
|
92
76
|
success: true,
|
|
93
77
|
classes: allClasses.length,
|
|
94
78
|
frontend: generatedCss.length,
|
|
95
|
-
stylesVer: Date.now(),
|
|
96
|
-
generatedCss,
|
|
79
|
+
stylesVer: Date.now(),
|
|
80
|
+
generatedCss,
|
|
97
81
|
}),
|
|
98
82
|
{
|
|
99
83
|
status: 200,
|