diff --git a/packages/idea-transformer/tests/Transformer.test.ts b/packages/idea-transformer/tests/Transformer.test.ts index d869fc7..6dd11f6 100644 --- a/packages/idea-transformer/tests/Transformer.test.ts +++ b/packages/idea-transformer/tests/Transformer.test.ts @@ -9,6 +9,7 @@ import { TypeConfig } from '@stackpress/idea-parser'; //resusable variables const cwd = __dirname; const idea = path.resolve(cwd, 'schema.idea'); +const use = path.resolve(cwd, 'use.idea'); describe('Transformer Tests', () => { it('Should get processed schema', () => { @@ -92,7 +93,15 @@ describe('Transformer Tests', () => { expect(parentType.attributes).to.deep.equal({ name: 'parent' }); }); - + it('Should allow use json file into an idea file', () => { + const transformerIdea = new Transformer(idea, { cwd }); + const transformerJson = new Transformer(use, { cwd }); + // Get the final schemas + const useIdea = transformerIdea.schema; + const useJson = transformerJson.schema; + // Check if the merged json file is deeply equal to the merged idea file + expect(useJson).to.deep.equal(useIdea); + }); }); \ No newline at end of file diff --git a/packages/idea-transformer/tests/another.json b/packages/idea-transformer/tests/another.json new file mode 100644 index 0000000..7b97529 --- /dev/null +++ b/packages/idea-transformer/tests/another.json @@ -0,0 +1,584 @@ +{ + "prop": { + "Config": { + "module": "another-idea" + } + }, + "enum": { + "Roles": { + "OWNER": "owner", + "MODERATOR": "moderator", + "MEMBER": "member" + } + }, + "type": { + "Address": { + "name": "Address", + "mutable": true, + "attributes": { + "label": [ + "Address", + "Addresses" + ], + "suggested": [ + "[name]" + ], + "icon": [ + "map-marker" + ] + }, + "columns": [ + { + "type": "String", + "name": "name", + "required": true, + "multiple": false, + "attributes": { + "label": [ + "Name" + ], + "field.text": true, + "is.required": [ + "Name is required" + ], + "list.detail": true, + "view.text": true + } + }, + { + "type": "Contact", + "name": "contact", + "required": true, + "multiple": false, + "attributes": { + "label": [ + "Contact" + ] + } + }, + { + "type": "String", + "name": "email", + "required": false, + "multiple": false, + "attributes": { + "label": [ + "Contact Email Address" + ], + "field.email": true, + "is.email": [ + "Should be a valid email address" + ], + "view.email": true + } + }, + { + "type": "String", + "name": "phone", + "required": false, + "multiple": false, + "attributes": { + "label": [ + "Contact Phone Number" + ], + "field.text": true, + "is.pattern": [ + "/^\\+[0-9]{0,3} [0-9]+$/", + "Should be a valid phone number" + ], + "view.phone": true + } + }, + { + "type": "String", + "name": "unit", + "required": false, + "multiple": false, + "attributes": { + "label": [ + "Unit Number" + ], + "field.text": true, + "list.text": true, + "view.text": true + } + }, + { + "type": "String", + "name": "building", + "required": false, + "multiple": false, + "attributes": { + "label": [ + "Building Name" + ], + "field.text": true, + "list.text": true, + "view.text": true + } + }, + { + "type": "String", + "name": "street", + "required": true, + "multiple": false, + "attributes": { + "label": [ + "Street Address" + ], + "field.text": true, + "is.required": [ + "Street is required" + ], + "list.text": true, + "view.text": true + } + }, + { + "type": "String", + "name": "neighborhood", + "required": false, + "multiple": false, + "attributes": { + "label": [ + "Neighborhood" + ], + "field.text": true, + "list.text": true, + "view.text": true + } + }, + { + "type": "String", + "name": "city", + "required": true, + "multiple": false, + "attributes": { + "label": [ + "City" + ], + "filterable": true, + "field.text": true, + "is.required": [ + "City is required" + ], + "list.text": true, + "view.text": true + } + }, + { + "type": "String", + "name": "state", + "required": false, + "multiple": false, + "attributes": { + "label": [ + "State" + ], + "filterable": true, + "field.text": true, + "list.text": true, + "view.text": true + } + }, + { + "type": "String", + "name": "region", + "required": false, + "multiple": false, + "attributes": { + "label": [ + "Region" + ], + "filterable": true, + "field.text": true, + "list.text": true, + "view.text": true + } + }, + { + "type": "String", + "name": "country", + "required": true, + "multiple": false, + "attributes": { + "label": [ + "Country" + ], + "filterable": true, + "field.country": true, + "is.required": [ + "Country is required" + ], + "list.text": true, + "view.text": true + } + }, + { + "type": "String", + "name": "postal", + "required": true, + "multiple": false, + "attributes": { + "label": [ + "Postal Code" + ], + "filterable": true, + "field.text": true, + "is.required": [ + "Postal Code is required" + ], + "list.text": true, + "view.text": true + } + }, + { + "type": "String", + "name": "notes", + "required": false, + "multiple": false, + "attributes": { + "label": [ + "Notes" + ], + "field.textarea": true, + "view.text": true + } + }, + { + "type": "Float", + "name": "latitude", + "required": false, + "multiple": false, + "attributes": { + "label": [ + "Latitude" + ] + } + }, + { + "type": "Float", + "name": "longitude", + "required": false, + "multiple": false, + "attributes": { + "label": [ + "Longitude" + ] + } + } + ] + }, + "Contact": { + "name": "Contact", + "mutable": true, + "attributes": { + "label": [ + "Contact", + "Contacts" + ], + "suggested": [ + "[name]" + ], + "icon": [ + "map-marker" + ] + }, + "columns": [ + { + "type": "String", + "name": "name", + "required": true, + "multiple": false, + "attributes": { + "label": [ + "Name" + ], + "field.text": true, + "is.required": [ + "Name is required" + ], + "list.detail": true, + "view.text": true + } + }, + { + "type": "String", + "name": "email", + "required": false, + "multiple": false, + "attributes": { + "label": [ + "Email Address" + ], + "field.email": true, + "is.email": [ + "Should be a valid email address" + ], + "view.email": true + } + }, + { + "type": "String", + "name": "phone", + "required": false, + "multiple": false, + "attributes": { + "label": [ + "Phone Number" + ], + "field.text": true, + "is.pattern": [ + "/^\\+[0-9]{0,3} [0-9]+$/", + "Should be a valid phone number" + ], + "view.phone": true + } + } + ] + } + }, + "model": { + "Profile": { + "name": "Profile", + "mutable": true, + "attributes": { + "label": [ + "Profile", + "Profiles" + ], + "suggested": [ + "[name]" + ], + "icon": [ + "user" + ] + }, + "columns": [ + { + "type": "String", + "name": "id", + "required": true, + "multiple": false, + "attributes": { + "label": [ + "ID" + ], + "id": true, + "generated": true, + "default": [ + "cuid()" + ], + "list.char": [ + { + "hellip": false, + "length": 8 + } + ] + } + }, + { + "type": "String", + "name": "name", + "required": true, + "multiple": false, + "attributes": { + "label": [ + "Name" + ], + "searchable": true, + "field.text": true, + "is.required": [ + "Name is required" + ], + "list.detail": true, + "view.text": true + } + }, + { + "type": "Address", + "name": "addresses", + "required": true, + "multiple": true, + "attributes": { + "label": [ + "Addresses" + ], + "default": [ + "[]" + ] + } + } + ] + }, + "File": { + "name": "File", + "mutable": true, + "attributes": { + "label": [ + "File", + "Files" + ], + "suggested": [ + "[name]" + ], + "icon": [ + "file" + ] + }, + "columns": [ + { + "type": "String", + "name": "id", + "required": true, + "multiple": false, + "attributes": { + "label": [ + "ID" + ], + "id": true, + "generated": true, + "default": [ + "cuid()" + ], + "list.char": [ + { + "hellip": false, + "length": 8 + } + ] + } + }, + { + "type": "String", + "name": "name", + "required": true, + "multiple": false, + "attributes": { + "label": [ + "Name" + ], + "searchable": true, + "field.text": true, + "is.required": [ + "Name is required" + ], + "list.detail": true, + "view.text": true + } + }, + { + "type": "String", + "name": "url", + "required": true, + "multiple": false, + "attributes": { + "label": [ + "URL" + ], + "searchable": true, + "field.url": true, + "is.required": [ + "URL is required" + ], + "view.link": true + } + }, + { + "type": "String", + "name": "tags", + "required": true, + "multiple": true, + "attributes": { + "label": [ + "Tags" + ], + "field.tags": true, + "list.hide": true, + "view.tags": true + } + }, + { + "type": "Hash", + "name": "references", + "required": false, + "multiple": false, + "attributes": { + "label": [ + "References" + ], + "field.metadata": true, + "list.hide": true, + "view.metadata": true + } + }, + { + "type": "Boolean", + "name": "active", + "required": true, + "multiple": false, + "attributes": { + "label": [ + "Active" + ], + "generated": true, + "active": true, + "default": [ + true + ], + "list.yesno": true, + "view.yesno": true + } + }, + { + "type": "Datetime", + "name": "created", + "required": true, + "multiple": false, + "attributes": { + "label": [ + "Created" + ], + "generated": true, + "created": true, + "spanable": true, + "sortable": true, + "default": [ + "now()" + ], + "list.date": [ + "m d, Y h:iA" + ], + "view.date": [ + "m d, Y h:iA" + ] + } + }, + { + "type": "Datetime", + "name": "updated", + "required": true, + "multiple": false, + "attributes": { + "label": [ + "Updated" + ], + "generated": true, + "updated": true, + "spanable": true, + "sortable": true, + "default": [ + "now()" + ], + "list.date": [ + "m d, Y h:iA" + ], + "view.date": [ + "m d, Y h:iA" + ] + } + } + ] + } + } +} \ No newline at end of file diff --git a/packages/idea-transformer/tests/use.idea b/packages/idea-transformer/tests/use.idea new file mode 100644 index 0000000..d0fb665 --- /dev/null +++ b/packages/idea-transformer/tests/use.idea @@ -0,0 +1,226 @@ +plugin "./in/make-enums" { + lang "ts" + output "./out/enums.ts" +} + +use "./another.json" + +//--------------------------------------------------------------------// +// User System + +//A profile can be a person, organization, or any other type of entity. +//Profiles can be authenticated or added from various sources. That's +//why we call it profile instead of user and company indicating it's +//just a general information of an entity. + +model Profile @label("Profile" "Profiles") @suggested("[name]") @icon("user") { + name String @label("Full Name") + @searchable + @field.text + @is.required("Name is required") + @list.detail @view.text + + image String? @label("Image") + @field.url + @list.image({ width 20 height 20 }) + @view.image({ width 100 height 100 }) + + description String? @label("Description") + @field.textarea + @list.none @view.text + + type String? @label("Type") + @default("person") + @filterable + @field.text + @list.lowercase @view.lowercase + + roles String[] @label("Roles") + @field.textlist + @list.hide + @view.tags + + tags String[] @label("Tags") + @field.tags + @list.hide + @view.tags + + references Hash? @label("References") + @field.metadata + @list.hide + @view.metadata + + active Boolean @label("Active") + @generated @active @default(true) + @list.hide @view.yesno + + created Datetime @label("Created") + @generated @created @spanable @sortable @default("now()") + @list.date("m d, Y h:iA") + @view.date("m d, Y h:iA") + + updated Datetime @label("Updated") + @generated @updated @spanable @sortable @default("now()") + @list.date("m d, Y h:iA") + @view.date("m d, Y h:iA") + + auth Auth? @label("Auth") + connections Connection[] @label("Connections") + memberships Connection[] @label("Memberships") + files File[] @label("Files") +} + +//Auth is used to authenticate a profile and create a session. +model Auth @label("Auth" "Auths") @suggested("[username]") @icon("lock") { + id String @label("ID") + @id @generated @default("cuid()") + @list.char({ hellip false length 8 }) + + profileId String @label("Profile") + @filterable + @field.relation("Profile" "id") + @is.required("Profile is required") + @list.relation("Profile") + @view.relation("Profile") + + username String @label("Username") + @unique @searchable @filterable + @field.text + @is.required("Username is required") + @is.cge(5 "Should more than 5 characters") + @list.detail @view.text + + email String? @label("Email Address") + @unique @searchable @filterable + @field.email + @is.email("Should be a valid email address") + @list.text @view.email + + phone String? @label("Phone Number") + @unique @searchable @filterable + @field.text + @is.pattern("/^\+[0-9]{0,3} [0-9]+$/" "Should be a valid phone number") + @list.text @view.phone + + password String @label("Password") + @field.password + @is.required("Password is required") + + twofa String? @label("2FA") + @field.text + + verified Int @label("Verified") + @generated @default(0) //0=unverified, 1=email, 2=phone, 3=both + + lastLogin Datetime @label("Last Logged In") + @generated @default("now()") + @list.date("m d, Y h:iA") + @view.date("m d, Y h:iA") + + active Boolean @label("Active") + @generated @active @default(true) + @list.yesno @view.yesno + + created Datetime @label("Created") + @generated @created @spanable @sortable @default("now()") + @list.date("m d, Y h:iA") + @view.date("m d, Y h:iA") + + updated Datetime @label("Updated") + @generated @updated @spanable @sortable @default("now()") + @list.date("m d, Y h:iA") + @view.date("m d, Y h:iA") + + profile Profile @relation({ local "profileId" foreign "id" }) +} + +//--------------------------------------------------------------------// +// Connection System + +//A connection is a list of connections between profiles +// ie. company, network, group, organization, etc. +// to do a company setup, make a company profile, then add members to it. + +model Connection @label("Connection" "Connections") @suggested("[owner.name] - [member.name]") @icon("users") { + ownerId String @label("Owner") + @id @relation("Profile" "id") + @is.required("Owner is required") + + memberId String @label("Member") + @id @relation("Profile" "id") + @is.required("Member is required") + + role Roles @label("Role") + @default("MEMBER") + @field.text + + tags String[] @label("Tags") + @field.tags + @list.hide + @view.tags + + active Boolean @label("Active") + @generated @active @default(true) + @list.yesno @view.yesno + + created Datetime @label("Created") + @generated @created @spanable @sortable @default("now()") + @list.date("m d, Y h:iA") + @view.date("m d, Y h:iA") + + updated Datetime @label("Updated") + @generated @updated @spanable @sortable @default("now()") + @list.date("m d, Y h:iA") + @view.date("m d, Y h:iA") + + owner Profile @relation({ name "connections" local "ownerId" foreign "id" }) + member Profile @relation({ name "memberships" local "memberId" foreign "id" }) +} + +//--------------------------------------------------------------------// +// File System + +model File! @label("File" "Files") @suggested("[name]") @icon("file") { + //FIELDS: + id String @label("ID") + @id @generated @default("cuid()") + @list.char({ hellip false length 8 }) + + profileId String @label("Profile") @filterable + @field.relation("Profile" "id") + @is.required("Profile is required") + + name String @label("Name") + @searchable + @field.text + @is.required("Name is required") + @list.detail @view.text + + url String @label("URL") + @searchable + @field.url + @is.required("URL is required") + @view.link + + tags String[] @label("Tags") + @field.tags + @list.hide + @view.tags + + active Boolean @label("Active") + @generated @active @default(true) + @list.yesno @view.yesno + + created Datetime @label("Created") + @generated @created @spanable @sortable @default("now()") + @list.date("m d, Y h:iA") + @view.date("m d, Y h:iA") + + updated Datetime @label("Updated") + @generated @updated @spanable @sortable @default("now()") + @list.date("m d, Y h:iA") + @view.date("m d, Y h:iA") + + profile Profile @relation({ local "profileId" foreign "id" }) +} +