@@ -18,9 +18,6 @@ export function activate(context: vscode.ExtensionContext) {
1818 vscode . commands . registerCommand ( 'objectql.validateSchema' , validateCurrentFile )
1919 ) ;
2020
21- // Configure YAML language server for ObjectQL files
22- configureYamlLanguageServer ( ) ;
23-
2421 // Show welcome message on first activation
2522 const hasShownWelcome = context . globalState . get ( 'objectql.hasShownWelcome' , false ) ;
2623 if ( ! hasShownWelcome ) {
@@ -66,11 +63,19 @@ async function createNewFile(context: vscode.ExtensionContext, fileType: 'object
6663 }
6764
6865 // Determine file path
66+ // Guess the location based on standard folder structure
67+ let folder = 'src' ;
68+ if ( fileType === 'object' ) {
69+ folder = 'src/objects' ;
70+ } else if ( fileType === 'app' ) {
71+ folder = 'src' ;
72+ }
73+
6974 const fullFileName = `${ fileName } .${ fileType } .yml` ;
70- const defaultPath = path . join ( workspaceFolder . uri . fsPath , 'src' , 'objects' , fullFileName ) ;
75+ const defaultPath = path . join ( workspaceFolder . uri . fsPath , folder , fullFileName ) ;
7176
7277 // Get template content
73- const template = getTemplate ( fileType , fileName ) ;
78+ const template = getTemplate ( context , fileType , fileName ) ;
7479
7580 try {
7681 // Ensure directory exists
@@ -104,198 +109,44 @@ async function createNewFile(context: vscode.ExtensionContext, fileType: 'object
104109}
105110
106111/**
107- * Get template content for file type
112+ * Get template content for file type from template files
108113 */
109- function getTemplate ( fileType : string , name : string ) : string {
110- switch ( fileType ) {
111- case 'object' :
112- return `# ObjectQL Object Definition
113- # Documentation: https://github.com/objectstack-ai/objectql
114-
115- name: ${ name }
116- label: ${ capitalizeWords ( name ) }
117- description: "${ capitalizeWords ( name ) } object"
118-
119- fields:
120- name:
121- type: text
122- label: Name
123- required: true
124- searchable: true
125- help_text: "The name of the ${ name } "
126-
127- description:
128- type: textarea
129- label: Description
130- help_text: "Detailed description"
131-
132- status:
133- type: select
134- label: Status
135- options:
136- - label: Active
137- value: active
138- - label: Inactive
139- value: inactive
140- defaultValue: active
141-
142- created_by:
143- type: lookup
144- label: Created By
145- reference_to: users
146- readonly: true
147-
148- created_at:
149- type: datetime
150- label: Created At
151- readonly: true
152-
153- # Indexes for performance
154- indexes:
155- name_idx:
156- fields: [name]
157- status_idx:
158- fields: [status]
159-
160- # Validation rules (optional)
161- validation:
162- rules:
163- - name: name_required
164- type: cross_field
165- message: "Name is required"
166- rule:
167- field: name
168- operator: "!="
169- value: null
170- ` ;
171-
172- case 'validation' :
173- return `# ObjectQL Validation Rules
174- # Documentation: https://github.com/objectstack-ai/objectql/docs/spec/validation.md
175-
176- # Object-level validation rules
177- rules:
178- # Cross-field validation example
179- - name: end_after_start
180- type: cross_field
181- message: "End date must be after start date"
182- fields: [start_date, end_date]
183- rule:
184- field: end_date
185- operator: ">"
186- compare_to: start_date
187- trigger: [create, update]
188- severity: error
189-
190- # Business rule example
191- - name: status_approval_required
192- type: business_rule
193- message: "Approval required before activation"
194- constraint:
195- expression: "status === 'active' && approved === true"
196- trigger: [create, update]
197- severity: error
198-
199- # Uniqueness validation
200- - name: unique_email
201- type: unique
202- message: "Email must be unique"
203- field: email
204- case_sensitive: false
205- trigger: [create, update]
206- ` ;
207-
208- case 'permission' :
209- return `# ObjectQL Permission Rules
210- # Documentation: https://github.com/objectstack-ai/objectql/docs/spec/permission.md
211-
212- # Role-based permissions
213- roles:
214- admin:
215- permissions:
216- create: true
217- read: true
218- update: true
219- delete: true
220-
221- user:
222- permissions:
223- create: true
224- read: true
225- update:
226- condition: "owner === $userId"
227- delete: false
228-
229- guest:
230- permissions:
231- create: false
232- read: true
233- update: false
234- delete: false
235-
236- # Field-level permissions
237- field_permissions:
238- sensitive_data:
239- roles: [admin]
240- mask: true
241-
242- internal_notes:
243- roles: [admin, user]
244-
245- # Record-level security (Row-Level Security)
246- record_permissions:
247- owner_only:
248- condition: "owner === $userId"
249- roles: [user]
250- ` ;
251-
252- case 'app' :
253- return `# ObjectQL Application Configuration
254- # Documentation: https://github.com/objectstack-ai/objectql/docs/spec/app.md
255-
256- name: ${ name }
257- label: ${ capitalizeWords ( name ) }
258- description: "${ capitalizeWords ( name ) } application"
259- version: "1.0.0"
260-
261- # Application metadata
262- metadata:
263- author: "Your Name"
264- license: "MIT"
265-
266- # Navigation and menu structure
267- navigation:
268- - label: Home
269- path: /
270- icon: home
271-
272- - label: ${ capitalizeWords ( name ) }
273- icon: database
274- children:
275- - label: List
276- path: /${ name }
277- object: ${ name }
278- - label: Create New
279- path: /${ name } /new
280- object: ${ name }
114+ function getTemplate ( context : vscode . ExtensionContext , fileType : string , name : string ) : string {
115+ try {
116+ // Check if we are running from 'out' or 'src'
117+ // Usually extension path is the root of the package.
118+
119+ let templatePath = path . join ( context . extensionPath , 'src' , 'templates' , `${ fileType } .template.yml` ) ;
120+
121+ // Fallback if not found (maybe flattened or in out)
122+ if ( ! fs . existsSync ( templatePath ) ) {
123+ templatePath = path . join ( context . extensionPath , 'out' , 'templates' , `${ fileType } .template.yml` ) ;
124+ }
281125
282- # Objects included in this app
283- objects:
284- - ${ name }
126+ if ( fs . existsSync ( templatePath ) ) {
127+ let content = fs . readFileSync ( templatePath , 'utf8' ) ;
128+ content = content . replace ( / { { name} } / g, name ) ;
129+ content = content . replace ( / { { label} } / g, capitalizeWords ( name ) ) ;
130+ return content ;
131+ }
285132
286- # Themes and branding
287- theme:
288- primary_color: "#0066cc"
289- secondary_color: "#6c757d"
290- ` ;
133+ // Fallback to hardcoded string if file read fails (Safety net)
134+ console . warn ( `Template file not found at ${ templatePath } , utilizing fallback.` ) ;
135+ return getFallbackTemplate ( fileType , name ) ;
291136
292- default :
293- return '' ;
137+ } catch ( e ) {
138+ console . error ( 'Error reading template:' , e ) ;
139+ return getFallbackTemplate ( fileType , name ) ;
294140 }
295141}
296142
143+ function getFallbackTemplate ( fileType : string , name : string ) : string {
144+ // Minimal fallback
145+ return `# ${ capitalizeWords ( name ) } ${ fileType } \nname: ${ name } \n` ;
146+ }
147+
297148/**
298- * Validate current file against schema
149+ * Validate current file by saving (triggers schema validation)
299150 */
300151async function validateCurrentFile ( ) {
301152 const editor = vscode . window . activeTextEditor ;
@@ -320,31 +171,6 @@ async function validateCurrentFile() {
320171 vscode . window . showInformationMessage ( 'Validation complete. Check Problems panel for issues.' ) ;
321172}
322173
323- /**
324- * Configure YAML language server settings for ObjectQL
325- */
326- function configureYamlLanguageServer ( ) {
327- const config = vscode . workspace . getConfiguration ( 'yaml' ) ;
328- const schemas = config . get ( 'schemas' , { } ) as Record < string , string | string [ ] > ;
329-
330- // Check if ObjectQL schemas are already configured
331- const hasObjectSchema = Object . values ( schemas ) . some ( val =>
332- ( Array . isArray ( val ) && val . some ( v => v . includes ( '*.object.yml' ) ) ) ||
333- ( typeof val === 'string' && val . includes ( '*.object.yml' ) )
334- ) ;
335-
336- if ( ! hasObjectSchema ) {
337- vscode . window . showInformationMessage (
338- 'ObjectQL extension works best with YAML language support. Please install "Red Hat YAML" extension if not already installed.' ,
339- 'Install'
340- ) . then ( ( selection : string | undefined ) => {
341- if ( selection === 'Install' ) {
342- vscode . commands . executeCommand ( 'workbench.extensions.search' , 'redhat.vscode-yaml' ) ;
343- }
344- } ) ;
345- }
346- }
347-
348174/**
349175 * Show welcome message
350176 */
0 commit comments