Skip to content

Commit

Permalink
refactor types to handle multiple importer / exporter
Browse files Browse the repository at this point in the history
  • Loading branch information
felixhaeberle committed Jul 29, 2024
1 parent 23908a9 commit fd41ed9
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 38 deletions.
18 changes: 5 additions & 13 deletions inlang/source-code/sdk-v2/src/types/module.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
import type { ProjectSettings2 } from "./project-settings.js"
import type { ImportFunction } from "../resolve-modules/import.js"
import { Plugin2, type ResolvePlugins2Function, type ResolvedPlugin2Api } from "./plugin.js"
import { MessageBundleLintRule } from "./lint.js"
import type { ModuleHasNoExportsError, ModuleImportError } from "./module-errors.js"
import type { resolveMessageBundleLintRules } from "../resolveMessageBundleLintRules.js"
import { Type } from "@sinclair/typebox"

/**
* An inlang module has a default export that is either a plugin or a message lint rule.
* An inlang plugin module has a default export that is a plugin.
*
* @example
* export default myPlugin
*/
// not using Static<infer T> here because the type is not inferred correctly
// due to type overwrites in modules.
export type InlangModule = { default: Plugin2 | MessageBundleLintRule }
export const InlangModule = Type.Object({
default: Type.Union([Plugin2, MessageBundleLintRule]),
export type InlangPlugin = { default: Plugin2 }
export const InlangPlugin = Type.Object({
default: Plugin2,
})

/**
Expand Down Expand Up @@ -47,16 +45,12 @@ export type ResolveModule2Function = (args: {
/**
* The resolved item id of the module.
*/
id: Plugin2["id"] | MessageBundleLintRule["id"]
id: Plugin2["id"]
}>
/**
* The resolved plugins.
*/
plugins: Array<Plugin2>
/**
* The resolved message lint rules.
*/
messageBundleLintRules: Array<MessageBundleLintRule>
/**
* The resolved api provided by plugins.
*/
Expand All @@ -67,13 +61,11 @@ export type ResolveModule2Function = (args: {
* This includes errors from:
* - importing module
* - resolving plugins
* - resolving lint rules
* - resolving the runtime plugin api
*/
errors: Array<
| ModuleHasNoExportsError
| ModuleImportError
| Awaited<ReturnType<ResolvePlugins2Function>>["errors"][number]
| Awaited<ReturnType<typeof resolveMessageBundleLintRules>>["errors"][number]
>
}>
53 changes: 28 additions & 25 deletions inlang/source-code/sdk-v2/src/types/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ import type {
import { NestedBundle } from "./schema.js"
import { TranslationFile, type TranslationFile as TranslationFileType } from "./translation-file.js"

export const PluginId = Type.String({
pattern: "^plugin\\.([a-z][a-zA-Z0-9]*)\\.([a-z][a-zA-Z0-9]*(?:[A-Z][a-z0-9]*)*)$",
examples: ["plugin.namespace.id"],
}) as unknown as TTemplateLiteral<[TLiteral<`plugin.${string}.${string}`>]>
export type PluginId = Static<typeof PluginId>

// ---------------------------- RUNTIME VALIDATION TYPES ---------------------------------------------

/**
Expand All @@ -33,13 +39,13 @@ import { TranslationFile, type TranslationFile as TranslationFileType } from "./
* You can use your own settings by extending the plugin with a generic:
*
* ```ts
* type PluginSettings = {
* filePath: string
* }
* type PluginSettings = {
* filePath: string
* }
*
* const plugin: Plugin<{
* "plugin.your.id": PluginSettings
* }>
* const plugin: Plugin<{
* "plugin.your.id": PluginSettings
* }>
* ```
*/
export type Plugin2<
Expand Down Expand Up @@ -67,9 +73,9 @@ export type Plugin2<
*
* @example
* addCustomApi: () => ({
* "app.inlang.ide-extension": {
* messageReferenceMatcher: () => {}
* }
* "app.inlang.ide-extension": {
* messageReferenceMatcher: () => {}
* }
* })
*/
addCustomApi?: (args: {
Expand All @@ -80,14 +86,11 @@ export type Plugin2<
}

export const Plugin2 = Type.Object({
id: Type.String({
pattern: "^plugin\\.([a-z][a-zA-Z0-9]*)\\.([a-z][a-zA-Z0-9]*(?:[A-Z][a-z0-9]*)*)$",
examples: ["plugin.namespace.id"],
}) as unknown as TTemplateLiteral<[TLiteral<`plugin.${string}.${string}`>]>,
id: PluginId,
displayName: Translatable(Type.String()),
description: Translatable(Type.String()),
/**
* Tyepbox must be used to validate the Json Schema.
* Typebox must be used to validate the Json Schema.
* Github discussion to upvote a plain Json Schema validator and read the benefits of Typebox
* https://github.com/opral/monorepo/discussions/1503
*/
Expand Down Expand Up @@ -144,25 +147,25 @@ export type ResolvePlugins2Function = (args: {
*/
export type ResolvedPlugin2Api = {
/**
* Importer / Exporter functions.
* * Importer / Exporter functions.
* see https://linear.app/opral/issue/MESDK-157/sdk-v2-release-on-sqlite
*/
toBeImportedFiles: Array<Plugin2["toBeImportedFiles"]>
importFiles: Array<Plugin2["importFiles"]>
exportFiles: Array<Plugin2["exportFiles"]>
toBeImportedFiles: Record<PluginId, Plugin2["toBeImportedFiles"] | undefined>
importFiles: Record<PluginId, Plugin2["importFiles"] | undefined>
exportFiles: Record<PluginId, Plugin2["exportFiles"] | undefined>
/**
* App specific APIs.
*
* @example
* // define
* customApi: ({ settings }) => ({
* "app.inlang.ide-extension": {
* messageReferenceMatcher: () => {
* // use settings
* settings.pathPattern
* return
* }
* }
* "app.inlang.ide-extension": {
* messageReferenceMatcher: () => {
* // use settings
* settings.pathPattern
* return
* }
* }
* })
* // use
* customApi['app.inlang.ide-extension'].messageReferenceMatcher()
Expand Down

0 comments on commit fd41ed9

Please sign in to comment.