@sintradigital/vustack
v2.0.22
Published
App Accelerator Stack
Downloads
1,283
Keywords
Readme
Configuration
The Vustack core module is a Vue plugin. Register it in your main entry file (main.js or main.ts):
// main.js or main.ts
import Vustack from '@sintradigital/vustack'; // or 'vustack' when linked
app.use(Vustack, {
axios: yourAxiosInstance, // optional; used by schemas/settings and extensions
schemasService: { ... },
services: { storeDataService: myDataServiceInstance, ... },
renderers: [],
appendRenderers: true,
ajv: myAjvInstance,
config: {},
getVariables: () => ({ ... }),
envMap: { 'localhost:*': 'local' },
variablePrefix: 'VITE'
});Accessing the instance: The plugin exposes the Vustack instance as vustack (not $vustack) on app.config.globalProperties and via Vue's provide/inject. In Composition API use inject('vustack'); in Options API a mixin provides this.vustack. Configuration is available as inject('vustackConfig') or this.vustackConfig.
Optional plugins: The plugins directory contains optional Vue plugins (e.g. http, uimessages). Import from the package path (e.g. @sintradigital/vustack/plugins/http) and register with app.use(...) if needed.
Plugin options (VustackOptions)
| Option | Description |
|--------|-------------|
| getVariables | Function returning environment variables (default uses import.meta.env or process.env). |
| envMap | Maps host patterns to environment names (e.g. { 'localhost:*': 'local' }). |
| variablePrefix | Prefix for env vars (e.g. VITE). |
| config | Custom config object; keys can be overridden by env (see Environments). |
| services | Record of service key → instance. Each key is provide()d so components can inject(key). Data services for DataGrid are registered here. |
| renderers | Array of JSON Forms renderers. Used by JsonFormCommonEditor. |
| appendRenderers | If true (default), built-in custom renderers (apiselect, monaco, map, latlng, timezone) are appended to renderers. |
| ajv | Ajv instance for JSON Schema validation in forms. |
| schemasService | Config for schema loading: templateUi(name), templateSchema(name), optional schemas, defaultOptionsByType. |
| axios | Axios instance used by SettingsService, SchemasService, and extensions (e.g. RestDataService). |
Quick start
- Install the package:
@sintradigital/vustack(or link the submodule). - Register the plugin with at least
schemasService,services, and optionallyaxios,renderers,ajv. - Register data services (instances implementing the data source interface) under
options.serviceswith string keys. - List view:
<DataGrid :dataServiceKey="'storeDataService'" :config="gridConfig" title="Stores" labelEdit="Store" />. - Schemas: Place JSON Schema and UI schema where
templateSchema/templateUipoint; setediting.options.entity(e.g.'store') in grid config.
routing menu
The setup provides a standard configuration for routing and menus. It operates using vue-router, where the necessary information for rendering the navigation menu is included within the route metadata.
The following parameters can be used in the route metadata:
| Parameter | Description |
|---------------|-------------------------------------------------------------------------------------------------|
| title | Represents the main label of the menu item. |
| subtitle | Represents a descriptive subtitle. |
| icon | Specifies the icon in MDI format, such as mdi-information, mdi-account. |
| enabled | Indicates whether the route should be included in the menu. |
| order | Specifies a number used to sort the menu items within the navigation tree. |
Note
Currently, the menu component only supports a single-level menu. However, in the future, more complex views may be implemented, potentially including a path field in the metadata to build a hierarchical navigation tree.
A typical route is like this:
const _routes=[
{
path: '/',
name: 'home',
meta:{
enabled: true,
title: "Home",
icon: "mdi-information",
subtitle: "Subtitle",
order:1
},
component: () => import('../views/HomeView.vue'),
}
//...
];
Vustack overview and components
Vustack provides data-driven components that receive their data from data services registered when installing the plugin. Data services are provided to the app; the DataGrid receives the service via inject using the dataServiceKey prop.
Data list components
| Component | Pagination | Editing | Filters | |---------------|----------------|-------------------|-------------------------| | List View | Yes | To be tested | To be implemented | | Data Grid | Yes | Yes | Yes |
Record view components
| Component | Status | |-----------------------|-----------------------------------------------------------| | JsonFormCommonEditor | Integrated with DataGrid edit/view; schema-based forms. | | PropertyView | To be tested and integrated with the list components. |
Data sources
Data sources implement the IRestDataService interface (see Api service below). Instances are registered in plugin options under services with a string key. The DataGrid then receives the service by injecting that key via the dataServiceKey prop.
| Implementation | Description |
|------------------------|---------------------------------------------------------------------------------|
| RestDataService | Class in extensions/restDataService; standard REST protocol, configurable. |
| apiStackDataService | Implements the ApiStack API protocol. |
Recommended pattern: Create data service instances (e.g. extend RestDataService or wrap your CRUD service), register them when calling app.use(Vustack, { services: { myKey: myInstance } }). In the view, use <DataGrid :dataServiceKey="'myKey'" :config="gridConfig" ... />. The plugin provide()s each key, so the DataGrid can inject(dataServiceKey).
CRUD service and DataGrid
- dataServiceKey: DataGrid gets the data service via
inject(dataServiceKey). The key must match a service registered in pluginoptions.services(e.g. at app init). - IRestDataService: The injected service must implement
IRestDataService(seeextensions/restDataService.ts):getPagedData,getItem,getEmptyItem,insert,update,deleteItem. Optional:entityName(for default export filename) andexportCsv(params?, filename?, fields?)for CSV export. - CRUD adapter pattern: Implement a wrapper (e.g.
CrudDataService) that extendsRestDataServiceand delegates to a backend CRUD service (e.g. one extendingBaseCrudServicefrom@sintradigital/vustack/services/crud). Register the wrapper under a key (e.g.storeDataService) and pass that key asdataServiceKeyto DataGrid. - BaseCrudService (vustack): The package exposes
BaseCrudServiceand types inlib/services/crud/. The host app provides an HTTP client viainitializeInternal(httpClient); the base implementsgetById,getPaged,save,insert,update,delete,exportCsv, etc. So: the host extendsBaseCrudService, wraps it in aRestDataService-compatible adapter that implementsexportCsvandentityName, and registers that adapter inservices. - Export from grid: When the user clicks "Export CSV", DataGrid calls
dataService.exportCsv({ ids }, filename, fields)if the service exposes it. Export columns are derived fromconfig.headersandconfig.headersOverride(see Headers / exportable above).
Example: registering and using a data service
// In main.ts: create and register data services
import Vustack from '@sintradigital/vustack';
import { RestDataService } from '@sintradigital/vustack/extensions/restDataService';
const storeDataService = new RestDataService({
entity: 'store',
serviceConf: { axios: axiosInstance },
onSuccess: (msg) => toast.success(msg),
onError: (msg) => toast.error(msg)
});
app.use(Vustack, {
services: { storeDataService, ... },
// ... other options
});<!-- In a view (e.g. StoreList.vue) -->
<template>
<DataGrid
:dataServiceKey="'storeDataService'"
:config="gridConfig"
labelEdit="Store"
title="Stores"
/>
</template>
<script setup>
import DataGrid from '@sintradigital/vustack/components/DataGrid.vue';
import gridConfig from './list';
</script>dataServiceKey is required when using the inject-based pattern.
List View Component
The List View component displays paginated data from the data source. The presentation logic is entirely managed at the templating level. See the example below:
// Example of List View templating
<ListView labelEdit="Action" title="Applications" >
<template v-slot:itemTitle="{ item }">
{{item.first_name}} {{item.last_name}}
</template>
<template v-slot:itemSubTitle="{ item }">
{{item.email}} ({{item.gebder}})
</template>
</ListView>
If the editing.enabled configuration parameter is set to true, action components for editing and deleting records, as well as a button for adding new entries, will be displayed. The editing form should also be implemented at the templating level within the "edit" slot.
// Example of List View templating with editing
<ListView labelEdit="Action" title="Applications" >
//...
<template v-slot:edit="{ editingItem }">
XXX EDITING
</template>
</ListView>Data Grid Component
The DataGrid displays paginated tabular data and uses a data service injected by key. It can be configured via a config object and optional slots.
DataGrid props
| Prop | Description |
|-------------------|---------------------------------------------------------------------------------|
| title | Title for the grid (e.g. page or card title). |
| labelEdit | Label for the edit action (e.g. entity name). |
| config | Configuration object (paging, editing, view, delete, filters, headers, actions). |
| dataServiceKey | Injection key for the data service. Must match a key in options.services. Required when using inject-based data. |
| selectedItems | Optional model for selected rows (e.g. for bulk actions). |
Config sections
The config object can include: paging, editing (e.g. openingMode, fullscreen), view, delete, filters, headers, headersOverride, defaultSort, actions, selection, bottomToolbar.
Selection
When config.selection.enabled is true, the grid enables row selection (v-model on the table). The grid then exposes:
- selected: array of selected row objects.
- selectedItemsModel:
{ allSelected, allVisibleSelected, items }for bulk actions.
The bottom toolbar is shown only when at least one row is selected (selected?.length > 0). Use it for bulk actions (e.g. Export CSV) or custom actions on selected items.
Bottom toolbar
When selection is enabled and rows are selected, a toolbar appears above the table footer. It is driven by:
- config.bottomToolbar.enabled: when
true, the toolbar is shown when there are selected rows. - config.bottomToolbar.actions: e.g.
dropdownOptions,buttonOptions(default actions).
Slot override: Use the name="bottom" slot to replace the default toolbar. The slot receives: itemsPerPage, totalItems, items, selected, selectedItems, status. Example: <template #bottom="{ selected, selectedItems, ... }"> ... </template>.
Custom component: Set config.bottomToolbar.component.componentName and config.bottomToolbar.component.options to render a custom component instead of BottomGridAction. The component receives the same props and can emit applyToSelectedItems for bulk actions.
Default Export CSV: If buttonOptions does not already contain an action with action === 'exportCsv', the grid adds a default "Export CSV" button. To hide it or customize, pass buttonOptions that already includes an export action (or a no-op).
Paging
| Parameter | Description |
|-----------------|------------------------------------------------------------------------|
| itemsPerPage | Number of items displayed per page by default. |
| enabled | Pagination for the data grid cannot be disabled. |
Editing
| Parameter | Description |
|-----------------|------------------------------------------------------------------------|
| enabled | If true, enables data editing (insert and update). |
| component | Specifies the component to use for the entry/edit form. This can be any registered component or a path for dynamic loading. |
| options | Properties that will be passed to the component. |
delete
| Parameter | Description |
|-----------------|------------------------------------------------------------------------|
| enabled | If true, enables data deletion. |
| component | Specifies the component to use for the entry/edit form. This can be any registered component or a path for dynamic loading. |
| options | Properties that will be passed to the component. |
view
| Parameter | Description |
|-----------------|------------------------------------------------------------------------|
| enabled | If true, enables data view. |
| component | Specifies the component to use for the entry/edit form. This can be any registered component or a path for dynamic loading. |
| options | Properties that will be passed to the component. |
Filters
| Parameter | Description |
|-----------------|------------------------------------------------------------------------|
| enabled | If true, enables search filters. |
| component | Specifies the component to use for the filters form. This can be any registered component or a path for dynamic loading. |
| options | Properties that will be passed to the component. |
Headers
The headers configuration is an array defining the standard columns of the native Vuetify table component. Refer to the official documentation for all available options.
In addition to the standard headers, for each header you can include these custom attributes:
| Parameter | Description |
|-----------------|
| sorted | true if the column is pre sortered |
| asc | contains a constant string value |
| exportable | When false, the column is excluded from CSV export. Default is exportable. For export, column label is title ?? key and property name is key with optional item. prefix stripped. |
Header Override
The headerOverrides array in the configuration allows column customization. Any column defined in the headers section can be overriden (you can use keys not present in the model, adding fully computed fields).
There are three ways of extending a column:
- use a constant value
- use a render function
- use a ready to be used component
| Parameter | Description |
|-----------------|------------------------------------------------------------------------|
| key | it is the concatenation of type (item or header) and the key of the column (eg. header.id oritem.id) |
| component | if not empty print a component. This is an object with componentName and options fields available. Options properties are passed as props to the component. The value attribute allows to re-define the javacript expressoin for compute a custom column value, like in the render section |
| render | it is a javascript snippet with no return statement. the scope contains item,index, column, value when available. eg. value+'fdsfsf'+item.field |
| text | contains a constant string value |
| exportable | When false, the column is excluded from CSV export. Default is exportable. Export uses title ?? key as column label and key (with item. stripped) as property name. |
component,render, field are not mutually exclusive: the are rendered one above the other. Use only one at once if you need it.
Here a list of examples.
Constant value
{
key: "item.id",
text: "hello worlds"
}Render Function
{
key: "item.id",
render: "value+' myconstant'"
}Component
{
key: "item.id",
component: {
componentName:"v-alert",
options:{
text:"prova",
type:"success"
},
}
}Javascript function
Javascript functions are allowed inside render and component.value elements. Both of them have the following prototype. The parameters availability depends on the context (item or header).
The expression:
"component": {
"value":"value+' ssdfdsf'",
"componentName": "SimpleText"
}
is equivalent to:
function computeValue(item,index, column, value){
return value+' ssdfdsf';
}Default sorting
Ecco la descrizione con una tabella per i parametri:
Default Sort
The defaultSort section is an array that contains additional sorting conditions beyond those mapped directly onto the grid columns. These conditions are static and are applied before any dynamic conditions set by the data grid. This attribute allows you to enforce default sorting rules, including sorting by non-visible columns. If sorting is applied to a column already present, the values defined in defaultSort take precedence (i.e., the sorting cannot be modified by the user if specified here).
Parameters of defaultSort Elements:
| Parameter | Description | Values |
|-----------|------------------------------------|-------------------------|
| key | The name of the field | Any column field name |
| order | The sorting direction | asc (ascending), desc (descending) |
Example:
"defaultSort": [
{
"key": "routeShortName",
"order": "asc"
}
]Actions
The actions section controls the action column in the data grid (the one that contains edit, view, delete, and custom actions).
| Parameter | Description |
| ------------- | ------------------------------------------------------------------------------------------- |
| addDefaults | Defines whether the standard buttons (edit, view, delete) must be added. Default is true. |
| items | List of additional buttons to add. Each button supports the following options: |
Parameters of items
| Parameter | Description |
| ------------- | --------------------------------------------------------------------------- |
| label | Text shown as a tooltip or menu label. |
| position | Defines button placement: submenu (inside a three-dots menu) or inline. |
| icon | Material Design Icon name (e.g., "mdi-account"). |
| action | Function or string name of the function to invoke. |
| args | (Optional) Arguments to pass to the function when invoked. |
| options | (Optional) attributes trasposed to the menu item. |
Event handling
Functions can be passed directly in the configuration. Functions can be implemented inside the grid extension through component composition. Alternatively, the actionClicked event can be listened to in order to handle actions globally.
Action example
actions: {
addDefaults: true,
items: [
{
label:"New",
position: "submenu",
icon:"mdi-account",
action: function (item){
alert("Injected");
}
},
{
label:"New2",
icon:"mdi-account",
action: "new2!",
args:{
"ccc":"ddd"
}
}
]
}Full example
Below is a complete example of a configuration:
{
paging:{
itemsPerPage:4,
},
editing:{
enabled:true,
component:'JsonFormCommonEditor',
options:{
entity:'accounts'
}
},
filters: {
enabled:true,
options:{
filtersDef:{
fields:[
{
name:"campo1",
label:"Campo 1",
component :"v-text-field"
},
{
name:"campo2",
label:"Campo 2",
component :"v-switch"
},
{
name:"campo3",
label:"Campo 3",
component :"v-select",
options:{
items:[12,213,123,234]
}
}],
}
},
component: "FilterForm"
},
headers: [
{
align: 'start',
key: 'id',
sortable: false,
title: 'id',
},
{ key: 'name', title: 'Name' },
{ key: 'code', title: 'Code' },
],
actions:{
addDefaults: true,
items:[
{
label:"New",
position: "submenu",
icon:"mdi-account",
action: function (item){
alert("Injected"+JSON.stringify(item));
}
}
]
}
}Moreover, you can override filters or edit component by changing the template via slots:
<template>
<DataGrid labelEdit="Action" title="Applications" :config="config">
<template v-slot:edit="{ editingItem }">
<!-- my implementation-->
</template>
<template v-slot:filters="{ }">
<!-- my implementation-->
</template>
</DataGrid>
</template>
JsonFormCommonEditor Component
Overview
The JsonFormCommonEditor component implements a JSON form within a container that provides dual visualization modes: JSON (raw data) and form view. This dual-view feature is particularly useful for debugging or technical applications. The two views, hosted in separate tabs, are synchronized and accessible, allowing users to seamlessly switch between them. The dual-mode feature is enabled via the debug parameter.
Features
- Dual view: JSON raw data and form, synchronized in real-time.
- Debugging support: The dual-mode view, enabled by the
debugparameter, helps in identifying and resolving issues efficiently. - Tab-based layout: JSON and form views are presented in separate, easy-to-navigate tabs.
Parameters
entity
- The
entityprop is the logical name of the form. Schema and UI schema are resolved by the schemas service (vustack.services.schemas):getSchema(entity)andgetSchemaUi(entity). - The URLs are configurable via plugin options. Set
schemasService.templateSchema(name)andschemasService.templateUi(name)when installing Vustack. For example, withtemplateSchema: (name) => \/config/${name}/schema.json`andtemplateUi: (name) => `/config/${name}/uischema.json`, anentityof"store"loads/config/store/schema.jsonand/config/store/uischema.json`.
The JSON Schema defines the data structure; the UI Schema follows the JSON Forms format. The component uses vustack.options.renderers and vustack.options.ajv for rendering and validation.
Documentation
For full documentation, visit: the json form website and the UI plugin for vuetify
Demo and Materials
For a demo and additional resources, visit: Demo with examples
Example using dynamic component
Suppose to have the following data model:
{
"date": "2022-06-15",
"stringDate": "2022-06",
"stringDateFull": "2022-06-15",
"stringYear": "324"
}
The config for a dynamic component:
{
"componentName": "JsonFormCommonEditor",
"options":{
"entity":"test",
"debug":false
}
}
The JSON Schema (e.g. at the path returned by templateSchema('test')):
{
"type": "object",
"properties": {
"date": {
"type": "string",
"format": "date"
},
"stringDate": {
"type": "string"
},
"stringYear": {
"type": "string"
},
"stringDateFull": {
"type": "string"
}
}
}
The UI Schema (e.g. at the path returned by templateUi('test')):
{
"type": "Categorization",
"elements": [
{
"type": "Category",
"label": "Hide Actions",
"elements": [
{
"type": "VerticalLayout",
"elements": [
{
"type": "Group",
"label": "Schema Based",
"elements": [
{
"type": "HorizontalLayout",
"elements": [
{
"type": "Control",
"scope": "#/properties/date",
"label": "Date",
"options": {
"dateFormat": "MM/DD/YYYY",
"dateSaveFormat": "YYYY-MM-DD"
}
}
]
}
]
},
//... omissisNote: JsonFormCommonEditor can be used in the edit or view form of a DataGrid or ListView (e.g. config.editing.options.entity: 'store').
Api service
Data sources must implement the IRestDataService contract (see extensions/restDataService.ts). The RestDataService class is the default implementation. Register service instances in options.services when installing the plugin; the DataGrid injects the service using the dataServiceKey prop.
The interface is as follows (optional members support export and default filename):
{
getPagedData: async function (page, itemsPerPage, sortBy, filters) {},
getItem: async function (id, force) {},
getEmptyItem: async function () {},
insert: async function (data) {},
update: async function (data) {},
deleteItem: async function (data) {},
entityName: undefined, // optional; used for default export filename
exportCsv: async function (params, filename, fields) {} // optional; when present, Export CSV uses it
}Functionality Overview
| Method | Description |
|------------------|---------------------------------------------------------------------------------------------------------------|
| getPagedData | Returns a paginated list of data. |
| getItem | Returns a single item based on the id. If the force parameter is false, it retrieves the item from local cache if available. |
| getEmptyItem | Returns an empty item template for new records. |
| insert | Provides functionality to insert new data. |
| update | Provides functionality to update existing data. |
| deleteItem | Provides functionality to delete data. |
| entityName | Optional. Entity name for default export filename when grid title is not set. |
| exportCsv | Optional. (params?, filename?, fields?) => Promise<void>. When present, the grid calls it for Export CSV; params can include ids for selected rows. |
Hooks by Implementation
restDataSource
| Hook | Description |
|--------------------------|------------------------------------------------------------------------|
| createListRequest | Creates a request for listing data. |
| createInsertRequest | Creates a request for inserting data. |
| createUpsertRequest | Creates a request for updating or inserting data (upsert). |
| unpackGetListRequest | Unpacks the request for listing data. |
| unpackGetRequest | Unpacks the request for retrieving a single item. |
| unpackUpsertResponse | Unpacks the response from an upsert request. |
ApiStack
| Variable | Description | |-------------------------|---------------------------------------------------------------------------------------------------------------| | Entity Name | The name of the entity being managed. | | URL | The URL used for the API requests. If not specified, defaults to the base configuration. |
Renderers
Renderers are JSON Forms renderers: they map schema and UI schema to Vue components. They are used by JsonFormCommonEditor (and thus in DataGrid edit/view forms). Vustack ships with the standard Vuetify renderers plus custom renderers for specialized controls.
Built-in custom renderers
When appendRenderers is true (default), the following custom renderers are appended: apiselect (ApiSelectRender), monaco (MonacoRender), map (MapRender), latlng (LatLngRender), timezone (Timezone).
How selection works
Each custom renderer is registered via getTester (services/uiFormUtils.ts). The built-in custom renderers match when the UI schema Control has options.rendererHint equal to the hint name (e.g. "apiselect", "monaco").
Using a built-in renderer
In your UI schema, set options.rendererHint on the Control. For apiselect, options under options.apiselect include: serviceName, method, params, displayTitle, multiple, returnObject, returnPath.
Adding a custom renderer
- Implement a Vue component compatible with JSON Forms (e.g. using
useJsonFormsControl/useVuetifyControl). - Register it with
getTester('myHint', myComponent)fromservices/uiFormUtilsand push the result into your renderers array. - Pass your array in
options.rendererswithappendRenderers: true. In the UI schema, setoptions.rendererHintto"myHint"for controls that should use your renderer.
Dynamic Loading
The DynamicComponent renders a component and options determined by external configuration. Configuration can be supplied by configName (loaded via the settings service) or configSource (object or function, resolved via the reflection service).
The SettingsService loads JSON from paths like /settings/${name}.json (relative to the axios base URL). So configName: "test" loads /settings/test.json.
1. Json file (configName)
This approach uses JSON static configuration files. The file name acts as a key. For example, configName: "test" causes the settings service to fetch /settings/test.json.
Pros
- Can be served as a static asset.
- Can also be fetched from a database or other backend service.
- Lightweight and simple.
Cons
- Cannot contain code, functions, or component inclusions.
- Limited to pure JSON structures.
Example:
// Using configName with static JSON file
const _routes = [{
path: '/dynamic',
name: 'dynamic',
component: DynamicComponent,
props: {
configName: "test" // will load /settings/test.json
}
}]You can also read settings programmatically:
let config = await this.vustack.services.settings.getSettings(this.configName);Example
import settings from '../settings/jssettings.js'
const _routes = [{
path: '/dynamic',
name: 'dynamic',
component: DynamicComponent,
props: {
configSource: settings
}
}]2. JavaScript
This approach uses JavaScript modules (objects) instead of plain JSON. The configuration can therefore include functions, computed values, or reusable structures.
Pros
- Can include dynamic code and functions.
- Reusable and composable.
- Ideal when configuration needs logic.
Cons
- Must be bundled as part of the source code.
- Less flexible for runtime changes compared to static JSON.
Example
const _routes = [{
path: '/dynamic',
name: 'dynamic',
component: DynamicComponent,
props: {
configSource: () => import('../settings/jssettings.js')
}
}]
Settings structure
The configuration file or object can contain: componentName (globally registered component or dynamic path), options (props passed to the component), extension (object merged with the main component).
Note: DynamicComponent can also reference a data source via config.dataService and vustackConfig.dataSources. That pattern is legacy. For DataGrid and list views, the recommended approach is to register data services in options.services and use the dataServiceKey prop on DataGrid (provide/inject).
Full example
Below is a complete example demonstrating the loading of a DataGrid component:
// Complete example of loading a DataGrid component
{
"componentName": "DataGrid",
"extension":["restDataService"],
"options": {
"config": {
"paging": {
"itemsPerPage": 4
},
"editing": {
"enabled": true
},
"filters": {
"enabled": true,
"options": {
"filtersDef": {
"fields": [
{
"name": "routeId",
"label": "Route Id",
"component": "v-text-field"
},
{
"name": "campo1",
"label": "Campo 1",
"component": "v-text-field"
},
{
"name": "campo2",
"label": "Campo 2",
"component": "v-switch"
},
{
"name": "campo3",
"label": "Campo 3",
"component": "v-select",
"options": {
"items": [
12,
213,
123,
234
]
}
}
]
}
},
"component": "FilterForm"
},
"headers": [
{
"align": "start",
"key": "id",
"sortable": false,
"title": "id"
},
{
"key": "routeId",
"title": "Route id"
},
{
"key": "routeLongName",
"title": "Name"
},
{
"key": "routeShortName",
"title": "Code"
}
]
}
}
}
Environments and deploy
Configuration
Vustack provides dynamic configuration management to facilitate flexible deployment environments for Single Page Applications (SPA). Due to the nature of SPA applications, all environment variables need to be embedded inside the application container at runtime. For example, environment variables might be:
VITE_TEST_VARIABLE1VITE_PROD_VARIABLE
Where test and prod represent different environments.
The configuration of Vustack revolves around a few core options that allow for environment-specific behavior and dynamic retrieval of variables.
- Always ensure that all required environment variables are available at build-time since SPAs require them to be embedded into the container.
- Custom logic in
getVariablesallows for advanced configurations like fetching values from APIs or dynamically setting values based on conditions.
This configuration provides the flexibility needed to handle different environments and dynamic variable management for modern SPAs.
Configurable Options
| Option | Description | Default Value | Example |
|------------------|-----------------------------------------------------------------------------------------------------------|---------------|--------------------------------------------------------------------------------------------------|
| envMap | Maps navigation URLs to specific environments. Supports regular expressions and expects HOST:PORT format.| N/A | {'localhost': 'local', 'prod.mysite.com': 'prod'} |
| variablePrefix| Defines the prefix for environment variables based on the tool used (Vite, Webpack, Node, etc.). | VITE | Vite: VITE_TEST_VARIABLE, Webpack: WEBPACK_TEST_VARIABLE, Node: NODE_TEST_VARIABLE |
| getVariables | A custom function to retrieve environment variables. Supports dynamic variables and external system fetches.| N/A | javascript getVariables: () => ({ VITE_API_URL: process.env.VITE_API_URL }) |
Example Configuration
Here is an example of how you can configure Vustack for a typical use case:
const vustackConfig = {
...
envMap: {
'localhost': 'local',
'dev.mysite.com': 'dev',
'prod.mysite.com': 'production',
},
variablePrefix: 'VITE',
getVariables: () => {
return {
VITE_LOCAL_URL: "localhost/api",
VITE_DEV_URL: "web.server/api",
};
}
};
In this example:
- The
envMapmaps different URLs to specific environments. - The
variablePrefixis set toVITE, which would prefix all environment variables. - The
getVariablesfunction retrieves the environment variables dynamically usingprocess.env.
Branching and npm releases (contributors)
This package is released from GitHub Actions with semantic-release. Branch rules, npm dist-tags (latest vs vN-latest), and steps to add a new maintenance line are documented in the vustack repository readme — Branching and release workflow.
Project structure
The lib folder is the publishable package.
lib/
├── components/ # DataGrid, ListView, FilterForm, JsonFormCommonEditor, DynamicComponent, PropertyView, etc.
│ └── renderers/ # JSON Forms custom renderers (apiselect, monaco, map, latlng, timezone)
├── extensions/ # restDataService (RestDataService class, IRestDataService), apiStackDataService
├── plugins/ # Optional: ajv, http, uimessages, vuetify
├── services/ # settings, schemas, reflectionService, uiFormUtils, comboboxService, objectStorage
├── types/ # DataGrid.types.ts
├── index.ts # Plugin entry
└── readme.mdFolder usage: components/ – DataGrid, ListView, FilterForm, JsonFormCommonEditor, DynamicComponent; renderers/ – JSON Forms custom controls. extensions/ – Data source implementations (RestDataService, IRestDataService). plugins/ – Optional Vue plugins. services/ – settings (dynamic config), schemas (schema/uischema URLs), reflection (resolve configSource), uiFormUtils (renderer testers).
