@datagrok/sequence-translator 0.0.8 → 1.0.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/jest.config.js ADDED
@@ -0,0 +1,33 @@
1
+ module.exports = {
2
+ "roots": [
3
+ "<rootDir>/src"
4
+ ],
5
+ "testMatch": [
6
+ "**/__jest__/**/*.test.+(ts|tsx)"
7
+ ],
8
+ moduleFileExtensions: [
9
+ 'ts',
10
+ 'js',
11
+ ],
12
+ "transform": {
13
+ "^.+\\.(ts|tsx)$": "ts-jest"
14
+ },
15
+ transformIgnorePatterns: ['^.+\\.js$'],
16
+ globals: {
17
+ 'ts-jest': {
18
+ 'tsconfig': {
19
+ "target": "es6",
20
+ "module": "es2020",
21
+ }
22
+ }
23
+ },
24
+ reporters: [
25
+ "default",
26
+ [
27
+ "./node_modules/jest-html-reporter",
28
+ {
29
+ "includeConsoleLog": true
30
+ }
31
+ ]
32
+ ]
33
+ }
package/package.json CHANGED
@@ -1,14 +1,19 @@
1
1
  {
2
2
  "name": "@datagrok/sequence-translator",
3
- "friendlyName": "SequenceTranslator",
4
- "version": "0.0.8",
5
- "description": "",
3
+ "friendlyName": "Sequence Translator",
4
+ "version": "1.0.0",
5
+ "description": "SequenceTranslator is a [package](https://datagrok.ai/help/develop/develop#packages) for the [Datagrok](https://datagrok.ai) platform, used to translate [oligonucleotide](https://en.wikipedia.org/wiki/Oligonucleotide) sequences between [different representations](https://github.com/datagrok-ai/public/tree/master/packages/SequenceTranslator#sequence-representations).",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/datagrok-ai/public.git",
9
+ "directory": "packages/SequenceTranslator"
10
+ },
6
11
  "dependencies": {
7
12
  "@datagrok-libraries/utils": "^0.1.0",
8
13
  "@types/react": "latest",
9
- "datagrok-api": ">0.94.10",
14
+ "datagrok-api": "^1.1.7",
10
15
  "datagrok-tools": "^4.1.2",
11
- "npm": "^7.11.2",
16
+ "npm": "^8.11.0",
12
17
  "save-svg-as-png": "^1.4.17",
13
18
  "ts-loader": "latest",
14
19
  "typescript": "latest",
@@ -23,8 +28,14 @@
23
28
  "debug-sequencetranslator-public": "grok publish public --rebuild",
24
29
  "release-sequencetranslator-public": "grok publish public --rebuild --release",
25
30
  "debug-sequencetranslator-local": "grok publish local --rebuild",
26
- "release-sequencetranslator-local": "grok publish local --rebuild --release"
31
+ "release-sequencetranslator-local": "grok publish local --rebuild --release",
32
+ "test": "set HOST=dev && jest",
33
+ "test-dev": "set HOST=dev && jest",
34
+ "test-local": "set HOST=localhost && jest"
27
35
  },
36
+ "sources": [
37
+ "css/style.css"
38
+ ],
28
39
  "devDependencies": {
29
40
  "@typescript-eslint/eslint-plugin": "^4.29.1",
30
41
  "@typescript-eslint/parser": "^4.29.1",
@@ -32,6 +43,12 @@
32
43
  "eslint": "^7.32.0",
33
44
  "eslint-config-google": "^0.14.0",
34
45
  "webpack": "^5.31.0",
35
- "webpack-cli": "^4.6.0"
36
- }
46
+ "webpack-cli": "^4.6.0",
47
+ "jest-html-reporter": "^3.5.0",
48
+ "jest": "^27.0.0",
49
+ "@types/jest": "^27.0.0",
50
+ "ts-jest": "^27.0.0",
51
+ "puppeteer": "^13.7.0"
52
+ },
53
+ "category": "Bioinformatics"
37
54
  }
package/setup.cmd CHANGED
@@ -8,4 +8,4 @@ call npm link datagrok-api
8
8
  cd ../../packages/SequenceTranslator
