@things-factory/id-rule-base 8.0.0 → 9.0.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/id-rule-base",
3
- "version": "8.0.0",
3
+ "version": "9.0.0-beta.3",
4
4
  "main": "dist-server/index.js",
5
5
  "browser": "dist-client/index.js",
6
6
  "things-factory": true,
@@ -27,12 +27,12 @@
27
27
  "migration:create": "node ../../node_modules/typeorm/cli.js migration:create ./server/migrations/migration"
28
28
  },
29
29
  "dependencies": {
30
- "@operato/data-grist": "^8.0.0",
31
- "@operato/input": "^8.0.0",
32
- "@things-factory/i18n-base": "^8.0.0",
33
- "@things-factory/setting-base": "^8.0.0",
34
- "@things-factory/shell": "^8.0.0",
30
+ "@operato/data-grist": "^9.0.0-beta",
31
+ "@operato/input": "^9.0.0-beta",
32
+ "@things-factory/i18n-base": "^9.0.0-beta.3",
33
+ "@things-factory/setting-base": "^9.0.0-beta.3",
34
+ "@things-factory/shell": "^9.0.0-beta.0",
35
35
  "ses": "^1.5.0"
36
36
  },
37
- "gitHead": "07ef27d272dd9a067a9648ac7013748510556a18"
37
+ "gitHead": "1d7e0dd4c88f3c3f3bd311c00e4b1d1542d53634"
38
38
  }
