Skip to content

Commit

Permalink
update resolveModules2 & resolvePlugins2
Browse files Browse the repository at this point in the history
  • Loading branch information
felixhaeberle committed Jul 29, 2024
1 parent fd41ed9 commit 3d5c782
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 79 deletions.
23 changes: 7 additions & 16 deletions inlang/source-code/sdk-v2/src/resolveModules2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,23 @@ import {
ModuleSettingsAreInvalidError,
} from "./resolve-modules/errors.js"
import { tryCatch } from "@inlang/result"
import { resolveMessageBundleLintRules } from "./resolveMessageBundleLintRules.js"
import { resolvePlugins2 } from "./resolvePlugins2.js"
import { TypeCompiler } from "@sinclair/typebox/compiler"
import { validatedModuleSettings } from "./validatedModuleSettings.js"
import type { Plugin2 } from "./types/plugin.js"
import { InlangModule, type ResolveModule2Function } from "./types/module.js"
import type { MessageBundleLintRule } from "./types/lint.js"
import { InlangPlugin, type ResolveModule2Function } from "./types/module.js"

const ModuleCompiler = TypeCompiler.Compile(InlangModule)
const ModuleCompiler = TypeCompiler.Compile(InlangPlugin)

export const resolveModules: ResolveModule2Function = async (args) => {
const _import = args._import

const allPlugins: Array<Plugin2> = []
const allMessageLintRules: Array<MessageBundleLintRule> = []
const meta: Awaited<ReturnType<ResolveModule2Function>>["meta"] = []
const moduleErrors: Array<ModuleError> = []

async function resolveModule(module: string) {
const importedModule = await tryCatch<InlangModule>(() => _import(module))
const importedModule = await tryCatch<InlangPlugin>(() => _import(module))

// -- FAILED TO IMPORT --
if (importedModule.error) {
Expand All @@ -48,9 +45,9 @@ export const resolveModules: ResolveModule2Function = async (args) => {
return
}

// -- CHECK IF MODULE IS SYNTACTIALLY VALID
// -- CHECK IF MODULE IS SYNTACTICALLY VALID
const isValidModule = ModuleCompiler.Check(importedModule.data)
if (isValidModule === false) {
if (!isValidModule) {
const errors = [...ModuleCompiler.Errors(importedModule.data)]
moduleErrors.push(
new ModuleExportIsInvalidError({
Expand All @@ -63,7 +60,6 @@ export const resolveModules: ResolveModule2Function = async (args) => {
}

// -- VALIDATE MODULE SETTINGS

const result = validatedModuleSettings({
settingsSchema: importedModule.data.default.settingsSchema,
moduleSettings: (args.settings as any)[importedModule.data.default.id],
Expand All @@ -80,12 +76,10 @@ export const resolveModules: ResolveModule2Function = async (args) => {

if (importedModule.data.default.id.startsWith("plugin.")) {
allPlugins.push(importedModule.data.default as Plugin2)
} else if (importedModule.data.default.id.startsWith("messageBundleLintRule.")) {
allMessageLintRules.push(importedModule.data.default as MessageBundleLintRule)
} else {
moduleErrors.push(
new ModuleError(
`Unimplemented module type ${importedModule.data.default.id}.The module has not been installed.`,
`Unimplemented module type ${importedModule.data.default.id}. The module has not been installed.`,
{ module: module }
)
)
Expand All @@ -98,13 +92,10 @@ export const resolveModules: ResolveModule2Function = async (args) => {
settings: args.settings,
})

const resolvedLintRules = resolveMessageBundleLintRules({ messageLintRules: allMessageLintRules })

return {
meta,
messageBundleLintRules: allMessageLintRules,
plugins: allPlugins,
resolvedPluginApi: resolvedPlugins.data,
errors: [...moduleErrors, ...resolvedLintRules.errors, ...resolvedPlugins.errors],
errors: [...moduleErrors, ...resolvedPlugins.errors],
}
}
97 changes: 34 additions & 63 deletions inlang/source-code/sdk-v2/src/resolvePlugins2.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import type { ResolvePlugins2Function } from "./types/index.js"
import { Plugin } from "@inlang/plugin"
import {
PluginReturnedInvalidCustomApiError,
PluginImportFilesFunctionAlreadyDefinedError,
Expand All @@ -13,33 +11,24 @@ import {
import { deepmerge } from "deepmerge-ts"
import { TypeCompiler } from "@sinclair/typebox/compiler"
import { tryCatch } from "@inlang/result"
import { Plugin2 } from "./types/plugin.js"

// @ts-ignore - type mismatch error
const PluginCompiler = TypeCompiler.Compile(Plugin)
const PluginCompiler = TypeCompiler.Compile(Plugin2)

export const resolvePlugins2: ResolvePlugins2Function = async (args) => {
const result: Awaited<ReturnType<ResolvePlugins2Function>> = {
data: {
toBeImportedFiles: undefined as any,
importFiles: undefined as any,
exportFiles: undefined as any,
toBeImportedFiles: {},
importFiles: {},
exportFiles: {},
customApi: {},
},
errors: [],
}

const experimentalPersistence = !!args.settings.experimental?.persistence
if (experimentalPersistence) {
// debug("Using experimental persistence")
}

for (const plugin of args.plugins) {
const errors = [...PluginCompiler.Errors(plugin)]

/**
* -------------- RESOLVE PLUGIN --------------
*/

// -- INVALID ID in META --
const hasInvalidId = errors.some((error) => error.path === "/id")
if (hasInvalidId) {
Expand All @@ -56,25 +45,35 @@ export const resolvePlugins2: ResolvePlugins2Function = async (args) => {
)
}

// -- ALREADY DEFINED IMPORTFILES / EXPORTFILES / DETECTEDLANGUAGETAGS --
if (
typeof plugin.toBeImportedFiles === "function" &&
result.data.toBeImportedFiles !== undefined
) {
result.errors.push(new PluginToBeImportedFilesFunctionAlreadyDefinedError({ id: plugin.id }))
// -- CHECK FOR ALREADY DEFINED FUNCTIONS --
if (typeof plugin.toBeImportedFiles === "function") {
if (result.data.toBeImportedFiles[plugin.id]) {
result.errors.push(
new PluginToBeImportedFilesFunctionAlreadyDefinedError({ id: plugin.id })
)
} else {
result.data.toBeImportedFiles[plugin.id] = plugin.toBeImportedFiles
}
}

if (typeof plugin.importFiles === "function" && result.data.importFiles !== undefined) {
result.errors.push(new PluginImportFilesFunctionAlreadyDefinedError({ id: plugin.id }))
if (typeof plugin.importFiles === "function") {
if (result.data.importFiles[plugin.id]) {
result.errors.push(new PluginImportFilesFunctionAlreadyDefinedError({ id: plugin.id }))
} else {
result.data.importFiles[plugin.id] = plugin.importFiles
}
}

if (typeof plugin.exportFiles === "function" && result.data.exportFiles !== undefined) {
result.errors.push(new PluginExportFilesFunctionAlreadyDefinedError({ id: plugin.id }))
if (typeof plugin.exportFiles === "function") {
if (result.data.exportFiles[plugin.id]) {
result.errors.push(new PluginExportFilesFunctionAlreadyDefinedError({ id: plugin.id }))
} else {
result.data.exportFiles[plugin.id] = plugin.exportFiles
}
}

// --- ADD APP SPECIFIC API ---
// -- ADD APP SPECIFIC API --
if (typeof plugin.addCustomApi === "function") {
// TODO: why do we call this function 2 times (here for validation and later for retrieving the actual value)?
const { data: customApi, error } = tryCatch(() =>
plugin.addCustomApi!({
settings: args.settings,
Expand All @@ -89,50 +88,22 @@ export const resolvePlugins2: ResolvePlugins2Function = async (args) => {
cause: new Error(`The return value must be an object. Received "${typeof customApi}".`),
})
)
} else {
result.data.customApi = deepmerge(result.data.customApi, customApi)
}
}

// -- CONTINUE IF ERRORS --
if (result.errors.length > 0) {
if (errors.length > 0) {
continue
}

/**
* -------------- BEGIN ADDING TO RESULT --------------
*/

if (typeof plugin.toBeImportedFiles === "function") {
result.data.toBeImportedFiles = [
...(result.data.toBeImportedFiles ?? []),
plugin.toBeImportedFiles,
]
}

if (typeof plugin.importFiles === "function") {
result.data.importFiles = [...(result.data.importFiles ?? []), plugin.importFiles]
}

if (typeof plugin.exportFiles === "function") {
result.data.exportFiles = [...(result.data.exportFiles ?? []), plugin.exportFiles]
}

if (typeof plugin.addCustomApi === "function") {
const { data: customApi } = tryCatch(() =>
plugin.addCustomApi!({
settings: args.settings,
})
)
if (customApi) {
result.data.customApi = deepmerge(result.data.customApi, customApi)
}
}
}

// --- LOADMESSAGE / SAVEMESSAGE NOT DEFINED ---

// -- IMPORT / EXPORT NOT DEFINED FOR ANY PLUGIN --
if (
!experimentalPersistence &&
(typeof result.data.importFiles !== "function" || typeof result.data.exportFiles !== "function")
Object.keys(result.data.toBeImportedFiles).length === 0 &&
Object.keys(result.data.importFiles).length === 0 &&
Object.keys(result.data.exportFiles).length === 0
) {
result.errors.push(new PluginsDoNotProvideImportOrExportFilesError())
}
Expand Down

0 comments on commit 3d5c782

Please sign in to comment.