zenstack 0.5.0 → 0.6.0-pre.2

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 (62) hide show
  1. package/{LICENSE.md → LICENSE} +0 -0
  2. package/bin/cli +1 -1
  3. package/package.json +17 -13
  4. package/bin/post-install.js +0 -0
  5. package/bundle/asset/logo-256-bg.png +0 -0
  6. package/bundle/asset/logo-dark-256.png +0 -0
  7. package/bundle/asset/logo-light-256.png +0 -0
  8. package/bundle/cli/index.js +0 -6952
  9. package/bundle/extension.js +0 -39
  10. package/bundle/language-server/main.js +0 -6208
  11. package/bundle/res/package.template.json +0 -9
  12. package/bundle/res/prism-zmodel.js +0 -22
  13. package/bundle/res/stdlib.zmodel +0 -218
  14. package/bundle/res/tsconfig.template.json +0 -17
  15. package/src/cli/cli-error.ts +0 -4
  16. package/src/cli/cli-util.ts +0 -214
  17. package/src/cli/index.ts +0 -246
  18. package/src/extension.ts +0 -76
  19. package/src/generator/ast-utils.ts +0 -18
  20. package/src/generator/constants.ts +0 -6
  21. package/src/generator/field-constraint/index.ts +0 -304
  22. package/src/generator/index.ts +0 -86
  23. package/src/generator/prisma/expression-writer.ts +0 -360
  24. package/src/generator/prisma/index.ts +0 -44
  25. package/src/generator/prisma/prisma-builder.ts +0 -370
  26. package/src/generator/prisma/query-guard-generator.ts +0 -249
  27. package/src/generator/prisma/schema-generator.ts +0 -313
  28. package/src/generator/prisma/typescript-expression-transformer.ts +0 -108
  29. package/src/generator/react-hooks/index.ts +0 -273
  30. package/src/generator/service/index.ts +0 -113
  31. package/src/generator/tsc/index.ts +0 -59
  32. package/src/generator/types.ts +0 -20
  33. package/src/global.d.ts +0 -3
  34. package/src/language-server/constants.ts +0 -29
  35. package/src/language-server/generated/ast.ts +0 -643
  36. package/src/language-server/generated/grammar.ts +0 -2492
  37. package/src/language-server/generated/module.ts +0 -24
  38. package/src/language-server/langium-ext.d.ts +0 -22
  39. package/src/language-server/main.ts +0 -13
  40. package/src/language-server/types.ts +0 -25
  41. package/src/language-server/utils.ts +0 -21
  42. package/src/language-server/validator/attribute-validator.ts +0 -11
  43. package/src/language-server/validator/datamodel-validator.ts +0 -426
  44. package/src/language-server/validator/datasource-validator.ts +0 -102
  45. package/src/language-server/validator/enum-validator.ts +0 -14
  46. package/src/language-server/validator/expression-validator.ts +0 -48
  47. package/src/language-server/validator/schema-validator.ts +0 -31
  48. package/src/language-server/validator/utils.ts +0 -158
  49. package/src/language-server/validator/zmodel-validator.ts +0 -91
  50. package/src/language-server/zmodel-linker.ts +0 -453
  51. package/src/language-server/zmodel-module.ts +0 -131
  52. package/src/language-server/zmodel-scope.ts +0 -45
  53. package/src/language-server/zmodel-workspace-manager.ts +0 -23
  54. package/src/language-server/zmodel.langium +0 -207
  55. package/src/res/package.template.json +0 -9
  56. package/src/res/prism-zmodel.js +0 -22
  57. package/src/res/stdlib.zmodel +0 -218
  58. package/src/res/tsconfig.template.json +0 -17
  59. package/src/telemetry.ts +0 -119
  60. package/src/utils/exec-utils.ts +0 -8
  61. package/src/utils/indent-string.ts +0 -9
  62. package/src/utils/pkg-utils.ts +0 -63
