@openfga/frontend-utils
Version:
Exposes helpful utilities for building authoring experiences of OpenFGA Models.
209 lines (208 loc) • 9.43 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.provideCompletionItems = void 0;
const syntax_transformer_1 = require("@openfga/syntax-transformer");
const keyword_1 = require("../../../constants/keyword");
const single_indentation_1 = require("../../../constants/single-indentation");
const assert_never_1 = require("../../../inner-utils/assert-never");
const schema_version_1 = require("../../../constants/schema-version");
function getSuggestions(monaco, range, schemaVersion, samples = {}) {
const suggestions = [];
["entitlements", "expenses", "gdrive", "generic", "github", "iot", "slack", "customRoles"].forEach((key) => {
const sampleModel = samples === null || samples === void 0 ? void 0 : samples[key];
if (sampleModel) {
suggestions.push({
label: `sample-${key}`,
kind: monaco.languages.CompletionItemKind.Struct,
insertText: syntax_transformer_1.transformer.transformJSONToDSL(schemaVersion === schema_version_1.SchemaVersion.OneDotOne || schemaVersion === schema_version_1.SchemaVersion.OneDotTwo
? sampleModel
: {
schema_version: schema_version_1.SchemaVersion.OneDotZero,
type_definitions: sampleModel.type_definitions.map((typeDef) => ({
type: typeDef.type,
relations: typeDef.relations,
})),
}),
range,
});
}
});
return suggestions;
}
const provideCompletionItemsOneDotOne = (monaco, completionExtraOptions = {}) => (model, position) => {
let suggestions = [];
const word = model.getWordUntilPosition(position);
const range = {
startLineNumber: position.lineNumber,
endLineNumber: position.lineNumber,
startColumn: word.startColumn,
endColumn: word.endColumn,
};
if (position.column === 2) {
suggestions = [
{
label: keyword_1.Keyword.TYPE,
kind: monaco.languages.CompletionItemKind.Function,
// eslint-disable-next-line no-template-curly-in-string
insertText: `${keyword_1.Keyword.TYPE} \${1:typeName}
${single_indentation_1.SINGLE_INDENTATION}${keyword_1.Keyword.RELATIONS}
${single_indentation_1.SINGLE_INDENTATION}${single_indentation_1.SINGLE_INDENTATION}${keyword_1.Keyword.DEFINE} \${2:relationName}: [\${3:typeName}]`,
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
range,
},
{
label: "type_group",
kind: monaco.languages.CompletionItemKind.Function,
// eslint-disable-next-line no-template-curly-in-string
insertText: `${keyword_1.Keyword.TYPE} \${1:group}
${single_indentation_1.SINGLE_INDENTATION}${keyword_1.Keyword.RELATIONS}
${single_indentation_1.SINGLE_INDENTATION}${single_indentation_1.SINGLE_INDENTATION}${keyword_1.Keyword.DEFINE} \${2:member}: [\${3:user, group#member}]`,
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
range,
},
{
label: keyword_1.Keyword.TYPE,
kind: monaco.languages.CompletionItemKind.Keyword,
insertText: keyword_1.Keyword.TYPE,
range,
},
{
label: keyword_1.Keyword.MODEL,
kind: monaco.languages.CompletionItemKind.Function,
// eslint-disable-next-line no-template-curly-in-string
insertText: `${keyword_1.Keyword.MODEL}
${single_indentation_1.SINGLE_INDENTATION}${keyword_1.Keyword.SCHEMA} \${1:1.1}`,
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
range,
},
{
label: keyword_1.Keyword.MODEL,
kind: monaco.languages.CompletionItemKind.Keyword,
insertText: keyword_1.Keyword.TYPE,
range,
},
{
label: keyword_1.Keyword.CONDITION,
kind: monaco.languages.CompletionItemKind.Function,
// eslint-disable-next-line no-template-curly-in-string
insertText: `${keyword_1.Keyword.CONDITION} \${1:conditionName}(\${2:parameterName}: \${3:string}) {
\${4}
}`,
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
range,
},
];
}
else if (position.column === 4) {
suggestions = [
{
label: keyword_1.Keyword.RELATIONS,
kind: monaco.languages.CompletionItemKind.Keyword,
insertText: keyword_1.Keyword.RELATIONS,
range,
},
];
}
else if (position.column > 6) {
suggestions = [
{
label: keyword_1.Keyword.OR,
kind: monaco.languages.CompletionItemKind.Keyword,
insertText: keyword_1.Keyword.OR,
range,
},
{
label: keyword_1.Keyword.AND,
kind: monaco.languages.CompletionItemKind.Keyword,
insertText: keyword_1.Keyword.AND,
range,
},
{
label: keyword_1.Keyword.BUT_NOT,
kind: monaco.languages.CompletionItemKind.Keyword,
insertText: keyword_1.Keyword.BUT_NOT,
range,
},
{
label: keyword_1.Keyword.FROM,
kind: monaco.languages.CompletionItemKind.Function,
// eslint-disable-next-line no-template-curly-in-string
insertText: `\${1:relation1} ${keyword_1.Keyword.FROM} \${1:relation2}`,
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
range,
},
{
label: keyword_1.Keyword.FROM,
kind: monaco.languages.CompletionItemKind.Keyword,
insertText: keyword_1.Keyword.FROM,
range,
},
{
label: keyword_1.Keyword.CONDITION,
kind: monaco.languages.CompletionItemKind.Keyword,
insertText: keyword_1.Keyword.CONDITION,
range,
},
];
}
else if (position.column === 6) {
suggestions = [
{
label: "define-assignable",
kind: monaco.languages.CompletionItemKind.Function,
// eslint-disable-next-line no-template-curly-in-string
insertText: "define ${1:relationName}: [${2:typeName}]",
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
range,
},
{
label: "define-from-other-relation",
kind: monaco.languages.CompletionItemKind.Function,
// eslint-disable-next-line no-template-curly-in-string
insertText: "define ${1:relationName}: ${2:otherRelationName}",
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
range,
},
{
label: "define-from-other-relation-assignable",
kind: monaco.languages.CompletionItemKind.Function,
// eslint-disable-next-line no-template-curly-in-string
insertText: "define ${1:relationName}: [${2:typeName}] or ${3:otherRelationName}",
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
range,
},
{
label: "define-from-object",
kind: monaco.languages.CompletionItemKind.Function,
// eslint-disable-next-line no-template-curly-in-string
insertText: "define ${1:relationName}: ${2:relationInRelatedObject} from ${3:relationInThisType}}",
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
range,
},
{
label: "define",
kind: monaco.languages.CompletionItemKind.Keyword,
insertText: "define",
range,
},
];
}
else {
suggestions = getSuggestions(monaco, range, schema_version_1.SchemaVersion.OneDotOne, completionExtraOptions.samples);
}
return {
suggestions,
};
};
const provideCompletionItems = (monaco, schemaVersion = schema_version_1.SchemaVersion.OneDotZero, completionExtraOptions = {}) => (model, position) => {
switch (schemaVersion) {
case schema_version_1.SchemaVersion.OneDotTwo:
case schema_version_1.SchemaVersion.OneDotOne:
return provideCompletionItemsOneDotOne(monaco, completionExtraOptions)(model, position);
case schema_version_1.SchemaVersion.OneDotZero:
throw new Error("unsupported schema version");
default:
(0, assert_never_1.assertNever)(schemaVersion);
}
};
exports.provideCompletionItems = provideCompletionItems;