@riboseinc/paneron-registry-kit 2.2.10 → 2.2.12

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 (102) hide show
  1. package/index.d.ts +2 -4
  2. package/index.js +18 -0
  3. package/index.js.map +1 -1
  4. package/package.json +2 -2
  5. package/site-builder/index.d.ts +3 -0
  6. package/site-builder/index.js +75 -0
  7. package/site-builder/index.js.map +1 -0
  8. package/site-builder/jsx-runtime.d.ts +18 -0
  9. package/site-builder/jsx-runtime.js +107 -0
  10. package/site-builder/jsx-runtime.js.map +1 -0
  11. package/site-builder/page.d.ts +6 -0
  12. package/site-builder/page.js +24 -0
  13. package/site-builder/page.js.map +1 -0
  14. package/types/cr.d.ts +22 -0
  15. package/types/cr.js +41 -1
  16. package/types/cr.js.map +1 -1
  17. package/types/item.d.ts +1 -1
  18. package/types/item.js.map +1 -1
  19. package/types/stakeholder.d.ts +3 -1
  20. package/types/stakeholder.js +20 -0
  21. package/types/stakeholder.js.map +1 -1
  22. package/types/util.d.ts +2 -0
  23. package/types/util.js.map +1 -1
  24. package/types/views.d.ts +22 -0
  25. package/types/views.js.map +1 -1
  26. package/views/AnnotatedChange.js +7 -5
  27. package/views/AnnotatedChange.js.map +1 -1
  28. package/views/BrowserCtx.d.ts +3 -11
  29. package/views/BrowserCtx.js +1 -0
  30. package/views/BrowserCtx.js.map +1 -1
  31. package/views/FilterCriteria/criteriaGroupToQueryExpression.d.ts +1 -1
  32. package/views/FilterCriteria/criteriaGroupToQueryExpression.js.map +1 -1
  33. package/views/FilterCriteria/models.d.ts +1 -1
  34. package/views/FilterCriteria/models.js.map +1 -1
  35. package/views/GenericRelatedItemView.js +11 -51
  36. package/views/GenericRelatedItemView.js.map +1 -1
  37. package/views/ItemDrawer.d.ts +11 -0
  38. package/views/ItemDrawer.js +69 -0
  39. package/views/ItemDrawer.js.map +1 -0
  40. package/views/SearchQuery.js +25 -14
  41. package/views/SearchQuery.js.map +1 -1
  42. package/views/change-request/ChangeProposalContext.d.ts +3 -0
  43. package/views/change-request/ChangeProposalContext.js +4 -0
  44. package/views/change-request/ChangeProposalContext.js.map +1 -0
  45. package/views/change-request/ChangeRequestContext.d.ts +18 -2
  46. package/views/change-request/ChangeRequestContext.js +29 -5
  47. package/views/change-request/ChangeRequestContext.js.map +1 -1
  48. package/views/change-request/Proposals.d.ts +2 -0
  49. package/views/change-request/Proposals.js +116 -80
  50. package/views/change-request/Proposals.js.map +1 -1
  51. package/views/change-request/State.d.ts +0 -0
  52. package/views/change-request/State.js +1 -0
  53. package/views/change-request/State.js.map +1 -0
  54. package/views/change-request/Summary.d.ts +12 -0
  55. package/views/change-request/Summary.js +59 -0
  56. package/views/change-request/Summary.js.map +1 -0
  57. package/views/change-request/TransitionHistory.d.ts +30 -0
  58. package/views/change-request/TransitionHistory.js +307 -0
  59. package/views/change-request/TransitionHistory.js.map +1 -0
  60. package/views/change-request/TransitionOptions.d.ts +38 -0
  61. package/views/{detail/ChangeRequest/transitions.js → change-request/TransitionOptions.js} +61 -51
  62. package/views/change-request/TransitionOptions.js.map +1 -0
  63. package/views/change-request/objectChangeset.d.ts +7 -4
  64. package/views/change-request/objectChangeset.js +60 -23
  65. package/views/change-request/objectChangeset.js.map +1 -1
  66. package/views/detail/ChangeRequest/index.js +129 -142
  67. package/views/detail/ChangeRequest/index.js.map +1 -1
  68. package/views/detail/RegisterHome/ActiveProposalDetails.d.ts +15 -0
  69. package/views/detail/RegisterHome/ActiveProposalDetails.js +104 -0
  70. package/views/detail/RegisterHome/ActiveProposalDetails.js.map +1 -0
  71. package/views/detail/RegisterHome/Block.d.ts +19 -0
  72. package/views/detail/RegisterHome/Block.js +49 -0
  73. package/views/detail/RegisterHome/Block.js.map +1 -0
  74. package/views/detail/RegisterHome/MetaSummary.d.ts +9 -0
  75. package/views/detail/RegisterHome/MetaSummary.js +39 -0
  76. package/views/detail/RegisterHome/MetaSummary.js.map +1 -0
  77. package/views/detail/RegisterHome/Proposal.d.ts +14 -0
  78. package/views/detail/RegisterHome/Proposal.js +296 -0
  79. package/views/detail/RegisterHome/Proposal.js.map +1 -0
  80. package/views/detail/RegisterHome/index.js +345 -141
  81. package/views/detail/RegisterHome/index.js.map +1 -1
  82. package/views/detail/RegisterItem/index.d.ts +2 -3
  83. package/views/detail/RegisterItem/index.js +238 -140
  84. package/views/detail/RegisterItem/index.js.map +1 -1
  85. package/views/detail/RegisterMeta/RegisterMetaForm.js +37 -45
  86. package/views/detail/RegisterMeta/RegisterMetaForm.js.map +1 -1
  87. package/views/detail/RegisterMeta/index.js +14 -11
  88. package/views/detail/RegisterMeta/index.js.map +1 -1
  89. package/views/diffing/InlineDiff.d.ts +27 -1
  90. package/views/diffing/InlineDiff.js +113 -2
  91. package/views/diffing/InlineDiff.js.map +1 -1
  92. package/views/hooks/useCustomView.js +1 -1
  93. package/views/hooks/useCustomView.js.map +1 -1
  94. package/views/index.js +4 -2
  95. package/views/index.js.map +1 -1
  96. package/views/sidebar/Search/index.js +12 -2
  97. package/views/sidebar/Search/index.js.map +1 -1
  98. package/views/util.d.ts +43 -6
  99. package/views/util.js +240 -11
  100. package/views/util.js.map +1 -1
  101. package/views/detail/ChangeRequest/transitions.d.ts +0 -28
  102. package/views/detail/ChangeRequest/transitions.js.map +0 -1