@@ -1,207 +0,0 @@
1
- grammar ZModel
2
-
3
- entry Model:
4
- (
5
- declarations+=AbstractDeclaration
6
- )*;
7
-
8
- AbstractDeclaration:
9
- DataSource | DataModel | Enum | Function | Attribute;
10
-
11
- // datasource
12
- DataSource:
13
- 'datasource' name=ID '{' (fields+=DataSourceField)* '}';
14
-
15
- DataSourceField:
16
- (name=ID '=' value=(LiteralExpr|InvocationExpr));
17
-
18
- // expression
19
- Expression:
20
- LogicalExpr;
21
-
22
- LiteralExpr:
23
- value=(BOOLEAN | NUMBER | STRING);
24
-
25
- ArrayExpr:
26
- '[' (items+=Expression (',' items+=Expression)*)? ']';
27
-
28
- type ReferenceTarget = FunctionParam | DataModelField | EnumField;
29
-
30
- ThisExpr:
31
- value=THIS;
32
-
33
- NullExpr:
34
- value=NULL;
35
-
36
- ReferenceExpr:
37
- target=[ReferenceTarget:ID] ('(' ReferenceArgList ')')?;
38
-
39
- fragment ReferenceArgList:
40
- args+=ReferenceArg (',' args+=ReferenceArg)*;
41
-
42
- ReferenceArg:
43
- name=('sort') ':' value=('Asc'| 'Desc');
44
-
45
- InvocationExpr:
46
- function=[Function] '(' ArgumentList? ')';
47
-
48
- UnaryExpr:
49
- operator=('!') operand=Expression;
50
-
51
- // binary operator precedence follow Javascript's rules:
52
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#table
53
-
54
- MemberAccessExpr infers Expression:
55
- PrimaryExpr (
56
- {infer MemberAccessExpr.operand=current}
57
- ('.' member=[DataModelField])
58
- )*;
59
-
60
- CollectionPredicateExpr infers Expression:
61
- MemberAccessExpr (
62
- {infer BinaryExpr.left=current}
63
- operator=('?'|'!'|'^')
64
- '[' right=Expression ']'
65
- )*;
66
-
67
- // TODO: support arithmetics?
68
- //
69
- // MultDivExpr infers Expression:
70
- // CollectionPredicateExpr (
71
- // {infer BinaryExpr.left=current}
72
- // operator=('*'|'/')
73
- // right=CollectionPredicateExpr
74
- // )*;
75
-
76
- // AddSubExpr infers Expression:
77
- // MultDivExpr (
78
- // {infer BinaryExpr.left=current}
79
- // operator=('+'|'-')
80
- // right=MultDivExpr
81
- // )*;
82
-
83
- ComparisonExpr infers Expression:
84
- CollectionPredicateExpr (
85
- {infer BinaryExpr.left=current}
86
- operator=('>'|'<'|'>='|'<=')
87
- right=CollectionPredicateExpr
88
- )*;
89
-
90
- EqualityExpr infers Expression:
91
- ComparisonExpr (
92
- {infer BinaryExpr.left=current}
93
- operator=('=='|'!=')
94
- right=ComparisonExpr
95
- )*;
96
-
97
- LogicalExpr infers Expression:
98
- EqualityExpr (
99
- {infer BinaryExpr.left=current}
100
- operator=('&&'|'||')
101
- right=EqualityExpr
102
- )*;
103
-
104
- PrimaryExpr infers Expression:
105
- '(' Expression ')' |
106
- ThisExpr |
107
- NullExpr |
108
- LiteralExpr |
109
- InvocationExpr |
110
- ArrayExpr|
111
- ReferenceExpr |
112
- UnaryExpr;
113
-
114
- fragment ArgumentList:
115
- args+=Argument (',' args+=Argument)*;
116
-
117
- Argument:
118
- (name=ID ':')? value=Expression;
119
-
120
- // model
121
- DataModel:
122
- 'model' name=ID '{' (
123
- fields+=DataModelField
124
- | attributes+=DataModelAttribute
125
- )+
126
- '}';
127
-
128
- DataModelField:
129
- name=ID type=DataModelFieldType (attributes+=DataModelFieldAttribute)*;
130
-
131
- DataModelFieldType:
132
- (type=BuiltinType | reference=[TypeDeclaration:ID]) (array?='[]')? (optional?='?')?;
133
-
134
- // enum
135
- Enum:
136
- 'enum' name=ID '{' (fields+=EnumField)+ '}';
137
-
138
- EnumField:
139
- name=ID;
140
-
141
- // function
142
- Function:
143
- 'function' name=ID '(' (params+=FunctionParam (',' params+=FunctionParam)*)? ')' ':' returnType=FunctionParamType '{' (expression=Expression)? '}';
144
-
145
- FunctionParam:
146
- name=ID ':' type=FunctionParamType;
147
-
148
- FunctionParamType:
149
- (type=ExpressionType | reference=[TypeDeclaration]) (array?='[]')?;
150
-
151
- // attribute-level attribute
152
- AttributeAttributeName returns string:
153
- '@@@' ID;
154
-
155
- // model-level attribute
156
- DataModelAttributeName returns string:
157
- '@@' ID;
158
-
159
- // field-level attribute
160
- DataModelFieldAttributeName returns string:
161
- '@' ID;
162
-
163
- AttributeName returns string:
164
- DataModelAttributeName | DataModelFieldAttributeName | AttributeAttributeName;
165
-
166
- // attribute
167
- Attribute:
168
- 'attribute' name=AttributeName '(' (params+=AttributeParam (',' params+=AttributeParam)*)? ')' (attributes+=AttributeAttribute)*;
169
-
170
- AttributeParam:
171
- (default?='_')? name=ID ':' type=AttributeParamType;
172
-
173
- AttributeParamType:
174
- (type=(ExpressionType | 'FieldReference' | 'ContextType') | reference=[TypeDeclaration:ID]) (array?='[]')? (optional?='?')?;
175
-
176
- type TypeDeclaration = DataModel | Enum;
177
-
178
- DataModelFieldAttribute:
179
- decl=[Attribute:DataModelFieldAttributeName] ('(' AttributeArgList? ')')?;
180
-
181
- DataModelAttribute:
182
- decl=[Attribute:DataModelAttributeName] ('(' AttributeArgList? ')')?;
183
-
184
- AttributeAttribute:
185
- decl=[Attribute:AttributeAttributeName] ('(' AttributeArgList? ')')?;
186
-
187
- fragment AttributeArgList:
188
- args+=AttributeArg (',' args+=AttributeArg)*;
189
-
190
- AttributeArg:
191
- (name=ID ':')? value=Expression;
192
-
193
- ExpressionType returns string:
194
- 'String' | 'Int' | 'Float' | 'Boolean' | 'DateTime' | 'Null' | 'Any';
195
-
196
- BuiltinType returns string:
197
- 'String'|'Boolean'|'Int'|'BigInt'|'Float'|'Decimal'|'DateTime'|'Json'|'Bytes';
198
-
199
- hidden terminal WS: /\s+/;
200
- terminal BOOLEAN returns boolean: /true|false/;
201
- terminal NULL: 'null';
202
- terminal THIS: 'this';
203
- terminal ID: /[_a-zA-Z][\w_]*/;
204
- terminal STRING: /"[^"]*"|'[^']*'/;
205
- terminal NUMBER returns number: /[+-]?[0-9]+(\.[0-9]+)?/;
206
- hidden terminal ML_COMMENT: /\/\*[\s\S]*?\*\//;
207
- hidden terminal SL_COMMENT: /\/\/[^\n\r]*/;
@@ -1,9 +0,0 @@
1
- {
2
- "name": ".zenstack",
3
- "version": "1.0.0",
4
- "description": "ZenStack generated code",
5
- "main": "lib/index.js",
6
- "types": "lib/index.d.ts",
7
- "author": "ZenStack",
8
- "license": "MIT"
9
- }
@@ -1,22 +0,0 @@
1
- // based on: https://github.com/prisma/docs/blob/c72eb087fcf57f3c00d153f86c549ef28b3d0f44/src/components/customMdx/prism/prism-prisma.js
2
-
3
- (function (Prism) {
4
- Prism.languages.zmodel = Prism.languages.extend('clike', {
5
- keyword:
6
- /\b(?:datasource|enum|generator|model|attribute|function|null|this)\b/,
7
- 'type-class-name': /(\b()\s+)[\w.\\]+/,
8
- });
9
-
10
- Prism.languages.javascript['class-name'][0].pattern =
11
- /(\b(?:model|datasource|enum|generator)\s+)[\w.\\]+/;
12
-
13
- Prism.languages.insertBefore('zmodel', 'function', {
14
- annotation: {
15
- pattern: /(^|[^.])@+\w+/,
16
- lookbehind: true,
17
- alias: 'punctuation',
18
- },
19
- });
20
-
21
- Prism.languages.json5 = Prism.languages.js;
22
- })(Prism);
@@ -1,218 +0,0 @@
1
- /*
2
- * Enum representing referential integrity related actions
3
- */
4
- enum ReferentialAction {
5
- /*
6
- * Used with "onDelete": deleting a referenced record will trigger the deletion of referencing record.
7
- * Used with "onUpdate": updates the relation scalar fields if the referenced scalar fields of the dependent record are updated.
8
- */
9
- Cascade
10
-
11
- /*
12
- * Used with "onDelete": prevents the deletion if any referencing records exist.
13
- * Used with "onUpdate": prevents the identifier of a referenced record from being changed.
14
- */
15
- Restrict
16
-
17
- /*
18
- * Similar to 'Restrict', the difference between the two is dependent on the database being used.
19
- * See details: https://www.prisma.io/docs/concepts/components/prisma-schema/relations/referential-actions#noaction
20
- */
21
- NoAction
22
-
23
- /*
24
- * Used with "onDelete": the scalar field of the referencing object will be set to NULL.
25
- * Used with "onUpdate": when updating the identifier of a referenced object, the scalar fields of the referencing objects will be set to NULL.
26
- */
27
- SetNull
28
-
29
- /*
30
- * Used with "onDelete": the scalar field of the referencing object will be set to the fields default value.
31
- * Used with "onUpdate": the scalar field of the referencing object will be set to the fields default value.
32
- */
33
- SetDefault
34
- }
35
-
36
- /*
37
- * Enum representing all possible field types
38
- */
39
- enum AttributeTargetField {
40
- StringField
41
- IntField
42
- FloatField
43
- DecimalField
44
- BooleanField
45
- DateTimeField
46
- JsonField
47
- BytesField
48
- ModelField
49
- }
50
-
51
- /*
52
- * Reads value from an environment variable.
53
- */
54
- function env(name: String): String {}
55
-
56
- /*
57
- * Gets the current login user.
58
- */
59
- function auth(): Any {}
60
-
61
- /*
62
- * Gets current date-time (as DateTime type).
63
- */
64
- function now(): DateTime {}
65
-
66
- /*
67
- * Generates a globally unique identifier based on the UUID specs.
68
- */
69
- function uuid(): String {}
70
-
71
- /*
72
- * Generates a globally unique identifier based on the CUID spec.
73
- */
74
- function cuid(): String {}
75
-
76
- /*
77
- * Creates a sequence of integers in the underlying database and assign the incremented
78
- * values to the ID values of the created records based on the sequence.
79
- */
80
- function autoincrement(): Int {}
81
-
82
- /*
83
- * Represents default values that cannot be expressed in the Prisma schema (such as random()).
84
- */
85
- function dbgenerated(expr: String): Any {}
86
-
87
- attribute @@@targetField(targetField: AttributeTargetField[])
88
-
89
- attribute @@@prisma()
90
-
91
- /*
92
- * Defines an ID on the model.
93
- */
94
- attribute @id(map: String?) @@@prisma
95
-
96
- /*
97
- * Defines a default value for a field.
98
- */
99
- attribute @default(_ value: ContextType) @@@prisma
100
-
101
- /*
102
- * Defines a unique constraint for this field.
103
- */
104
- attribute @unique(map: String?) @@@prisma
105
-
106
- /*
107
- * Defines a compound unique constraint for the specified fields.
108
- */
109
- attribute @@unique(_ fields: FieldReference[], name: String?, map: String?) @@@prisma
110
-
111
- /*
112
- * Defines an index in the database.
113
- */
114
- attribute @@index(_ fields: FieldReference[], map: String?) @@@prisma
115
-
116
- /*
117
- * Defines meta information about the relation.
118
- */
119
- attribute @relation(_ name: String?, fields: FieldReference[]?, references: FieldReference[]?, onDelete: ReferentialAction?, onUpdate: ReferentialAction?, map: String?) @@@prisma
120
-
121
- /*
122
- * Maps a field name or enum value from the schema to a column with a different name in the database.
123
- */
124
- attribute @map(_ name: String) @@@prisma
125
-
126
- /*
127
- * Maps the schema model name to a table with a different name, or an enum name to a different underlying enum in the database.
128
- */
129
- attribute @@map(_ name: String) @@@prisma
130
-
131
- /*
132
- * Automatically stores the time when a record was last updated.
133
- */
134
- attribute @updatedAt() @@@targetField([DateTimeField]) @@@prisma
135
-
136
- /*
137
- * Defines an access policy that allows a set of operations when the given condition is true.
138
- */
139
- attribute @@allow(_ operation: String, _ condition: Boolean)
140
-
141
- /*
142
- * Defines an access policy that denies a set of operations when the given condition is true.
143
- */
144
- attribute @@deny(_ operation: String, _ condition: Boolean)
145
-
146
- /*
147
- * Indicates that the field is a password field and needs to be hashed before persistence.
148
- *
149
- * ZenStack uses `bcryptjs` library to hash password. You can use the `saltLength` parameter
150
- * to configure the cost of hashing, or use `salt` parameter to provide an explicit salt.
151
- * By default, salt length of 12 is used.
152
- *
153
- * @see https://www.npmjs.com/package/bcryptjs for details
154
- *
155
- * @saltLength: length of salt to use (cost factor for the hash function)
156
- * @salt: salt to use (a pregenerated valid salt)
157
- */
158
- attribute @password(saltLength: Int?, salt: String?) @@@targetField([StringField])
159
-
160
- /*
161
- * Indicates that the field should be omitted when read from the generated services.
162
- */
163
- attribute @omit()
164
-
165
- /*
166
- * Validates length of a string field.
167
- */
168
- attribute @length(_ min: Int?, _ max: Int?) @@@targetField([StringField])
169
-
170
- /*
171
- * Validates a string field value matches a regex.
172
- */
173
- attribute @regex(_ regex: String) @@@targetField([StringField])
174
-
175
- /*
176
- * Validates a string field value starts with the given text.
177
- */
178
- attribute @startsWith(_ text: String) @@@targetField([StringField])
179
-
180
- /*
181
- * Validates a string field value ends with the given text.
182
- */
183
- attribute @endsWith(_ text: String) @@@targetField([StringField])
184
-
185
- /*
186
- * Validates a string field value is a valid email address.
187
- */
188
- attribute @email() @@@targetField([StringField])
189
-
190
- /*
191
- * Validates a string field value is a valid ISO datetime.
192
- */
193
- attribute @datetime() @@@targetField([StringField])
194
-
195
- /*
196
- * Validates a string field value is a valid url.
197
- */
198
- attribute @url() @@@targetField([StringField])
199
-
200
- /*
201
- * Validates a number field is greater than the given value.
202
- */
203
- attribute @gt(_ value: Int) @@@targetField([IntField, FloatField, DecimalField])
204
-
205
- /*
206
- * Validates a number field is greater than or equal to the given value.
207
- */
208
- attribute @gte(_ value: Int) @@@targetField([IntField, FloatField, DecimalField])
209
-
210
- /*
211
- * Validates a number field is less than the given value.
212
- */
213
- attribute @lt(_ value: Int) @@@targetField([IntField, FloatField, DecimalField])
214
-
215
- /*
216
- * Validates a number field is less than or equal to the given value.
217
- */
218
- attribute @lte(_ value: Int) @@@targetField([IntField, FloatField, DecimalField])
@@ -1,17 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES6",
4
- "module": "CommonJS",
5
- "lib": ["ESNext", "DOM"],
6
- "sourceMap": true,
7
- "outDir": "lib",
8
- "strict": true,
9
- "moduleResolution": "node",
10
- "esModuleInterop": true,
11
- "skipLibCheck": true,
12
- "declaration": true,
13
- "resolveJsonModule": true
14
- },
15
- "include": ["**/*.ts"],
16
- "exclude": ["node_modules", ".prisma", "**/*.d.ts"]
17
- }
package/src/telemetry.ts DELETED
@@ -1,119 +0,0 @@
1
- import { Mixpanel, init } from 'mixpanel';
2
- import { TELEMETRY_TRACKING_TOKEN } from 'env';
3
- import { machineIdSync } from 'node-machine-id';
4
- import cuid from 'cuid';
5
- import * as os from 'os';
6
- import sleep from 'sleep-promise';
7
- import exitHook from 'async-exit-hook';
8
- import { CliError } from './cli/cli-error';
9
- import { CommanderError } from 'commander';
10
-
11
- /**
12
- * Telemetry events
13
- */
14
- export type TelemetryEvents =
15
- | 'cli:start'
16
- | 'cli:complete'
17
- | 'cli:error'
18
- | 'cli:command:start'
19
- | 'cli:command:complete'
20
- | 'cli:command:error'
21
- | 'cli:generator:start'
22
- | 'cli:generator:complete'
23
- | 'cli:generator:error';
24
-
25
- /**
26
- * Utility class for sending telemetry
27
- */
28
- export class Telemetry {
29
- private readonly mixpanel: Mixpanel | undefined;
30
- private readonly hostId = machineIdSync();
31
- private readonly sessionid = cuid();
32
- private readonly trackingToken = TELEMETRY_TRACKING_TOKEN;
33
- private readonly _os = os.platform();
34
- // eslint-disable-next-line @typescript-eslint/no-var-requires
35
- private readonly version = require('../package.json').version;
36
- private exitWait = 200;
37
-
38
- constructor() {
39
- if (process.env.DO_NOT_TRACK !== '1' && this.trackingToken) {
40
- this.mixpanel = init(this.trackingToken, {
41
- geolocate: true,
42
- });
43
- }
44
-
45
- exitHook(async (callback) => {
46
- if (this.mixpanel) {
47
- // a small delay to ensure telemetry is sent
48
- await sleep(this.exitWait);
49
- }
50
- callback();
51
- });
52
-
53
- exitHook.uncaughtExceptionHandler(async (err) => {
54
- this.track('cli:error', {
55
- message: err.message,
56
- stack: err.stack,
57
- });
58
- if (this.mixpanel) {
59
- // a small delay to ensure telemetry is sent
60
- await sleep(this.exitWait);
61
- }
62
-
63
- if (err instanceof CliError || err instanceof CommanderError) {
64
- // error already handled
65
- } else {
66
- throw err;
67
- }
68
-
69
- process.exit(1);
70
- });
71
- }
72
-
73
- track(event: TelemetryEvents, properties: Record<string, unknown> = {}) {
74
- if (this.mixpanel) {
75
- const payload = {
76
- distinct_id: this.hostId,
77
- session: this.sessionid,
78
- time: new Date(),
79
- $os: this._os,
80
- nodeVersion: process.version,
81
- version: this.version,
82
- ...properties,
83
- };
84
- this.mixpanel.track(event, payload);
85
- }
86
- }
87
-
88
- async trackSpan(
89
- startEvent: TelemetryEvents,
90
- completeEvent: TelemetryEvents,
91
- errorEvent: TelemetryEvents,
92
- properties: Record<string, unknown>,
93
- action: () => Promise<unknown> | void
94
- ) {
95
- this.track(startEvent, properties);
96
- const start = Date.now();
97
- let success = true;
98
- try {
99
- await Promise.resolve(action());
100
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
101
- } catch (err: any) {
102
- this.track(errorEvent, {
103
- message: err.message,
104
- stack: err.stack,
105
- ...properties,
106
- });
107
- success = false;
108
- throw err;
109
- } finally {
110
- this.track(completeEvent, {
111
- duration: Date.now() - start,
112
- success,
113
- ...properties,
114
- });
115
- }
116
- }
117
- }
118
-
119
- export default new Telemetry();
@@ -1,8 +0,0 @@
1
- import { execSync as _exec } from 'child_process';
2
-
3
- /**
4
- * Utility for executing command synchronously and prints outputs on current console
5
- */
6
- export function execSync(cmd: string): void {
7
- _exec(cmd, { encoding: 'utf-8', stdio: 'inherit' });
8
- }
@@ -1,9 +0,0 @@
1
- // https://github.com/sindresorhus/indent-string
2
-
3
- /**
4
- * Utility for indenting strings
5
- */
6
- export default function indentString(string: string, count = 4): string {
7
- const indent = ' ';
8
- return string.replace(/^(?!\s*$)/gm, indent.repeat(count));
9
- }
@@ -1,63 +0,0 @@
1
- import fs from 'fs';
2
- import path from 'path';
3
- import { execSync } from './exec-utils';
4
-
5
- export type PackageManagers = 'npm' | 'yarn' | 'pnpm';
6
-
7
- function getPackageManager(projectPath = '.'): PackageManagers {
8
- if (fs.existsSync(path.join(projectPath, 'yarn.lock'))) {
9
- return 'yarn';
10
- } else if (fs.existsSync(path.join(projectPath, 'pnpm-lock.yaml'))) {
11
- return 'pnpm';
12
- } else {
13
- return 'npm';
14
- }
15
- }
16
-
17
- export function installPackage(
18
- pkg: string,
19
- dev: boolean,
20
- pkgManager: PackageManagers | undefined = undefined,
21
- projectPath = '.'
22
- ) {
23
- const manager = pkgManager ?? getPackageManager(projectPath);
24
- console.log(`Installing package "${pkg}" with ${manager}`);
25
- switch (manager) {
26
- case 'yarn':
27
- execSync(
28
- `yarn --cwd "${projectPath}" add ${pkg} ${
29
- dev ? ' --dev' : ''
30
- } --ignore-engines`
31
- );
32
- break;
33
-
34
- case 'pnpm':
35
- execSync(
36
- `pnpm add -C "${projectPath}" ${
37
- dev ? ' --save-dev' : ''
38
- } ${pkg}`
39
- );
40
- break;
41
-
42
- default:
43
- execSync(
44
- `npm install --prefix "${projectPath}" ${
45
- dev ? ' --save-dev' : ''
46
- } ${pkg}`
47
- );
48
- break;
49
- }
50
- }
51
-
52
- export function ensurePackage(
53
- pkg: string,
54
- dev: boolean,
55
- pkgManager: PackageManagers | undefined = undefined,
56
- projectPath = '.'
57
- ) {
58
- try {
59
- require(pkg);
60
- } catch {
61
- installPackage(pkg, dev, pkgManager, projectPath);
62
- }
63
- }