@miso.ai/client-sdk-codegen 1.11.6-beta.0 → 1.11.6-beta.1

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.
Files changed (47) hide show
  1. package/dist/cjs/codegen.js +11 -24
  2. package/dist/cjs/index.js +8 -18
  3. package/dist/cjs/output.js +37 -0
  4. package/dist/cjs/params.js +11 -3
  5. package/dist/cjs/spec/features.js +30 -26
  6. package/dist/cjs/spec/index.js +15 -5
  7. package/dist/cjs/spec/presets.js +29 -0
  8. package/dist/cjs/spec/utils.js +10 -0
  9. package/dist/cjs/spec/workflows.js +25 -29
  10. package/dist/cjs/spec/workflows.slug.js +23 -0
  11. package/dist/cjs/template/client.js +29 -0
  12. package/dist/cjs/template/entrypoints.js +15 -0
  13. package/dist/cjs/template/features.js +19 -0
  14. package/dist/cjs/{utils.js → template/helpers.js} +26 -8
  15. package/dist/cjs/template/index.js +39 -0
  16. package/dist/cjs/ui/hybrid-search.js +74 -0
  17. package/dist/cjs/ui/index.js +38 -0
  18. package/dist/cjs/ui/search.js +91 -0
  19. package/dist/cjs/ui/ui.js +36 -0
  20. package/package.json +2 -2
  21. package/src/codegen.js +8 -20
  22. package/src/index.js +2 -2
  23. package/src/output.js +33 -0
  24. package/src/params.js +11 -2
  25. package/src/spec/features.js +24 -26
  26. package/src/spec/index.js +2 -5
  27. package/src/spec/presets.js +24 -0
  28. package/src/spec/utils.js +5 -0
  29. package/src/spec/workflows.js +23 -35
  30. package/src/spec/workflows.slug.js +24 -0
  31. package/src/template/client.js +25 -0
  32. package/src/template/entrypoints.js +10 -0
  33. package/src/template/features.js +10 -0
  34. package/src/{utils.js → template/helpers.js} +19 -0
  35. package/src/template/index.js +4 -0
  36. package/src/ui/hybrid-search.js +71 -0
  37. package/src/ui/index.js +3 -0
  38. package/src/ui/search.js +91 -0
  39. package/src/ui/ui.js +26 -0
  40. package/dist/cjs/features.js +0 -12
  41. package/dist/cjs/templates.js +0 -34
  42. package/dist/cjs/workflow/hybrid-search.js +0 -51
  43. package/dist/cjs/workflow/index.js +0 -22
  44. package/src/features.js +0 -5
  45. package/src/templates.js +0 -26
  46. package/src/workflow/hybrid-search.js +0 -48
  47. package/src/workflow/index.js +0 -3
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.search = search;
7
+ var _presets = require("../spec/presets.js");
8
+ var _helpers = require("../template/helpers.js");
9
+ var _index = require("../template/index.js");
10
+ var _features = require("../template/features.js");
11
+ const _excluded = ["facets"];
12
+ function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
13
+ function normalizeOptions(_ref = {}) {
14
+ let {
15
+ facets
16
+ } = _ref,
17
+ options = _objectWithoutPropertiesLoose(_ref, _excluded);
18
+ if (facets === true) {
19
+ facets = ['categories'];
20
+ }
21
+ return Object.assign({}, options, {
22
+ facets
23
+ });
24
+ }
25
+ function search(options) {
26
+ options = normalizeOptions((0, _helpers.resolvePreset)(_presets.search, options));
27
+ // TODO: extra styles for concatenate format
28
+ const items = [];
29
+ if (options.elements !== false) {
30
+ items.push({
31
+ type: 'html',
32
+ name: 'HTML (Search box)',
33
+ content: htmlSearchBox(options)
34
+ }, {
35
+ type: 'html',
36
+ name: 'HTML (Results)',
37
+ content: htmlResults(options)
38
+ });
39
+ }
40
+ items.push({
41
+ type: 'js',
42
+ name: 'JavaScript',
43
+ content: js(options)
44
+ });
45
+ return items;
46
+ }
47
+ function js(options) {
48
+ // TODO: support loading from Node module
49
+ return (0, _index.misocmd)(`
50
+ // client
51
+ ${(0, _index.createClient)(options)}
52
+
53
+ // workflow
54
+ const workflow = client.ui.search;
55
+
56
+ // setup: TODO
57
+ ${(0, _features.facets)(options.facets)}
58
+
59
+ ${(0, _features.autoQuery)(options.autoQuery)}
60
+ `);
61
+ }
62
+ function html(options) {
63
+ if (options.elements === false) {
64
+ return '';
65
+ }
66
+ return `
67
+ ${htmlSearchBox(options)}
68
+ <hr>
69
+ ${htmlResults(options)}
70
+ `.trim();
71
+ }
72
+ function htmlSearchBox(options) {
73
+ return `
74
+ <miso-search>
75
+ <miso-query></miso-query>
76
+ </miso-search>
77
+ `.trim();
78
+ }
79
+ function htmlResults(options) {
80
+ // TODO: useLink
81
+ return `
82
+ <miso-search visible-when="loading ready">
83
+ <div class="info">
84
+ <div class="keywords">You searched for “<miso-keywords></miso-keywords>”</div>
85
+ <div class="total"><miso-total></miso-total> Results</div>
86
+ </div>
87
+ <miso-facets></miso-facets>
88
+ <miso-products></miso-products>
89
+ </miso-search>
90
+ `.trim();
91
+ }
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.ui = ui;
7
+ var _hybridSearch = require("./hybrid-search.js");
8
+ var _search = require("./search.js");
9
+ const _excluded = ["workflow"];
10
+ function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
11
+ const workflows = {
12
+ ['hybrid-search']: _hybridSearch.hybridSearch,
13
+ search: _search.search
14
+ };
15
+ function normalizeOptions(_ref = {}) {
16
+ let {
17
+ workflow
18
+ } = _ref,
19
+ options = _objectWithoutPropertiesLoose(_ref, _excluded);
20
+ if (!workflow) {
21
+ throw new Error('Workflow is required');
22
+ }
23
+ return Object.assign({
24
+ workflow
25
+ }, options);
26
+ }
27
+ function ui(options) {
28
+ options = normalizeOptions(options);
29
+ const {
30
+ workflow
31
+ } = options;
32
+ if (!workflows[workflow]) {
33
+ throw new Error(`Workflow "${workflow}" is not found`);
34
+ }
35
+ return workflows[workflow](options);
36
+ }
package/package.json CHANGED
@@ -26,7 +26,7 @@
26
26
  "url": "https://github.com/MisoAI/miso-client-js-sdk/issues"
