@ronin/compiler
Advanced tools
Comparing version 0.2.1 to 0.2.2
@@ -85,2 +85,3 @@ // src/utils/index.ts | ||
// src/utils/schema.ts | ||
import title from "title"; | ||
var getSchemaBySlug = (schemas, slug) => { | ||
@@ -101,5 +102,2 @@ const schema = schemas.find((schema2) => { | ||
}; | ||
var getSchemaName = (schema) => { | ||
return schema.name || schema.slug; | ||
}; | ||
var composeMetaSchemaSlug = (suffix) => convertToCamelCase(`ronin_${suffix}`); | ||
@@ -131,3 +129,3 @@ var composeAssociationSchemaSlug = (schema, field) => composeMetaSchemaSlug(`${schema.pluralSlug}_${field.slug}`); | ||
throw new RoninError({ | ||
message: `${errorPrefix} does not exist in schema "${getSchemaName(schema)}".`, | ||
message: `${errorPrefix} does not exist in schema "${schema.name}".`, | ||
code: "FIELD_NOT_FOUND", | ||
@@ -207,3 +205,8 @@ field: fieldPath, | ||
{ slug: "type", type: "string", required: true }, | ||
{ slug: "schema", type: "reference", target: { pluralSlug: "schemas" } }, | ||
{ | ||
slug: "schema", | ||
type: "reference", | ||
target: { slug: "schema" }, | ||
required: true | ||
}, | ||
{ slug: "required", type: "boolean" }, | ||
@@ -214,3 +217,3 @@ { slug: "defaultValue", type: "string" }, | ||
// Only allowed for fields of type "reference". | ||
{ slug: "target", type: "reference", target: { pluralSlug: "schemas" } }, | ||
{ slug: "target", type: "reference", target: { slug: "schema" } }, | ||
{ slug: "kind", type: "string" }, | ||
@@ -221,6 +224,36 @@ { slug: "actions", type: "group" }, | ||
] | ||
}, | ||
{ | ||
name: "Index", | ||
pluralName: "Indexes", | ||
slug: "index", | ||
pluralSlug: "indexes", | ||
fields: [ | ||
...SYSTEM_FIELDS, | ||
{ slug: "slug", type: "string", required: true }, | ||
{ | ||
slug: "schema", | ||
type: "reference", | ||
target: { slug: "schema" }, | ||
required: true | ||
}, | ||
{ slug: "unique", type: "boolean" }, | ||
{ slug: "filter", type: "json" } | ||
] | ||
} | ||
]; | ||
var SYSTEM_SCHEMA_SLUGS = SYSTEM_SCHEMAS.flatMap(({ slug, pluralSlug }) => [ | ||
slug, | ||
pluralSlug | ||
]); | ||
var prepareSchema = (schema) => { | ||
const copiedSchema = { ...schema }; | ||
if (!copiedSchema.pluralSlug) copiedSchema.pluralSlug = pluralize(copiedSchema.slug); | ||
if (!copiedSchema.name) copiedSchema.name = slugToName(copiedSchema.slug); | ||
if (!copiedSchema.pluralName) | ||
copiedSchema.pluralName = slugToName(copiedSchema.pluralSlug); | ||
return copiedSchema; | ||
}; | ||
var addSystemSchemas = (schemas) => { | ||
const list = [...SYSTEM_SCHEMAS, ...schemas].map((schema) => ({ ...schema })); | ||
const list = [...SYSTEM_SCHEMAS, ...schemas].map(prepareSchema); | ||
for (const schema of list) { | ||
@@ -230,3 +263,3 @@ const defaultIncluding = {}; | ||
if (field.type === "reference" && !field.slug.startsWith("ronin.")) { | ||
const relatedSchema = getSchemaBySlug(list, field.target.pluralSlug); | ||
const relatedSchema = getSchemaBySlug(list, field.target.slug); | ||
let fieldSlug = relatedSchema.slug; | ||
@@ -263,3 +296,3 @@ if (field.kind === "many") { | ||
}; | ||
const relatedSchemaToModify = getSchemaBySlug(list, field.target.pluralSlug); | ||
const relatedSchemaToModify = getSchemaBySlug(list, field.target.slug); | ||
if (!relatedSchemaToModify) throw new Error("Missing related schema"); | ||
@@ -309,3 +342,3 @@ relatedSchemaToModify.including = { | ||
const actions = field.actions || {}; | ||
const targetTable = convertToSnakeCase(field.target.pluralSlug); | ||
const targetTable = convertToSnakeCase(pluralize(field.target.slug)); | ||
statement += ` REFERENCES ${targetTable}("id")`; | ||
@@ -323,14 +356,11 @@ for (const trigger in actions) { | ||
if (!["create", "set", "drop"].includes(queryType)) return; | ||
if (!["schema", "schemas", "field", "fields"].includes(querySchema)) return; | ||
if (!SYSTEM_SCHEMA_SLUGS.includes(querySchema)) return; | ||
const instructionName = mappedInstructions[queryType]; | ||
const instructionList = queryInstructions[instructionName]; | ||
const kind = ["schema", "schemas"].includes(querySchema) ? "schemas" : "fields"; | ||
const instructionTarget = kind === "schemas" ? instructionList : instructionList?.schema; | ||
const kind = getSchemaBySlug(SYSTEM_SCHEMAS, querySchema).pluralSlug; | ||
let tableAction = "ALTER"; | ||
let schemaPluralSlug = null; | ||
let queryTypeReadable = null; | ||
switch (queryType) { | ||
case "create": { | ||
if (kind === "schemas") tableAction = "CREATE"; | ||
schemaPluralSlug = instructionTarget?.pluralSlug; | ||
if (kind === "schemas" || kind === "indexes") tableAction = "CREATE"; | ||
queryTypeReadable = "creating"; | ||
@@ -341,3 +371,2 @@ break; | ||
if (kind === "schemas") tableAction = "ALTER"; | ||
schemaPluralSlug = instructionTarget?.pluralSlug?.being || instructionTarget?.pluralSlug; | ||
queryTypeReadable = "updating"; | ||
@@ -347,4 +376,3 @@ break; | ||
case "drop": { | ||
if (kind === "schemas") tableAction = "DROP"; | ||
schemaPluralSlug = instructionTarget?.pluralSlug?.being || instructionTarget?.pluralSlug; | ||
if (kind === "schemas" || kind === "indexes") tableAction = "DROP"; | ||
queryTypeReadable = "deleting"; | ||
@@ -354,14 +382,31 @@ break; | ||
} | ||
if (!schemaPluralSlug) { | ||
const field = kind === "schemas" ? "pluralSlug" : "schema.pluralSlug"; | ||
const slug = instructionList?.slug?.being || instructionList?.slug; | ||
if (!slug) { | ||
throw new RoninError({ | ||
message: `When ${queryTypeReadable} ${kind}, a \`${field}\` field must be provided in the \`${instructionName}\` instruction.`, | ||
message: `When ${queryTypeReadable} ${kind}, a \`slug\` field must be provided in the \`${instructionName}\` instruction.`, | ||
code: "MISSING_FIELD", | ||
fields: [field] | ||
fields: ["slug"] | ||
}); | ||
} | ||
const table = convertToSnakeCase(schemaPluralSlug); | ||
const fields = [...SYSTEM_FIELDS]; | ||
let statement = `${tableAction} TABLE "${table}"`; | ||
const schemaInstruction = instructionList?.schema; | ||
const schemaSlug = schemaInstruction?.slug?.being || schemaInstruction?.slug; | ||
if (kind !== "schemas" && !schemaSlug) { | ||
throw new RoninError({ | ||
message: `When ${queryTypeReadable} ${kind}, a \`schema.slug\` field must be provided in the \`${instructionName}\` instruction.`, | ||
code: "MISSING_FIELD", | ||
fields: ["schema.slug"] | ||
}); | ||
} | ||
const tableName = convertToSnakeCase(pluralize(kind === "schemas" ? slug : schemaSlug)); | ||
if (kind === "indexes") { | ||
const indexName = convertToSnakeCase(slug); | ||
const unique = instructionList?.unique; | ||
let statement2 = `${tableAction}${unique ? " UNIQUE" : ""} INDEX "${indexName}"`; | ||
if (queryType === "create") statement2 += ` ON "${tableName}"`; | ||
writeStatements.push(statement2); | ||
return; | ||
} | ||
let statement = `${tableAction} TABLE "${tableName}"`; | ||
if (kind === "schemas") { | ||
const fields = [...SYSTEM_FIELDS]; | ||
if (queryType === "create") { | ||
@@ -371,17 +416,12 @@ const columns = fields.map(getFieldStatement).filter(Boolean); | ||
} else if (queryType === "set") { | ||
const newSlug = queryInstructions.to?.pluralSlug; | ||
const newSlug = queryInstructions.to?.slug; | ||
if (newSlug) { | ||
const newTable = convertToSnakeCase(newSlug); | ||
const newTable = convertToSnakeCase(pluralize(newSlug)); | ||
statement += ` RENAME TO "${newTable}"`; | ||
} | ||
} | ||
} else if (kind === "fields") { | ||
const fieldSlug = instructionTarget?.slug?.being || instructionList?.slug; | ||
if (!fieldSlug) { | ||
throw new RoninError({ | ||
message: `When ${queryTypeReadable} fields, a \`slug\` field must be provided in the \`${instructionName}\` instruction.`, | ||
code: "MISSING_FIELD", | ||
fields: ["slug"] | ||
}); | ||
} | ||
writeStatements.push(statement); | ||
return; | ||
} | ||
if (kind === "fields") { | ||
if (queryType === "create") { | ||
@@ -399,10 +439,26 @@ if (!instructionList.type) { | ||
if (newSlug) { | ||
statement += ` RENAME COLUMN "${fieldSlug}" TO "${newSlug}"`; | ||
statement += ` RENAME COLUMN "${slug}" TO "${newSlug}"`; | ||
} | ||
} else if (queryType === "drop") { | ||
statement += ` DROP COLUMN "${fieldSlug}"`; | ||
statement += ` DROP COLUMN "${slug}"`; | ||
} | ||
writeStatements.push(statement); | ||
} | ||
writeStatements.push(statement); | ||
}; | ||
var slugToName = (slug) => { | ||
const name = slug.replace(/([a-z])([A-Z])/g, "$1 $2"); | ||
return title(name); | ||
}; | ||
var VOWELS = ["a", "e", "i", "o", "u"]; | ||
var pluralize = (word) => { | ||
const lastLetter = word.slice(-1).toLowerCase(); | ||
const secondLastLetter = word.slice(-2, -1).toLowerCase(); | ||
if (lastLetter === "y" && !VOWELS.includes(secondLastLetter)) { | ||
return `${word.slice(0, -1)}ies`; | ||
} | ||
if (lastLetter === "s" || word.slice(-2).toLowerCase() === "ch" || word.slice(-2).toLowerCase() === "sh" || word.slice(-2).toLowerCase() === "ex") { | ||
return `${word}es`; | ||
} | ||
return `${word}s`; | ||
}; | ||
@@ -527,3 +583,3 @@ // src/instructions/with.ts | ||
} else { | ||
const relatedSchema = getSchemaBySlug(schemas, schemaField.target.pluralSlug); | ||
const relatedSchema = getSchemaBySlug(schemas, schemaField.target.slug); | ||
const subQuery = { | ||
@@ -692,3 +748,3 @@ get: { | ||
throw new RoninError({ | ||
message: `The provided \`for\` shortcut "${shortcut}" does not exist in schema "${getSchemaName(schema)}".`, | ||
message: `The provided \`for\` shortcut "${shortcut}" does not exist in schema "${schema.name}".`, | ||
code: "INVALID_FOR_VALUE" | ||
@@ -725,3 +781,3 @@ }); | ||
throw new RoninError({ | ||
message: `The provided \`including\` shortcut "${shortcut}" does not exist in schema "${getSchemaName(schema)}".`, | ||
message: `The provided \`including\` shortcut "${shortcut}" does not exist in schema "${schema.name}".`, | ||
code: "INVALID_INCLUDING_VALUE" | ||
@@ -728,0 +784,0 @@ }); |
{ | ||
"name": "@ronin/compiler", | ||
"version": "0.2.1", | ||
"version": "0.2.2", | ||
"type": "module", | ||
@@ -31,3 +31,4 @@ "description": "Compiles RONIN queries to SQL statements.", | ||
"dependencies": { | ||
"@paralleldrive/cuid2": "2.2.2" | ||
"@paralleldrive/cuid2": "2.2.2", | ||
"title": "3.5.3" | ||
}, | ||
@@ -37,2 +38,3 @@ "devDependencies": { | ||
"@types/bun": "1.1.10", | ||
"@types/title": "3.4.3", | ||
"tsup": "8.3.0", | ||
@@ -39,0 +41,0 @@ "typescript": "5.6.2", |
@@ -52,3 +52,2 @@ # RONIN Compiler | ||
{ | ||
pluralSlug: 'accounts', | ||
slug: 'account', | ||
@@ -55,0 +54,0 @@ }, |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
362297
5847
2
6
83
+ Addedtitle@3.5.3
+ Addedansi-styles@3.2.1(transitive)
+ Addedarch@2.2.0(transitive)
+ Addedarg@1.0.0(transitive)
+ Addedchalk@2.3.0(transitive)
+ Addedclipboardy@1.2.2(transitive)
+ Addedcolor-convert@1.9.3(transitive)
+ Addedcolor-name@1.1.3(transitive)
+ Addedcross-spawn@5.1.0(transitive)
+ Addedescape-string-regexp@1.0.5(transitive)
+ Addedexeca@0.8.0(transitive)
+ Addedget-stream@3.0.0(transitive)
+ Addedhas-flag@2.0.0(transitive)
+ Addedis-stream@1.1.0(transitive)
+ Addedisexe@2.0.0(transitive)
+ Addedlru-cache@4.1.5(transitive)
+ Addednpm-run-path@2.0.2(transitive)
+ Addedp-finally@1.0.0(transitive)
+ Addedpath-key@2.0.1(transitive)
+ Addedpseudomap@1.0.2(transitive)
+ Addedshebang-command@1.2.0(transitive)
+ Addedshebang-regex@1.0.0(transitive)
+ Addedsignal-exit@3.0.7(transitive)
+ Addedstrip-eof@1.0.0(transitive)
+ Addedsupports-color@4.5.0(transitive)
+ Addedtitle@3.5.3(transitive)
+ Addedtitleize@1.0.0(transitive)
+ Addedwhich@1.3.1(transitive)
+ Addedyallist@2.1.2(transitive)