@@ -1,8 +0,0 @@
1
- import { registerEditor } from '@operato/data-grist'
2
-
3
- import { GristCodeInput } from './editors/grist-code-input'
4
-
5
- export default function bootstrap() {
6
- /* id-rule 의 GristRenderer는 텍스트와 같으므로, 별도로 정의하지 않음. */
7
- registerEditor('id-rule', GristCodeInput)
8
- }
@@ -1,196 +0,0 @@
1
- import '@material/web/button/elevated-button.js'
2
- import '@operato/i18n/ox-i18n.js'
3
- import '@operato/input/ox-input-code.js'
4
-
5
- import gql from 'graphql-tag'
6
- import { css, html, LitElement } from 'lit'
7
- import { customElement, property, query, state } from 'lit/decorators.js'
8
-
9
- import { i18next } from '@operato/i18n'
10
- import { client } from '@operato/graphql'
11
- import { ColumnConfig, GristRecord } from '@operato/data-grist'
12
- import { OxInputCode } from '@operato/input'
13
-
14
- const FETCH_ID_RULE_GQL = type => {
15
- return gql`
16
- {
17
- idRule(type:"${type}") {
18
- id,
19
- type,
20
- rule
21
- }
22
- }
23
- `
24
- }
25
-
26
- @customElement('grist-code-input-popup')
27
- export class GristCodeInputPopup extends LitElement {
28
- static styles = [
29
- css`
30
- :host {
31
- display: flex;
32
- flex-direction: column;
33
- padding: 0;
34
- align-items: center;
35
- box-sizing: border-box;
36
- width: 100%;
37
- border: 0;
38
- color: var(--popup-content-color);
39
- background-color: var(--popup-content-background-color);
40
-
41
- font: var(--grist-object-editor-font);
42
-
43
- justify-content: inherit;
44
- }
45
-
46
- :host * {
47
- box-sizing: border-box;
48
- }
49
-
50
- #wrapper {
51
- flex: 1;
52
- width: 100%;
53
- display: flex;
54
- flex-direction: column;
55
- padding: 5px;
56
- }
57
-
58
- #wrapper > h4 {
59
- margin: 0;
60
- }
61
-
62
- #wrapper > ul {
63
- width: 100%;
64
- }
65
-
66
- #wrapper > ul > li {
67
- display: flex;
68
- }
69
- #wrapper > ul > li > span {
70
- font-weight: bold;
71
- flex-basis: 200px;
72
- }
73
-
74
- #wrapper > ul > li > ox-i18n {
75
- flex: 1;
76
- }
77
-
78
- ox-input-code {
79
- width: 100%;
80
- flex: 1;
81
- }
82
-
83
- #footer {
84
- display: flex;
85
- justify-content: flex-end;
86
- }
87
- `
88
- ]
89
-
90
- @property({ type: String }) value?: string
91
- @property({ type: Object }) column?: ColumnConfig
92
- @property({ type: Object }) record?: GristRecord
93
- @property({ type: Number }) row?: number
94
- @property({ type: Object }) field?: any
95
- @property({ type: Object }) _idRule?: any
96
- @property({ type: Object }) headers?: { [header: string]: string }
97
-
98
- @query('ox-input-code') ruleEditor!: OxInputCode
99
-
100
- render() {
101
- return html`
102
- <div id="wrapper">
103
- <h4><ox-i18n msgid="label.arguments"></ox-i18n></h4>
104
- <ul>
105
- <li><span>domain</span><ox-i18n msgid="label.argument domain description"></ox-i18n></li>
106
- <li><span>seed</span><ox-i18n msgid="label.argument seed description"></ox-i18n></li>
107
- </ul>
108
- <ox-input-code id="rule-editor" type="text" .value=${(this._idRule || {}).rule}></ox-input-code>
109
-
110
- <div id="footer">
111
- <md-elevated-button
112
- label=${String(i18next.t('button.save'))}
113
- @click=${(e: Event) => {
114
- this.updateIdRule()
115
- }}
116
- ></md-elevated-button>
117
- </div>
118
- </div>
119
- `
120
- }
121
-
122
- updated(changed) {
123
- if (changed.has('value')) {
124
- if (this.value && typeof this.value === 'string') {
125
- this.getRule()
126
- }
127
- }
128
- }
129
-
130
- async getRule() {
131
- var response = await client.query({
132
- query: FETCH_ID_RULE_GQL(this.value)
133
- })
134
-
135
- let idRule = response.data.idRule
136
- if (!idRule) {
137
- idRule = await this.createIdRule()
138
- }
139
-
140
- this._idRule = idRule
141
- this.requestUpdate()
142
- }
143
-
144
- async createIdRule() {
145
- var idRule = {
146
- type: this.value,
147
- rule: `return ''`
148
- }
149
-
150
- return (
151
- await client.mutate({
152
- mutation: gql`
153
- mutation createIdRule($idRule: NewIdRule!) {
154
- createIdRule(idRule: $idRule) {
155
- type
156
- rule
157
- }
158
- }
159
- `,
160
- variables: { idRule }
161
- })
162
- ).data?.createIdRule
163
- }
164
-
165
- async updateIdRule() {
166
- if (!this._idRule) console.error('ID Rule not found')
167
-
168
- const rule = this.ruleEditor.value
169
-
170
- const type = this._idRule.type
171
-
172
- const patch = {
173
- ...this._idRule,
174
- rule
175
- }
176
-
177
- await client.mutate({
178
- mutation: gql`
179
- mutation updateIdRule($type: String!, $patch: IdRulePatch!) {
180
- updateIdRule(type: $type, patch: $patch) {
181
- type
182
- rule
183
- }
184
- }
185
- `,
186
- variables: { type, patch }
187
- })
188
-
189
- this.dispatchEvent(
190
- new CustomEvent('close-popup', {
191
- bubbles: true,
192
- composed: true
193
- })
194
- )
195
- }
196
- }
@@ -1,121 +0,0 @@
1
- import '@material/web/icon/icon.js'
2
-
3
- import { css, html } from 'lit'
4
- import { customElement, property } from 'lit/decorators.js'
5
- import { OxGristEditor } from '@operato/data-grist'
6
- import { i18next } from '@operato/i18n'
7
- import { OxPopup } from '@operato/popup'
8
-
9
- import './grist-code-input-popup'
10
-
11
- @customElement('grist-code-input')
12
- export class GristCodeInput extends OxGristEditor {
13
- static styles = [
14
- css`
15
- :host {
16
- display: flex;
17
- flex-flow: row nowrap;
18
- align-items: center;
19
-
20
- padding: 7px 0px;
21
- box-sizing: border-box;
22
-
23
- width: 100%;
24
- height: 100%;
25
-
26
- border: 0;
27
- background-color: transparent;
28
-
29
- font: var(--grist-object-editor-font);
30
- color: var(--grist-object-editor-color);
31
-
32
- justify-content: inherit;
33
- }
34
-
35
- md-icon {
36
- width: 20px;
37
- font-size: 1.5em;
38
- }
39
-
40
- #popup {
41
- display: flex;
42
- overflow: hidden;
43
- }
44
-
45
- input {
46
- border: none;
47
- background-color: transparent;
48
- }
49
-
50
- input:focus {
51
- outline: none;
52
- border: none;
53
- }
54
- `
55
- ]
56
-
57
- @property({ type: Object }) headers?: Object
58
- @property({ type: Object }) popup?: OxPopup | null
59
-
60
- render() {
61
- return html`
62
- <input
63
- type="text"
64
- .value=${this.value}
65
- .record=${this.record}
66
- .column=${this.column}
67
- .field=${this.column}
68
- .row=${this.row}
69
- ></input>
70
-
71
- <md-icon id="more" @click=${e => this.openPopup()}>more_vert</md-icon>
72
- `
73
- }
74
-
75
- async firstUpdated() {
76
- await this.updateComplete
77
- await super.firstUpdated()
78
- }
79
-
80
- openPopup() {
81
- if (this.record.__dirty__) {
82
- document.dispatchEvent(
83
- new CustomEvent('notify', {
84
- detail: {
85
- level: 'error',
86
- message: i18next.t('text.please_save_your_modifications_first')
87
- }
88
- })
89
- )
90
-
91
- return
92
- }
93
-
94
- document.dispatchEvent(
95
- new CustomEvent('open-popup', {
96
- detail: {
97
- template: html`
98
- <grist-code-input-popup
99
- .value=${this.value}
100
- .column=${this.column}
101
- .record=${this.record}
102
- .row=${this.row}
103
- .field=${this.field}
104
- .headers=${this.headers}
105
- @close-popup=${e => {
106
- this.popup?.close()
107
- this.popup = null
108
- }}
109
- ></grist-code-input-popup>
110
- `,
111
- options: {
112
- title: i18next.t('title.ID Rule Editor')
113
- },
114
- callback: popup => {
115
- this.popup = popup
116
- }
117
- }
118
- })
119
- )
120
- }
121
- }
package/client/index.ts DELETED
File without changes
@@ -1 +0,0 @@
1
- export * from './sequence-type'
@@ -1,3 +0,0 @@
1
- export const SEQUENCE_TYPE = {
2
- PRODUCT_LABEL_COUNTER: 'PRODUCT_LABEL_COUNTER'
3
- }
@@ -1,75 +0,0 @@
1
- import { MoreThan } from 'typeorm'
2
- import { Domain, getRepository } from '@things-factory/shell'
3
- import { IdRule } from '../service/id-rule/id-rule'
4
- import { Sequence } from '../service/sequence/sequence'
5
- import 'ses'
6
-
7
- type getNextArgs = {
8
- domain: Domain
9
- pattern: string
10
- expirationDate?: Date
11
- }
12
-
13
- export async function generateId({ domain, type, seed }) {
14
- const idRuleRepo = getRepository(IdRule)
15
- const rule = await idRuleRepo.findOne({
16
- where: {
17
- domain: { id: domain.id },
18
- type
19
- }
20
- })
21
-
22
- if (!rule) throw Error('Rule not found')
23
-
24
- const compartment = new Compartment({
25
- domain,
26
- seed,
27
- console
28
- })
29
-
30
- let evalFunc
31
- try {
32
- evalFunc = compartment.evaluate(`(async (domain, seed, getNext) => {
33
- ${rule.rule}
34
- })`)
35
- } catch (err) {
36
- throw new Error(`Failed to evaluate rule: ${err.message}`)
37
- }
38
-
39
- const nextId = await evalFunc(domain, {
40
- ...seed,
41
- },
42
- getNext)
43
-
44
- return nextId
45
- }
46
-
47
- export async function getNext({ domain, pattern, expirationDate }: getNextArgs) {
48
- const seqRepo = getRepository(Sequence)
49
- const now = new Date()
50
- let last = await seqRepo.findOneBy({
51
- domain: { id: domain.id },
52
- pattern,
53
- expiresAt: MoreThan(now)
54
- })
55
-
56
- var expiresAt = expirationDate
57
- if (!expirationDate) expiresAt = new Date(now.setMonth(now.getMonth() + 6))
58
-
59
- if (last) {
60
- last.seq++
61
- last.expiresAt = expiresAt
62
- await seqRepo.save(last)
63
- } else {
64
- if (!expirationDate) now.setMonth(now.getMonth() + 6)
65
-
66
- last = await seqRepo.save({
67
- domain,
68
- pattern,
69
- seq: 1,
70
- expiresAt
71
- })
72
- }
73
-
74
- return last.seq
75
- }
@@ -1 +0,0 @@
1
- export * from './id-generator'
package/server/index.ts DELETED
@@ -1,6 +0,0 @@
1
- import './routes'
2
-
3
- export * from './service'
4
- export * from './migrations'
5
- export * from './controllers'
6
- export * from './constants'
@@ -1,9 +0,0 @@
1
- const glob = require('glob')
2
- const path = require('path')
3
-
4
- export var migrations = []
5
-
6
- glob.sync(path.resolve(__dirname, '.', '**', '*.js')).forEach(function(file) {
7
- if (file.indexOf('index.js') !== -1) return
8
- migrations = migrations.concat(Object.values(require(path.resolve(file))) || [])
9
- })
package/server/routes.ts DELETED
@@ -1,25 +0,0 @@
1
- import { generateId } from './controllers/id-generator'
2
-
3
- process.on('bootstrap-module-domain-private-route' as any, (app, routes) => {
4
- /*
5
- * koa application에 routes 를 추가할 수 있다.
6
- *
7
- * ex) routes.get('/path', async(context, next) => {})
8
- * ex) routes.post('/path', async(context, next) => {})
9
- */
10
- routes.get('/get-next-pattern/:type/:domain', async (context, next) => {
11
- const { type, domain } = context.params
12
-
13
- var id = await generateId({
14
- domain,
15
- type,
16
- seed: {
17
- productId: 'ASUS',
18
- receiver: 'LA'
19
- }
20
- })
21
-
22
- context.status = 200
23
- context.body = id
24
- })
25
- })
@@ -1,121 +0,0 @@
1
-
2
- import { Resolver, Mutation, Arg, Ctx, Directive } from 'type-graphql'
3
- import { In } from 'typeorm'
4
- import { DocNumber } from './doc-number'
5
- import { NewDocNumber, DocNumberPatch } from './doc-number-type'
6
- import { Domain, getRepository } from '@things-factory/shell'
7
- import { User } from '@things-factory/auth-base'
8
-
9
- @Resolver(DocNumber)
10
- export class DocNumberMutation {
11
- @Directive('@transaction')
12
- @Mutation(returns => DocNumber, { description: 'To create new DocNumber' })
13
- async createDocNumber(@Arg('docNumber') docNumber: NewDocNumber, @Ctx() context: any): Promise<DocNumber> {
14
- const { domain, user, tx } = context.state
15
-
16
- return await tx.getRepository(DocNumber).save({
17
- ...docNumber,
18
- domain,
19
- creator: user,
20
- updater: user
21
- })
22
- }
23
-
24
- @Directive('@transaction')
25
- @Mutation(returns => DocNumber, { description: 'To modify DocNumber information' })
26
- async updateDocNumber(
27
- @Arg('id') id: string,
28
- @Arg('patch') patch: DocNumberPatch,
29
- @Ctx() context: any
30
- ): Promise<DocNumber> {
31
- const { domain, user, tx } = context.state
32
-
33
- const repository = tx.getRepository(DocNumber)
34
- const docNumber = await repository.findOne(
35
- {
36
- where: { domain: { id: domain.id }, id },
37
- relations: ['domain','updater','creator']
38
- }
39
- )
40
-
41
- return await repository.save({
42
- ...docNumber,
43
- ...patch,
44
- updater: user
45
- })
46
- }
47
-
48
- @Directive('@transaction')
49
- @Mutation(returns => [DocNumber], { description: "To modify multiple DocNumbers' information" })
50
- async updateMultipleDocNumber(
51
- @Arg('patches', type => [DocNumberPatch]) patches: DocNumberPatch[],
52
- @Ctx() context: any
53
- ): Promise<DocNumber[]> {
54
- const { domain, user, tx } = context.state
55
-
56
- let results = []
57
- const _createRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === '+')
58
- const _updateRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === 'M')
59
- const docNumberRepo = tx.getRepository(DocNumber)
60
-
61
- if (_createRecords.length > 0) {
62
- for (let i = 0; i < _createRecords.length; i++) {
63
- const newRecord = _createRecords[i]
64
-
65
- const result = await docNumberRepo.save({
66
- ...newRecord,
67
- domain,
68
- creator: user,
69
- updater: user
70
- })
71
-
72
- results.push({ ...result, cuFlag: '+' })
73
- }
74
- }
75
-
76
- if (_updateRecords.length > 0) {
77
- for (let i = 0; i < _updateRecords.length; i++) {
78
- const updRecord = _updateRecords[i]
79
- const docNumber = await docNumberRepo.findOne({
80
- where: { domain: { id: domain.id }, id:updRecord.id },
81
- relations: ['domain','updater','creator']
82
- })
83
-
84
- const result = await docNumberRepo.save({
85
- ...docNumber,
86
- ...updRecord,
87
- updater: user
88
- })
89
-
90
- results.push({ ...result, cuFlag: 'M' })
91
- }
92
- }
93
-
94
- return results
95
- }
96
-
97
- @Directive('@transaction')
98
- @Mutation(returns => Boolean, { description: 'To delete DocNumber' })
99
- async deleteDocNumber(@Arg('id') id: string, @Ctx() context: any): Promise<boolean> {
100
- const { domain, tx, user } = context.state
101
- await tx.getRepository(DocNumber).remove({ domain, id, updater:user })
102
- return true
103
- }
104
-
105
- @Directive('@transaction')
106
- @Mutation(returns => Boolean, { description: 'To delete multiple docNumbers' })
107
- async deleteDocNumbers(
108
- @Arg('ids', type => [String]) ids: string[],
109
- @Ctx() context: any
110
- ): Promise<boolean> {
111
- const { domain, tx, user } = context.state
112
-
113
- let delEntitis = ids.map(id=>{
114
- return {domain,id,updater:user}
115
- })
116
-
117
- await tx.getRepository(DocNumber).remove(delEntitis)
118
-
119
- return true
120
- }
121
- }