Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 43 additions & 11 deletions src/SDK/Language/Deno.php
Original file line number Diff line number Diff line change
Expand Up @@ -175,16 +175,48 @@ public function getParamExample(array $param): string
};
}

return match ($type) {
self::TYPE_ARRAY, self::TYPE_INTEGER, self::TYPE_NUMBER => $example,
self::TYPE_FILE => 'InputFile.fromPath(\'/path/to/file.png\', \'file.png\')',
self::TYPE_BOOLEAN => ($example) ? 'true' : 'false',
self::TYPE_OBJECT => ($example === '{}')
? '{}'
: (($formatted = json_encode(json_decode($example, true), JSON_PRETTY_PRINT))
? preg_replace('/\n/', "\n ", $formatted)
: $example),
self::TYPE_STRING => "'{$example}'",
};
switch ($type) {
case self::TYPE_ARRAY:
if (is_array($example)) {
return json_encode($example, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}

$decoded = json_decode($example, true);
if (null !== $decoded && is_array($decoded)) {
return json_encode($decoded, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}

// Fallback: normalize permission-like tokens inside array elements
$fixed = preg_replace_callback('/([a-zA-Z_][a-zA-Z0-9_]*)\(\s*"([^"\)]*)"\s*\)/', function ($m) {
return $m[1] . "('" . $m[2] . "')";
}, $example);

return $fixed ?? $example;

Comment on lines +189 to +195
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Escape single quotes in permission-token fallback.

Ensure read("O'Connor") becomes read('O'Connor'), not invalid JS.

Apply:

-                $fixed = preg_replace_callback('/([a-zA-Z_][a-zA-Z0-9_]*)\(\s*"([^"\)]*)"\s*\)/', function ($m) {
-                    return $m[1] . "('" . $m[2] . "')";
-                }, $example);
+                $fixed = preg_replace_callback('/([a-zA-Z_][a-zA-Z0-9_]*)\(\s*"([^"\)]*)"\s*\)/', function ($m) {
+                    $inner = str_replace("'", "\\'", $m[2]);
+                    return $m[1] . "('{$inner}')";
+                }, (string) $example);

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/SDK/Language/Deno.php around lines 189 to 195, the preg_replace_callback
builds a single-quoted token string but doesn’t escape inner single quotes, so
input like read("O'Connor") becomes invalid JS; update the callback to escape
single quotes in $m[2] before embedding (e.g. replace ' with \' via str_replace
or similar) so the returned string is $m[1] . "('" . <escaped $m[2]> . "')";
keep the rest of the logic unchanged.

case self::TYPE_INTEGER:
case self::TYPE_NUMBER:
return $example;

case self::TYPE_FILE:
return 'InputFile.fromPath(\'/path/to/file.png\', \'file.png\')';

case self::TYPE_BOOLEAN:
return ($example) ? 'true' : 'false';

case self::TYPE_OBJECT:
if ($example === '{}') {
return '{}';
}
$decodedObj = json_decode($example, true);
if (null !== $decodedObj && is_array($decodedObj)) {
$formatted = json_encode($decodedObj, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
return preg_replace('/\n/', "\n ", $formatted);
}
return $example;

case self::TYPE_STRING:
default:
return json_encode((string) $example, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}
}
}
96 changes: 47 additions & 49 deletions src/SDK/Language/Node.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public function getReturn(array $method, array $spec): string
$this->populateGenerics($method['responseModel'], $spec, $models);

$models = array_unique($models);
$models = array_filter($models, fn ($model) => $model != $this->toPascalCase($method['responseModel']));
$models = array_filter($models, fn($model) => $model != $this->toPascalCase($method['responseModel']));

if (!empty($models)) {
$ret .= '<' . implode(', ', $models) . '>';
Expand All @@ -118,14 +118,14 @@ public function getReturn(array $method, array $spec): string
return 'Promise<{}>';
}

/**
/**
* @param array $param
* @return string
*/
public function getParamExample(array $param): string
{
$type = $param['type'] ?? '';
$example = $param['example'] ?? '';
$type = $param['type'] ?? '';
$example = $param['example'] ?? '';

$hasExample = !empty($example) || $example === 0 || $example === false;

Expand All @@ -139,16 +139,49 @@ public function getParamExample(array $param): string
};
}

return match ($type) {
self::TYPE_ARRAY, self::TYPE_FILE, self::TYPE_INTEGER, self::TYPE_NUMBER => $example,
self::TYPE_BOOLEAN => ($example) ? 'true' : 'false',
self::TYPE_OBJECT => ($example === '{}')
? '{}'
: (($formatted = json_encode(json_decode($example, true), JSON_PRETTY_PRINT))
? preg_replace('/\n/', "\n ", $formatted)
: $example),
self::TYPE_STRING => "'{$example}'",
};
switch ($type) {
case self::TYPE_ARRAY:
if (is_array($example)) {
return json_encode($example, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}

$decoded = json_decode($example, true);
if (null !== $decoded && is_array($decoded)) {
return json_encode($decoded, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}

// Fallback for permission-like tokens inside array elements: read("role") -> read('role')
$fixed = preg_replace_callback('/([a-zA-Z_][a-zA-Z0-9_]*)\(\s*"([^"\)]*)"\s*\)/', function ($m) {
return $m[1] . "('" . $m[2] . "')";
}, $example);

return $fixed ?? $example;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Escape single quotes in permission-token fallback.

Prevent invalid JS when value contains apostrophes.

Apply:

-                $fixed = preg_replace_callback('/([a-zA-Z_][a-zA-Z0-9_]*)\(\s*"([^"\)]*)"\s*\)/', function ($m) {
-                    return $m[1] . "('" . $m[2] . "')";
-                }, $example);
+                $fixed = preg_replace_callback('/([a-zA-Z_][a-zA-Z0-9_]*)\(\s*"([^"\)]*)"\s*\)/', function ($m) {
+                    $inner = str_replace("'", "\\'", $m[2]);
+                    return $m[1] . "('{$inner}')";
+                }, (string) $example);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Fallback for permission-like tokens inside array elements: read("role") -> read('role')
$fixed = preg_replace_callback('/([a-zA-Z_][a-zA-Z0-9_]*)\(\s*"([^"\)]*)"\s*\)/', function ($m) {
return $m[1] . "('" . $m[2] . "')";
}, $example);
return $fixed ?? $example;
// Fallback for permission-like tokens inside array elements: read("role") -> read('role')
$fixed = preg_replace_callback(
'/([a-zA-Z_][a-zA-Z0-9_]*)\(\s*"([^"\)]*)"\s*\)/',
function ($m) {
$inner = str_replace("'", "\\'", $m[2]);
return $m[1] . "('{$inner}')";
},
(string) $example
);
return $fixed ?? $example;
🤖 Prompt for AI Agents
In src/SDK/Language/Node.php around lines 153 to 159, the fallback that converts
double-quoted permission tokens to single-quoted form doesn't escape single
quotes (or backslashes) in the token value, which can produce invalid JS when
the value contains an apostrophe; change the callback to escape backslashes and
single quotes in $m[2] (e.g. replace "\" with "\\\\" and "'" with "\\'") before
embedding it in the returned string so the produced single-quoted JS literal is
safe.

case self::TYPE_INTEGER:
case self::TYPE_NUMBER:
return $example;

case self::TYPE_FILE:
return 'document.getElementById(\'uploader\').files[0]';

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Wrong FILE example for NodeJS runtime.

Node examples shouldn’t reference document; use InputFile.fromPath for Node.

Apply:

-            case self::TYPE_FILE:
-                return 'document.getElementById(\'uploader\').files[0]';
+            case self::TYPE_FILE:
+                return 'InputFile.fromPath(\'/path/to/file\', \'filename\')';
🤖 Prompt for AI Agents
In src/SDK/Language/Node.php around lines 164 to 166, the NodeJS example returns
a browser DOM file reference (document.getElementById(...).files[0]) which is
invalid for Node; replace that return value with a Node-friendly InputFile
example such as using InputFile.fromPath('path/to/file') (update any surrounding
example text to reflect a path parameter and mention using InputFile.fromPath
for file uploads in Node).

case self::TYPE_BOOLEAN:
return ($example) ? 'true' : 'false';

case self::TYPE_OBJECT:
if ($example === '{}') {
return '{}';
}
$decodedObj = json_decode($example, true);
if (null !== $decodedObj && is_array($decodedObj)) {
$formatted = json_encode($decodedObj, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
return preg_replace('/\n/', "\n ", $formatted);
}
return $example;

case self::TYPE_STRING:
default:
return json_encode((string) $example, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}
}

/**
Expand All @@ -157,41 +190,6 @@ public function getParamExample(array $param): string
public function getFiles(): array
{
return [
[
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any reason for removing these files? pretty sure they are needed

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this was accidentally pushed I'm reverting it. Please review changes for web, deno & react-native.

'scope' => 'default',
'destination' => 'src/index.ts',
'template' => 'node/src/index.ts.twig',
],
[
'scope' => 'default',
'destination' => 'src/client.ts',
'template' => 'node/src/client.ts.twig',
],
[
'scope' => 'default',
'destination' => 'src/inputFile.ts',
'template' => 'node/src/inputFile.ts.twig',
],
[
'scope' => 'service',
'destination' => 'src/services/{{service.name | caseKebab}}.ts',
'template' => 'node/src/services/template.ts.twig',
],
[
'scope' => 'default',
'destination' => 'src/models.ts',
'template' => 'web/src/models.ts.twig',
],
[
'scope' => 'default',
'destination' => 'src/permission.ts',
'template' => 'web/src/permission.ts.twig',
],
[
'scope' => 'default',
'destination' => 'src/role.ts',
'template' => 'web/src/role.ts.twig',
],
[
'scope' => 'default',
'destination' => 'src/id.ts',
Expand Down
55 changes: 44 additions & 11 deletions src/SDK/Language/ReactNative.php
Original file line number Diff line number Diff line change
Expand Up @@ -203,16 +203,49 @@ public function getParamExample(array $param): string
};
}

return match ($type) {
self::TYPE_ARRAY, self::TYPE_FILE, self::TYPE_INTEGER, self::TYPE_NUMBER => $example,
self::TYPE_BOOLEAN => ($example) ? 'true' : 'false',
self::TYPE_OBJECT => ($example === '{}')
? '{}'
: (($formatted = json_encode(json_decode($example, true), JSON_PRETTY_PRINT))
? preg_replace('/\n/', "\n ", $formatted)
: $example),
self::TYPE_STRING => "'{$example}'",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we only needed change in type string, any reasons for changing all the others?

};
switch ($type) {
case self::TYPE_ARRAY:
if (is_array($example)) {
return json_encode($example, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}

$decoded = json_decode($example, true);
if (null !== $decoded && is_array($decoded)) {
return json_encode($decoded, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}

// Fallback: normalize permission-like tokens inside array elements
$fixed = preg_replace_callback('/([a-zA-Z_][a-zA-Z0-9_]*)\(\s*"([^"\)]*)"\s*\)/', function ($m) {
return $m[1] . "('" . $m[2] . "')";
}, $example);

return $fixed ?? $example;

Comment on lines +217 to +223
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Escape single quotes in permission-token fallback.

Values like read("O'Connor") will render invalid JS: read('O'Connor'). Escape inner single quotes and cast $example to string.

Apply:

-                $fixed = preg_replace_callback('/([a-zA-Z_][a-zA-Z0-9_]*)\(\s*"([^"\)]*)"\s*\)/', function ($m) {
-                    return $m[1] . "('" . $m[2] . "')";
-                }, $example);
+                $fixed = preg_replace_callback('/([a-zA-Z_][a-zA-Z0-9_]*)\(\s*"([^"\)]*)"\s*\)/', function ($m) {
+                    $inner = str_replace("'", "\\'", $m[2]);
+                    return $m[1] . "('{$inner}')";
+                }, (string) $example);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Fallback: normalize permission-like tokens inside array elements
$fixed = preg_replace_callback('/([a-zA-Z_][a-zA-Z0-9_]*)\(\s*"([^"\)]*)"\s*\)/', function ($m) {
return $m[1] . "('" . $m[2] . "')";
}, $example);
return $fixed ?? $example;
// Fallback: normalize permission-like tokens inside array elements
$fixed = preg_replace_callback('/([a-zA-Z_][a-zA-Z0-9_]*)\(\s*"([^"\)]*)"\s*\)/', function ($m) {
$inner = str_replace("'", "\\'", $m[2]);
return $m[1] . "('{$inner}')";
}, (string) $example);
return $fixed ?? $example;
🤖 Prompt for AI Agents
In src/SDK/Language/ReactNative.php around lines 217-223, the
preg_replace_callback fallback doesn't escape single quotes and doesn't ensure
$example is a string; update the callback to escape inner single quotes in the
permission token (e.g. replace ' with \') when building the replacement, cast
$example to string when passing it to preg_replace_callback (or at least in the
return), and return the escaped result or (string)$example if no replacement
occurred.

case self::TYPE_INTEGER:
case self::TYPE_NUMBER:
return $example;

case self::TYPE_FILE:
return 'InputFile.fromPath(\'/path/to/file\', \'filename\')';

case self::TYPE_BOOLEAN:
return ($example) ? 'true' : 'false';

case self::TYPE_OBJECT:
if ($example === '{}') {
return '{}';
}
$decodedObj = json_decode($example, true);
if (null !== $decodedObj && is_array($decodedObj)) {
$formatted = json_encode($decodedObj, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
return preg_replace('/\n/', "\n ", $formatted);
}
return $example;

case self::TYPE_STRING:
default:
return json_encode((string) $example, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}
}

public function getReturn(array $method, array $spec): string
Expand Down Expand Up @@ -241,7 +274,7 @@ public function getReturn(array $method, array $spec): string
$this->populateGenerics($method['responseModel'], $spec, $models);

$models = array_unique($models);
$models = array_filter($models, fn ($model) => $model != $this->toPascalCase($method['responseModel']));
$models = array_filter($models, fn($model) => $model != $this->toPascalCase($method['responseModel']));

if (!empty($models)) {
$ret .= '<' . implode(', ', $models) . '>';
Expand Down
63 changes: 49 additions & 14 deletions src/SDK/Language/Web.php
Original file line number Diff line number Diff line change
Expand Up @@ -144,17 +144,52 @@ public function getParamExample(array $param): string
};
}

return match ($type) {
self::TYPE_ARRAY, self::TYPE_INTEGER, self::TYPE_NUMBER => $example,
self::TYPE_FILE => 'document.getElementById(\'uploader\').files[0]',
self::TYPE_BOOLEAN => ($example) ? 'true' : 'false',
self::TYPE_OBJECT => ($example === '{}')
? '{}'
: (($formatted = json_encode(json_decode($example, true), JSON_PRETTY_PRINT))
? preg_replace('/\n/', "\n ", $formatted)
: $example),
self::TYPE_STRING => "'{$example}'",
};
switch ($type) {
case self::TYPE_ARRAY:
// Try to decode JSON array and re-encode to ensure valid JS array literal
if (is_array($example)) {
return json_encode($example, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}

$decoded = json_decode($example, true);
if (null !== $decoded && is_array($decoded)) {
return json_encode($decoded, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}

// Fallback: handle permission-like strings that contain unescaped inner quotes,
// e.g. ["read("any")"] -> ["read('any')"] by converting inner double-quotes to single-quotes
$fixed = preg_replace_callback('/([a-zA-Z_]+)\(\"([^\"]+)\"\)/', function ($m) {
return $m[1] . "('" . $m[2] . "')";
}, $example);

return $fixed ?? $example;

case self::TYPE_INTEGER:
case self::TYPE_NUMBER:
return $example;

case self::TYPE_FILE:
return 'document.getElementById(\'uploader\').files[0]';

case self::TYPE_BOOLEAN:
return ($example) ? 'true' : 'false';

case self::TYPE_OBJECT:
if ($example === '{}') {
return '{}';
}
$decodedObj = json_decode($example, true);
if (null !== $decodedObj && is_array($decodedObj)) {
$formatted = json_encode($decodedObj, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
return preg_replace('/\n/', "\n ", $formatted);
}
return $example;

case self::TYPE_STRING:
default:
// Use json_encode to produce properly quoted and escaped JS string literal
return json_encode((string) $example, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
}
Comment on lines +147 to +192
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

❓ Verification inconclusive

Robustness gap: TYPE_OBJECT may throw TypeError when example is array/object.

json_decode expects string; passing array/object can error in PHP 8+. Handle non-string examples directly and tighten decoding.

Proposed patch:

         switch ($type) {
             case self::TYPE_ARRAY:
                 // Try to decode JSON array and re-encode to ensure valid JS array literal
                 if (is_array($example)) {
                     return json_encode($example, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
                 }
@@
                 return ($example) ? 'true' : 'false';
 
             case self::TYPE_OBJECT:
-                if ($example === '{}') {
-                    return '{}';
-                }
-                $decodedObj = json_decode($example, true);
-                if (null !== $decodedObj && is_array($decodedObj)) {
-                    $formatted = json_encode($decodedObj, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
-                    return preg_replace('/\n/', "\n    ", $formatted);
-                }
-                return $example;
+                // Accept pre-parsed examples
+                if (is_array($example) || is_object($example)) {
+                    $formatted = json_encode($example, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
+                    return preg_replace('/\n/', "\n    ", $formatted);
+                }
+                if ($example === '{}' || \trim((string) $example) === '{}') {
+                    return '{}';
+                }
+                $decodedObj = json_decode((string) $example, true);
+                if (json_last_error() === JSON_ERROR_NONE && is_array($decodedObj)) {
+                    $formatted = json_encode($decodedObj, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
+                    return preg_replace('/\n/', "\n    ", $formatted);
+                }
+                return (string) $example;
 
             case self::TYPE_STRING:
             default:
                 // Use json_encode to produce properly quoted and escaped JS string literal
                 return json_encode((string) $example, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
         }

Also, optional: after fixing inner quotes in TYPE_ARRAY, consider trimming and returning the normalized string (current approach is fine for JS literals).


Handle non-string $example in TYPE_OBJECT to prevent TypeError: In the TYPE_OBJECT case of src/SDK/Language/Web.php, first check is_array($example) || is_object($example) and format with json_encode, then cast $example to string for json_decode and verify json_last_error().

}

public function getReadOnlyProperties(array $parameter, string $responseModel, array $spec = []): array
Expand Down Expand Up @@ -270,7 +305,7 @@ public function getGenerics(string $model, array $spec, bool $skipFirst = false)
}

$generics = array_unique($generics);
$generics = array_map(fn ($type) => "{$type} extends Models.{$type} = Models.Default{$type}", $generics);
$generics = array_map(fn($type) => "{$type} extends Models.{$type} = Models.Default{$type}", $generics);

return '<' . implode(', ', $generics) . '>';
}
Expand Down Expand Up @@ -303,7 +338,7 @@ public function getReturn(array $method, array $spec): string
$this->populateGenerics($method['responseModel'], $spec, $models);

$models = array_unique($models);
$models = array_filter($models, fn ($model) => $model != $this->toPascalCase($method['responseModel']));
$models = array_filter($models, fn($model) => $model != $this->toPascalCase($method['responseModel']));

if (!empty($models)) {
$ret .= '<' . implode(', ', $models) . '>';
Expand All @@ -323,7 +358,7 @@ public function getSubSchema(array $property, array $spec, string $methodName =
$generics = [];
$this->populateGenerics($property['sub_schema'], $spec, $generics);

$generics = array_filter($generics, fn ($model) => $model != $this->toPascalCase($property['sub_schema']));
$generics = array_filter($generics, fn($model) => $model != $this->toPascalCase($property['sub_schema']));

$ret .= $this->toPascalCase($property['sub_schema']);
if (!empty($generics)) {
Expand Down
3 changes: 3 additions & 0 deletions src/SDK/SDK.php
Original file line number Diff line number Diff line change
Expand Up @@ -916,6 +916,9 @@ protected function render(TemplateWrapper $template, string $destination, ?strin
throw new Exception('No minifier found for ' . $ext . ' file');
}
}

// No post-processing here: per-language getParamExample implementations should
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why was this added?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pushed accidentally, I'm reverting it.

// produce properly escaped, language-appropriate example literals.
}

/**
Expand Down
10 changes: 5 additions & 5 deletions templates/deno/src/permission.ts.twig
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
export class Permission {

static read = (role: string): string => {
return `read("${role}")`
return `read('${role}')`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, not related

}

static write = (role: string): string => {
return `write("${role}")`
return `write('${role}')`
}

static create = (role: string): string => {
return `create("${role}")`
return `create('${role}')`
}

static update = (role: string): string => {
return `update("${role}")`
return `update('${role}')`
}

static delete = (role: string): string => {
return `delete("${role}")`
return `delete('${role}')`
}
}
Loading
Loading