9
9
  call npm install
10
10
  call npm link datagrok-api @datagrok-libraries/utils
11
- webpack
11
+ webpack
package/src/ICDs.ts ADDED
@@ -0,0 +1,3 @@
1
+ export const ICDS = `DISPLAY
2
+ NO DATA
3
+ `;
package/src/IDPs.ts ADDED
@@ -0,0 +1,3 @@
1
+ export const IDPS = `DISPLAY
2
+ NO DATA
3
+ `;
@@ -0,0 +1,49 @@
1
+ /**
2
+ * @jest-environment jsdom
3
+ */
4
+
5
+ import * as utils from './test-node';
6
+ import puppeteer from 'puppeteer';
7
+
8
+ const P_START_TIMEOUT: number = 100000;
9
+ let browser: puppeteer.Browser;
10
+ let page: puppeteer.Page;
11
+
12
+ beforeAll(async () => {
13
+ let out = await utils.getBrowserPage(puppeteer);
14
+ browser = out.browser;
15
+ page = out.page;
16
+ }, P_START_TIMEOUT);
17
+
18
+ afterAll(async () => {
19
+ await browser.close();
20
+ });
21
+
22
+ it('TEST', async () => {
23
+ const target_package:string = process.env.TARGET_PACKAGE ?? 'SequenceTranslator';
24
+ console.log(`Testing ${target_package} package`);
25
+
26
+ //console.log(require('root-require')('package.json').version);
27
+ let r = await page.evaluate((target_package):Promise<object> => {
28
+ return new Promise<object>((resolve, reject) => {
29
+ (<any>window).grok.functions.eval(target_package + ':test()').then((df: any) => {
30
+ let cStatus = df.columns.byName('success');
31
+ let cMessage = df.columns.byName('result');
32
+ let cCat = df.columns.byName('category');
33
+ let cName = df.columns.byName('name');
34
+ let failed = false;
35
+ let report = '';
36
+ for (let i = 0; i < df.rowCount; i++)
37
+ if (!cStatus.get(i)) {
38
+ report += `${cCat.get(i)}.${cName.get(i)}: ${cMessage.get(i)}\n`;
39
+ failed = true;
40
+ }
41
+ resolve({report, failed});
42
+ }).catch((e: any) => reject(e));
43
+ });
44
+ }, target_package);
45
+ // @ts-ignore
46
+ console.log(r.report);
47
+ // @ts-ignore
48
+ expect(r.failed).toBe(false);
49
+ }, 100000);
@@ -0,0 +1,96 @@
1
+ import * as path from "path";
2
+ import * as os from "os";
3
+ import * as fs from "fs";
4
+ // @ts-ignore
5
+ import * as yaml from 'js-yaml';
6
+ const fetch = require('node-fetch');
7
+
8
+ export async function getToken(url: string, key: string) {
9
+ let response = await fetch(`${url}/users/login/dev/${key}`, {method: 'POST'});
10
+ let json = await response.json();
11
+ if (json.isSuccess == true)
12
+ return json.token;
13
+ else
14
+ throw 'Unable to login to server. Check your dev key';
15
+ }
16
+
17
+ export async function getWebUrl(url: string, token: string) {
18
+ let response = await fetch(`${url}/admin/plugins/admin/settings`, {headers: {Authorization: token}});
19
+ let json = await response.json();
20
+ return json.settings.webRoot;
21
+ }
22
+
23
+ const grokDir = path.join(os.homedir(), '.grok');
24
+ const confPath = path.join(grokDir, 'config.yaml');
25
+
26
+ function mapURL(conf: Config): Indexable {
27
+ let urls: Indexable = {};
28
+ for (let server in conf.servers) {
29
+ urls[conf['servers'][server]['url']] = conf['servers'][server];
30
+ }
31
+ return urls;
32
+ }
33
+
34
+ export function getDevKey(hostKey: string): {url: string, key: string} {
35
+ let config = yaml.load(fs.readFileSync(confPath, 'utf8')) as any;
36
+ let host = hostKey == '' ? config.default : hostKey;
37
+ host = host.trim();
38
+ let urls = mapURL(config);
39
+ let key = '';
40
+ let url = '';
41
+ try {
42
+ let url = new URL(host).href;
43
+ if (url.endsWith('/')) url = url.slice(0, -1);
44
+ if (url in urls) key = config['servers'][urls[url]]['key'];
45
+ } catch (error) {
46
+ if (config['servers'][host] == null)
47
+ throw `Unknown server alias. Please add it to ${confPath}`;
48
+ url = config['servers'][host]['url'];
49
+ key = config['servers'][host]['key'];
50
+ }
51
+ return {url, key};
52
+ }
53
+
54
+ export async function getBrowserPage(puppeteer: any): Promise<{browser: any, page: any}> {
55
+ let url:string = process.env.HOST ?? '';
56
+ let cfg = getDevKey(url);
57
+ url = cfg.url;
58
+
59
+ let key = cfg.key;
60
+ let token = await getToken(url, key);
61
+ url = await getWebUrl(url, token);
62
+ console.log(`Using web root: ${url}`);
63
+
64
+ let browser = await puppeteer.launch({
65
+ args: ['--disable-dev-shm-usage', '--disable-features=site-per-process'],
66
+ ignoreHTTPSErrors: true,
67
+ });
68
+
69
+ let page = await browser.newPage();
70
+ await page.goto(`${url}/oauth/`);
71
+ await page.setCookie({name: 'auth', value: token});
72
+ await page.evaluate((token: any) => {
73
+ window.localStorage.setItem('auth', token);
74
+ }, token);
75
+ await page.goto(url);
76
+ try {
77
+ await page.waitForSelector('.grok-preloader');
78
+ await page.waitForFunction(() => document.querySelector('.grok-preloader') == null, {timeout: 100000});
79
+ } catch (error) {
80
+ throw error;
81
+ }
82
+ return {browser, page};
83
+ }
84
+
85
+
86
+ interface Config {
87
+ servers: {
88
+ [alias: string]: {
89
+ url: string,
90
+ key: string
91
+ }
92
+ },
93
+ default: string,
94
+ }
95
+
96
+ interface Indexable { [key: string]: any }
@@ -114,7 +114,7 @@ export function defineAxolabsPattern() {
114
114
  asPtoLinkages = asPtoLinkages.concat(Array(maximalAsLength - asBases.length).fill(fullyPto));
115
115
  asBases = asBases.concat(Array(maximalAsLength - asBases.length).fill(sequenceBase));
116
116
  let nucleotideCounter = 0;
117
- for (let i = 0; i < asLength.value; i++) {
117
+ for (let i = 0; i < asLength.value!; i++) {
118
118
  asPtoLinkages[i] = ui.boolInput('', asPtoLinkages[i].value, () => {
119
119
  updateSvgScheme();
120
120
  updateOutputExamples();
@@ -157,7 +157,7 @@ export function defineAxolabsPattern() {
157
157
  ssPtoLinkages = ssPtoLinkages.concat(Array(maximalSsLength - ssBases.length).fill(fullyPto));
158
158
  ssBases = ssBases.concat(Array(maximalSsLength - ssBases.length).fill(sequenceBase));
159
159
  let nucleotideCounter = 0;
160
- for (let i = 0; i < ssLength.value; i++) {
160
+ for (let i = 0; i < ssLength.value!; i++) {
161
161
  ssPtoLinkages[i] = ui.boolInput('', ssPtoLinkages[i].value, () => {
162
162
  updateSvgScheme();
163
163
  updateOutputExamples();
@@ -196,11 +196,11 @@ export function defineAxolabsPattern() {
196
196
  }
197
197
 
198
198
  function updateUiForNewSequenceLength() {
199
- if (ssLength.value < maximalValidSequenceLength && asLength.value < maximalValidSequenceLength) {
200
- if (ssLength.value > maximalSsLength)
201
- maximalSsLength = ssLength.value;
202
- if (asLength.value > maximalAsLength)
203
- maximalAsLength = asLength.value;
199
+ if (ssLength.value! < maximalValidSequenceLength && asLength.value! < maximalValidSequenceLength) {
200
+ if (ssLength.value! > maximalSsLength)
201
+ maximalSsLength = ssLength.value!;
202
+ if (asLength.value! > maximalAsLength)
203
+ maximalAsLength = asLength.value!;
204
204
  updateSsModification();
205
205
  updateAsModification();
206
206
  updateSvgScheme();
@@ -236,17 +236,17 @@ export function defineAxolabsPattern() {
236
236
  }
237
237
 
238
238
  function updateInputExamples() {
239
- ssInputExample.value = generateExample(ssLength.value, sequenceBase.value);
239
+ ssInputExample.value = generateExample(ssLength.value!, sequenceBase.value!);
240
240
  if (createAsStrand.value)
241
- asInputExample.value = generateExample(asLength.value, sequenceBase.value);
241
+ asInputExample.value = generateExample(asLength.value!, sequenceBase.value!);
242
242
  }
243
243
 
244
244
  function updateOutputExamples() {
245
245
  ssOutputExample.value = translateSequence(
246
- ssInputExample.value, ssBases, ssPtoLinkages, ssFiveModification, ssThreeModification, firstSsPto.value);
246
+ ssInputExample.value, ssBases, ssPtoLinkages, ssFiveModification, ssThreeModification, firstSsPto.value!);
247
247
  if (createAsStrand.value) {
248
248
  asOutputExample.value = translateSequence(
249
- asInputExample.value, asBases, asPtoLinkages, asFiveModification, asThreeModification, firstAsPto.value);
249
+ asInputExample.value, asBases, asPtoLinkages, asFiveModification, asThreeModification, firstAsPto.value!);
250
250
  }
251
251
  }
252
252
 
@@ -256,11 +256,11 @@ export function defineAxolabsPattern() {
256
256
  ui.span([
257
257
  drawAxolabsPattern(
258
258
  getShortName(saveAs.value),
259
- createAsStrand.value,
260
- ssBases.slice(0, ssLength.value).map((e) => e.value),
261
- asBases.slice(0, asLength.value).map((e) => e.value),
262
- [firstSsPto.value].concat(ssPtoLinkages.slice(0, ssLength.value).map((e) => e.value)),
263
- [firstAsPto.value].concat(asPtoLinkages.slice(0, asLength.value).map((e) => e.value)),
259
+ createAsStrand.value!,
260
+ ssBases.slice(0, ssLength.value!).map((e) => e.value),
261
+ asBases.slice(0, asLength.value!).map((e) => e.value),
262
+ [firstSsPto.value!].concat(ssPtoLinkages.slice(0, ssLength.value!).map((e) => e.value)),
263
+ [firstAsPto.value!].concat(asPtoLinkages.slice(0, asLength.value!).map((e) => e.value)),
264
264
  ssThreeModification.value,
265
265
  ssFiveModification.value,
266
266
  asThreeModification.value,
@@ -329,7 +329,7 @@ export function defineAxolabsPattern() {
329
329
  }
330
330
 
331
331
  function checkWhetherAllValuesInColumnHaveTheSameLength(colName: string): boolean {
332
- const col = tables.value.columns.byName(colName);
332
+ const col = tables.value!.columns.byName(colName);
333
333
  let allLengthsAreTheSame = true;
334
334
  for (let i = 1; i < col.length; i++) {
335
335
  if (col.get(i - 1).length != col.get(i).length) {
@@ -344,10 +344,10 @@ export function defineAxolabsPattern() {
344
344
  .add(ui.divText('The sequence length should match the number of Raw sequences in the input file'))
345
345
  .add(ui.divText('\'ADD COLUMN\' to see sequences lengths'))
346
346
  .addButton('ADD COLUMN', () => {
347
- tables.value.columns.addNewInt('Sequences lengths in ' + colName).init((j: number) => col.get(j).length);
348
- grok.shell.info('Column with lengths added to \'' + tables.value.name + '\'');
347
+ tables.value!.columns.addNewInt('Sequences lengths in ' + colName).init((j: number) => col.get(j).length);
348
+ grok.shell.info('Column with lengths added to \'' + tables.value!.name + '\'');
349
349
  dialog.close();
350
- grok.shell.v = grok.shell.getTableView(tables.value.name);
350
+ grok.shell.v = grok.shell.getTableView(tables.value!.name);
351
351
  })
352
352
  .show();
353
353
  }
@@ -368,10 +368,10 @@ export function defineAxolabsPattern() {
368
368
  userStorageKey,
369
369
  saveAs.stringValue,
370
370
  JSON.stringify({
371
- 'ssBases': ssBases.slice(0, ssLength.value).map((e) => e.value),
372
- 'asBases': asBases.slice(0, asLength.value).map((e) => e.value),
373
- 'ssPtoLinkages': [firstSsPto.value].concat(ssPtoLinkages.slice(0, ssLength.value).map((e) => e.value)),
374
- 'asPtoLinkages': [firstAsPto.value].concat(asPtoLinkages.slice(0, asLength.value).map((e) => e.value)),
371
+ 'ssBases': ssBases.slice(0, ssLength.value!).map((e) => e.value),
372
+ 'asBases': asBases.slice(0, asLength.value!).map((e) => e.value),
373
+ 'ssPtoLinkages': [firstSsPto.value].concat(ssPtoLinkages.slice(0, ssLength.value!).map((e) => e.value)),
374
+ 'asPtoLinkages': [firstAsPto.value].concat(asPtoLinkages.slice(0, asLength.value!).map((e) => e.value)),
375
375
  'ssThreeModification': ssThreeModification.value,
376
376
  'ssFiveModification': ssFiveModification.value,
377
377
  'asThreeModification': asThreeModification.value,
@@ -506,24 +506,24 @@ export function defineAxolabsPattern() {
506
506
 
507
507
  function validateSsColumn(colName: string) {
508
508
  const allLengthsAreTheSame: boolean = checkWhetherAllValuesInColumnHaveTheSameLength(colName);
509
- const firstSequence = tables.value.columns.byName(colName).get(0);
509
+ const firstSequence = tables.value!.columns.byName(colName).get(0);
510
510
  if (allLengthsAreTheSame && firstSequence.length != ssLength.value)
511
- ssLength.value = tables.value.columns.byName(colName).get(0).length;
511
+ ssLength.value = tables.value!.columns.byName(colName).get(0).length;
512
512
  ssInputExample.value = firstSequence;
513
513
  }
514
514
 
515
515
  function validateAsColumn(colName: string) {
516
516
  const allLengthsAreTheSame: boolean = checkWhetherAllValuesInColumnHaveTheSameLength(colName);
517
- const firstSequence = tables.value.columns.byName(colName).get(0);
517
+ const firstSequence = tables.value!.columns.byName(colName).get(0);
518
518
  if (allLengthsAreTheSame && firstSequence.length != asLength.value)
519
- asLength.value = tables.value.columns.byName(colName).get(0).length;
519
+ asLength.value = tables.value!.columns.byName(colName).get(0).length;
520
520
  asLengthDiv.innerHTML = '';
521
521
  asLengthDiv.append(asLength.root);
522
522
  asInputExample.value = firstSequence;
523
523
  }
524
524
 
525
525
  function validateIdsColumn(colName: string) {
526
- const col = tables.value.columns.byName(colName);
526
+ const col = tables.value!.columns.byName(colName);
527
527
  if (col.type != DG.TYPE.INT)
528
528
  grok.shell.error('Column should contain integers only');
529
529
  else if (col.categories.length < col.length) {
@@ -531,32 +531,35 @@ export function defineAxolabsPattern() {
531
531
  ui.dialog('Non-unique IDs')
532
532
  .add(ui.divText('Press \'OK\' to select rows with non-unique values'))
533
533
  .onOK(() => {
534
- const selection = tables.value.selection;
534
+ const selection = tables.value!.selection;
535
535
  selection.init((i: number) => duplicates.indexOf(col.get(i)) > -1);
536
- grok.shell.v = grok.shell.getTableView(tables.value.name);
537
- grok.shell.info('Rows are selected in table \'' + tables.value.name + '\'');
536
+ grok.shell.v = grok.shell.getTableView(tables.value!.name);
537
+ grok.shell.info('Rows are selected in table \'' + tables.value!.name + '\'');
538
538
  })
539
539
  .show();
540
540
  }
541
541
  }
542
542
 
543
543
  const tables = ui.tableInput('Tables', grok.shell.tables[0], grok.shell.tables, (t: DG.DataFrame) => {
544
- inputSsColumn = ui.choiceInput('SS Column', '', t.columns.names(), (colName: string) => validateSsColumn(colName));
544
+ const inputSsColumn =
545
+ ui.choiceInput('SS Column', '', t.columns.names(), (colName: string) => validateSsColumn(colName));
545
546
  inputSsColumnDiv.innerHTML = '';
546
547
  inputSsColumnDiv.append(inputSsColumn.root);
547
- inputAsColumn = ui.choiceInput('AS Column', '', t.columns.names(), (colName: string) => validateAsColumn(colName));
548
+ const inputAsColumn =
549
+ ui.choiceInput('AS Column', '', t.columns.names(), (colName: string) => validateAsColumn(colName));
548
550
  inputAsColumnDiv.innerHTML = '';
549
551
  inputAsColumnDiv.append(inputAsColumn.root);
550
- inputIdColumn = ui.choiceInput('ID Column', '', t.columns.names(), (colName: string) => validateIdsColumn(colName));
552
+ const inputIdColumn =
553
+ ui.choiceInput('ID Column', '', t.columns.names(), (colName: string) => validateIdsColumn(colName));
551
554
  inputIdColumnDiv.innerHTML = '';
552
555
  inputIdColumnDiv.append(inputIdColumn.root);
553
556
  });
554
557
 
555
- let inputSsColumn = ui.choiceInput('SS Column', '', []);
558
+ const inputSsColumn = ui.choiceInput('SS Column', '', []);
556
559
  inputSsColumnDiv.append(inputSsColumn.root);
557
- let inputAsColumn = ui.choiceInput('AS Column', '', []);
560
+ const inputAsColumn = ui.choiceInput('AS Column', '', []);
558
561
  inputAsColumnDiv.append(inputAsColumn.root);
559
- let inputIdColumn = ui.choiceInput('ID Column', '', []);
562
+ const inputIdColumn = ui.choiceInput('ID Column', '', []);
560
563
  inputIdColumnDiv.append(inputIdColumn.root);
561
564
 
562
565
  updatePatternsList();
@@ -573,8 +576,8 @@ export function defineAxolabsPattern() {
573
576
  updateOutputExamples();
574
577
  });
575
578
 
576
- const firstSsPto = ui.boolInput('First SS PTO', fullyPto.value, () => updateSvgScheme());
577
- const firstAsPto = ui.boolInput('First AS PTO', fullyPto.value, () => updateSvgScheme());
579
+ const firstSsPto = ui.boolInput('First SS PTO', fullyPto.value!, () => updateSvgScheme());
580
+ const firstAsPto = ui.boolInput('First AS PTO', fullyPto.value!, () => updateSvgScheme());
578
581
  firstAsPtoDiv.append(firstAsPto.root);
579
582
 
580
583
  const createAsStrand = ui.boolInput('Create AS Strand', true, (v: boolean) => {
@@ -643,34 +646,34 @@ export function defineAxolabsPattern() {
643
646
  dialog
644
647
  .add(ui.divText('Length of sequences in columns doesn\'t match entered length. Update length value?'))
645
648
  .addButton('YES', () => {
646
- ssLength.value = tables.value.columns.byName(inputSsColumn.value).getString(0).length;
647
- asLength.value = tables.value.columns.byName(inputAsColumn.value).getString(0).length;
649
+ ssLength.value = tables.value!.columns.byName(inputSsColumn.value!).getString(0).length;
650
+ asLength.value = tables.value!.columns.byName(inputAsColumn.value!).getString(0).length;
648
651
  dialog.close();
649
652
  })
650
653
  .show();
651
654
  } else {
652
655
  if (inputIdColumn.value != null)
653
- addColumnWithIds(tables.value.name, inputIdColumn.value, getShortName(saveAs.value));
656
+ addColumnWithIds(tables.value!.name, inputIdColumn.value, getShortName(saveAs.value));
654
657
  addColumnWithTranslatedSequences(
655
- tables.value.name, inputSsColumn.value, ssBases, ssPtoLinkages,
656
- ssFiveModification, ssThreeModification, firstSsPto.value);
658
+ tables.value!.name, inputSsColumn.value, ssBases, ssPtoLinkages,
659
+ ssFiveModification, ssThreeModification, firstSsPto.value!);
657
660
  if (createAsStrand.value) {
658
661
  addColumnWithTranslatedSequences(
659
- tables.value.name, inputAsColumn.value, asBases, asPtoLinkages,
660
- asFiveModification, asThreeModification, firstAsPto.value);
662
+ tables.value!.name, inputAsColumn.value!, asBases, asPtoLinkages,
663
+ asFiveModification, asThreeModification, firstAsPto.value!);
661
664
  }
662
- grok.shell.v = grok.shell.getTableView(tables.value.name);
665
+ grok.shell.v = grok.shell.getTableView(tables.value!.name);
663
666
  grok.shell.info(((createAsStrand.value) ? 'Columns were' : 'Column was') +
664
- ' added to table \'' + tables.value.name + '\'');
667
+ ' added to table \'' + tables.value!.name + '\'');
665
668
  }
666
669
  });
667
670
 
668
- const ssInputExample = ui.textInput('Sense Strand', generateExample(ssLength.value, sequenceBase.value), () => {
671
+ const ssInputExample = ui.textInput('Sense Strand', generateExample(ssLength.value!, sequenceBase.value!), () => {
669
672
  ssOutputExample.value = translateSequence(ssInputExample.value, ssBases, ssPtoLinkages,
670
- ssFiveModification, ssThreeModification, firstSsPto.value);
673
+ ssFiveModification, ssThreeModification, firstSsPto.value!);
671
674
  });
672
675
  const ssOutputExample = ui.textInput(' ', translateSequence(
673
- ssInputExample.value, ssBases, ssPtoLinkages, ssThreeModification, ssFiveModification, firstSsPto.value));
676
+ ssInputExample.value, ssBases, ssPtoLinkages, ssThreeModification, ssFiveModification, firstSsPto.value!));
674
677
  (ssInputExample.input as HTMLElement).style.resize = 'none';
675
678
  (ssInputExample.input as HTMLElement).style.minWidth = exampleMinWidth;
676
679
  (ssOutputExample.input as HTMLElement).style.resize = 'none';
@@ -686,12 +689,12 @@ export function defineAxolabsPattern() {
686
689
  ], 'ui-input-options'),
687
690
  );
688
691
 
689
- const asInputExample = ui.textInput('Antisense Strand', generateExample(asLength.value, sequenceBase.value), () => {
692
+ const asInputExample = ui.textInput('Antisense Strand', generateExample(asLength.value!, sequenceBase.value!), () => {
690
693
  asOutputExample.value = translateSequence(
691
- asInputExample.value, asBases, asPtoLinkages, asFiveModification, asThreeModification, firstSsPto.value);
694
+ asInputExample.value, asBases, asPtoLinkages, asFiveModification, asThreeModification, firstSsPto.value!);
692
695
  });
693
696
  const asOutputExample = ui.textInput(' ', translateSequence(
694
- asInputExample.value, asBases, asPtoLinkages, asFiveModification, asThreeModification, firstSsPto.value));
697
+ asInputExample.value, asBases, asPtoLinkages, asFiveModification, asThreeModification, firstSsPto.value!));
695
698
  (asInputExample.input as HTMLElement).style.resize = 'none';
696
699
  (asInputExample.input as HTMLElement).style.minWidth = exampleMinWidth;
697
700
  (asOutputExample.input as HTMLElement).style.resize = 'none';
@@ -1,8 +1,9 @@
1
1
  import * as DG from 'datagrok-api/dg';
2
- import {runTests} from '@datagrok-libraries/utils/src/test';
2
+ import {runTests, tests} from '@datagrok-libraries/utils/src/test';
3
3
  import './tests/smiles-tests';
4
4
 
5
5
  export const _package = new DG.Package();
6
+ export {tests};
6
7
 
7
8
  //name: test
8
9
  //output: dataframe result