package/index.d.ts CHANGED
@@ -14,11 +14,9 @@ declare const _default: {
14
14
  BrowserCtx: React.Context<BrowserCtx>;
15
15
  CRITERIA_CONFIGURATION: import("./views/FilterCriteria/models").CriteriaConfiguration;
16
16
  GenericRelatedItemView: React.FC<import("./types").GenericRelatedItemViewProps>;
17
- PropertyDetailView: React.FC<{
18
- title: React.ReactNode;
17
+ PropertyDetailView: React.FC<import("@blueprintjs/core").IFormGroupProps & {
18
+ title?: React.ReactNode;
19
19
  secondaryTitle?: React.ReactNode;
20
- inline?: boolean | undefined;
21
- className?: string | undefined;
22
20
  }>;
23
21
  };
24
22
  export default _default;
package/index.js CHANGED
@@ -9,6 +9,8 @@ var _react = _interopRequireDefault(require("react"));
9
9
 
10
10
  var _paneronExtensionKit = require("@riboseinc/paneron-extension-kit");
11
11
 
12
+ var _ErrorBoundary = _interopRequireDefault(require("@riboseinc/paneron-extension-kit/widgets/ErrorBoundary"));
13
+
12
14
  var _initial = _interopRequireDefault(require("./migrations/initial"));
13
15
 
14
16
  var _views = require("./views");
@@ -30,6 +32,22 @@ const makeRegistryExtension = function (opts) {
30
32
  name
31
33
  } = opts;
32
34
 
35
+ for (const cls of Object.values(opts.itemClassConfiguration)) {
36
+ for (const [viewID, view] of Object.entries(cls.views)) {
37
+ const View = view;
38
+
39
+ if (View) {
40
+ cls.views[viewID] = function WrappedRegisterItemView(...props) {
41
+ return _react.default.createElement(_ErrorBoundary.default, {
42
+ viewName: `Detail view for ${cls.meta.title}`
43
+ }, _react.default.createElement(View, { ...props,
44
+ inline: viewID === 'listItemView'
45
+ }));
46
+ };
47
+ }
48
+ }
49
+ }
50
+
33
51
  const mainView = function _RegistryView() {
34
52
  return _react.default.createElement(_views.RegistryView, {
35
53
  itemClassConfiguration: opts.itemClassConfiguration,
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAIjE,OAAO,kBAAkB,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAQvC,MAAM,CAAC,MAAM,qBAAqB,GAA2B,UAAU,IAAI;IACzE,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;IAEtB,MAAM,QAAQ,GAAoC,SAAS,aAAa;QACtE,OAAO,CACL,oBAAC,YAAY,IACX,sBAAsB,EAAE,IAAI,CAAC,sBAAsB,EACnD,YAAY,EAAE,IAAI,CAAC,YAAY,GAC/B,CACH,CAAC;IACJ,CAAC,CAAC;IAEF,OAAO,aAAa,CAAC;QACnB,QAAQ;QACR,IAAI;QACJ,sBAAsB,EAAE,OAAO;QAC/B,iBAAiB,EAAE,EAAE;QACrB,kBAAkB;KACnB,CAAC,CAAC;AACL,CAAC,CAAC;AAGF,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,iCAAiC,EAAE,MAAM,uBAAuB,CAAC;AAC7F,OAAO,sBAAsB,MAAM,gCAAgC,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,sBAAsB,MAAM,+CAA+C,CAAC;AAEnF,eAAe;IACb,qBAAqB;IACrB,iBAAiB;IACjB,iCAAiC;IACjC,UAAU;IACV,sBAAsB;IACtB,sBAAsB;IACtB,kBAAkB;CACnB,CAAC","sourcesContent":["import React from 'react';\nimport { makeExtension } from '@riboseinc/paneron-extension-kit';\nimport type { Extension } from '@riboseinc/paneron-extension-kit/types';\nimport type { ExtensionMakerProps } from '@riboseinc/paneron-extension-kit/types/extension-maker';\nimport type { RegistryViewProps } from './types';\nimport datasetInitializer from './migrations/initial';\nimport { RegistryView } from './views';\n\nexport type RegistryExtensionMakerProps =\n Pick<ExtensionMakerProps, 'name'> & RegistryViewProps\n\nexport type RegistryExtensionMaker =\n (opts: RegistryExtensionMakerProps) => Promise<Extension>;\n\nexport const makeRegistryExtension: RegistryExtensionMaker = function (opts) {\n const { name } = opts;\n\n const mainView: ExtensionMakerProps[\"mainView\"] = function _RegistryView () {\n return (\n <RegistryView\n itemClassConfiguration={opts.itemClassConfiguration}\n subregisters={opts.subregisters}\n />\n );\n };\n\n return makeExtension({\n mainView,\n name,\n requiredHostAppVersion: '2.0.0',\n datasetMigrations: {},\n datasetInitializer,\n });\n};\n\n\nimport { BrowserCtx } from './views/BrowserCtx';\nimport { itemRefToItemPath, incompleteItemRefToItemPathPrefix } from './views/itemPathUtils';\nimport GenericRelatedItemView from './views/GenericRelatedItemView';\nimport { PropertyDetailView } from './views/util';\nimport CRITERIA_CONFIGURATION from './views/FilterCriteria/CRITERIA_CONFIGURATION';\n\nexport default {\n makeRegistryExtension,\n itemRefToItemPath,\n incompleteItemRefToItemPathPrefix,\n BrowserCtx,\n CRITERIA_CONFIGURATION,\n GenericRelatedItemView,\n PropertyDetailView,\n};\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAEjE,OAAO,aAAa,MAAM,wDAAwD,CAAC;AAInF,OAAO,kBAAkB,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAQvC,MAAM,CAAC,MAAM,qBAAqB,GAA2B,UAAU,IAAI;IACzE,MAAM,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC;IAEtB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,EAAE;QAC5D,KAAK,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;YACtD,MAAM,IAAI,GAAG,IAAW,CAAC;YACzB,IAAI,IAAI,EAAE;gBACR,GAAG,CAAC,KAAK,CAAC,MAAoD,CAAC,GAAG,SAAS,uBAAuB,CAAC,GAAG,KAAK;oBACzG,OAAO,CACL,oBAAC,aAAa,IAAC,QAAQ,EAAE,mBAAmB,GAAG,CAAC,IAAI,CAAC,KAAK,EAAE;wBAC1D,oBAAC,IAAI,OAAK,KAAK,EAAE,MAAM,EAAE,MAAM,KAAK,cAAc,GAAI,CACxC,CACjB,CAAC;gBACJ,CAAC,CAAC;aACH;SACF;KACF;IAED,MAAM,QAAQ,GAAoC,SAAS,aAAa;QACtE,OAAO,CACL,oBAAC,YAAY,IACX,sBAAsB,EAAE,IAAI,CAAC,sBAAsB,EACnD,YAAY,EAAE,IAAI,CAAC,YAAY,GAC/B,CACH,CAAC;IACJ,CAAC,CAAC;IAEF,OAAO,aAAa,CAAC;QACnB,QAAQ;QACR,IAAI;QACJ,sBAAsB,EAAE,OAAO;QAC/B,iBAAiB,EAAE,EAAE;QACrB,kBAAkB;KACnB,CAAC,CAAC;AACL,CAAC,CAAC;AAGF,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,iCAAiC,EAAE,MAAM,uBAAuB,CAAC;AAC7F,OAAO,sBAAsB,MAAM,gCAAgC,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,sBAAsB,MAAM,+CAA+C,CAAC;AAEnF,eAAe;IACb,qBAAqB;IACrB,iBAAiB;IACjB,iCAAiC;IACjC,UAAU;IACV,sBAAsB;IACtB,sBAAsB;IACtB,kBAAkB;CACnB,CAAC","sourcesContent":["import React from 'react';\nimport { makeExtension } from '@riboseinc/paneron-extension-kit';\nimport type { Extension } from '@riboseinc/paneron-extension-kit/types';\nimport ErrorBoundary from '@riboseinc/paneron-extension-kit/widgets/ErrorBoundary';\nimport type { ExtensionMakerProps } from '@riboseinc/paneron-extension-kit/types/extension-maker';\nimport type { RegistryViewProps } from './types';\nimport type { ItemClassConfiguration } from './types/views';\nimport datasetInitializer from './migrations/initial';\nimport { RegistryView } from './views';\n\nexport type RegistryExtensionMakerProps =\n Pick<ExtensionMakerProps, 'name'> & RegistryViewProps\n\nexport type RegistryExtensionMaker =\n (opts: RegistryExtensionMakerProps) => Promise<Extension>;\n\nexport const makeRegistryExtension: RegistryExtensionMaker = function (opts) {\n const { name } = opts;\n\n for (const cls of Object.values(opts.itemClassConfiguration)) {\n for (const [viewID, view] of Object.entries(cls.views)) {\n const View = view as any;\n if (View) {\n cls.views[viewID as keyof ItemClassConfiguration<any>[\"views\"]] = function WrappedRegisterItemView(...props) {\n return (\n <ErrorBoundary viewName={`Detail view for ${cls.meta.title}`}>\n <View {...props} inline={viewID === 'listItemView'} />\n </ErrorBoundary>\n );\n };\n }\n }\n }\n\n const mainView: ExtensionMakerProps[\"mainView\"] = function _RegistryView () {\n return (\n <RegistryView\n itemClassConfiguration={opts.itemClassConfiguration}\n subregisters={opts.subregisters}\n />\n );\n };\n\n return makeExtension({\n mainView,\n name,\n requiredHostAppVersion: '2.0.0',\n datasetMigrations: {},\n datasetInitializer,\n });\n};\n\n\nimport { BrowserCtx } from './views/BrowserCtx';\nimport { itemRefToItemPath, incompleteItemRefToItemPathPrefix } from './views/itemPathUtils';\nimport GenericRelatedItemView from './views/GenericRelatedItemView';\nimport { PropertyDetailView } from './views/util';\nimport CRITERIA_CONFIGURATION from './views/FilterCriteria/CRITERIA_CONFIGURATION';\n\nexport default {\n makeRegistryExtension,\n itemRefToItemPath,\n incompleteItemRefToItemPathPrefix,\n BrowserCtx,\n CRITERIA_CONFIGURATION,\n GenericRelatedItemView,\n PropertyDetailView,\n};\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riboseinc/paneron-registry-kit",
3
- "version": "2.2.10",
3
+ "version": "2.2.12",
4
4
  "main": "index.js",
5
5
  "author": "Ribose Inc. <open.source@ribose.com>",
6
6
  "scripts": {
@@ -28,7 +28,7 @@
28
28
  "@blueprintjs/select": "~4.9.10",
29
29
  "@emotion/react": "^11.10.6",
30
30
  "@emotion/styled": "^11.10.6",
31
- "@riboseinc/paneron-extension-kit": "2.2.6",
31
+ "@riboseinc/paneron-extension-kit": "2.2.10",
32
32
  "@types/react": "17.0.53",
33
33
  "@types/react-dom": "^17.0.2",
34
34
  "@types/react-helmet": "^6.1.2",
@@ -0,0 +1,3 @@
1
+ import type { ExporterConstructor } from '@riboseinc/paneron-extension-kit/types/export-formats';
2
+ declare const exporter: ExporterConstructor;
3
+ export default exporter;
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _common = require("../common");
9
+
10
+ var _register = require("../types/register");
11
+
12
+ var _page = _interopRequireDefault(require("./page"));
13
+
14
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
+
16
+ //import type { RegisterItem } from '../types/item';
17
+ //import { REGISTER_ITEM_QUERY } from '../views/itemQueryUtils';
18
+ const exporter = async function* exportPublicSite({
19
+ getObjectData,
20
+ getMapReducedData,
21
+ onProgress
22
+ }) {
23
+ const registerMeta = (await getObjectData({
24
+ objectPaths: [`/${_common.REGISTER_METADATA_FILENAME}`]
25
+ })).data[`/${_common.REGISTER_METADATA_FILENAME}`];
26
+
27
+ if (!(0, _register.isRegisterMetadata)(registerMeta)) {
28
+ throw new Error("Invalid register metadata found");
29
+ } //const itemsByClass: { [clsID: string]: RegisterItem<any> } = await getMapReducedData({
30
+ // chains: {
31
+ // byClass: {
32
+ // mapFunc: PUBLIC_ITEM_MAPPER,
33
+ // reduceFunc: PUBLIC_ITEM_REDUCER,
34
+ // },
35
+ // },
36
+ //});
37
+ //const classIDs = Object.keys(itemsByClass);
38
+
39
+
40
+ yield {
41
+ '/hello.txt': enc.encode('hello'),
42
+ '/index.html': enc.encode((0, _page.default)({
43
+ title: "Register"
44
+ })),
45
+ '/register-meta.json': enc.encode(JSON.stringify(registerMeta))
46
+ };
47
+ };
48
+
49
+ var _default = exporter;
50
+ exports.default = _default;
51
+ const enc = new TextEncoder(); // const PUBLIC_ITEM_PREDICATE = `
52
+ // (${REGISTER_ITEM_QUERY}) && obj.status === 'valid'
53
+ // `;
54
+ //
55
+ // /** Emits register items keyed by class ID. */
56
+ //const PUBLIC_ITEM_MAPPER = `
57
+ // if (${PUBLIC_ITEM_PREDICATE}) {
58
+ // const pathWithoutSubregister = objPath.replace(/^\/subregisters/, '');
59
+ // const components = pathWithoutSubregister.split('/');
60
+ // const clsID = components[1];
61
+ // emit([clsID, obj]);
62
+ // }
63
+ //`;
64
+ //
65
+ //const PUBLIC_ITEM_REDUCER = `
66
+ // const acc = accumulator ?? {};
67
+ //
68
+ // // value[0] is item class ID
69
+ // acc[value[0]] ??= [];
70
+ //
71
+ // // value[1] is full register item data
72
+ // acc[value[0]].push(value[1]);
73
+ //
74
+ // return acc;
75
+ //`;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/site-builder/index.ts"],"names":[],"mappings":"AAEA,oDAAoD;AACpD,OAAO,EAAE,0BAA0B,EAAE,MAAM,WAAW,CAAC;AACvD,gEAAgE;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,OAAO,MAAM,QAAQ,CAAC;AAG7B,MAAM,QAAQ,GAAwB,KAAK,SAAU,CAAC,CAAC,gBAAgB,CAAC,EACtE,aAAa,EACb,iBAAiB,EACjB,UAAU,GACX;IACC,MAAM,YAAY,GAAG,CAAC,MAAM,aAAa,CAAC;QACxC,WAAW,EAAE,CAAC,IAAI,0BAA0B,EAAE,CAAC;KAChD,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,0BAA0B,EAAE,CAAC,CAAC;IAE3C,IAAI,CAAC,kBAAkB,CAAC,YAAY,CAAC,EAAE;QACrC,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;KACpD;IAED,wFAAwF;IACxF,aAAa;IACb,gBAAgB;IAChB,oCAAoC;IACpC,wCAAwC;IACxC,QAAQ;IACR,MAAM;IACN,KAAK;IAEL,6CAA6C;IAE7C,MAAM;QACJ,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC;QACjC,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,CAAC;QACzD,qBAAqB,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;KAChE,CAAC;AACJ,CAAC,CAAC;AAGF,eAAe,QAAQ,CAAC;AAGxB,MAAM,GAAG,GAAG,IAAI,WAAW,EAAE,CAAC;AAG9B,kCAAkC;AAClC,uDAAuD;AACvD,KAAK;AACL,GAAG;AACH,iDAAiD;AACjD,8BAA8B;AAC9B,mCAAmC;AACnC,4EAA4E;AAC5E,2DAA2D;AAC3D,kCAAkC;AAClC,yBAAyB;AACzB,KAAK;AACL,IAAI;AACJ,EAAE;AACF,+BAA+B;AAC/B,kCAAkC;AAClC,EAAE;AACF,gCAAgC;AAChC,yBAAyB;AACzB,EAAE;AACF,0CAA0C;AAC1C,iCAAiC;AACjC,EAAE;AACF,eAAe;AACf,IAAI","sourcesContent":["import type { BufferDataset } from '@riboseinc/paneron-extension-kit/types/buffers';\nimport type { ExporterConstructor } from '@riboseinc/paneron-extension-kit/types/export-formats';\n//import type { RegisterItem } from '../types/item';\nimport { REGISTER_METADATA_FILENAME } from '../common'; \n//import { REGISTER_ITEM_QUERY } from '../views/itemQueryUtils';\nimport { isRegisterMetadata } from '../types/register';\nimport getHTML from './page';\n\n\nconst exporter: ExporterConstructor = async function * exportPublicSite({\n getObjectData,\n getMapReducedData,\n onProgress,\n}): AsyncGenerator<BufferDataset, void, void> {\n const registerMeta = (await getObjectData({\n objectPaths: [`/${REGISTER_METADATA_FILENAME}`],\n })).data[`/${REGISTER_METADATA_FILENAME}`];\n\n if (!isRegisterMetadata(registerMeta)) {\n throw new Error(\"Invalid register metadata found\");\n }\n\n //const itemsByClass: { [clsID: string]: RegisterItem<any> } = await getMapReducedData({\n // chains: {\n // byClass: {\n // mapFunc: PUBLIC_ITEM_MAPPER,\n // reduceFunc: PUBLIC_ITEM_REDUCER,\n // },\n // },\n //});\n\n //const classIDs = Object.keys(itemsByClass);\n\n yield {\n '/hello.txt': enc.encode('hello'),\n '/index.html': enc.encode(getHTML({ title: \"Register\" })),\n '/register-meta.json': enc.encode(JSON.stringify(registerMeta)),\n };\n};\n\n\nexport default exporter;\n\n\nconst enc = new TextEncoder();\n\n\n// const PUBLIC_ITEM_PREDICATE = `\n// (${REGISTER_ITEM_QUERY}) && obj.status === 'valid'\n// `;\n// \n// /** Emits register items keyed by class ID. */\n//const PUBLIC_ITEM_MAPPER = `\n// if (${PUBLIC_ITEM_PREDICATE}) {\n// const pathWithoutSubregister = objPath.replace(/^\\/subregisters/, '');\n// const components = pathWithoutSubregister.split('/');\n// const clsID = components[1];\n// emit([clsID, obj]);\n// }\n//`;\n//\n//const PUBLIC_ITEM_REDUCER = `\n// const acc = accumulator ?? {};\n//\n// // value[0] is item class ID\n// acc[value[0]] ??= [];\n//\n// // value[1] is full register item data\n// acc[value[0]].push(value[1]);\n//\n// return acc;\n//`;\n"]}
@@ -0,0 +1,18 @@
1
+ export declare namespace JSX {
2
+ type Element = string;
3
+ interface IntrinsicElements {
4
+ [el: string]: any;
5
+ }
6
+ }
7
+ declare type AttributeValue = number | string | Date | boolean;
8
+ export interface Children {
9
+ children?: string | string[];
10
+ }
11
+ export interface CustomElementHandler {
12
+ (attributes: Attributes & Children, contents: string[]): string;
13
+ }
14
+ export interface Attributes {
15
+ [key: string]: AttributeValue;
16
+ }
17
+ declare function createElement(name: string | CustomElementHandler, attributes: Attributes & Children | undefined, ...contents: string[]): string;
18
+ export { createElement as jsxs, createElement as jsx };
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.jsx = exports.jsxs = createElement;
7
+ const capitalACharCode = 'A'.charCodeAt(0);
8
+ const capitalZCharCode = 'Z'.charCodeAt(0);
9
+
10
+ function isUpper(input, index) {
11
+ const charCode = input.charCodeAt(index);
12
+ return capitalACharCode <= charCode && capitalZCharCode >= charCode;
13
+ }
14
+
15
+ ;
16
+
17
+ function toKebabCase(camelCased) {
18
+ let kebabCased = '';
19
+
20
+ for (let i = 0; i < camelCased.length; i++) {
21
+ const prevUpperCased = i > 0 ? isUpper(camelCased, i - 1) : true;
22
+ const currentUpperCased = isUpper(camelCased, i);
23
+ const nextUpperCased = i < camelCased.length - 1 ? isUpper(camelCased, i + 1) : true;
24
+
25
+ if (!prevUpperCased && currentUpperCased || currentUpperCased && !nextUpperCased) {
26
+ kebabCased += '-';
27
+ kebabCased += camelCased[i].toLowerCase();
28
+ } else {
29
+ kebabCased += camelCased[i];
30
+ }
31
+ }
32
+
33
+ return kebabCased;
34
+ }
35
+
36
+ ;
37
+
38
+ function escapeAttrNodeValue(value) {
39
+ return value.replace(/(&)|(")|(\u00A0)/g, (_, amp, quote) => {
40
+ if (amp) {
41
+ return '&amp;';
42
+ } else if (quote) {
43
+ return '&quot;';
44
+ } else {
45
+ return '&nbsp;';
46
+ }
47
+ });
48
+ }
49
+
50
+ ;
51
+
52
+ function getAttributeStringifier(attributes) {
53
+ return function attributeToString(name) {
54
+ const value = attributes[name];
55
+ const formattedName = toKebabCase(name);
56
+
57
+ const makeAttribute = value => `${formattedName}="${value}"`;
58
+
59
+ if (value instanceof Date) {
60
+ return makeAttribute(value.toISOString());
61
+ } else switch (typeof value) {
62
+ case 'boolean':
63
+ if (value) {
64
+ return formattedName;
65
+ } else {
66
+ return '';
67
+ }
68
+
69
+ default:
70
+ return makeAttribute(escapeAttrNodeValue(value.toString()));
71
+ }
72
+ };
73
+ }
74
+
75
+ ;
76
+
77
+ function attributesToString(attributes) {
78
+ const spaceSeparated = Object.keys(attributes).filter(attribute => attribute !== 'children').map(getAttributeStringifier(attributes)).filter(attribute => attribute.length).join(' ');
79
+
80
+ if (spaceSeparated.trim()) {
81
+ return ` ${spaceSeparated}`;
82
+ } else {
83
+ return '';
84
+ }
85
+ }
86
+
87
+ ;
88
+
89
+ function contentsToString(contents) {
90
+ var _a;
91
+
92
+ return (_a = contents.map(elements => Array.isArray(elements) ? elements.join('\n') : elements).join('\n')) !== null && _a !== void 0 ? _a : '';
93
+ }
94
+
95
+ ;
96
+
97
+ function createElement(name, attributes, ...contents) {
98
+ if (typeof name === 'function') {
99
+ return name(attributes !== null && attributes !== void 0 ? attributes : {}, contents);
100
+ } else {
101
+ const tagName = toKebabCase(name);
102
+ const inner1 = contentsToString(contents);
103
+ const inner2 = (attributes === null || attributes === void 0 ? void 0 : attributes.children) ? contentsToString(Array.isArray(attributes.children) ? attributes.children : [attributes.children]) : '';
104
+ const inner = inner1 && inner2 ? `${inner1}\n${inner2}` : inner1 || inner2;
105
+ return `<${tagName}${attributes ? attributesToString(attributes) : ''}>${inner}</${tagName}>`;
106
+ }
107
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsx-runtime.js","sourceRoot":"","sources":["../../src/site-builder/jsx-runtime.ts"],"names":[],"mappings":"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","sourcesContent":["export namespace JSX {\n export type Element = string;\n export interface IntrinsicElements {\n [el: string]: any\n }\n}\n\ntype AttributeValue = number | string | Date | boolean;\n\nexport interface Children {\n children?: string | string[];\n}\n\nexport interface CustomElementHandler {\n (attributes: Attributes & Children, contents: string[]): string;\n}\n\nexport interface Attributes {\n [key: string]: AttributeValue;\n}\n\nconst capitalACharCode = 'A'.charCodeAt(0);\nconst capitalZCharCode = 'Z'.charCodeAt(0);\n\nfunction isUpper(input: string, index: number) {\n const charCode = input.charCodeAt(index);\n return capitalACharCode <= charCode && capitalZCharCode >= charCode;\n};\n\nfunction toKebabCase(camelCased: string) {\n let kebabCased = '';\n for (let i = 0; i < camelCased.length; i++) {\n const prevUpperCased = i > 0 ? isUpper(camelCased, i - 1) : true;\n const currentUpperCased = isUpper(camelCased, i);\n const nextUpperCased = i < camelCased.length - 1 ? isUpper(camelCased, i + 1) : true;\n if (!prevUpperCased && currentUpperCased || currentUpperCased && !nextUpperCased) {\n kebabCased += '-';\n kebabCased += camelCased[i].toLowerCase();\n } else {\n kebabCased += camelCased[i];\n }\n }\n return kebabCased;\n};\n\nfunction escapeAttrNodeValue(value: string) {\n return (\n value.replace(/(&)|(\")|(\\u00A0)/g, (_, amp, quote) => {\n if (amp) { return '&amp;'; }\n else if (quote) { return '&quot;'; }\n else { return '&nbsp;'; }\n })\n );\n};\n\nfunction getAttributeStringifier(attributes: Attributes) {\n return function attributeToString(name: string): string {\n const value = attributes[name];\n const formattedName = toKebabCase(name);\n const makeAttribute = (value: string) => `${formattedName}=\"${value}\"`;\n\n if (value instanceof Date) {\n return makeAttribute(value.toISOString());\n } else switch (typeof value) {\n case 'boolean':\n if (value) {\n return formattedName;\n } else {\n return '';\n }\n default:\n return makeAttribute(escapeAttrNodeValue(value.toString()));\n }\n }\n};\n\nfunction attributesToString(attributes: Attributes) {\n const spaceSeparated = Object.keys(attributes).\n filter(attribute => attribute !== 'children').\n map(getAttributeStringifier(attributes)).\n filter(attribute => attribute.length).\n join(' ');\n if (spaceSeparated.trim()) {\n return ` ${spaceSeparated}`;\n } else {\n return '';\n }\n};\n\nfunction contentsToString(contents: string[]) {\n return contents.\n map(elements => Array.isArray(elements) ? elements.join('\\n') : elements).\n join('\\n') ?? ''\n};\n\nfunction createElement(\n name: string | CustomElementHandler,\n attributes: Attributes & Children | undefined,\n ...contents: string[]\n): string {\n if (typeof name === 'function') {\n return name(attributes ?? {}, contents);\n } else {\n const tagName = toKebabCase(name);\n const inner1 = contentsToString(contents);\n const inner2 = attributes?.children\n ? contentsToString(\n Array.isArray(attributes.children)\n ? attributes.children\n : [attributes.children]\n )\n : '';\n const inner = inner1 && inner2\n ? `${inner1}\\n${inner2}`\n : inner1 || inner2;\n return `<${tagName}${attributes ? attributesToString(attributes) : ''}>${inner}</${tagName}>`;\n }\n}\n\nexport { createElement as jsxs, createElement as jsx }\n"]}
@@ -0,0 +1,6 @@
1
+ /** @jsxImportSource . */
2
+ interface PageMeta {
3
+ title: string;
4
+ }
5
+ export default function getHTML(meta: PageMeta): string;
6
+ export {};
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = getHTML;
7
+
8
+ var _jsxRuntime = require("./jsx-runtime");
9
+
10
+ function getHTML(meta) {
11
+ return (0, _jsxRuntime.jsxs)("html", {
12
+ children: [(0, _jsxRuntime.jsx)("head", {
13
+ children: (0, _jsxRuntime.jsx)("title", {
14
+ children: meta.title
15
+ })
16
+ }), (0, _jsxRuntime.jsx)("body", {
17
+ children: (0, _jsxRuntime.jsx)("div", {
18
+ children: "test"
19
+ })
20
+ })]
21
+ });
22
+ }
23
+
24
+ ;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page.js","sourceRoot":"","sources":["../../src/site-builder/page.tsx"],"names":[],"mappings":";AAQA,MAAM,CAAC,OAAO,UAAU,OAAO,CAAC,IAAc;IAC5C,OAAO,2BACL,yBACE,0BAAQ,IAAI,CAAC,KAAK,GAAS,GACtB,EACP,yBACE,iCAAe,GACV,IACF,CAAC;AACV,CAAC;AAAA,CAAC","sourcesContent":["/** @jsxImportSource . */\n\n\ninterface PageMeta {\n title: string\n}\n\n\nexport default function getHTML(meta: PageMeta): string {\n return <html>\n <head>\n <title>{meta.title}</title>\n </head>\n <body>\n <div>test</div>\n </body>\n </html>;\n};\n\n// XXX: Write `getHead()`\n"]}
package/types/cr.d.ts CHANGED
@@ -49,9 +49,26 @@ export interface Base<S extends StateType = StateType> {
49
49
  * A link to external discussion.
50
50
  */
51
51
  externalDiscussionURI?: string;
52
+ pastTransitions?: TransitionEntry[];
53
+ }
54
+ export interface TransitionEntry {
55
+ /** Verb in past tense. */
56
+ label: string;
57
+ timestamp: Date;
58
+ fromState: StateType;
59
+ toState: StateType;
60
+ stakeholder: RegisterStakeholder;
61
+ input: StateInput;
52
62
  }
53
63
  export declare function isCreatedBy(stakeholder: RegisterStakeholder, cr: Base): boolean;
64
+ /** Whether given `cr` can be edited (as in, items changed) by specified stakeholder. */
54
65
  export declare function canBeEditedBy(stakeholder: RegisterStakeholder, cr: Base): boolean;
66
+ /**
67
+ * Whether given `cr` can be deleted by given stakeholder.
68
+ * Unlike editing, deletion is possible only if there are no items
69
+ * and CR was never proposed.
70
+ */
71
+ export declare function canBeDeletedBy(stakeholder: RegisterStakeholder, cr: Base): boolean;
55
72
  /** Proposal structure for single-file proposal import format. */
56
73
  export interface ImportableCR {
57
74
  /** Proposal data. */
@@ -91,10 +108,12 @@ export declare function isDisposed(cr: Base): cr is Base & {
91
108
  };
92
109
  export interface SubmittedForControlBodyReview extends Omit<Proposed, 'state'>, RegisterManagerInput, Base<typeof State.SUBMITTED_FOR_CONTROL_BODY_REVIEW> {
93
110
  }
111
+ export declare function isSubmittedForControlBodyReview(cr: Base): cr is SubmittedForControlBodyReview;
94
112
  export interface ReturnedForClarificationByManager extends Omit<Proposed, 'state'>, RegisterManagerInput, Base<typeof State.RETURNED_FOR_CLARIFICATION> {
95
113
  }
96
114
  export interface ReturnedForClarificationByControlBody extends Omit<SubmittedForControlBodyReview, 'state'>, ControlBodyInput, Base<typeof State.RETURNED_FOR_CLARIFICATION> {
97
115
  }
116
+ export declare function isReturnedForClarification(cr: Base): cr is (ReturnedForClarificationByManager | ReturnedForClarificationByControlBody);
98
117
  export interface Accepted extends Omit<SubmittedForControlBodyReview, 'state'>, ControlBodyInput, Base<typeof State.ACCEPTED> {
99
118
  timeDisposed: Date;
100
119
  }
@@ -102,6 +121,7 @@ export declare function isAccepted(cr: Base): cr is Accepted;
102
121
  export interface Rejected extends Omit<SubmittedForControlBodyReview, 'state'>, ControlBodyInput, Base<typeof State.REJECTED> {
103
122
  timeDisposed: Date;
104
123
  }
124
+ export declare function isRejected(cr: Base): cr is Rejected;
105
125
  export interface Appealed extends Omit<Rejected, 'state' | 'timeDisposed'>, AppealRequest, Base<typeof State.APPEALED> {
106
126
  timeDisposed: undefined;
107
127
  }
@@ -109,6 +129,7 @@ export declare function isAppealed(cr: Base): cr is Appealed;
109
129
  export interface RejectionUpheld extends Omit<Appealed, 'state' | 'timeDisposed'>, RegisterOwnerInput, Base<typeof State.REJECTION_UPHELD_ON_APPEAL> {
110
130
  timeDisposed: Date;
111
131
  }
132
+ export declare function isRejectedOnAppeal(cr: Base): cr is RejectionUpheld;
112
133
  export interface AcceptedOnAppeal extends Omit<Appealed, 'state' | 'timeDisposed'>, RegisterOwnerInput, Base<typeof State.ACCEPTED_ON_APPEAL> {
113
134
  timeDisposed: Date;
114
135
  }
@@ -116,6 +137,7 @@ export declare function isAcceptedOnAppeal(cr: Base): cr is AcceptedOnAppeal;
116
137
  export interface RejectedWithAppealWithdrawn extends Omit<Appealed, 'state' | 'timeDisposed'>, Base<typeof State.APPEAL_WITHDRAWN> {
117
138
  timeDisposed: Date;
118
139
  }
140
+ export declare function isRejectedWithAppealWithdrawn(cr: Base): cr is RejectedWithAppealWithdrawn;
119
141
  export interface SubmitterInput {
120
142
  justification: string;
121
143
  }
package/types/cr.js CHANGED
@@ -8,15 +8,21 @@ exports.isState = isState;
8
8
  exports.isEditableState = isEditableState;
9
9
  exports.isCreatedBy = isCreatedBy;
10
10
  exports.canBeEditedBy = canBeEditedBy;
11
+ exports.canBeDeletedBy = canBeDeletedBy;
11
12
  exports.isImportableCR = isImportableCR;
12
13
  exports.isDrafted = isDrafted;
13
14
  exports.isProposed = isProposed;
14
15
  exports.isWithdrawn = isWithdrawn;
15
16
  exports.hadBeenProposed = hadBeenProposed;
16
17
  exports.isDisposed = isDisposed;
18
+ exports.isSubmittedForControlBodyReview = isSubmittedForControlBodyReview;
19
+ exports.isReturnedForClarification = isReturnedForClarification;
17
20
  exports.isAccepted = isAccepted;
21
+ exports.isRejected = isRejected;
18
22
  exports.isAppealed = isAppealed;
23
+ exports.isRejectedOnAppeal = isRejectedOnAppeal;
19
24
  exports.isAcceptedOnAppeal = isAcceptedOnAppeal;
25
+ exports.isRejectedWithAppealWithdrawn = isRejectedWithAppealWithdrawn;
20
26
  exports.hasSubmitterInput = hasSubmitterInput;
21
27
  exports.hasRegisterManagerInput = hasRegisterManagerInput;
22
28
  exports.hasControlBodyInput = hasControlBodyInput;
@@ -65,12 +71,26 @@ function isEditableState(state) {
65
71
  }
66
72
 
67
73
  function isCreatedBy(stakeholder, cr) {
68
- return stakeholder.gitServerUsername === cr.submittingStakeholderGitServerUsername;
74
+ var _a;
75
+
76
+ return ((_a = stakeholder.gitServerUsername) === null || _a === void 0 ? void 0 : _a.trim()) !== '' && stakeholder.gitServerUsername === cr.submittingStakeholderGitServerUsername;
69
77
  }
78
+ /** Whether given `cr` can be edited (as in, items changed) by specified stakeholder. */
79
+
70
80
 
71
81
  function canBeEditedBy(stakeholder, cr) {
72
82
  return isCreatedBy(stakeholder, cr) && isEditableState(cr.state);
73
83
  }
84
+ /**
85
+ * Whether given `cr` can be deleted by given stakeholder.
86
+ * Unlike editing, deletion is possible only if there are no items
87
+ * and CR was never proposed.
88
+ */
89
+
90
+
91
+ function canBeDeletedBy(stakeholder, cr) {
92
+ return isCreatedBy(stakeholder, cr) && isEditableState(cr.state) && Object.keys(cr.items).length < 1 && !cr.timeProposed;
93
+ }
74
94
 
75
95
  function isImportableCR(val) {
76
96
  // TODO: More complete check
@@ -103,18 +123,38 @@ function isDisposed(cr) {
103
123
  //].some(s => cr.state === s);
104
124
  }
105
125
 
126
+ function isSubmittedForControlBodyReview(cr) {
127
+ return isInState(cr, State.SUBMITTED_FOR_CONTROL_BODY_REVIEW);
128
+ }
129
+
130
+ function isReturnedForClarification(cr) {
131
+ return isInState(cr, State.RETURNED_FOR_CLARIFICATION);
132
+ }
133
+
106
134
  function isAccepted(cr) {
107
135
  return isInState(cr, State.ACCEPTED);
108
136
  }
109
137
 
138
+ function isRejected(cr) {
139
+ return isInState(cr, State.REJECTED);
140
+ }
141
+
110
142
  function isAppealed(cr) {
111
143
  return isInState(cr, State.APPEALED);
112
144
  }
113
145
 
146
+ function isRejectedOnAppeal(cr) {
147
+ return isInState(cr, State.REJECTION_UPHELD_ON_APPEAL);
148
+ }
149
+
114
150
  function isAcceptedOnAppeal(cr) {
115
151
  return isInState(cr, State.ACCEPTED_ON_APPEAL);
116
152
  }
117
153
 
154
+ function isRejectedWithAppealWithdrawn(cr) {
155
+ return isInState(cr, State.APPEAL_WITHDRAWN);
156
+ }
157
+
118
158
  function hasSubmitterInput(val) {
119
159
  return val.hasOwnProperty('justification') && typeof val.justification === 'string';
120
160
  }
package/types/cr.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cr.js","sourceRoot":"","sources":["../../src/types/cr.ts"],"names":[],"mappings":"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","sourcesContent":["/** Change request types, states and state transitions. */\n\nimport type React from 'react';\nimport type { ProposalSet } from './proposal';\nimport { type RegisterStakeholder } from './stakeholder';\nimport type { RegisterItem } from './item';\n\n\n\nexport function isSubmittedBy(stakeholder: RegisterStakeholder, cr: Base): boolean {\n return (\n //isSubmitter(stakeholder) &&\n stakeholder.gitServerUsername === cr.submittingStakeholderGitServerUsername);\n}\n\n\n\n// =====================\n// Change request states\n// =====================\n\n/** Used in place of enum for convenience. */\nexport const State = {\n DRAFT: 'draft',\n PROPOSED: 'proposed',\n SUBMITTED_FOR_CONTROL_BODY_REVIEW: 'pending-control-body-review',\n RETURNED_FOR_CLARIFICATION: 'returned-for-clarification',\n WITHDRAWN: 'withdrawn',\n ACCEPTED: 'accepted',\n REJECTED: 'rejected',\n APPEALED: 'rejection-appealed-to-owner',\n ACCEPTED_ON_APPEAL: 'accepted-on-appeal',\n REJECTION_UPHELD_ON_APPEAL: 'rejection-upheld-on-appeal',\n APPEAL_WITHDRAWN: 'appeal-withdrawn',\n} as const;\n\nexport type StateType = typeof State[keyof typeof State];\n\nexport function isState(val: string): val is StateType {\n return Object.values(State).indexOf(val as StateType) >= 0;\n}\n\n/** A subset of `State` that represents editable states. */\nexport const EditableState = [\n State.DRAFT,\n State.RETURNED_FOR_CLARIFICATION,\n] as const;\n\nexport type EditableStateType = StateType & typeof EditableState[number];\n\nexport function isEditableState(state: StateType): state is EditableStateType {\n return EditableState.indexOf(state as EditableStateType) >= 0;\n}\n\n\n\n// ======================\n// Change request classes\n// ======================\n\n/**\n * Base change request type.\n *\n * Note that e.g. type Base<typeof State.DRAFT> does not equal to Drafted\n * because Drafted includes additional information (namely, SubmitterInput).\n *\n * If the state of a CR matters, this type should not be used directly\n * and concrete types should be used instead.\n */\nexport interface Base<S extends StateType = StateType>\n{\n id: string;\n // decision: typeof Decision[keyof typeof Decision]\n // disposition?: typeof Disposition[keyof typeof Disposition]\n state: S;\n\n /**\n * Used to match against stakeholders declared in register metadata.\n */\n submittingStakeholderGitServerUsername: string;\n\n items: ProposalSet;\n\n /**\n * Against to which register version changes were proposed.\n */\n registerVersion: string;\n\n /**\n * A link to external discussion.\n */\n externalDiscussionURI?: string;\n}\n\n\nexport function isCreatedBy(stakeholder: RegisterStakeholder, cr: Base): boolean {\n return stakeholder.gitServerUsername === cr.submittingStakeholderGitServerUsername;\n}\n\nexport function canBeEditedBy(stakeholder: RegisterStakeholder, cr: Base): boolean {\n return isCreatedBy(stakeholder, cr) && isEditableState(cr.state);\n}\n\n\n/** Proposal structure for single-file proposal import format. */\nexport interface ImportableCR {\n /** Proposal data. */\n proposalDraft: Drafted,\n /** Register item data for additions & clarifications. */\n itemPayloads: Record<string, RegisterItem<any>>,\n}\nexport function isImportableCR(val: any): val is ImportableCR {\n // TODO: More complete check\n return (\n val.proposalDraft.id\n && isDrafted(val.proposalDraft as Base)\n && Object.keys(val.itemPayloads).length > 0);\n}\n\n\n/**\n * A change request in any state.\n * Contains a superset of all possible properties, but all optional.\n * XXX: ^^^ This is a lie. Should be changed from | to & with Partial<>?\n */\nexport type SomeCR = \n | Drafted\n | Proposed\n | Withdrawn\n | ReturnedForClarificationByManager\n | SubmittedForControlBodyReview\n | ReturnedForClarificationByControlBody\n | Accepted\n | Rejected\n | RejectionUpheld\n | AcceptedOnAppeal\n | RejectedWithAppealWithdrawn;\n\nexport type Withdrawable =\n | Proposed\n | SubmittedForControlBodyReview\n | ReturnedForClarificationByManager\n | ReturnedForClarificationByControlBody;\n\nexport type Proposable =\n | Drafted\n | ReturnedForClarificationByManager\n | ReturnedForClarificationByControlBody;\n\nexport type SomeEditable =\n | Drafted\n | ReturnedForClarificationByManager\n | ReturnedForClarificationByControlBody;\n\nexport type Disposed =\n | Withdrawn\n | Accepted\n | Rejected\n | AcceptedOnAppeal\n | RejectionUpheld;\n\n\n// More specific change request types.\n// TODO: Refactor to avoid confusiong between current state e.g. Proposed)\n// and type (Proposed, to which all inheriting classes also conform)\n\nexport interface Drafted extends\n SubmitterInput,\n Base<typeof State.DRAFT> { timeStarted: Date, timeEdited: Date }\nexport function isDrafted(cr: Base): cr is Drafted {\n return isInState(cr, State.DRAFT);\n}\n\nexport interface Proposed extends\n Omit<Drafted, 'state'>,\n Base<typeof State.PROPOSED> { timeProposed: Date }\nexport function isProposed(cr: Base): cr is Proposed {\n return isInState(cr, State.PROPOSED);\n}\n\nexport interface Withdrawn extends\n Omit<Withdrawable, 'state'>,\n Base<typeof State.WITHDRAWN> { timeDisposed: Date }\nexport function isWithdrawn(cr: Base): cr is Withdrawn {\n return isInState(cr, State.WITHDRAWN);\n}\n\nexport function hadBeenProposed(cr: Base): cr is Base & { timeProposed: Date } {\n return cr && cr.hasOwnProperty('timeProposed') && !!(cr as Proposed).timeProposed;\n}\nexport function isDisposed(cr: Base): cr is Base & { timeDisposed: Date } {\n return cr && cr.hasOwnProperty('timeDisposed') && !!(cr as Disposed).timeDisposed;\n //return [\n // State.WITHDRAWN,\n // State.ACCEPTED,\n // State.REJECTED,\n // State.REJECTION_UPHELD_ON_APPEAL,\n // State.ACCEPTED_ON_APPEAL,\n //].some(s => cr.state === s);\n}\n\nexport interface SubmittedForControlBodyReview extends\n Omit<Proposed, 'state'>,\n RegisterManagerInput,\n Base<typeof State.SUBMITTED_FOR_CONTROL_BODY_REVIEW> {}\n\nexport interface ReturnedForClarificationByManager extends\n Omit<Proposed, 'state'>,\n RegisterManagerInput,\n Base<typeof State.RETURNED_FOR_CLARIFICATION> {}\n\nexport interface ReturnedForClarificationByControlBody extends\n Omit<SubmittedForControlBodyReview, 'state'>,\n ControlBodyInput,\n Base<typeof State.RETURNED_FOR_CLARIFICATION> {}\n\nexport interface Accepted extends\n Omit<SubmittedForControlBodyReview, 'state'>,\n ControlBodyInput,\n Base<typeof State.ACCEPTED> { timeDisposed: Date }\nexport function isAccepted(cr: Base): cr is Accepted {\n return isInState(cr, State.ACCEPTED);\n}\n\nexport interface Rejected extends\n Omit<SubmittedForControlBodyReview, 'state'>,\n ControlBodyInput,\n Base<typeof State.REJECTED> { timeDisposed: Date }\n\nexport interface Appealed extends\n Omit<Rejected, 'state' | 'timeDisposed'>,\n AppealRequest,\n Base<typeof State.APPEALED> { timeDisposed: undefined }\nexport function isAppealed(cr: Base): cr is Appealed {\n return isInState(cr, State.APPEALED);\n}\n\nexport interface RejectionUpheld extends\n Omit<Appealed, 'state' | 'timeDisposed'>,\n RegisterOwnerInput,\n Base<typeof State.REJECTION_UPHELD_ON_APPEAL> { timeDisposed: Date }\n\nexport interface AcceptedOnAppeal extends\n Omit<Appealed, 'state' | 'timeDisposed'>,\n RegisterOwnerInput,\n Base<typeof State.ACCEPTED_ON_APPEAL> { timeDisposed: Date }\nexport function isAcceptedOnAppeal(cr: Base): cr is AcceptedOnAppeal {\n return isInState(cr, State.ACCEPTED_ON_APPEAL);\n}\n\nexport interface RejectedWithAppealWithdrawn extends\n Omit<Appealed, 'state' | 'timeDisposed'>,\n Base<typeof State.APPEAL_WITHDRAWN> { timeDisposed: Date }\n\n\n\n// Input required when transitioning to different states\n\nexport interface SubmitterInput {\n justification: string;\n}\nexport function hasSubmitterInput(val: any): val is SubmitterInput {\n return val.hasOwnProperty('justification') && typeof val.justification === 'string';\n}\nexport interface RegisterManagerInput {\n registerManagerNotes: string;\n}\nexport function hasRegisterManagerInput(val: any): val is RegisterManagerInput {\n return val.hasOwnProperty('registerManagerNotes') && typeof val.registerManagerNotes === 'string';\n}\nexport interface ControlBodyInput {\n controlBodyNotes: string;\n}\nexport function hasControlBodyInput(val: any): val is ControlBodyInput {\n return (\n val.hasOwnProperty('controlBodyNotes') && typeof val.controlBodyNotes === 'string' &&\n val.hasOwnProperty('controlBodyDecisionEvent') && typeof val.controlBodyDecisionEvent === 'string');\n}\nexport interface AppealRequest {\n appealReason: string;\n}\nexport function hasAppealRequest(val: any): val is AppealRequest {\n return val.hasOwnProperty('appealReason') && typeof val.appealReason === 'string';\n}\nexport interface RegisterOwnerInput {\n registerOwnerNotes: string;\n}\nexport function hasRegisterOwnerInput(val: any): val is RegisterOwnerInput {\n return val.hasOwnProperty('registerOwnerNotes') && typeof val.registerOwnerNotes === 'string';\n}\n\nexport type StateInput =\n | SubmitterInput\n | RegisterManagerInput\n | ControlBodyInput\n | AppealRequest\n | RegisterOwnerInput;\n\n\n/** \n * CR type guard helper.\n * Normally you would not use it directly and instead use\n * more specific is[Type]() helper from this module.\n *\n * Checks CR type using the `state` property.\n * Does not validate other properties.\n *\n * Usage:\n *\n * @example\n * ```ts\n * let someCR;\n * if (isInState<Drafted>(someCR, State.DRAFT)) {\n * // Can assume someCR is Drafted\n * }\n * ```\n *\n * It’ll try to tell you if you mismatch those.\n *\n * @example\n * Will not compile:\n * ```ts\n * let someCR;\n * if (isInState<Drafted>(someCR, State.PROPOSED)) {\n * // Compile error\n * // because State.PROPOSED is not a possible value of Drafted[\"state\"]\n * }\n * ```\n *\n * @example\n * Incorrect usage (do not do this):\n * ```ts\n * let someCR;\n * if (isInState(someCR, State.DRAFT)) {\n * // Can NOT assume someCR is Drafted\n * // The compiler must know the expected concrete CR type\n * }\n * ```\n */\nfunction isInState<CR extends Base>(cr: Base, s: CR[\"state\"]): cr is CR {\n return cr.state === s;\n}\n\n\n\n\n// ===========\n// Transitions\n// ===========\n\n/**\n * A function that transitions CR1 to CR2.\n *\n * The function is declared to return the object\n * without the `state` field, it is set\n * by common wrapper function to reduce duplication.\n */\nexport type Transition<\n /** From CR of this subtype */\n CR1 extends Base,\n /** To CR of this subtype */\n CR2 extends Base,\n /** Using this extra information */\n P extends Record<string, any> | null = null,\n> = (cr: CR1, payload: P) => Omit<CR2, 'state'>;\n\n\n/**\n * Describes a transition.\n *\n * @typeParam CR1: Change request source state type\n * @typeParam CR2: Change request target state type\n * @typeParam P: Extra input needed to transition, if any\n */\nexport interface TransitionConfig<CR1 extends Base, CR2 extends Base, P extends Record<string, any> | null = null> {\n /**\n * Function that implements the transition.\n * Takes a CR in the original state and returns CR in the new state.\n * Additionally, takes appropriate payload, if any, for the transition\n * (e.g., register manager or control body notes).\n *\n * For function implementor:\n *\n * - Function MUST NOT modify CR in place.\n * - Function should throw if submitted payload does not conform to requirements.\n */\n func: Transition<CR1, CR2, P>;\n\n targetState: CR2[\"state\"];\n\n /** Title. Use verb. */\n title: string;\n\n hint?: string | JSX.Element;\n\n /** Widget that can be used to view or enter extra input. */\n Widget: P extends null ? null : React.FC<{ value: P, onChange?: (userInput: P) => void }>;\n\n /**\n * Function that returns true\n * if given stakeholder can perform this transition on given CR.\n */\n canBeTransitionedBy: (stakeholder: RegisterStakeholder, cr: CR1) => boolean;\n}\n\n\n// type TransitionSpec = {\n// [S1 in StateType]?: {\n// [S2 in StateType]?: Transition<Base<S1>, Base<S2>, Record<string, any>>\n// }\n// }\n\n\n/**\n * Source of truth for available transitions.\n * When updating change request business logic,\n * this is the type that should be modified.\n *\n * It will cause compile errors until transition implementation\n * is updated correspondingly.\n */\nexport type Transitions = {\n [State.DRAFT]: {\n // [State.DRAFT]:\n // TransitionConfig<Drafted, Drafted, SubmitterInput>;\n [State.WITHDRAWN]:\n TransitionConfig<Proposed, Withdrawn>;\n [State.PROPOSED]:\n TransitionConfig<Drafted, Proposed, SubmitterInput>;\n };\n [State.PROPOSED]: {\n [State.WITHDRAWN]:\n TransitionConfig<Proposed, Withdrawn>;\n [State.SUBMITTED_FOR_CONTROL_BODY_REVIEW]:\n TransitionConfig<Proposed, SubmittedForControlBodyReview, RegisterManagerInput>;\n [State.RETURNED_FOR_CLARIFICATION]:\n TransitionConfig<Proposed, ReturnedForClarificationByManager, RegisterManagerInput>;\n };\n [State.SUBMITTED_FOR_CONTROL_BODY_REVIEW]: {\n [State.WITHDRAWN]:\n TransitionConfig<SubmittedForControlBodyReview, Withdrawn>;\n [State.RETURNED_FOR_CLARIFICATION]:\n TransitionConfig<SubmittedForControlBodyReview, ReturnedForClarificationByControlBody, ControlBodyInput>;\n [State.REJECTED]:\n TransitionConfig<SubmittedForControlBodyReview, Rejected, ControlBodyInput>;\n [State.ACCEPTED]:\n TransitionConfig<SubmittedForControlBodyReview, Accepted, ControlBodyInput>;\n };\n [State.RETURNED_FOR_CLARIFICATION]: {\n [State.PROPOSED]:\n TransitionConfig<ReturnedForClarificationByManager | ReturnedForClarificationByControlBody, Proposed, SubmitterInput>;\n [State.WITHDRAWN]:\n TransitionConfig<ReturnedForClarificationByManager | ReturnedForClarificationByControlBody, Withdrawn>;\n };\n [State.REJECTED]: {\n [State.APPEALED]:\n TransitionConfig<Rejected, Appealed, AppealRequest>;\n };\n [State.APPEALED]: {\n [State.APPEAL_WITHDRAWN]:\n TransitionConfig<Appealed, RejectedWithAppealWithdrawn>;\n [State.ACCEPTED_ON_APPEAL]:\n TransitionConfig<Appealed, AcceptedOnAppeal, RegisterOwnerInput>;\n [State.REJECTION_UPHELD_ON_APPEAL]:\n TransitionConfig<Appealed, RejectionUpheld, RegisterOwnerInput>;\n };\n}\n"]}
1
+ {"version":3,"file":"cr.js","sourceRoot":"","sources":["../../src/types/cr.ts"],"names":[],"mappings":"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","sourcesContent":["/** Change request types, states and state transitions. */\n\nimport type React from 'react';\nimport type { ProposalSet } from './proposal';\nimport { type RegisterStakeholder } from './stakeholder';\nimport type { RegisterItem } from './item';\n\n\n\nexport function isSubmittedBy(stakeholder: RegisterStakeholder, cr: Base): boolean {\n return (\n //isSubmitter(stakeholder) &&\n stakeholder.gitServerUsername === cr.submittingStakeholderGitServerUsername);\n}\n\n\n\n// =====================\n// Change request states\n// =====================\n\n/** Used in place of enum for convenience. */\nexport const State = {\n DRAFT: 'draft',\n PROPOSED: 'proposed',\n SUBMITTED_FOR_CONTROL_BODY_REVIEW: 'pending-control-body-review',\n RETURNED_FOR_CLARIFICATION: 'returned-for-clarification',\n WITHDRAWN: 'withdrawn',\n ACCEPTED: 'accepted',\n REJECTED: 'rejected',\n APPEALED: 'rejection-appealed-to-owner',\n ACCEPTED_ON_APPEAL: 'accepted-on-appeal',\n REJECTION_UPHELD_ON_APPEAL: 'rejection-upheld-on-appeal',\n APPEAL_WITHDRAWN: 'appeal-withdrawn',\n} as const;\n\nexport type StateType = typeof State[keyof typeof State];\n\nexport function isState(val: string): val is StateType {\n return Object.values(State).indexOf(val as StateType) >= 0;\n}\n\n/** A subset of `State` that represents editable states. */\nexport const EditableState = [\n State.DRAFT,\n State.RETURNED_FOR_CLARIFICATION,\n] as const;\n\nexport type EditableStateType = StateType & typeof EditableState[number];\n\nexport function isEditableState(state: StateType): state is EditableStateType {\n return EditableState.indexOf(state as EditableStateType) >= 0;\n}\n\n\n\n// ======================\n// Change request classes\n// ======================\n\n/**\n * Base change request type.\n *\n * Note that e.g. type Base<typeof State.DRAFT> does not equal to Drafted\n * because Drafted includes additional information (namely, SubmitterInput).\n *\n * If the state of a CR matters, this type should not be used directly\n * and concrete types should be used instead.\n */\nexport interface Base<S extends StateType = StateType>\n{\n id: string;\n // decision: typeof Decision[keyof typeof Decision]\n // disposition?: typeof Disposition[keyof typeof Disposition]\n state: S;\n\n /**\n * Used to match against stakeholders declared in register metadata.\n */\n submittingStakeholderGitServerUsername: string;\n\n items: ProposalSet;\n\n /**\n * Against to which register version changes were proposed.\n */\n registerVersion: string;\n\n /**\n * A link to external discussion.\n */\n externalDiscussionURI?: string;\n\n pastTransitions?: TransitionEntry[];\n}\n\n\nexport interface TransitionEntry {\n /** Verb in past tense. */\n label: string;\n\n timestamp: Date;\n fromState: StateType;\n toState: StateType;\n stakeholder: RegisterStakeholder;\n input: StateInput;\n}\n\n\nexport function isCreatedBy(stakeholder: RegisterStakeholder, cr: Base): boolean {\n return stakeholder.gitServerUsername?.trim() !== '' && stakeholder.gitServerUsername === cr.submittingStakeholderGitServerUsername;\n}\n\n/** Whether given `cr` can be edited (as in, items changed) by specified stakeholder. */\nexport function canBeEditedBy(stakeholder: RegisterStakeholder, cr: Base): boolean {\n return isCreatedBy(stakeholder, cr) && isEditableState(cr.state);\n}\n\n/**\n * Whether given `cr` can be deleted by given stakeholder.\n * Unlike editing, deletion is possible only if there are no items\n * and CR was never proposed.\n */\nexport function canBeDeletedBy(stakeholder: RegisterStakeholder, cr: Base): boolean {\n return (\n isCreatedBy(stakeholder, cr)\n && isEditableState(cr.state)\n && Object.keys(cr.items).length < 1\n && !((cr as Proposed).timeProposed)\n );\n}\n\n\n/** Proposal structure for single-file proposal import format. */\nexport interface ImportableCR {\n /** Proposal data. */\n proposalDraft: Drafted,\n /** Register item data for additions & clarifications. */\n itemPayloads: Record<string, RegisterItem<any>>,\n}\nexport function isImportableCR(val: any): val is ImportableCR {\n // TODO: More complete check\n return (\n val.proposalDraft.id\n && isDrafted(val.proposalDraft as Base)\n && Object.keys(val.itemPayloads).length > 0);\n}\n\n\n/**\n * A change request in any state.\n * Contains a superset of all possible properties, but all optional.\n * XXX: ^^^ This is a lie. Should be changed from | to & with Partial<>?\n */\nexport type SomeCR = \n | Drafted\n | Proposed\n | Withdrawn\n | ReturnedForClarificationByManager\n | SubmittedForControlBodyReview\n | ReturnedForClarificationByControlBody\n | Accepted\n | Rejected\n | RejectionUpheld\n | AcceptedOnAppeal\n | RejectedWithAppealWithdrawn;\n\nexport type Withdrawable =\n | Proposed\n | SubmittedForControlBodyReview\n | ReturnedForClarificationByManager\n | ReturnedForClarificationByControlBody;\n\nexport type Proposable =\n | Drafted\n | ReturnedForClarificationByManager\n | ReturnedForClarificationByControlBody;\n\nexport type SomeEditable =\n | Drafted\n | ReturnedForClarificationByManager\n | ReturnedForClarificationByControlBody;\n\nexport type Disposed =\n | Withdrawn\n | Accepted\n | Rejected\n | AcceptedOnAppeal\n | RejectionUpheld;\n\n\n// More specific change request types.\n// TODO: Refactor to avoid confusiong between current state e.g. Proposed)\n// and type (Proposed, to which all inheriting classes also conform)\n\nexport interface Drafted extends\n SubmitterInput,\n Base<typeof State.DRAFT> { timeStarted: Date, timeEdited: Date }\nexport function isDrafted(cr: Base): cr is Drafted {\n return isInState(cr, State.DRAFT);\n}\n\nexport interface Proposed extends\n Omit<Drafted, 'state'>,\n Base<typeof State.PROPOSED> { timeProposed: Date }\nexport function isProposed(cr: Base): cr is Proposed {\n return isInState(cr, State.PROPOSED);\n}\n\nexport interface Withdrawn extends\n Omit<Withdrawable, 'state'>,\n Base<typeof State.WITHDRAWN> { timeDisposed: Date }\nexport function isWithdrawn(cr: Base): cr is Withdrawn {\n return isInState(cr, State.WITHDRAWN);\n}\n\nexport function hadBeenProposed(cr: Base): cr is Base & { timeProposed: Date } {\n return cr && cr.hasOwnProperty('timeProposed') && !!(cr as Proposed).timeProposed;\n}\nexport function isDisposed(cr: Base): cr is Base & { timeDisposed: Date } {\n return cr && cr.hasOwnProperty('timeDisposed') && !!(cr as Disposed).timeDisposed;\n //return [\n // State.WITHDRAWN,\n // State.ACCEPTED,\n // State.REJECTED,\n // State.REJECTION_UPHELD_ON_APPEAL,\n // State.ACCEPTED_ON_APPEAL,\n //].some(s => cr.state === s);\n}\n\nexport interface SubmittedForControlBodyReview extends\n Omit<Proposed, 'state'>,\n RegisterManagerInput,\n Base<typeof State.SUBMITTED_FOR_CONTROL_BODY_REVIEW> {}\n\nexport function isSubmittedForControlBodyReview(cr: Base): cr is SubmittedForControlBodyReview {\n return isInState(cr, State.SUBMITTED_FOR_CONTROL_BODY_REVIEW)\n}\n\nexport interface ReturnedForClarificationByManager extends\n Omit<Proposed, 'state'>,\n RegisterManagerInput,\n Base<typeof State.RETURNED_FOR_CLARIFICATION> {}\n\nexport interface ReturnedForClarificationByControlBody extends\n Omit<SubmittedForControlBodyReview, 'state'>,\n ControlBodyInput,\n Base<typeof State.RETURNED_FOR_CLARIFICATION> {}\n\nexport function isReturnedForClarification(cr: Base): cr is (ReturnedForClarificationByManager | ReturnedForClarificationByControlBody) {\n return isInState(cr, State.RETURNED_FOR_CLARIFICATION)\n}\n\nexport interface Accepted extends\n Omit<SubmittedForControlBodyReview, 'state'>,\n ControlBodyInput,\n Base<typeof State.ACCEPTED> { timeDisposed: Date }\nexport function isAccepted(cr: Base): cr is Accepted {\n return isInState(cr, State.ACCEPTED);\n}\n\nexport interface Rejected extends\n Omit<SubmittedForControlBodyReview, 'state'>,\n ControlBodyInput,\n Base<typeof State.REJECTED> { timeDisposed: Date }\nexport function isRejected(cr: Base): cr is Rejected {\n return isInState(cr, State.REJECTED);\n}\n\nexport interface Appealed extends\n Omit<Rejected, 'state' | 'timeDisposed'>,\n AppealRequest,\n Base<typeof State.APPEALED> { timeDisposed: undefined }\nexport function isAppealed(cr: Base): cr is Appealed {\n return isInState(cr, State.APPEALED);\n}\n\nexport interface RejectionUpheld extends\n Omit<Appealed, 'state' | 'timeDisposed'>,\n RegisterOwnerInput,\n Base<typeof State.REJECTION_UPHELD_ON_APPEAL> { timeDisposed: Date }\nexport function isRejectedOnAppeal(cr: Base): cr is RejectionUpheld {\n return isInState(cr, State.REJECTION_UPHELD_ON_APPEAL);\n}\n\nexport interface AcceptedOnAppeal extends\n Omit<Appealed, 'state' | 'timeDisposed'>,\n RegisterOwnerInput,\n Base<typeof State.ACCEPTED_ON_APPEAL> { timeDisposed: Date }\nexport function isAcceptedOnAppeal(cr: Base): cr is AcceptedOnAppeal {\n return isInState(cr, State.ACCEPTED_ON_APPEAL);\n}\n\nexport interface RejectedWithAppealWithdrawn extends\n Omit<Appealed, 'state' | 'timeDisposed'>,\n Base<typeof State.APPEAL_WITHDRAWN> { timeDisposed: Date }\nexport function isRejectedWithAppealWithdrawn(cr: Base): cr is RejectedWithAppealWithdrawn {\n return isInState(cr, State.APPEAL_WITHDRAWN);\n}\n\n\n\n// Input required when transitioning to different states\n\nexport interface SubmitterInput {\n justification: string;\n}\nexport function hasSubmitterInput(val: any): val is SubmitterInput {\n return val.hasOwnProperty('justification') && typeof val.justification === 'string';\n}\nexport interface RegisterManagerInput {\n registerManagerNotes: string;\n}\nexport function hasRegisterManagerInput(val: any): val is RegisterManagerInput {\n return val.hasOwnProperty('registerManagerNotes') && typeof val.registerManagerNotes === 'string';\n}\nexport interface ControlBodyInput {\n controlBodyNotes: string;\n}\nexport function hasControlBodyInput(val: any): val is ControlBodyInput {\n return (\n val.hasOwnProperty('controlBodyNotes') && typeof val.controlBodyNotes === 'string' &&\n val.hasOwnProperty('controlBodyDecisionEvent') && typeof val.controlBodyDecisionEvent === 'string');\n}\nexport interface AppealRequest {\n appealReason: string;\n}\nexport function hasAppealRequest(val: any): val is AppealRequest {\n return val.hasOwnProperty('appealReason') && typeof val.appealReason === 'string';\n}\nexport interface RegisterOwnerInput {\n registerOwnerNotes: string;\n}\nexport function hasRegisterOwnerInput(val: any): val is RegisterOwnerInput {\n return val.hasOwnProperty('registerOwnerNotes') && typeof val.registerOwnerNotes === 'string';\n}\n\nexport type StateInput =\n | SubmitterInput\n | RegisterManagerInput\n | ControlBodyInput\n | AppealRequest\n | RegisterOwnerInput;\n\n\n/** \n * CR type guard helper.\n * Normally you would not use it directly and instead use\n * more specific is[Type]() helper from this module.\n *\n * Checks CR type using the `state` property.\n * Does not validate other properties.\n *\n * Usage:\n *\n * @example\n * ```ts\n * let someCR;\n * if (isInState<Drafted>(someCR, State.DRAFT)) {\n * // Can assume someCR is Drafted\n * }\n * ```\n *\n * It’ll try to tell you if you mismatch those.\n *\n * @example\n * Will not compile:\n * ```ts\n * let someCR;\n * if (isInState<Drafted>(someCR, State.PROPOSED)) {\n * // Compile error\n * // because State.PROPOSED is not a possible value of Drafted[\"state\"]\n * }\n * ```\n *\n * @example\n * Incorrect usage (do not do this):\n * ```ts\n * let someCR;\n * if (isInState(someCR, State.DRAFT)) {\n * // Can NOT assume someCR is Drafted\n * // The compiler must know the expected concrete CR type\n * }\n * ```\n */\nfunction isInState<CR extends Base>(cr: Base, s: CR[\"state\"]): cr is CR {\n return cr.state === s;\n}\n\n\n\n\n// ===========\n// Transitions\n// ===========\n\n/**\n * A function that transitions CR1 to CR2.\n *\n * The function is declared to return the object\n * without the `state` field, it is set\n * by common wrapper function to reduce duplication.\n */\nexport type Transition<\n /** From CR of this subtype */\n CR1 extends Base,\n /** To CR of this subtype */\n CR2 extends Base,\n /** Using this extra information */\n P extends Record<string, any> | null = null,\n> = (cr: CR1, payload: P) => Omit<CR2, 'state'>;\n\n\n/**\n * Describes a transition.\n *\n * @typeParam CR1: Change request source state type\n * @typeParam CR2: Change request target state type\n * @typeParam P: Extra input needed to transition, if any\n */\nexport interface TransitionConfig<CR1 extends Base, CR2 extends Base, P extends Record<string, any> | null = null> {\n /**\n * Function that implements the transition.\n * Takes a CR in the original state and returns CR in the new state.\n * Additionally, takes appropriate payload, if any, for the transition\n * (e.g., register manager or control body notes).\n *\n * For function implementor:\n *\n * - Function MUST NOT modify CR in place.\n * - Function should throw if submitted payload does not conform to requirements.\n */\n func: Transition<CR1, CR2, P>;\n\n targetState: CR2[\"state\"];\n\n /** Title. Use verb. */\n title: string;\n\n hint?: string | JSX.Element;\n\n /** Widget that can be used to view or enter extra input. */\n Widget: P extends null ? null : React.FC<{ value: P, onChange?: (userInput: P) => void }>;\n\n /**\n * Function that returns true\n * if given stakeholder can perform this transition on given CR.\n */\n canBeTransitionedBy: (stakeholder: RegisterStakeholder, cr: CR1) => boolean;\n}\n\n\n// type TransitionSpec = {\n// [S1 in StateType]?: {\n// [S2 in StateType]?: Transition<Base<S1>, Base<S2>, Record<string, any>>\n// }\n// }\n\n\n/**\n * Source of truth for available transitions.\n * When updating change request business logic,\n * this is the type that should be modified.\n *\n * It will cause compile errors until transition implementation\n * is updated correspondingly.\n */\nexport type Transitions = {\n [State.DRAFT]: {\n // [State.DRAFT]:\n // TransitionConfig<Drafted, Drafted, SubmitterInput>;\n [State.WITHDRAWN]:\n TransitionConfig<Proposed, Withdrawn>;\n [State.PROPOSED]:\n TransitionConfig<Drafted, Proposed, SubmitterInput>;\n };\n [State.PROPOSED]: {\n [State.WITHDRAWN]:\n TransitionConfig<Proposed, Withdrawn>;\n [State.SUBMITTED_FOR_CONTROL_BODY_REVIEW]:\n TransitionConfig<Proposed, SubmittedForControlBodyReview, RegisterManagerInput>;\n [State.RETURNED_FOR_CLARIFICATION]:\n TransitionConfig<Proposed, ReturnedForClarificationByManager, RegisterManagerInput>;\n };\n [State.SUBMITTED_FOR_CONTROL_BODY_REVIEW]: {\n [State.WITHDRAWN]:\n TransitionConfig<SubmittedForControlBodyReview, Withdrawn>;\n [State.RETURNED_FOR_CLARIFICATION]:\n TransitionConfig<SubmittedForControlBodyReview, ReturnedForClarificationByControlBody, ControlBodyInput>;\n [State.REJECTED]:\n TransitionConfig<SubmittedForControlBodyReview, Rejected, ControlBodyInput>;\n [State.ACCEPTED]:\n TransitionConfig<SubmittedForControlBodyReview, Accepted, ControlBodyInput>;\n };\n [State.RETURNED_FOR_CLARIFICATION]: {\n [State.PROPOSED]:\n TransitionConfig<ReturnedForClarificationByManager | ReturnedForClarificationByControlBody, Proposed, SubmitterInput>;\n [State.WITHDRAWN]:\n TransitionConfig<ReturnedForClarificationByManager | ReturnedForClarificationByControlBody, Withdrawn>;\n };\n [State.REJECTED]: {\n [State.APPEALED]:\n TransitionConfig<Rejected, Appealed, AppealRequest>;\n };\n [State.APPEALED]: {\n [State.APPEAL_WITHDRAWN]:\n TransitionConfig<Appealed, RejectedWithAppealWithdrawn>;\n [State.ACCEPTED_ON_APPEAL]:\n TransitionConfig<Appealed, AcceptedOnAppeal, RegisterOwnerInput>;\n [State.REJECTION_UPHELD_ON_APPEAL]:\n TransitionConfig<Appealed, RejectionUpheld, RegisterOwnerInput>;\n };\n}\n"]}
package/types/item.d.ts CHANGED
@@ -33,7 +33,7 @@ interface ExternalSource extends AbstractItemSource {
33
33
  citation: Citation;
34
34
  }
35
35
  declare type RegisterItemSource = PaneronRegisterItemSource | ExternalSource;
36
- export interface RegisterItem<P extends Payload> {
36
+ export interface RegisterItem<P extends Payload = Payload> {
37
37
  id: string;
38
38
  status: ItemStatus;
39
39
  dateAccepted: Date;
package/types/item.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"item.js","sourceRoot":"","sources":["../../src/types/item.ts"],"names":[],"mappings":"AAKA,MAAM,aAAa,GAAG;IACpB,WAAW;IACX,OAAO;IACP,YAAY;IACZ,SAAS;IACT,SAAS;CACD,CAAC;AA2BX,MAAM,UAAU,uBAAuB,CAAC,GAAQ;IAC9C,OAAO,CACL,GAAG;QACH,GAAG,CAAC,cAAc,CAAC,QAAQ,CAAC;QAC5B,GAAG,CAAC,cAAc,CAAC,SAAS,CAAC;QAC7B,OAAO,GAAG,CAAC,QAAQ,CAAC,IAAI,QAAQ;QAChC,OAAO,GAAG,CAAC,SAAS,CAAC,IAAI,QAAQ,CAClC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,SAAS,GAA0B;IAC9C,MAAM,EAAE,qBAAqB;IAC7B,OAAO,EAAE,sBAAsB;IAC/B,aAAa,EAAE,SAAS;CAChB,CAAC;AA0CX,MAAM,UAAU,cAAc,CAAC,GAAQ;IACrC,OAAO,CACL,GAAG;QACH,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC;QACxB,GAAG,CAAC,cAAc,CAAC,MAAM,CAAC;QAC1B,GAAG,CAAC,cAAc,CAAC,QAAQ,CAAC;QAC5B,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CACvC,CAAC;AACJ,CAAC","sourcesContent":["import type { Citation, LocalizedAlternative } from './util';\n\n\nexport type Payload = Record<string, any>\n\nconst ITEM_STATUSES = [\n 'submitted',\n 'valid',\n 'superseded',\n 'retired',\n 'invalid',\n] as const;\n\nexport type ItemStatus = typeof ITEM_STATUSES[number];\n\n\nexport interface RegisterItemID {\n classID: string\n itemID: string\n}\n\n\nexport interface RegisterItemClass {\n id: string\n title: string\n description?: string\n alternativeNames?: Readonly<LocalizedAlternative<string>[]>\n}\n\ninterface ItemReference {\n registerID: string\n subregisterID?: string\n classID: string\n itemID: string\n}\n\nexport type InternalItemReference = Omit<ItemReference, 'registerID'>\n\nexport function isInternalItemReference(val: any): val is InternalItemReference {\n return (\n val &&\n val.hasOwnProperty('itemID') &&\n val.hasOwnProperty('classID') &&\n typeof val['itemID'] == 'string' &&\n typeof val['classID'] == 'string'\n );\n}\n\nexport const DUMMY_REF: InternalItemReference = {\n itemID: 'NONEXISTENT_ITEM_ID',\n classID: 'NONEXISTENT_CLASS_ID',\n subregisterID: undefined,\n} as const;\n\n\ninterface AbstractItemSource {\n type: string\n}\ninterface PaneronRegisterItemSource extends AbstractItemSource {\n type: 'paneron_register'\n itemRef: ItemReference\n}\ninterface ExternalSource extends AbstractItemSource {\n type: 'external'\n citation: Citation\n}\ntype RegisterItemSource = PaneronRegisterItemSource | ExternalSource\n\nexport interface RegisterItem<P extends Payload> {\n id: string // UUID\n\n status: ItemStatus\n\n dateAccepted: Date\n // This is a mandatory property, since until their acceptance items “live” as part of their corresponding change requests\n\n /** UUID of change request that defined the current version. */\n amendedInCR?: string\n\n // TODO: Denormalized, should be validated with consistency checks\n supersededBy?: InternalItemReference[]\n supersedes?: InternalItemReference[]\n\n /**\n * Register item data. Domain-specific. May include additional human-readable identifiers.\n * In ISO 19135-1 was represented by “definition”.\n */\n data: P\n\n source?: RegisterItemSource\n // TODO: Citations were suggested to be moved to proposals, as motivating/substantiating evidence.\n // TODO: Register item, however, should have a relationship that points to the original proto-item from another register.\n}\n\nexport function isRegisterItem(val: any): val is RegisterItem<any> {\n return (\n val &&\n val.hasOwnProperty('id') &&\n val.hasOwnProperty('data') &&\n val.hasOwnProperty('status') &&\n ITEM_STATUSES.indexOf(val.status) >= 0\n );\n}\n"]}
1
+ {"version":3,"file":"item.js","sourceRoot":"","sources":["../../src/types/item.ts"],"names":[],"mappings":"AAKA,MAAM,aAAa,GAAG;IACpB,WAAW;IACX,OAAO;IACP,YAAY;IACZ,SAAS;IACT,SAAS;CACD,CAAC;AA2BX,MAAM,UAAU,uBAAuB,CAAC,GAAQ;IAC9C,OAAO,CACL,GAAG;QACH,GAAG,CAAC,cAAc,CAAC,QAAQ,CAAC;QAC5B,GAAG,CAAC,cAAc,CAAC,SAAS,CAAC;QAC7B,OAAO,GAAG,CAAC,QAAQ,CAAC,IAAI,QAAQ;QAChC,OAAO,GAAG,CAAC,SAAS,CAAC,IAAI,QAAQ,CAClC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,SAAS,GAA0B;IAC9C,MAAM,EAAE,qBAAqB;IAC7B,OAAO,EAAE,sBAAsB;IAC/B,aAAa,EAAE,SAAS;CAChB,CAAC;AA0CX,MAAM,UAAU,cAAc,CAAC,GAAQ;IACrC,OAAO,CACL,GAAG;QACH,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC;QACxB,GAAG,CAAC,cAAc,CAAC,MAAM,CAAC;QAC1B,GAAG,CAAC,cAAc,CAAC,QAAQ,CAAC;QAC5B,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CACvC,CAAC;AACJ,CAAC","sourcesContent":["import type { Citation, LocalizedAlternative } from './util';\n\n\nexport type Payload = Record<string, any>\n\nconst ITEM_STATUSES = [\n 'submitted',\n 'valid',\n 'superseded',\n 'retired',\n 'invalid',\n] as const;\n\nexport type ItemStatus = typeof ITEM_STATUSES[number];\n\n\nexport interface RegisterItemID {\n classID: string\n itemID: string\n}\n\n\nexport interface RegisterItemClass {\n id: string\n title: string\n description?: string\n alternativeNames?: Readonly<LocalizedAlternative<string>[]>\n}\n\ninterface ItemReference {\n registerID: string\n subregisterID?: string\n classID: string\n itemID: string\n}\n\nexport type InternalItemReference = Omit<ItemReference, 'registerID'>\n\nexport function isInternalItemReference(val: any): val is InternalItemReference {\n return (\n val &&\n val.hasOwnProperty('itemID') &&\n val.hasOwnProperty('classID') &&\n typeof val['itemID'] == 'string' &&\n typeof val['classID'] == 'string'\n );\n}\n\nexport const DUMMY_REF: InternalItemReference = {\n itemID: 'NONEXISTENT_ITEM_ID',\n classID: 'NONEXISTENT_CLASS_ID',\n subregisterID: undefined,\n} as const;\n\n\ninterface AbstractItemSource {\n type: string\n}\ninterface PaneronRegisterItemSource extends AbstractItemSource {\n type: 'paneron_register'\n itemRef: ItemReference\n}\ninterface ExternalSource extends AbstractItemSource {\n type: 'external'\n citation: Citation\n}\ntype RegisterItemSource = PaneronRegisterItemSource | ExternalSource\n\nexport interface RegisterItem<P extends Payload = Payload> {\n id: string // UUID\n\n status: ItemStatus\n\n dateAccepted: Date\n // This is a mandatory property, since until their acceptance items “live” as part of their corresponding change requests\n\n /** UUID of change request that defined the current version. */\n amendedInCR?: string\n\n // TODO: Denormalized, should be validated with consistency checks\n supersededBy?: InternalItemReference[]\n supersedes?: InternalItemReference[]\n\n /**\n * Register item data. Domain-specific. May include additional human-readable identifiers.\n * In ISO 19135-1 was represented by “definition”.\n */\n data: P\n\n source?: RegisterItemSource\n // TODO: Citations were suggested to be moved to proposals, as motivating/substantiating evidence.\n // TODO: Register item, however, should have a relationship that points to the original proto-item from another register.\n}\n\nexport function isRegisterItem(val: any): val is RegisterItem<any> {\n return (\n val &&\n val.hasOwnProperty('id') &&\n val.hasOwnProperty('data') &&\n val.hasOwnProperty('status') &&\n ITEM_STATUSES.indexOf(val.status) >= 0\n );\n}\n"]}