@inlang/sdk 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapter/solidAdapter.d.ts +2 -2
- package/dist/adapter/solidAdapter.d.ts.map +1 -1
- package/dist/adapter/solidAdapter.js +2 -2
- package/dist/adapter/solidAdapter.test.js +68 -78
- package/dist/api.d.ts +10 -6
- package/dist/api.d.ts.map +1 -1
- package/dist/api.test-d.d.ts +2 -0
- package/dist/api.test-d.d.ts.map +1 -0
- package/dist/api.test-d.js +4 -0
- package/dist/createMessageLintReportsQuery.d.ts +2 -2
- package/dist/createMessageLintReportsQuery.d.ts.map +1 -1
- package/dist/createMessageLintReportsQuery.js +11 -11
- package/dist/createMessagesQuery.js +1 -1
- package/dist/errors.d.ts +3 -3
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +6 -6
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/lint/message/lintMessages.d.ts +3 -7
- package/dist/lint/message/lintMessages.d.ts.map +1 -1
- package/dist/lint/message/lintMessages.test.js +38 -36
- package/dist/lint/message/lintSingleMessage.d.ts +3 -7
- package/dist/lint/message/lintSingleMessage.d.ts.map +1 -1
- package/dist/lint/message/lintSingleMessage.js +10 -10
- package/dist/lint/message/lintSingleMessage.test.js +71 -65
- package/dist/{openInlangProject.d.ts → loadProject.d.ts} +3 -3
- package/dist/loadProject.d.ts.map +1 -0
- package/dist/{openInlangProject.js → loadProject.js} +70 -66
- package/dist/loadProject.test.d.ts +2 -0
- package/dist/loadProject.test.d.ts.map +1 -0
- package/dist/{openInlangProject.test.js → loadProject.test.js} +160 -176
- package/dist/parseConfig.d.ts +2 -2
- package/dist/parseConfig.d.ts.map +1 -1
- package/dist/parseConfig.js +3 -3
- package/dist/resolve-modules/import.js +1 -1
- package/dist/resolve-modules/message-lint-rules/resolveMessageLintRules.js +1 -1
- package/dist/resolve-modules/plugins/errors.d.ts +1 -1
- package/dist/resolve-modules/plugins/errors.d.ts.map +1 -1
- package/dist/resolve-modules/plugins/resolvePlugins.js +15 -15
- package/dist/resolve-modules/plugins/resolvePlugins.test.js +55 -94
- package/dist/resolve-modules/plugins/types.d.ts +1 -1
- package/dist/resolve-modules/plugins/types.d.ts.map +1 -1
- package/dist/resolve-modules/plugins/types.test.js +10 -14
- package/dist/resolve-modules/resolveModules.d.ts.map +1 -1
- package/dist/resolve-modules/resolveModules.js +9 -9
- package/dist/resolve-modules/resolveModules.test.js +28 -42
- package/dist/resolve-modules/types.d.ts +3 -3
- package/dist/resolve-modules/types.d.ts.map +1 -1
- package/dist/versionedInterfaces.d.ts +1 -1
- package/dist/versionedInterfaces.d.ts.map +1 -1
- package/dist/versionedInterfaces.js +1 -1
- package/package.json +3 -3
- package/src/adapter/solidAdapter.test.ts +77 -87
- package/src/adapter/solidAdapter.ts +4 -4
- package/src/api.test-d.ts +8 -0
- package/src/api.ts +10 -6
- package/src/createMessageLintReportsQuery.ts +15 -20
- package/src/createMessagesQuery.ts +1 -1
- package/src/errors.ts +6 -6
- package/src/index.ts +4 -4
- package/src/lint/message/lintMessages.test.ts +38 -36
- package/src/lint/message/lintMessages.ts +3 -11
- package/src/lint/message/lintSingleMessage.test.ts +71 -65
- package/src/lint/message/lintSingleMessage.ts +13 -21
- package/src/{openInlangProject.test.ts → loadProject.test.ts} +165 -181
- package/src/{openInlangProject.ts → loadProject.ts} +81 -82
- package/src/parseConfig.ts +5 -3
- package/src/resolve-modules/import.ts +1 -1
- package/src/resolve-modules/message-lint-rules/resolveMessageLintRules.ts +1 -1
- package/src/resolve-modules/plugins/errors.ts +1 -1
- package/src/resolve-modules/plugins/resolvePlugins.test.ts +55 -94
- package/src/resolve-modules/plugins/resolvePlugins.ts +19 -19
- package/src/resolve-modules/plugins/types.test.ts +11 -15
- package/src/resolve-modules/plugins/types.ts +1 -1
- package/src/resolve-modules/resolveModules.test.ts +29 -43
- package/src/resolve-modules/resolveModules.ts +11 -9
- package/src/resolve-modules/types.ts +3 -3
- package/src/versionedInterfaces.ts +1 -1
- package/dist/openInlangProject.d.ts.map +0 -1
- package/dist/openInlangProject.test.d.ts +0 -2
- package/dist/openInlangProject.test.d.ts.map +0 -1
|
@@ -7,11 +7,10 @@ import type {
|
|
|
7
7
|
} from "./api.js"
|
|
8
8
|
import { type ImportFunction, resolveModules } from "./resolve-modules/index.js"
|
|
9
9
|
import { TypeCompiler } from "@sinclair/typebox/compiler"
|
|
10
|
-
import { Value } from "@sinclair/typebox/value"
|
|
11
10
|
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
ProjectSettingsFileJSONSyntaxError,
|
|
12
|
+
ProjectSettingsFileNotFoundError,
|
|
13
|
+
ProjectSettingsInvalidError,
|
|
15
14
|
PluginLoadMessagesError,
|
|
16
15
|
PluginSaveMessagesError,
|
|
17
16
|
} from "./errors.js"
|
|
@@ -19,10 +18,11 @@ import { createRoot, createSignal, createEffect } from "./reactivity/solid.js"
|
|
|
19
18
|
import { createMessagesQuery } from "./createMessagesQuery.js"
|
|
20
19
|
import { debounce } from "throttle-debounce"
|
|
21
20
|
import { createMessageLintReportsQuery } from "./createMessageLintReportsQuery.js"
|
|
22
|
-
import {
|
|
21
|
+
import { ProjectSettings, Message, type NodeishFilesystemSubset } from "./versionedInterfaces.js"
|
|
23
22
|
import { tryCatch, type Result } from "@inlang/result"
|
|
23
|
+
import { migrateIfOutdated } from "@inlang/project-settings/migration"
|
|
24
24
|
|
|
25
|
-
const
|
|
25
|
+
const settingsCompiler = TypeCompiler.Compile(ProjectSettings)
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* Creates an inlang instance.
|
|
@@ -31,8 +31,8 @@ const ConfigCompiler = TypeCompiler.Compile(ProjectConfig)
|
|
|
31
31
|
* and supporting legacy resolvedModules such as CJS.
|
|
32
32
|
*
|
|
33
33
|
*/
|
|
34
|
-
export const
|
|
35
|
-
|
|
34
|
+
export const loadProject = async (args: {
|
|
35
|
+
settingsFilePath: string
|
|
36
36
|
nodeishFs: NodeishFilesystemSubset
|
|
37
37
|
_import?: ImportFunction
|
|
38
38
|
_capture?: (id: string, props: Record<string, unknown>) => void
|
|
@@ -40,34 +40,34 @@ export const openInlangProject = async (args: {
|
|
|
40
40
|
return await createRoot(async () => {
|
|
41
41
|
const [initialized, markInitAsComplete, markInitAsFailed] = createAwaitable()
|
|
42
42
|
|
|
43
|
-
// --
|
|
43
|
+
// -- settings ------------------------------------------------------------
|
|
44
44
|
|
|
45
|
-
const [
|
|
45
|
+
const [settings, _setSettings] = createSignal<ProjectSettings>()
|
|
46
46
|
createEffect(() => {
|
|
47
|
-
|
|
48
|
-
.then((
|
|
49
|
-
|
|
50
|
-
args._capture?.("SDK used
|
|
47
|
+
loadSettings({ settingsFilePath: args.settingsFilePath, nodeishFs: args.nodeishFs })
|
|
48
|
+
.then((settings) => {
|
|
49
|
+
setSettings(settings)
|
|
50
|
+
args._capture?.("SDK used settings", settings)
|
|
51
51
|
})
|
|
52
52
|
.catch((err) => {
|
|
53
53
|
markInitAsFailed(err)
|
|
54
54
|
})
|
|
55
55
|
})
|
|
56
|
-
// TODO: create FS watcher and update
|
|
56
|
+
// TODO: create FS watcher and update settings on change
|
|
57
57
|
|
|
58
|
-
const
|
|
59
|
-
|
|
58
|
+
const writeSettingsToDisk = skipFirst((settings: ProjectSettings) =>
|
|
59
|
+
_writeSettingsToDisk({ nodeishFs: args.nodeishFs, settings }),
|
|
60
60
|
)
|
|
61
61
|
|
|
62
|
-
const
|
|
62
|
+
const setSettings = (settings: ProjectSettings): Result<void, ProjectSettingsInvalidError> => {
|
|
63
63
|
try {
|
|
64
|
-
const
|
|
65
|
-
|
|
64
|
+
const validatedSettings = parseSettings(settings)
|
|
65
|
+
_setSettings(validatedSettings)
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
writeSettingsToDisk(validatedSettings)
|
|
68
68
|
return { data: undefined }
|
|
69
69
|
} catch (error: unknown) {
|
|
70
|
-
if (error instanceof
|
|
70
|
+
if (error instanceof ProjectSettingsInvalidError) {
|
|
71
71
|
return { error }
|
|
72
72
|
}
|
|
73
73
|
|
|
@@ -81,10 +81,10 @@ export const openInlangProject = async (args: {
|
|
|
81
81
|
createSignal<Awaited<ReturnType<typeof resolveModules>>>()
|
|
82
82
|
|
|
83
83
|
createEffect(() => {
|
|
84
|
-
const
|
|
85
|
-
if (!
|
|
84
|
+
const _settings = settings()
|
|
85
|
+
if (!_settings) return
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
resolveModules({ settings: _settings, nodeishFs: args.nodeishFs, _import: args._import })
|
|
88
88
|
.then((resolvedModules) => {
|
|
89
89
|
setResolvedModules(resolvedModules)
|
|
90
90
|
|
|
@@ -95,12 +95,12 @@ export const openInlangProject = async (args: {
|
|
|
95
95
|
|
|
96
96
|
// -- messages ----------------------------------------------------------
|
|
97
97
|
|
|
98
|
-
let
|
|
99
|
-
createEffect(() => (
|
|
98
|
+
let settingsValue: ProjectSettings
|
|
99
|
+
createEffect(() => (settingsValue = settings()!)) // workaround to not run effects twice (e.g. settings change + modules change) (I'm sure there exists a solid way of doing this, but I haven't found it yet)
|
|
100
100
|
|
|
101
101
|
const [messages, setMessages] = createSignal<Message[]>()
|
|
102
102
|
createEffect(() => {
|
|
103
|
-
const conf =
|
|
103
|
+
const conf = settings()
|
|
104
104
|
if (!conf) return
|
|
105
105
|
|
|
106
106
|
const _resolvedModules = resolvedModules()
|
|
@@ -113,8 +113,8 @@ export const openInlangProject = async (args: {
|
|
|
113
113
|
|
|
114
114
|
makeTrulyAsync(
|
|
115
115
|
_resolvedModules.resolvedPluginApi.loadMessages({
|
|
116
|
-
languageTags:
|
|
117
|
-
sourceLanguageTag:
|
|
116
|
+
languageTags: settingsValue!.languageTags,
|
|
117
|
+
sourceLanguageTag: settingsValue!.sourceLanguageTag,
|
|
118
118
|
}),
|
|
119
119
|
)
|
|
120
120
|
.then((messages) => {
|
|
@@ -133,14 +133,14 @@ export const openInlangProject = async (args: {
|
|
|
133
133
|
return resolvedModules()!.messageLintRules.map(
|
|
134
134
|
(rule) =>
|
|
135
135
|
({
|
|
136
|
-
|
|
136
|
+
id: rule.id,
|
|
137
|
+
displayName: rule.displayName,
|
|
138
|
+
description: rule.description,
|
|
137
139
|
module:
|
|
138
|
-
resolvedModules()?.meta.find((m) => m.id.includes(rule.
|
|
140
|
+
resolvedModules()?.meta.find((m) => m.id.includes(rule.id))?.module ??
|
|
139
141
|
"Unknown module. You stumbled on a bug in inlang's source code. Please open an issue.",
|
|
140
|
-
|
|
141
142
|
// default to warning, see https://github.com/inlang/monorepo/issues/1254
|
|
142
|
-
|
|
143
|
-
configValue.settings["project.messageLintRuleLevels"]?.[rule.meta.id] ?? "warning",
|
|
143
|
+
level: settingsValue["messageLintRuleLevels"]?.[rule.id] ?? "warning",
|
|
144
144
|
} satisfies InstalledMessageLintRule),
|
|
145
145
|
) satisfies Array<InstalledMessageLintRule>
|
|
146
146
|
}
|
|
@@ -148,9 +148,11 @@ export const openInlangProject = async (args: {
|
|
|
148
148
|
const installedPlugins = () => {
|
|
149
149
|
if (!resolvedModules()) return []
|
|
150
150
|
return resolvedModules()!.plugins.map((plugin) => ({
|
|
151
|
-
|
|
151
|
+
id: plugin.id,
|
|
152
|
+
displayName: plugin.displayName,
|
|
153
|
+
description: plugin.description,
|
|
152
154
|
module:
|
|
153
|
-
resolvedModules()?.meta.find((m) => m.id.includes(plugin.
|
|
155
|
+
resolvedModules()?.meta.find((m) => m.id.includes(plugin.id))?.module ??
|
|
154
156
|
"Unknown module. You stumbled on a bug in inlang's source code. Please open an issue.",
|
|
155
157
|
})) satisfies Array<InstalledPlugin>
|
|
156
158
|
}
|
|
@@ -162,7 +164,7 @@ export const openInlangProject = async (args: {
|
|
|
162
164
|
const messagesQuery = createMessagesQuery(() => messages() || [])
|
|
163
165
|
const lintReportsQuery = createMessageLintReportsQuery(
|
|
164
166
|
messages,
|
|
165
|
-
|
|
167
|
+
settings as () => ProjectSettings,
|
|
166
168
|
installedMessageLintRules,
|
|
167
169
|
resolvedModules,
|
|
168
170
|
)
|
|
@@ -172,7 +174,7 @@ export const openInlangProject = async (args: {
|
|
|
172
174
|
500,
|
|
173
175
|
async (newMessages) => {
|
|
174
176
|
try {
|
|
175
|
-
await resolvedModules()
|
|
177
|
+
await resolvedModules()?.resolvedPluginApi.saveMessages({ messages: newMessages })
|
|
176
178
|
} catch (err) {
|
|
177
179
|
throw new PluginSaveMessagesError("Error in saving messages", {
|
|
178
180
|
cause: err,
|
|
@@ -204,8 +206,8 @@ export const openInlangProject = async (args: {
|
|
|
204
206
|
// have a query error exposed
|
|
205
207
|
//...(lintErrors() ?? []),
|
|
206
208
|
]),
|
|
207
|
-
|
|
208
|
-
|
|
209
|
+
settings: createSubscribable(() => settings() as ProjectSettings),
|
|
210
|
+
setSettings,
|
|
209
211
|
customApi: createSubscribable(() => resolvedModules()?.resolvedPluginApi.customApi || {}),
|
|
210
212
|
query: {
|
|
211
213
|
messages: messagesQuery,
|
|
@@ -219,70 +221,67 @@ export const openInlangProject = async (args: {
|
|
|
219
221
|
|
|
220
222
|
// ------------------------------------------------------------------------------------------------
|
|
221
223
|
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
+
const loadSettings = async (args: {
|
|
225
|
+
settingsFilePath: string
|
|
224
226
|
nodeishFs: NodeishFilesystemSubset
|
|
225
227
|
}) => {
|
|
226
|
-
const { data:
|
|
227
|
-
async () => await args.nodeishFs.readFile(args.
|
|
228
|
+
const { data: settingsFile, error: settingsFileError } = await tryCatch(
|
|
229
|
+
async () => await args.nodeishFs.readFile(args.settingsFilePath, { encoding: "utf-8" }),
|
|
228
230
|
)
|
|
229
|
-
if (
|
|
230
|
-
throw new
|
|
231
|
-
`Could not locate
|
|
231
|
+
if (settingsFileError)
|
|
232
|
+
throw new ProjectSettingsFileNotFoundError(
|
|
233
|
+
`Could not locate settings file in (${args.settingsFilePath}).`,
|
|
232
234
|
{
|
|
233
|
-
cause:
|
|
235
|
+
cause: settingsFileError,
|
|
234
236
|
},
|
|
235
237
|
)
|
|
236
238
|
|
|
237
|
-
const
|
|
238
|
-
if (parseConfigError)
|
|
239
|
-
throw new ProjectFileJSONSyntaxError(`The config is not a valid JSON file.`, {
|
|
240
|
-
cause: parseConfigError,
|
|
241
|
-
})
|
|
242
|
-
return validateConfig(parsedConfig)
|
|
243
|
-
}
|
|
239
|
+
const json = tryCatch(() => JSON.parse(settingsFile!))
|
|
244
240
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
throw new InvalidConfigError(`The config is invalid according to the schema.`, {
|
|
249
|
-
cause: typeErrors,
|
|
241
|
+
if (json.error) {
|
|
242
|
+
throw new ProjectSettingsFileJSONSyntaxError(`The settings is not a valid JSON file.`, {
|
|
243
|
+
cause: json.error,
|
|
250
244
|
})
|
|
251
245
|
}
|
|
246
|
+
return parseSettings(json.data)
|
|
247
|
+
}
|
|
252
248
|
|
|
253
|
-
|
|
254
|
-
|
|
249
|
+
const parseSettings = (settings: unknown) => {
|
|
250
|
+
const withMigration = migrateIfOutdated(settings as any)
|
|
251
|
+
if (settingsCompiler.Check(withMigration) === false) {
|
|
252
|
+
const typeErrors = [...settingsCompiler.Errors(settings)]
|
|
253
|
+
if (typeErrors.length > 0) {
|
|
254
|
+
throw new ProjectSettingsInvalidError(`The settings is invalid according to the schema.`, {
|
|
255
|
+
cause: typeErrors,
|
|
256
|
+
})
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return withMigration
|
|
255
260
|
}
|
|
256
261
|
|
|
257
|
-
const
|
|
262
|
+
const _writeSettingsToDisk = async (args: {
|
|
258
263
|
nodeishFs: NodeishFilesystemSubset
|
|
259
|
-
|
|
264
|
+
settings: ProjectSettings
|
|
260
265
|
}) => {
|
|
261
|
-
const { data:
|
|
266
|
+
const { data: serializedSettings, error: serializeSettingsError } = tryCatch(() =>
|
|
262
267
|
// TODO: this will probably not match the original formatting
|
|
263
|
-
JSON.stringify(args.
|
|
268
|
+
JSON.stringify(args.settings, undefined, 2),
|
|
264
269
|
)
|
|
265
|
-
if (
|
|
270
|
+
if (serializeSettingsError) {
|
|
271
|
+
throw serializeSettingsError
|
|
272
|
+
}
|
|
266
273
|
|
|
267
|
-
const { error:
|
|
268
|
-
args.nodeishFs.writeFile("./project.inlang.json",
|
|
274
|
+
const { error: writeSettingsError } = await tryCatch(async () =>
|
|
275
|
+
args.nodeishFs.writeFile("./project.inlang.json", serializedSettings),
|
|
269
276
|
)
|
|
270
|
-
|
|
277
|
+
|
|
278
|
+
if (writeSettingsError) {
|
|
279
|
+
throw writeSettingsError
|
|
280
|
+
}
|
|
271
281
|
}
|
|
272
282
|
|
|
273
283
|
// ------------------------------------------------------------------------------------------------
|
|
274
284
|
|
|
275
|
-
const loadModules = async (args: {
|
|
276
|
-
config: ProjectConfig
|
|
277
|
-
nodeishFs: NodeishFilesystemSubset
|
|
278
|
-
_import?: ImportFunction
|
|
279
|
-
}) =>
|
|
280
|
-
resolveModules({
|
|
281
|
-
config: args.config,
|
|
282
|
-
nodeishFs: args.nodeishFs,
|
|
283
|
-
_import: args._import,
|
|
284
|
-
})
|
|
285
|
-
|
|
286
285
|
const createAwaitable = () => {
|
|
287
286
|
let resolve: () => void
|
|
288
287
|
let reject: () => void
|
package/src/parseConfig.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ProjectSettings } from "./versionedInterfaces.js"
|
|
2
2
|
import type { Result } from "@inlang/result"
|
|
3
3
|
import { TypeCompiler } from "@sinclair/typebox/compiler"
|
|
4
4
|
|
|
@@ -13,9 +13,11 @@ export class ParseConfigError extends Error {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
// @ts-ignore - fix after refactor
|
|
16
|
-
const ConfigCompiler = TypeCompiler.Compile(
|
|
16
|
+
const ConfigCompiler = TypeCompiler.Compile(ProjectSettings)
|
|
17
17
|
|
|
18
|
-
export const
|
|
18
|
+
export const parseSettings = (
|
|
19
|
+
config: ProjectSettings,
|
|
20
|
+
): Result<ProjectSettings, ParseConfigError> => {
|
|
19
21
|
if (ConfigCompiler.Check(config)) {
|
|
20
22
|
return {
|
|
21
23
|
data: config,
|
|
@@ -10,7 +10,7 @@ export const resolveMessageLintRules = (args: { messageLintRules: Array<MessageL
|
|
|
10
10
|
for (const rule of args.messageLintRules) {
|
|
11
11
|
if (Value.Check(MessageLintRule, rule) === false) {
|
|
12
12
|
result.errors.push(
|
|
13
|
-
new MessageLintRuleIsInvalidError(`Couldn't parse lint rule "${rule.
|
|
13
|
+
new MessageLintRuleIsInvalidError(`Couldn't parse lint rule "${rule.id}"`, {
|
|
14
14
|
module: "not implemented",
|
|
15
15
|
}),
|
|
16
16
|
)
|
|
@@ -15,17 +15,12 @@ import type { Plugin } from "@inlang/plugin"
|
|
|
15
15
|
describe("generally", () => {
|
|
16
16
|
it("should return an error if a plugin uses an invalid id", async () => {
|
|
17
17
|
const mockPlugin: Plugin = {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
displayName: { en: "My plugin" },
|
|
23
|
-
},
|
|
18
|
+
// @ts-expect-error - invalid id
|
|
19
|
+
id: "no-namespace",
|
|
20
|
+
description: { en: "My plugin description" },
|
|
21
|
+
displayName: { en: "My plugin" },
|
|
24
22
|
loadMessages: () => undefined as any,
|
|
25
23
|
saveMessages: () => undefined as any,
|
|
26
|
-
addCustomApi() {
|
|
27
|
-
return {}
|
|
28
|
-
},
|
|
29
24
|
}
|
|
30
25
|
|
|
31
26
|
const resolved = await resolvePlugins({
|
|
@@ -39,11 +34,9 @@ describe("generally", () => {
|
|
|
39
34
|
|
|
40
35
|
it("should return an error if a plugin uses APIs that are not available", async () => {
|
|
41
36
|
const mockPlugin: Plugin = {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
displayName: { en: "My plugin" },
|
|
46
|
-
},
|
|
37
|
+
id: "plugin.namespace.undefinedApi",
|
|
38
|
+
description: { en: "My plugin description" },
|
|
39
|
+
displayName: { en: "My plugin" },
|
|
47
40
|
// @ts-expect-error the key is not available in type
|
|
48
41
|
nonExistentKey: {
|
|
49
42
|
nonexistentOptions: "value",
|
|
@@ -63,11 +56,9 @@ describe("generally", () => {
|
|
|
63
56
|
|
|
64
57
|
it("should not initialize a plugin that uses the 'inlang' namespace except for inlang whitelisted plugins", async () => {
|
|
65
58
|
const mockPlugin: Plugin = {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
displayName: { en: "My plugin" },
|
|
70
|
-
},
|
|
59
|
+
id: "plugin.inlang.notWhitelisted",
|
|
60
|
+
description: { en: "My plugin description" },
|
|
61
|
+
displayName: { en: "My plugin" },
|
|
71
62
|
loadMessages: () => undefined as any,
|
|
72
63
|
}
|
|
73
64
|
|
|
@@ -84,11 +75,9 @@ describe("generally", () => {
|
|
|
84
75
|
describe("loadMessages", () => {
|
|
85
76
|
it("should load messages from a local source", async () => {
|
|
86
77
|
const mockPlugin: Plugin = {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
displayName: { en: "My plugin" },
|
|
91
|
-
},
|
|
78
|
+
id: "plugin.namespace.placeholder",
|
|
79
|
+
description: { en: "My plugin description" },
|
|
80
|
+
displayName: { en: "My plugin" },
|
|
92
81
|
loadMessages: async () => [{ id: "test", expressions: [], selectors: [], variants: [] }],
|
|
93
82
|
}
|
|
94
83
|
|
|
@@ -108,19 +97,15 @@ describe("loadMessages", () => {
|
|
|
108
97
|
|
|
109
98
|
it("should collect an error if function is defined twice in multiple plugins", async () => {
|
|
110
99
|
const mockPlugin: Plugin = {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
displayName: { en: "My plugin" },
|
|
115
|
-
},
|
|
100
|
+
id: "plugin.namepsace.loadMessagesFirst",
|
|
101
|
+
description: { en: "My plugin description" },
|
|
102
|
+
displayName: { en: "My plugin" },
|
|
116
103
|
loadMessages: async () => undefined as any,
|
|
117
104
|
}
|
|
118
105
|
const mockPlugin2: Plugin = {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
displayName: { en: "My plugin" },
|
|
123
|
-
},
|
|
106
|
+
id: "plugin.namepsace.loadMessagesSecond",
|
|
107
|
+
description: { en: "My plugin description" },
|
|
108
|
+
displayName: { en: "My plugin" },
|
|
124
109
|
loadMessages: async () => undefined as any,
|
|
125
110
|
}
|
|
126
111
|
|
|
@@ -135,11 +120,9 @@ describe("loadMessages", () => {
|
|
|
135
120
|
|
|
136
121
|
it("should return an error if no plugin defines loadMessages", async () => {
|
|
137
122
|
const mockPlugin: Plugin = {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
displayName: { en: "My plugin" },
|
|
142
|
-
},
|
|
123
|
+
id: "plugin.namepsace.loadMessagesFirst",
|
|
124
|
+
description: { en: "My plugin description" },
|
|
125
|
+
displayName: { en: "My plugin" },
|
|
143
126
|
saveMessages: async () => undefined as any,
|
|
144
127
|
}
|
|
145
128
|
|
|
@@ -157,11 +140,9 @@ describe("loadMessages", () => {
|
|
|
157
140
|
describe("saveMessages", () => {
|
|
158
141
|
it("should save messages to a local source", async () => {
|
|
159
142
|
const mockPlugin: Plugin = {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
displayName: { en: "My plugin" },
|
|
164
|
-
},
|
|
143
|
+
id: "plugin.namespace.placeholder",
|
|
144
|
+
description: { en: "My plugin description" },
|
|
145
|
+
displayName: { en: "My plugin" },
|
|
165
146
|
loadMessages: async () => undefined as any,
|
|
166
147
|
saveMessages: async () => undefined as any,
|
|
167
148
|
}
|
|
@@ -177,19 +158,15 @@ describe("saveMessages", () => {
|
|
|
177
158
|
|
|
178
159
|
it("should collect an error if function is defined twice in multiple plugins", async () => {
|
|
179
160
|
const mockPlugin: Plugin = {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
displayName: { en: "My plugin" },
|
|
184
|
-
},
|
|
161
|
+
id: "plugin.namepsace.saveMessages",
|
|
162
|
+
description: { en: "My plugin description" },
|
|
163
|
+
displayName: { en: "My plugin" },
|
|
185
164
|
saveMessages: async () => undefined as any,
|
|
186
165
|
}
|
|
187
166
|
const mockPlugin2: Plugin = {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
displayName: { en: "My plugin" },
|
|
192
|
-
},
|
|
167
|
+
id: "plugin.namepsace.saveMessages2",
|
|
168
|
+
description: { en: "My plugin description" },
|
|
169
|
+
displayName: { en: "My plugin" },
|
|
193
170
|
|
|
194
171
|
saveMessages: async () => undefined as any,
|
|
195
172
|
}
|
|
@@ -205,11 +182,9 @@ describe("saveMessages", () => {
|
|
|
205
182
|
|
|
206
183
|
it("should return an error if no plugin defines saveMessages", async () => {
|
|
207
184
|
const mockPlugin: Plugin = {
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
displayName: { en: "My plugin" },
|
|
212
|
-
},
|
|
185
|
+
id: "plugin.namepsace.loadMessagesFirst",
|
|
186
|
+
description: { en: "My plugin description" },
|
|
187
|
+
displayName: { en: "My plugin" },
|
|
213
188
|
loadMessages: async () => undefined as any,
|
|
214
189
|
}
|
|
215
190
|
|
|
@@ -226,22 +201,18 @@ describe("saveMessages", () => {
|
|
|
226
201
|
describe("detectedLanguageTags", () => {
|
|
227
202
|
it("should merge language tags from plugins", async () => {
|
|
228
203
|
const mockPlugin: Plugin = {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
displayName: { en: "My plugin" },
|
|
233
|
-
},
|
|
204
|
+
id: "plugin.namepsace.detectedLanguageTags",
|
|
205
|
+
description: { en: "My plugin description" },
|
|
206
|
+
displayName: { en: "My plugin" },
|
|
234
207
|
detectedLanguageTags: async () => ["de", "en"],
|
|
235
208
|
addCustomApi: () => {
|
|
236
209
|
return {}
|
|
237
210
|
},
|
|
238
211
|
}
|
|
239
212
|
const mockPlugin2: Plugin = {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
displayName: { en: "My plugin" },
|
|
244
|
-
},
|
|
213
|
+
id: "plugin.namepsace.detectedLanguageTags2",
|
|
214
|
+
description: { en: "My plugin description" },
|
|
215
|
+
displayName: { en: "My plugin" },
|
|
245
216
|
addCustomApi: () => {
|
|
246
217
|
return {}
|
|
247
218
|
},
|
|
@@ -261,11 +232,9 @@ describe("detectedLanguageTags", () => {
|
|
|
261
232
|
describe("addCustomApi", () => {
|
|
262
233
|
it("it should resolve app specific api", async () => {
|
|
263
234
|
const mockPlugin: Plugin = {
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
displayName: { en: "My plugin" },
|
|
268
|
-
},
|
|
235
|
+
id: "plugin.namespace.placeholder",
|
|
236
|
+
description: { en: "My plugin description" },
|
|
237
|
+
displayName: { en: "My plugin" },
|
|
269
238
|
|
|
270
239
|
addCustomApi: () => ({
|
|
271
240
|
"my-app": {
|
|
@@ -285,11 +254,9 @@ describe("addCustomApi", () => {
|
|
|
285
254
|
|
|
286
255
|
it("it should resolve multiple app specific apis", async () => {
|
|
287
256
|
const mockPlugin: Plugin = {
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
displayName: { en: "My plugin" },
|
|
292
|
-
},
|
|
257
|
+
id: "plugin.namespace.placeholder",
|
|
258
|
+
description: { en: "My plugin description" },
|
|
259
|
+
displayName: { en: "My plugin" },
|
|
293
260
|
addCustomApi: () => ({
|
|
294
261
|
"my-app-1": {
|
|
295
262
|
functionOfMyApp1: () => undefined as any,
|
|
@@ -300,11 +267,9 @@ describe("addCustomApi", () => {
|
|
|
300
267
|
}),
|
|
301
268
|
}
|
|
302
269
|
const mockPlugin2: Plugin = {
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
displayName: { en: "My plugin" },
|
|
307
|
-
},
|
|
270
|
+
id: "plugin.namespace.placeholder2",
|
|
271
|
+
description: { en: "My plugin description" },
|
|
272
|
+
displayName: { en: "My plugin" },
|
|
308
273
|
|
|
309
274
|
addCustomApi: () => ({
|
|
310
275
|
"my-app-3": {
|
|
@@ -326,11 +291,9 @@ describe("addCustomApi", () => {
|
|
|
326
291
|
|
|
327
292
|
it("it should throw an error if return value is not an object", async () => {
|
|
328
293
|
const mockPlugin: Plugin = {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
displayName: { en: "My plugin" },
|
|
333
|
-
},
|
|
294
|
+
id: "plugin.namespace.placeholder",
|
|
295
|
+
description: { en: "My plugin description" },
|
|
296
|
+
displayName: { en: "My plugin" },
|
|
334
297
|
// @ts-expect-error - invalid return type
|
|
335
298
|
addCustomApi: () => undefined,
|
|
336
299
|
}
|
|
@@ -346,11 +309,9 @@ describe("addCustomApi", () => {
|
|
|
346
309
|
|
|
347
310
|
it("it should throw an error if the passed options are not defined inside customApi", async () => {
|
|
348
311
|
const mockPlugin: Plugin = {
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
displayName: { en: "My plugin" },
|
|
353
|
-
},
|
|
312
|
+
id: "plugin.namepsace.placeholder",
|
|
313
|
+
description: { en: "My plugin description" },
|
|
314
|
+
displayName: { en: "My plugin" },
|
|
354
315
|
addCustomApi: () => ({
|
|
355
316
|
"app.inlang.placeholder": {
|
|
356
317
|
messageReferenceMatcher: () => {
|