27
27
  },
28
28
  "dependencies": {
29
- "@miso.ai/commons": "1.11.6-beta.0"
29
+ "@miso.ai/commons": "1.11.6-beta.1"
30
30
  },
31
- "version": "1.11.6-beta.0"
31
+ "version": "1.11.6-beta.1"
32
32
  }
package/src/codegen.js CHANGED
@@ -1,23 +1,11 @@
1
- import * as workflows from './workflow/index.js';
1
+ import { ui } from './ui/index.js';
2
+ import Output from './output.js';
2
3
 
3
- function normalizeOptions({ workflow, ...options } = {}) {
4
- // turn workflow into camel case
5
- if (!workflow) {
6
- throw new Error('Workflow is required');
4
+ export function codegen({ schema = 'ui', ...options } = {}) {
5
+ switch (schema) {
6
+ case 'ui':
7
+ return new Output(ui(options));
8
+ default:
9
+ throw new Error(`Unrecognized schema: "${schema}"`);
7
10
  }
8
- workflow = workflow.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
9
-
10
- return {
11
- workflow,
12
- ...options,
13
- };
14
- }
15
-
16
- export function codegen(options) {
17
- options = normalizeOptions(options);
18
- const { workflow } = options;
19
- if (!workflows[workflow]) {
20
- throw new Error(`Workflow "${workflow}" is not found`);
21
- }
22
- return workflows[workflow](options);
23
11
  }
package/src/index.js CHANGED
@@ -1,4 +1,4 @@
1
+ export * as spec from './spec/index.js';
1
2
  export * from './params.js';
2
3
  export * from './codegen.js';
3
- export * from './spec/index.js';
4
- export * as workflows from './workflow/index.js';
4
+ export * as ui from './ui/index.js';
package/src/output.js ADDED
@@ -0,0 +1,33 @@
1
+ export default class Output {
2
+
3
+ constructor(items) {
4
+ this._items = items;
5
+ }
6
+
7
+ get items() {
8
+ return this._items;
9
+ }
10
+
11
+ [Symbol.iterator]() {
12
+ return this._items[Symbol.iterator]();
13
+ }
14
+
15
+ concat() {
16
+ return this._items.filter(item => item).map(item => asHtml(item)).join('\n');
17
+ }
18
+
19
+ }
20
+
21
+ function asHtml({ type, content } = {}) {
22
+ // TODO: minify
23
+ switch (type) {
24
+ case 'html':
25
+ return content;
26
+ case 'js':
27
+ return `<script async>\n${content}\n</script>`;
28
+ case 'css':
29
+ return `<style>\n${content}\n</style>`;
30
+ default:
31
+ throw new Error(`Unrecognized type: "${type}"`);
32
+ }
33
+ }
package/src/params.js CHANGED
@@ -1,11 +1,20 @@
1
- export function encodeParameters(params = {}) {
1
+ export function encodeParameters(params) {
2
+ if (params === undefined || params === null) {
3
+ return undefined;
4
+ }
5
+ if (typeof params !== 'object') {
6
+ throw new Error('params must be an object');
7
+ }
2
8
  // JSON string -> base64
3
9
  return base64Encode(JSON.stringify(params));
4
10
  }
5
11
 
6
12
  export function decodeParameters(params) {
13
+ if (params === undefined || params === null) {
14
+ return undefined;
15
+ }
7
16
  // base64 -> JSON string
8
- return params ? JSON.parse(base64Decode(params)) : {};
17
+ return JSON.parse(base64Decode(params));
9
18
  }
10
19
 
11
20
  function base64Encode(str) {
@@ -1,43 +1,41 @@
1
- import { resolveWorkflows } from './workflows.js';
1
+ import { toName } from './utils.js';
2
+ import { resolveWorkflows } from './workflows.slug.js';
2
3
 
3
- export const FEATURES = [
4
+ export default [
4
5
  {
5
6
  slug: 'use-api',
6
- name: 'useApi()',
7
- workflows: resolveWorkflows('*'),
7
+ workflows: '*',
8
8
  },
9
9
  {
10
10
  slug: 'use-link',
11
- name: 'useLink()',
12
- workflows: resolveWorkflows('ahes'),
11
+ workflows: 'ahes',
13
12
  },
14
13
  {
15
- slug: 'follow-up',
16
- name: 'Follow Up',
17
- workflows: resolveWorkflows('a'),
14
+ slug: 'autocomplete',
15
+ workflows: 'hs',
18
16
  },
19
17
  {
20
- slug: 'auto-query',
21
- name: 'Auto Query',
22
- workflows: resolveWorkflows('ahes'),
18
+ slug: 'pagination',
19
+ workflows: 'hs',
23
20
  },
24
21
  {
25
- slug: 'autocomplete',
26
- name: 'Autocomplete',
27
- workflows: resolveWorkflows('hs'),
22
+ slug: 'facets',
23
+ workflows: 'hs',
28
24
  },
29
25
  {
30
- slug: 'pagination',
31
- name: 'Pagination',
32
- workflows: resolveWorkflows('hs'),
26
+ slug: 'follow-up',
27
+ workflows: 'a',
33
28
  },
34
29
  {
35
- slug: 'facets',
36
- name: 'Facets',
37
- workflows: resolveWorkflows('hs'),
30
+ slug: 'auto-query',
31
+ workflows: 'ahes',
38
32
  },
39
- ];
40
-
41
- export function getFeatures(workflow) {
42
- return FEATURES.filter(feature => feature.workflows.includes(workflow));
43
- }
33
+ ].reduce((map, { slug, workflows, ...rest }) => {
34
+ map[slug] = Object.freeze({
35
+ slug,
36
+ name: toName(slug),
37
+ workflows: resolveWorkflows(workflows),
38
+ ...rest,
39
+ });
40
+ return map;
41
+ }, {});
package/src/spec/index.js CHANGED
@@ -1,5 +1,2 @@
1
- import { presets as hybridSearchPresets } from '../workflow/hybrid-search.js';
2
-
3
- export const presets = Object.freeze({
4
- hybridSearch: Object.keys(hybridSearchPresets),
5
- });
1
+ export { default as workflows } from './workflows.js';
2
+ export { default as features } from './features.js';
@@ -0,0 +1,24 @@
1
+ export const hybridSearch = Object.freeze({
2
+ standard: Object.freeze({
3
+ workflow: 'hybrid-search',
4
+ autoQuery: true,
5
+ autocomplete: true,
6
+ facets: ['categories'],
7
+ answerBox: true,
8
+ }),
9
+ minimal: Object.freeze({
10
+ workflow: 'hybrid-search',
11
+ }),
12
+ });
13
+
14
+ export const search = Object.freeze({
15
+ standard: Object.freeze({
16
+ workflow: 'search',
17
+ autoQuery: true,
18
+ autocomplete: true,
19
+ //facets: ['categories'],
20
+ }),
21
+ minimal: Object.freeze({
22
+ workflow: 'search',
23
+ }),
24
+ });
@@ -0,0 +1,5 @@
1
+ import { kebabOrSnakeToHuman, capitalize } from '@miso.ai/commons';
2
+
3
+ export function toName(str) {
4
+ return capitalize(kebabOrSnakeToHuman(str));
5
+ }
@@ -1,39 +1,27 @@
1
- import { kebabOrSnakeToHuman } from '@miso.ai/commons';
1
+ import { kebabToLowerCamel } from '@miso.ai/commons';
2
+ import { toName } from './utils.js';
3
+ import { WORKFLOW_SLUGS } from './workflows.slug.js';
4
+ import features from './features.js';
5
+ import * as presets from './presets.js';
2
6
 
3
- export const WORKFLOWS = ([
4
- {
5
- slug: 'ask',
6
- },
7
- {
8
- slug: 'hybrid-search',
9
- },
10
- {
11
- slug: 'explore',
12
- },
13
- {
14
- slug: 'search',
15
- },
16
- {
17
- slug: 'recommendation',
18
- },
19
- ]).map(workflow => ({
20
- ...workflow,
21
- name: kebabOrSnakeToHuman(workflow.slug),
22
- }));
7
+ function getFeatures(features, slug) {
8
+ return Object.values(features).filter(feature => feature.workflows.includes(slug));
9
+ }
23
10
 
24
- const ABV_TO_WORKFLOW = WORKFLOWS.reduce((map, workflow) => {
25
- map[workflow.slug.charAt(0)] = workflow;
26
- return map;
27
- }, {});
11
+ function getPresets(presets, slug) {
12
+ return Object.entries(presets[kebabToLowerCamel(slug)] || {}).map(([key, value]) => Object.freeze({
13
+ slug: key,
14
+ name: toName(key),
15
+ value,
16
+ }));
17
+ }
28
18
 
29
- export function resolveWorkflows(abvs) {
30
- if (abvs === '*') {
31
- return [...WORKFLOWS];
32
- }
33
- return abvs.split('').map(abv => {
34
- if (!ABV_TO_WORKFLOW[abv]) {
35
- throw new Error(`Workflow "${abv}" is not found`);
36
- }
37
- return ABV_TO_WORKFLOW[abv];
19
+ export default WORKFLOW_SLUGS.reduce((obj, slug) => {
20
+ obj[slug] = Object.freeze({
21
+ slug,
22
+ name: toName(slug),
23
+ features: getFeatures(features, slug),
24
+ presets: getPresets(presets, slug),
38
25
  });
39
- }
26
+ return obj;
27
+ }, {});
@@ -0,0 +1,24 @@
1
+ export const WORKFLOW_SLUGS = [
2
+ 'ask',
3
+ 'hybrid-search',
4
+ 'explore',
5
+ 'search',
6
+ 'recommendation',
7
+ ];
8
+
9
+ const ABV_TO_WORKFLOW = WORKFLOW_SLUGS.reduce((map, slug) => {
10
+ map[slug.charAt(0)] = slug;
11
+ return map;
12
+ }, {});
13
+
14
+ export function resolveWorkflows(abvs) {
15
+ if (abvs === '*') {
16
+ return [...WORKFLOW_SLUGS];
17
+ }
18
+ return abvs.split('').map(abv => {
19
+ if (!ABV_TO_WORKFLOW[abv]) {
20
+ throw new Error(`Workflow "${abv}" is not found`);
21
+ }
22
+ return ABV_TO_WORKFLOW[abv];
23
+ });
24
+ }
@@ -0,0 +1,25 @@
1
+ import { indent, blocks } from './helpers.js';
2
+
3
+ export function createClient(options) {
4
+ return blocks(
5
+ `const MisoClient = window.MisoClient;`,
6
+ ...clientPlugins(options),
7
+ `const client = new MisoClient(${clientOptions(options)});`
8
+ );
9
+ }
10
+
11
+ function clientPlugins({ dryRun } = {}) {
12
+ const blocks = [];
13
+ if (dryRun) {
14
+ blocks.push(`MisoClient.plugins.use("std:dry-run");`);
15
+ }
16
+ return blocks;
17
+ }
18
+
19
+ function clientOptions({ apiKey, apiKeyParam = false } = {}) {
20
+ if (!apiKeyParam) {
21
+ return `'${apiKey}'`;
22
+ }
23
+ apiKeyParam = apiKeyParam === true ? 'api-key' : apiKeyParam;
24
+ return `new URLSearchParams(window.location.search).get('${apiKeyParam}') || '${apiKey}'`;
25
+ }
@@ -0,0 +1,10 @@
1
+ import { indent } from './helpers.js';
2
+
3
+ export function misocmd(body) {
4
+ return `
5
+ const misocmd = window.misocmd || (window.misocmd = []);
6
+ misocmd.push(async () => {
7
+ ${indent(body, 2)}
8
+ });
9
+ `.trim();
10
+ }
@@ -0,0 +1,10 @@
1
+ import { format } from './helpers.js';
2
+
3
+ export function facets(options) {
4
+ return options ? `workflow.useFacets(${format(options, { multiline: true })});` : '';
5
+ }
6
+
7
+ export function autoQuery(options) {
8
+ // TODO: consider when options === false
9
+ return options ? `workflow.autoQuery(${typeof options === 'object' ? format(options, { multiline: true }) : ''});` : '';
10
+ }
@@ -1,4 +1,5 @@
1
1
  export function indent(str, level = 1) {
2
+ // TODO: trim and deal with blank lines
2
3
  return str.replace(/\n/g, '\n' + ' '.repeat(level));
3
4
  }
4
5
 
@@ -15,6 +16,24 @@ export function format(value, { multiline = false } = {}) {
15
16
  return JSON.stringify(value, null, multiline ? 2 : 0).replace(/"/g, "'").replace(/\s*:\s*/g, ': ');
16
17
  }
17
18
 
19
+ /**
20
+ * Join blocks with proper newlines
21
+ * @param {string[]} blocks - Blocks to join
22
+ * @returns {string}
23
+ */
24
+ export function blocks(...blocks) {
25
+ return blocks.map(block => block.trim()).filter(block => block).join('\n');
26
+ }
27
+
28
+ /**
29
+ * Join paragraphs with proper newlines
30
+ * @param {string[]} paragraphs - Paragraphs to join
31
+ * @returns {string}
32
+ */
33
+ export function paragraphs(...paragraphs) {
34
+ return paragraphs.map(paragraph => paragraph.trim()).filter(paragraph => paragraph).join('\n\n');
35
+ }
36
+
18
37
  /**
19
38
  * Resolve preset options
20
39
  * @param {Object} presets - Available presets
@@ -0,0 +1,4 @@
1
+ export * from './entrypoints.js';
2
+ export * from './client.js';
3
+ export * as features from './features.js';
4
+ export * as helpers from './helpers.js';
@@ -0,0 +1,71 @@
1
+ import { hybridSearch as presets } from '../spec/presets.js';
2
+ import { resolvePreset } from '../template/helpers.js';
3
+ import { misocmd, createClient } from '../template/index.js';
4
+ import { autoQuery } from '../template/features.js';
5
+
6
+ // TODO: refactor these
7
+ function normalizeOptions({ facets, ...options } = {}) {
8
+ if (facets === true) {
9
+ facets = ['categories'];
10
+ }
11
+ return {
12
+ ...options,
13
+ facets,
14
+ };
15
+ }
16
+
17
+ export function hybridSearch(options) {
18
+ options = normalizeOptions(resolvePreset(presets, options));
19
+ const items = [
20
+ {
21
+ type: 'html',
22
+ name: 'HTML',
23
+ content: html(options),
24
+ },
25
+ {
26
+ type: 'js',
27
+ name: 'JavaScript',
28
+ content: js(options),
29
+ },
30
+ ];
31
+ return items;
32
+ }
33
+
34
+ function js(options) {
35
+ // TODO: support loading from Node module
36
+ // TODO: useLink
37
+ return misocmd(`
38
+ // client
39
+ ${createClient(options)}
40
+
41
+ // workflow
42
+ const workflow = client.ui.hybridSearch;
43
+
44
+ // setup: TODO
45
+
46
+ ${jsElements(options)}
47
+
48
+ ${autoQuery(options.autoQuery)}
49
+ `);
50
+ }
51
+
52
+ function jsElements(options) {
53
+ if (options.elements === false) {
54
+ return '';
55
+ }
56
+ return `
57
+ // render Miso elements
58
+ await client.ui.ready;
59
+ const { templates, wireAnswerBox } = MisoClient.ui.defaults.hybridSearch;
60
+ const rootElement = document.querySelector('#miso-hybrid-search-combo');
61
+ rootElement.innerHTML = templates.root();
62
+ wireAnswerBox(client, rootElement);
63
+ `.trim();
64
+ }
65
+
66
+ function html(options) {
67
+ if (options.elements === false) {
68
+ return '';
69
+ }
70
+ return `<div id="miso-hybrid-search-combo" class="miso-hybrid-search-combo"></div>`.trim();
71
+ }
@@ -0,0 +1,3 @@
1
+ export * from './hybrid-search.js';
2
+ export * from './search.js';
3
+ export * from './ui.js';