astro-tractstack 2.0.30 → 2.0.32
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/index.js +10 -36
- package/package.json +1 -1
- package/templates/src/components/compositor/Compositor.tsx +8 -0
- package/templates/src/components/compositor/nodes/Pane_DesignLibrary.tsx +169 -48
- package/templates/src/components/compositor/nodes/Pane_eraser.tsx +153 -36
- package/templates/src/stores/nodes.ts +10 -0
- package/templates/src/utils/auth.ts +6 -3
- package/utils/inject-files.ts +0 -27
- package/templates/src/components/tenant/RegistrationForm.tsx +0 -449
- package/templates/src/pages/sandbox/activate.astro +0 -258
- package/templates/src/pages/sandbox/register.astro +0 -44
- package/templates/src/pages/sandbox/success.astro +0 -179
- package/templates/src/utils/api/tenantConfig.ts +0 -97
- package/templates/src/utils/api/tenantHelpers.ts +0 -172
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
// Tenant form validation and state helpers following TractStack v2 patterns
|
|
2
|
-
import type { TenantProvisioningData } from '@/types/multiTenant';
|
|
3
|
-
import type {
|
|
4
|
-
TenantRegistrationState,
|
|
5
|
-
TenantValidationErrors,
|
|
6
|
-
} from '@/types/multiTenant';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Convert tenant provisioning data to local form state
|
|
10
|
-
*/
|
|
11
|
-
export function convertToLocalState(
|
|
12
|
-
data?: TenantProvisioningData
|
|
13
|
-
): TenantRegistrationState {
|
|
14
|
-
if (!data) {
|
|
15
|
-
return {
|
|
16
|
-
tenantId: '',
|
|
17
|
-
adminPassword: '',
|
|
18
|
-
confirmPassword: '',
|
|
19
|
-
name: '',
|
|
20
|
-
email: '',
|
|
21
|
-
tursoEnabled: false,
|
|
22
|
-
tursoDatabaseURL: '',
|
|
23
|
-
tursoAuthToken: '',
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return {
|
|
28
|
-
tenantId: data.tenantId,
|
|
29
|
-
adminPassword: data.adminPassword,
|
|
30
|
-
confirmPassword: '',
|
|
31
|
-
name: data.name,
|
|
32
|
-
email: data.adminEmail,
|
|
33
|
-
tursoEnabled: data.tursoEnabled,
|
|
34
|
-
tursoDatabaseURL: data.tursoDatabaseURL || '',
|
|
35
|
-
tursoAuthToken: data.tursoAuthToken || '',
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Convert local form state to backend format
|
|
41
|
-
*/
|
|
42
|
-
export function convertToBackendFormat(
|
|
43
|
-
state: TenantRegistrationState
|
|
44
|
-
): TenantProvisioningData {
|
|
45
|
-
const data: TenantProvisioningData = {
|
|
46
|
-
tenantId: state.tenantId.trim(),
|
|
47
|
-
adminPassword: state.adminPassword.trim(),
|
|
48
|
-
name: state.name.trim(),
|
|
49
|
-
adminEmail: state.email.trim(),
|
|
50
|
-
tursoEnabled: state.tursoEnabled,
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
// Only include Turso credentials if enabled
|
|
54
|
-
if (state.tursoEnabled) {
|
|
55
|
-
data.tursoDatabaseURL = state.tursoDatabaseURL.trim();
|
|
56
|
-
data.tursoAuthToken = state.tursoAuthToken.trim();
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
return data;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Validate tenant registration form
|
|
64
|
-
*/
|
|
65
|
-
export function validateTenantRegistration(
|
|
66
|
-
state: TenantRegistrationState,
|
|
67
|
-
existingTenants?: string[],
|
|
68
|
-
isInitMode?: boolean
|
|
69
|
-
): TenantValidationErrors {
|
|
70
|
-
const errors: TenantValidationErrors = {};
|
|
71
|
-
|
|
72
|
-
// Skip ALL tenant ID validation in init mode
|
|
73
|
-
if (!isInitMode) {
|
|
74
|
-
const tenantId = state.tenantId.trim();
|
|
75
|
-
if (!tenantId) {
|
|
76
|
-
errors.tenantId = 'Tenant ID is required';
|
|
77
|
-
} else if (tenantId.length < 3 || tenantId.length > 12) {
|
|
78
|
-
errors.tenantId = 'Tenant ID must be 3-12 characters long';
|
|
79
|
-
} else if (tenantId !== tenantId.toLowerCase()) {
|
|
80
|
-
errors.tenantId = 'Tenant ID must be lowercase';
|
|
81
|
-
} else if (!/^[a-z0-9-]+$/.test(tenantId)) {
|
|
82
|
-
errors.tenantId =
|
|
83
|
-
'Tenant ID can only contain lowercase letters, numbers, and dashes';
|
|
84
|
-
} else if (tenantId === 'default') {
|
|
85
|
-
errors.tenantId = "'default' is a reserved tenant ID";
|
|
86
|
-
} else if (existingTenants && existingTenants.includes(tenantId)) {
|
|
87
|
-
errors.tenantId = 'This tenant ID is already taken';
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Admin password validation
|
|
92
|
-
if (!state.adminPassword.trim()) {
|
|
93
|
-
errors.adminPassword = 'Admin password is required';
|
|
94
|
-
} else if (state.adminPassword.length < 8) {
|
|
95
|
-
errors.adminPassword = 'Admin password must be at least 8 characters long';
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// Password confirmation validation - only if main password is valid
|
|
99
|
-
if (!errors.adminPassword && state.adminPassword !== state.confirmPassword) {
|
|
100
|
-
errors.confirmPassword = 'Passwords do not match';
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Name validation
|
|
104
|
-
if (!state.name.trim()) {
|
|
105
|
-
errors.name = 'Name is required';
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Email validation
|
|
109
|
-
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
110
|
-
if (!state.email.trim()) {
|
|
111
|
-
errors.email = 'Email is required';
|
|
112
|
-
} else if (!emailRegex.test(state.email.trim())) {
|
|
113
|
-
errors.email = 'Please enter a valid email address';
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Turso validation (if enabled)
|
|
117
|
-
if (state.tursoEnabled) {
|
|
118
|
-
if (!state.tursoDatabaseURL.trim()) {
|
|
119
|
-
errors.tursoDatabaseURL =
|
|
120
|
-
'Turso Database URL is required when Turso is enabled';
|
|
121
|
-
} else if (!state.tursoDatabaseURL.startsWith('libsql://')) {
|
|
122
|
-
errors.tursoDatabaseURL =
|
|
123
|
-
'Turso Database URL must start with "libsql://"';
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
if (!state.tursoAuthToken.trim()) {
|
|
127
|
-
errors.tursoAuthToken =
|
|
128
|
-
'Turso Auth Token is required when Turso is enabled';
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
return errors;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* State interceptor for cross-field logic
|
|
137
|
-
*/
|
|
138
|
-
export function tenantStateIntercept(
|
|
139
|
-
newState: TenantRegistrationState,
|
|
140
|
-
field: keyof TenantRegistrationState,
|
|
141
|
-
value: any
|
|
142
|
-
): TenantRegistrationState {
|
|
143
|
-
// Clear Turso fields when disabled
|
|
144
|
-
if (field === 'tursoEnabled' && !value) {
|
|
145
|
-
return {
|
|
146
|
-
...newState,
|
|
147
|
-
tursoEnabled: false,
|
|
148
|
-
tursoDatabaseURL: '',
|
|
149
|
-
tursoAuthToken: '',
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// Clear confirmation password when main password changes
|
|
154
|
-
if (field === 'adminPassword') {
|
|
155
|
-
return {
|
|
156
|
-
...newState,
|
|
157
|
-
adminPassword: value,
|
|
158
|
-
confirmPassword: '', // Clear confirmation to force re-entry
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Normalize tenant ID
|
|
163
|
-
if (field === 'tenantId' && typeof value === 'string') {
|
|
164
|
-
return {
|
|
165
|
-
...newState,
|
|
166
|
-
tenantId: value.toLowerCase().replace(/[^a-z0-9-]/g, ''),
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// Default behavior
|
|
171
|
-
return newState;
|
|
172
|
-
}
|