mirror of
https://github.com/nocodb/nocodb.git
synced 2026-02-01 20:37:46 +00:00
chore: move nc-cli to seperate repo
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
{
|
||||
"packages": [
|
||||
"packages/nc-cli",
|
||||
"packages/nc-gui",
|
||||
"packages/nocodb",
|
||||
"packages/nocodb-sdk"
|
||||
|
||||
10
packages/nc-cli/.gitignore
vendored
10
packages/nc-cli/.gitignore
vendored
@@ -1,10 +0,0 @@
|
||||
/node_modules/
|
||||
#build
|
||||
src/**.js
|
||||
.idea/*
|
||||
dist
|
||||
coverage
|
||||
.nyc_output
|
||||
*.log
|
||||
help
|
||||
yarn.lock
|
||||
@@ -1,16 +0,0 @@
|
||||
/node_modules/
|
||||
help
|
||||
src
|
||||
.idea/*
|
||||
coverage
|
||||
.nyc_output
|
||||
*.log
|
||||
yarn.lock
|
||||
webpack.config.js
|
||||
tsconfig.json
|
||||
tsconfig.module.json
|
||||
tslint.json
|
||||
package-lock.json
|
||||
dist/*.db-shm
|
||||
dist/*.db-wal
|
||||
/buildScript/
|
||||
@@ -1,661 +0,0 @@
|
||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
Version 3, 19 November 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU Affero General Public License is a free, copyleft license for
|
||||
software and other kinds of works, specifically designed to ensure
|
||||
cooperation with the community in the case of network server software.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
our General Public Licenses are intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
Developers that use our General Public Licenses protect your rights
|
||||
with two steps: (1) assert copyright on the software, and (2) offer
|
||||
you this License which gives you legal permission to copy, distribute
|
||||
and/or modify the software.
|
||||
|
||||
A secondary benefit of defending all users' freedom is that
|
||||
improvements made in alternate versions of the program, if they
|
||||
receive widespread use, become available for other developers to
|
||||
incorporate. Many developers of free software are heartened and
|
||||
encouraged by the resulting cooperation. However, in the case of
|
||||
software used on network servers, this result may fail to come about.
|
||||
The GNU General Public License permits making a modified version and
|
||||
letting the public access it on a server without ever releasing its
|
||||
source code to the public.
|
||||
|
||||
The GNU Affero General Public License is designed specifically to
|
||||
ensure that, in such cases, the modified source code becomes available
|
||||
to the community. It requires the operator of a network server to
|
||||
provide the source code of the modified version running there to the
|
||||
users of that server. Therefore, public use of a modified version, on
|
||||
a publicly accessible server, gives the public access to the source
|
||||
code of the modified version.
|
||||
|
||||
An older license, called the Affero General Public License and
|
||||
published by Affero, was designed to accomplish similar goals. This is
|
||||
a different license, not a version of the Affero GPL, but Affero has
|
||||
released a new version of the Affero GPL which permits relicensing under
|
||||
this license.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, if you modify the
|
||||
Program, your modified version must prominently offer all users
|
||||
interacting with it remotely through a computer network (if your version
|
||||
supports such interaction) an opportunity to receive the Corresponding
|
||||
Source of your version by providing access to the Corresponding Source
|
||||
from a network server at no charge, through some standard or customary
|
||||
means of facilitating copying of software. This Corresponding Source
|
||||
shall include the Corresponding Source for any work covered by version 3
|
||||
of the GNU General Public License that is incorporated pursuant to the
|
||||
following paragraph.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the work with which it is combined will remain governed by version
|
||||
3 of the GNU General Public License.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU Affero General Public License from time to time. Such new versions
|
||||
will be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU Affero General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU Affero General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU Affero General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If your software can interact with users remotely through a computer
|
||||
network, you should also make sure that it provides a way for users to
|
||||
get its source. For example, if your program is a web application, its
|
||||
interface could display a "Source" link that leads users to an archive
|
||||
of the code. There are many ways you could offer source, and different
|
||||
solutions will be better for different programs; see section 13 for the
|
||||
specific requirements.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
@@ -1,3 +0,0 @@
|
||||
# nc-cli
|
||||
|
||||
Create a NocoDB Application with CLI
|
||||
@@ -1,11 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const packageJson = JSON.parse(fs.readFileSync(path.join(__dirname,'..','package.json'), 'utf8'));
|
||||
|
||||
const version = packageJson.version.replace(/\.(\d+)$/, (_, v) => {
|
||||
return `.${++v}`
|
||||
});
|
||||
|
||||
packageJson.version = version;
|
||||
|
||||
fs.writeFileSync(path.join(__dirname,'..','package.json'), JSON.stringify(packageJson, null, 2));
|
||||
27678
packages/nc-cli/package-lock.json
generated
27678
packages/nc-cli/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,143 +0,0 @@
|
||||
{
|
||||
"name": "create-nocodb-app",
|
||||
"version": "0.1.28",
|
||||
"description": "Create NocoDB app using CLI",
|
||||
"private": true,
|
||||
"author": {
|
||||
"name": "NocoDB Inc",
|
||||
"url": "https://nocodb.com/"
|
||||
},
|
||||
"homepage": "https://github.com/nocodb/nocodb",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nocodb/nocodb.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/nocodb/nocodb/issues"
|
||||
},
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"main": "dist/bundle.js",
|
||||
"module": "dist/bundle.js",
|
||||
"keywords": [],
|
||||
"bin": {
|
||||
"noco": "./dist/bundle.js",
|
||||
"create-nocodb-app": "./dist/bundle.js",
|
||||
"nc-cli": "./dist/bundle.js"
|
||||
},
|
||||
"scripts": {
|
||||
"describe": "npm-scripts-info",
|
||||
"build": "webpack --config webpack.config.js",
|
||||
"build:publish": "export NODE_OPTIONS=--openssl-legacy-provider && rm -rf dist && npm run build && npm publish .",
|
||||
"fix": "run-s fix:*",
|
||||
"fix:prettier": "prettier \"src/**/*.ts\" --write",
|
||||
"fix:tslint": "tslint --fix --project .",
|
||||
"test": "run-s build test:*",
|
||||
"test:lint": "tslint --project . && prettier \"src/**/*.ts\" --list-different",
|
||||
"test:unit": "nyc --silent ava",
|
||||
"watch": "run-s clean build:main && run-p \"build:main -- -w\" \"test:unit -- --watch\"",
|
||||
"cov": "run-s build test:unit cov:html && open-cli coverage/index.html",
|
||||
"cov:html": "nyc report --reporter=html",
|
||||
"cov:send": "nyc report --reporter=lcov && codecov",
|
||||
"cov:check": "nyc report && nyc check-coverage --lines 100 --functions 100 --branches 100",
|
||||
"doc": "run-s doc:html && open-cli build/docs/index.html",
|
||||
"doc:html": "typedoc src/ --exclude **/*.spec.ts --target ES6 --mode file --out build/docs",
|
||||
"doc:json": "typedoc src/ --exclude **/*.spec.ts --target ES6 --mode file --json build/docs/typedoc.json",
|
||||
"doc:publish": "gh-pages -m \"[ci skip] Updates\" -d build/docs",
|
||||
"version": "standard-version",
|
||||
"reset": "git clean -dfx && git reset --hard && npm i",
|
||||
"clean": "trash build test",
|
||||
"prepare-release": "run-s reset test cov:check doc:html version doc:publish",
|
||||
"test:new": "./dist/bundle.js new "
|
||||
},
|
||||
"scripts-info": {
|
||||
"info": "Display information about the package scripts",
|
||||
"build": "Clean and rebuild the project",
|
||||
"fix": "Try to automatically fix any linting problems",
|
||||
"test": "Lint and unit test the project",
|
||||
"watch": "Watch and rebuild the project on save, then rerun relevant tests",
|
||||
"cov": "Rebuild, run tests, then create and open the coverage report",
|
||||
"doc": "Generate HTML API documentation and open it in a browser",
|
||||
"doc:json": "Generate API documentation in typedoc JSON format",
|
||||
"version": "Bump package.json version, update CHANGELOG.md, tag release",
|
||||
"reset": "Delete all untracked files and reset the repo to the last commit",
|
||||
"prepare-release": "One-step: clean, build, test, publish docs, and prep a release"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.9"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.21.1",
|
||||
"boxen": "^4.2.0",
|
||||
"chalk-pipe": "^4.0.0",
|
||||
"cli-table3": "0.6.1",
|
||||
"colors": "1.4.0",
|
||||
"download": "^8.0.0",
|
||||
"download-git-repo": "^3.0.2",
|
||||
"express": "^4.21.2",
|
||||
"fs-extra": "^9.0.1",
|
||||
"glob": "^7.1.6",
|
||||
"inquirer": "^7.3.3",
|
||||
"jsonfile": "^6.0.1",
|
||||
"knex": "^0.21.5",
|
||||
"linux-os-info": "^2.0.0",
|
||||
"mkdirp": "^1.0.4",
|
||||
"mssql": "^6.2.1",
|
||||
"mysql": "^2.18.1",
|
||||
"open": "^7.1.0",
|
||||
"ora": "^4.0.5",
|
||||
"os-locale": "^5.0.0",
|
||||
"pg": "^8.3.2",
|
||||
"shelljs": "^0.8.4",
|
||||
"tcp-port-used": "^1.0.1",
|
||||
"unique-names-generator": "^4.5.0",
|
||||
"update-notifier": "^4.1.0",
|
||||
"uuid": "^8.3.1",
|
||||
"yargs": "^15.4.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@bitjson/typedoc": "^0.15.0-0",
|
||||
"@istanbuljs/nyc-config-typescript": "^0.1.3",
|
||||
"ava": "2.2.0",
|
||||
"codecov": "^3.5.0",
|
||||
"cz-conventional-changelog": "^2.1.0",
|
||||
"gh-pages": "^2.0.1",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"nyc": "^14.1.1",
|
||||
"open-cli": "^5.0.0",
|
||||
"prettier": "^1.18.2",
|
||||
"standard-version": "^6.0.1",
|
||||
"trash-cli": "^3.0.0",
|
||||
"ts-loader": "^8.0.5",
|
||||
"ts-node": "^8.10.2",
|
||||
"tslint": "^5.18.0",
|
||||
"tslint-config-prettier": "^1.18.0",
|
||||
"tslint-immutable": "^6.0.1",
|
||||
"typescript": "^3.5.3",
|
||||
"webpack": "^5.76.0",
|
||||
"webpack-cli": "^4.10.0",
|
||||
"webpack-node-externals": "^2.5.2"
|
||||
},
|
||||
"ava": {
|
||||
"failFast": true,
|
||||
"files": [
|
||||
"build/main/**/*.spec.js"
|
||||
],
|
||||
"sources": [
|
||||
"build/main/**/*.js"
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
"commitizen": {
|
||||
"path": "cz-conventional-changelog"
|
||||
}
|
||||
},
|
||||
"prettier": {
|
||||
"singleQuote": true
|
||||
},
|
||||
"nyc": {
|
||||
"extends": "@istanbuljs/nyc-config-typescript",
|
||||
"exclude": [
|
||||
"**/*.spec.js"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
// #! /usr/bin/env node
|
||||
|
||||
import CliMgr from './lib/CliMgr';
|
||||
import SocialMgr from './lib/mgr/SocialMgr';
|
||||
import Util from './lib/util/Util';
|
||||
|
||||
import updateNotifier from 'update-notifier';
|
||||
|
||||
// tslint:disable-next-line:no-var-requires
|
||||
const pkg = require('../package.json');
|
||||
import yargs from 'yargs';
|
||||
|
||||
const {
|
||||
uniqueNamesGenerator,
|
||||
starWars,
|
||||
adjectives,
|
||||
animals
|
||||
} = require('unique-names-generator');
|
||||
|
||||
/* get cli args */
|
||||
const args = yargs
|
||||
.alias('u', 'url')
|
||||
.alias('m', 'module')
|
||||
.alias('n', 'nomodel')
|
||||
.help('help').argv;
|
||||
|
||||
/* cwd is reference to all commands */
|
||||
args.folder = process.cwd();
|
||||
|
||||
/* handle command */
|
||||
(async () => {
|
||||
// Checks for available update and returns an instance
|
||||
const notifier = updateNotifier({ pkg });
|
||||
|
||||
// Notify using the built-in convenience method
|
||||
notifier.notify();
|
||||
|
||||
if (args._) {
|
||||
if (!args._.length) {
|
||||
await SocialMgr.showPrompt();
|
||||
args._.unshift(
|
||||
uniqueNamesGenerator({
|
||||
dictionaries: [[starWars], [adjectives, animals]][
|
||||
Math.floor(Math.random() * 2)
|
||||
]
|
||||
})
|
||||
.toLowerCase()
|
||||
.replace(/[ -]/g, '_')
|
||||
);
|
||||
}
|
||||
await CliMgr.process(args);
|
||||
} else {
|
||||
Util.showHelp(args);
|
||||
process.exit(0);
|
||||
}
|
||||
})().catch(err => {
|
||||
console.error('\n\nThere was an error processing command:');
|
||||
console.error(err);
|
||||
});
|
||||
@@ -1,427 +0,0 @@
|
||||
import Util from './util/Util';
|
||||
|
||||
import('colors');
|
||||
import shell from 'shelljs';
|
||||
// import AppMgr from './mgr/AppMgr';
|
||||
import client from './mgr/Client';
|
||||
// import ComponentMgr from './mgr/ComponentMgr';
|
||||
// import MigrationMgr from './mgr/MigrationMgr';
|
||||
// import ModelMgr from './mgr/ModelMgr';
|
||||
// import OldNewMgr from './mgr/NewMgr';
|
||||
// import InstantMgr from './mgr/InstantMgr';
|
||||
// import PermissionsMgr from './mgr/PermissionsMgr';
|
||||
// import SocialMgr from './mgr/SocialMgr';
|
||||
// import DockerMgr from "./mgr/DockerMgr";
|
||||
import NewMgr from './mgr/NewMgr';
|
||||
// import TryMgr from "./mgr/TryMgr";
|
||||
|
||||
let cmdProcessedOnce = 0;
|
||||
let cmdOriginalArgs = null;
|
||||
|
||||
class CliMgr {
|
||||
public static async runCmd(str) {
|
||||
shell.echo(`\nNow, executing command : ${str}\n\n`.blue);
|
||||
if (shell.exec(str).code !== 0) {
|
||||
shell.echo(`\n\nError running command internally\n\n\t"${str}"`.red);
|
||||
shell.echo(`\nExiting...`.red);
|
||||
shell.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
public static async process(args) {
|
||||
cmdOriginalArgs = cmdOriginalArgs ? cmdOriginalArgs : args;
|
||||
|
||||
try {
|
||||
if (args._ && args._.length) {
|
||||
switch (args._[0]) {
|
||||
case 'man':
|
||||
if (args._.length > 1) {
|
||||
Util.showHelpForCommand(args);
|
||||
} else {
|
||||
Util.showHelp(args);
|
||||
}
|
||||
|
||||
process.exit(0);
|
||||
break;
|
||||
|
||||
/**************** START : new project with apis creation ****************/
|
||||
case 'n':
|
||||
case 'new':
|
||||
if (await NewMgr.getNewProjectInput(args)) {
|
||||
if (args._[0] === 'gap') {
|
||||
console.log('gRPC code generation is not yet supported.');
|
||||
process.exit(0);
|
||||
}
|
||||
await client.requestSend(args);
|
||||
} else {
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
/**************** END : new project with apis creation ****************/
|
||||
// /**************** START : new project with apis creation ****************/
|
||||
// case 'nold':
|
||||
// case 'newold':
|
||||
// if (await NewMgr.getNewProjectInputOld(args)) {
|
||||
// if (args._[0] === 'gap') {
|
||||
// console.log('gRPC code generation is not yet supported.');
|
||||
// process.exit(0)
|
||||
// }
|
||||
// await client.requestSend(args)
|
||||
// } else {
|
||||
// process.exit(0)
|
||||
// }
|
||||
//
|
||||
// break;
|
||||
//
|
||||
// /**************** END : new project with apis creation ****************/
|
||||
// /**************** START : try xc-instant with in-memory ****************/
|
||||
// case 't':
|
||||
// case 'try':
|
||||
// await TryMgr.getProjectInput(args);
|
||||
// process.exit(0)
|
||||
// break;
|
||||
//
|
||||
// case 'sg':
|
||||
// case 'sample.gql':
|
||||
// case 'sample.graphql':
|
||||
// await TryMgr.getProjectInput({_: ['sample', 'gql']});
|
||||
// process.exit(0)
|
||||
// break;
|
||||
//
|
||||
// case 'sr':
|
||||
// case 'sample.rest':
|
||||
// case 'sample':
|
||||
// case 's':
|
||||
// await TryMgr.getProjectInput({_: ['sample', 'rest']});
|
||||
// process.exit(0)
|
||||
// break;
|
||||
//
|
||||
// /**************** END : try xc-instant with in-memory ****************/
|
||||
//
|
||||
// /**************** START : new project with apis creation ****************/
|
||||
// // case 'nold':
|
||||
// // case 'newold':
|
||||
// // if (await OldNewMgr.getNewProjectInput(args)) {
|
||||
// // if (args._[0] === 'gap') {
|
||||
// // console.log('gRPC code generation is not yet supported.');
|
||||
// // process.exit(0)
|
||||
// // }
|
||||
// // await client.requestSend(args)
|
||||
// // } else {
|
||||
// // process.exit(0)
|
||||
// // }
|
||||
// //
|
||||
// // break;
|
||||
//
|
||||
// /**************** END : new project with apis creation ****************/
|
||||
//
|
||||
//
|
||||
// /**************** START : new project with apis creation ****************/
|
||||
// case 'd':
|
||||
// case 'docker':
|
||||
// await DockerMgr.genDockerfile(args)
|
||||
// break;
|
||||
//
|
||||
// /**************** END : new project with apis creation ****************/
|
||||
//
|
||||
// //
|
||||
// // /**************** START : instant apis creation ****************/
|
||||
// // case 'i':
|
||||
// // case 'instant':
|
||||
// // await InstantMgr.getNewProjectInput(args);
|
||||
// // break;
|
||||
// //
|
||||
// // /**************** END : instant apis creation ****************/
|
||||
// /**************** START : Init xc instant project ****************/
|
||||
// case 'i':
|
||||
// case 'init':
|
||||
// await NewMgr.initProject(args);
|
||||
// break;
|
||||
//
|
||||
// /**************** END : Init xc instant project ****************/
|
||||
//
|
||||
// /**************** START : apis creation ****************/
|
||||
// case 'ga':
|
||||
// case 'gar':
|
||||
// case 'gen.apis':
|
||||
// case 'gen.apis.rest':
|
||||
// // console.log(`xc : Generating REST APIs`.green, args);
|
||||
// await client.requestSend(args);
|
||||
// break;
|
||||
//
|
||||
// case 'gag':
|
||||
// case 'gen.apis.graphql':
|
||||
// case 'gen.apis.gql':
|
||||
// // console.log(`xc : Generating GraphQL APIs`.green);
|
||||
// await client.requestSend(args);
|
||||
// break;
|
||||
// /**************** END : apis creation ****************/
|
||||
//
|
||||
//
|
||||
// case 'gm':
|
||||
// case 'gen.module':
|
||||
// await client.requestSend(args);
|
||||
// break;
|
||||
//
|
||||
// /**************** START : rest components scaffolding ****************/
|
||||
// case 'gmr':
|
||||
// case 'gen.module.router':
|
||||
// await client.requestSend(args);
|
||||
// break;
|
||||
//
|
||||
// case 'gmm':
|
||||
// case 'gen.module.middleware':
|
||||
// await client.requestSend(args);
|
||||
// break;
|
||||
//
|
||||
// case 'gms':
|
||||
// case 'gen.module.service':
|
||||
// await client.requestSend(args);
|
||||
// break;
|
||||
// /**************** END : rest components scaffolding ****************/
|
||||
//
|
||||
//
|
||||
// /**************** START : graphql components scaffolding ****************/
|
||||
// case 'ggm':
|
||||
// case 'gen.gql.module':
|
||||
// await client.requestSend(args);
|
||||
// break;
|
||||
//
|
||||
// case 'ggmr':
|
||||
// case 'gen.gql.module.resolver':
|
||||
// await client.requestSend(args);
|
||||
// break;
|
||||
//
|
||||
// case 'ggmm':
|
||||
// case 'gen.gql.module.middleware':
|
||||
// await client.requestSend(args);
|
||||
// break;
|
||||
//
|
||||
// case 'ggms':
|
||||
// case 'gen.gql.module.service':
|
||||
// await client.requestSend(args);
|
||||
// break;
|
||||
// /**************** END : graphql components scaffolding ****************/
|
||||
//
|
||||
//
|
||||
// /**************** START : Migration stuff ****************/
|
||||
// case 'db.migrate.init' :
|
||||
// case 'dmi' :
|
||||
// console.log('migration init', args);
|
||||
// await MigrationMgr.init(args);
|
||||
// process.exit(0);
|
||||
// break;
|
||||
//
|
||||
// case 'db.migrate.sync' :
|
||||
// case 'dms' :
|
||||
// console.log('migration sync', args);
|
||||
// await MigrationMgr.sync(args);
|
||||
// process.exit(0);
|
||||
// break;
|
||||
//
|
||||
// case 'db.migrate.list' :
|
||||
// case 'dml' :
|
||||
// console.log('migration list');
|
||||
// await MigrationMgr.list(args);
|
||||
// process.exit(0);
|
||||
// break;
|
||||
//
|
||||
// case 'db.migrate.create' :
|
||||
// case 'dmc' :
|
||||
// console.log('migration create', args);
|
||||
// await MigrationMgr.create(args);
|
||||
// process.exit(0);
|
||||
// break;
|
||||
//
|
||||
// case 'db.migrate.up' :
|
||||
// case 'dmu' :
|
||||
// console.log('migration create', args);
|
||||
// await MigrationMgr.up(args);
|
||||
// process.exit(0);
|
||||
// break;
|
||||
//
|
||||
// case 'db.migrate.down' :
|
||||
// case 'dmd' :
|
||||
// console.log('migration down', args);
|
||||
// await MigrationMgr.down(args);
|
||||
// process.exit(0);
|
||||
// break;
|
||||
//
|
||||
// case 'db.migrate.term' :
|
||||
// case 'dmt' :
|
||||
// console.log('migration init', args);
|
||||
// await MigrationMgr.clean(args);
|
||||
// process.exit(0);
|
||||
// break;
|
||||
//
|
||||
// case 'db.migrate.sql.dump' :
|
||||
// case 'dmsd' :
|
||||
// console.log('migration meta dump', args);
|
||||
// await client.requestSend(args);
|
||||
// break;
|
||||
// /**************** END : Migration stuff ****************/
|
||||
//
|
||||
//
|
||||
// /**************** START : Meta stuff ****************/
|
||||
//
|
||||
// case 'meta.export' :
|
||||
// case 'me' :
|
||||
// console.log('meta export', args);
|
||||
// if (!('env' in args)) {
|
||||
// console.log(`Missing '${'env'.bold}' parameter`.red);
|
||||
// process.exit(0);
|
||||
// }
|
||||
//
|
||||
// await client.requestSend(args);
|
||||
// break;
|
||||
// case 'meta.import' :
|
||||
// case 'mi' :
|
||||
// console.log('meta import', args)
|
||||
// if (!('env' in args)) {
|
||||
// console.log(`Missing '${'env'.bold}' parameter`.red);
|
||||
// process.exit(0);
|
||||
// }
|
||||
//
|
||||
// await client.requestSend(args);
|
||||
// break;
|
||||
// case 'meta.reset' :
|
||||
// case 'mr' :
|
||||
// console.log('met reset', args)
|
||||
// if (!('env' in args)) {
|
||||
// console.log(`Missing '${'env'.bold}' parameter`.red);
|
||||
// process.exit(0);
|
||||
// }
|
||||
//
|
||||
// await client.requestSend(args);
|
||||
// break;
|
||||
// /**************** END : Meta stuff ****************/
|
||||
//
|
||||
//
|
||||
// /**************** START : ACL stuff ****************/
|
||||
// case 'permissions.set':
|
||||
// case 'ps':
|
||||
// await PermissionsMgr.set(args)
|
||||
// process.exit(0);
|
||||
// break;
|
||||
// case 'permissions.get':
|
||||
// case 'pg':
|
||||
// await PermissionsMgr.get(args)
|
||||
// process.exit(0);
|
||||
// break;
|
||||
// case 'permissions.role.add':
|
||||
// case 'pra':
|
||||
// await PermissionsMgr.userAdd(args)
|
||||
// process.exit(0);
|
||||
// break;
|
||||
// case 'permissions.role.delete':
|
||||
// case 'prd':
|
||||
// await PermissionsMgr.userDelete(args)
|
||||
// process.exit(0);
|
||||
// break;
|
||||
// case 'permissions.role.rename':
|
||||
// case 'prr':
|
||||
// await PermissionsMgr.userRename(args)
|
||||
// process.exit(0);
|
||||
// break;
|
||||
// /**************** END : ACL stuff ****************/
|
||||
//
|
||||
// /**************** START : App stuff ****************/
|
||||
// case 'app.install':
|
||||
// case 'ai':
|
||||
// await AppMgr.install(args);
|
||||
// process.exit(0);
|
||||
// break;
|
||||
// case 'app.open':
|
||||
// case 'ao':
|
||||
// await AppMgr.open(args);
|
||||
// process.exit(0);
|
||||
// break;
|
||||
//
|
||||
// /**************** END : App stuff ****************/
|
||||
//
|
||||
// /**************** START : Component stuff ****************/
|
||||
// case 'component.add':
|
||||
// case 'ca':
|
||||
// const prevComponentName = await ComponentMgr.add(args);
|
||||
// if (prevComponentName) {
|
||||
// args._.push(prevComponentName)
|
||||
// await client.requestSend(args);
|
||||
// } else {
|
||||
// process.exit(0)
|
||||
// }
|
||||
// break;
|
||||
//
|
||||
// case 'component.rename':
|
||||
// case 'cr':
|
||||
// await ComponentMgr.rename(args);
|
||||
// process.exit(0);
|
||||
// break;
|
||||
//
|
||||
// case 'component.delete':
|
||||
// case 'cd':
|
||||
// await ComponentMgr.add(args);
|
||||
// process.exit(0);
|
||||
// break;
|
||||
//
|
||||
// /**************** END : Component stuff ****************/
|
||||
//
|
||||
//
|
||||
// /**************** START : Social media stuff ****************/
|
||||
// case 'share':
|
||||
// await SocialMgr.shareSocial(args);
|
||||
// process.exit(0);
|
||||
// break;
|
||||
//
|
||||
// case 'noshare':
|
||||
// await SocialMgr.setShareRules('dontPrompt', true);
|
||||
// process.exit(0);
|
||||
// break;
|
||||
// /**************** END : Social media stuff ****************/
|
||||
//
|
||||
// /**************** START : Remove stuff ****************/
|
||||
// case 'remove.model.backup':
|
||||
// case 'rmb':
|
||||
// await ModelMgr.removeModelBackups(args);
|
||||
// process.exit(0);
|
||||
// break;
|
||||
//
|
||||
// /**************** END : Remove stuff ****************/
|
||||
//
|
||||
// // case 'menu':
|
||||
// // case 'm':
|
||||
// // await Menu.prepareCmd(client, args);
|
||||
// // // console.log(args);
|
||||
// // await this.process(client, args);
|
||||
// // break;
|
||||
//
|
||||
// case 'yelp':
|
||||
// case 'y':
|
||||
// Util.showHelp(args);
|
||||
// process.exit(0)
|
||||
// break;
|
||||
|
||||
default:
|
||||
if (!cmdProcessedOnce) {
|
||||
cmdProcessedOnce = 1;
|
||||
// await this.process(Util.getShortVersion(args));
|
||||
args._.unshift('new');
|
||||
await this.process(args);
|
||||
} else {
|
||||
console.log(
|
||||
`\nUnknown command. ${cmdOriginalArgs._[0]} -- please see help below`
|
||||
);
|
||||
Util.showHelp(cmdOriginalArgs);
|
||||
process.exit(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default CliMgr;
|
||||
@@ -1,166 +0,0 @@
|
||||
import axios from 'axios';
|
||||
import download from 'download';
|
||||
import osInfo from 'linux-os-info';
|
||||
import open from 'open';
|
||||
import ora from 'ora';
|
||||
import os from 'os';
|
||||
import shell from 'shelljs';
|
||||
|
||||
import('colors');
|
||||
|
||||
const PROGRESS_WIDTH = 30;
|
||||
|
||||
class AppMgr {
|
||||
public static async install(args) {
|
||||
try {
|
||||
const spinner = ora({
|
||||
text: 'Downloading Desktop App from Github..'.green.bold(),
|
||||
spinner: 'dots2',
|
||||
color: 'green'
|
||||
}).start();
|
||||
const { src, dest } = await AppMgr.getDownloadLink(args);
|
||||
|
||||
console.log(`\t${src}`);
|
||||
|
||||
await download(src, '.').on('downloadProgress', progress => {
|
||||
// console.log(progress)
|
||||
// Report download progress
|
||||
const p = PROGRESS_WIDTH * progress.percent;
|
||||
spinner.text = `Downloading Desktop App now..\n[${Array.from(
|
||||
{ length: PROGRESS_WIDTH },
|
||||
(_, i) => (i <= p ? '=' : ' ')
|
||||
).join('')}] ${(progress.transferred / (1024 * 1024)).toFixed(2)}MB/${(
|
||||
progress.total /
|
||||
(1024 * 1024)
|
||||
).toFixed(2)}MB\n`.green.bold();
|
||||
});
|
||||
// spinner.prefixText = '';
|
||||
spinner.succeed(
|
||||
`Installable downloaded successfully at ./${dest}`.green.bold()
|
||||
);
|
||||
console.log(`\nInstallable will open automatically now.`.green.bold);
|
||||
console.log(`If not, please install it manually.`.green.bold);
|
||||
if (os.type() === 'Windows_NT') {
|
||||
// open(dest, {wait: true, app: 'explorer.exe'})
|
||||
} else {
|
||||
open(dest, { wait: true });
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`Error in xc app.install`, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static async open(args) {
|
||||
try {
|
||||
const runCommand = AppMgr.getOpenCommand(args);
|
||||
if (!runCommand) {
|
||||
return;
|
||||
}
|
||||
if (shell.exec(runCommand).code !== 0) {
|
||||
shell.echo(`\n\nError running command internally`.red);
|
||||
shell.echo(`\nExiting...`.red);
|
||||
shell.exit(1);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`Error in xc app.open`, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static async getDownloadLink(args): Promise<any> {
|
||||
try {
|
||||
let src;
|
||||
let dest;
|
||||
const urls: any = {};
|
||||
|
||||
const res = await axios.get(
|
||||
'https://api.github.com/repos/xgenecloud/xc-desktop-app/releases?page=1'
|
||||
);
|
||||
|
||||
let status = 0;
|
||||
|
||||
for (let i = 0; i < res.data.length && status !== 15; i++) {
|
||||
const assets = res.data[i].assets;
|
||||
for (const { name, browser_download_url } of assets) {
|
||||
switch (
|
||||
name
|
||||
.split('.')
|
||||
.pop()
|
||||
.toLowerCase()
|
||||
) {
|
||||
case 'dmg':
|
||||
urls.dmg = urls.dmg || browser_download_url;
|
||||
status = status | 1;
|
||||
break;
|
||||
case 'deb':
|
||||
urls.deb = urls.deb || browser_download_url;
|
||||
status = status | 2;
|
||||
break;
|
||||
case 'rpm':
|
||||
urls.rpm = urls.rpm || browser_download_url;
|
||||
status = status | 4;
|
||||
break;
|
||||
case 'exe':
|
||||
urls.exe = urls.exe || browser_download_url;
|
||||
status = status | 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (os.type()) {
|
||||
case 'Linux':
|
||||
const linuxInfo = osInfo({ mode: 'sync' });
|
||||
if (args.debian) {
|
||||
src = urls.deb;
|
||||
} else if (args.rpm) {
|
||||
src = urls.rpm;
|
||||
} else {
|
||||
switch (linuxInfo.id) {
|
||||
case 'ubuntu':
|
||||
case 'raspberry':
|
||||
src = urls.deb;
|
||||
break;
|
||||
case 'fedora':
|
||||
src = urls.rpm;
|
||||
break;
|
||||
default:
|
||||
src = urls.rpm;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'Darwin':
|
||||
src = urls.dmg;
|
||||
break;
|
||||
case 'Windows_NT':
|
||||
src = urls.exe;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
dest = src.split('/').pop();
|
||||
return { src, dest };
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static getOpenCommand(_args): any {
|
||||
switch (os.type()) {
|
||||
case 'Linux':
|
||||
return 'xgenecloud';
|
||||
break;
|
||||
case 'Darwin':
|
||||
return 'open -a xgenecloud';
|
||||
break;
|
||||
case 'Windows_NT':
|
||||
console.info('Open xgenecloud desktop app from Windows start menu');
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default AppMgr;
|
||||
@@ -1,160 +0,0 @@
|
||||
// #! /usr/bin/env node
|
||||
import boxen from 'boxen';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
import shell from 'shelljs';
|
||||
// import tcpPortUsed from 'tcp-port-used';
|
||||
// import promprRunOrDownload from '../prompts/RunOrDownload';
|
||||
// import config from '../util/config';
|
||||
// import {CmdSocketServer} from 'nc-help';
|
||||
// import SocialMgr from './SocialMgr';
|
||||
|
||||
class Client {
|
||||
public static async requestSend(_args) {
|
||||
try {
|
||||
// await CmdSocketServer.cmdHandler(null, null, args);
|
||||
// const portOpen = await tcpPortUsed.check(config.port, 'localhost');
|
||||
// if (portOpen) {
|
||||
//
|
||||
// // client.emit('__REQUEST__', args);
|
||||
// } else {
|
||||
// await promprRunOrDownload.handle(args)
|
||||
// process.exit(0);
|
||||
// }
|
||||
} catch (e) {
|
||||
console.log('Error generating code.', e.message);
|
||||
throw e;
|
||||
}
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
public static async runCmd(str): Promise<any> {
|
||||
shell.echo(`\nNow, executing command : ${str}\n\n`.blue);
|
||||
const code = shell.exec(str).code;
|
||||
if (code !== 0) {
|
||||
// shell.echo(`\n\nError running command internally\n\n\t"${str}" - ${code}`.red);
|
||||
// shell.echo(`\nExiting...`.red);
|
||||
shell.exit(1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static async responseHandle(args) {
|
||||
try {
|
||||
switch (args._[0]) {
|
||||
case 'ga':
|
||||
case 'gar':
|
||||
case 'gen.apis':
|
||||
case 'gen.apis.rest':
|
||||
case 'gag':
|
||||
case 'gen.apis.graphql':
|
||||
case 'gen.apis.gql':
|
||||
if (!args.err) {
|
||||
// SocialMgr.setCreatedApis(true)
|
||||
if (os.type() === 'Windows_NT') {
|
||||
console.log(
|
||||
boxen(
|
||||
`# APIs generated successfully\n\n# Please run the following commands\n${
|
||||
(
|
||||
'cd ' +
|
||||
path.dirname(args.folder) +
|
||||
'; npm install ; npm run dev\n'
|
||||
).green.bold
|
||||
}`,
|
||||
{
|
||||
borderColor: 'green',
|
||||
borderStyle: 'round',
|
||||
margin: 1,
|
||||
padding: 1
|
||||
} as any
|
||||
)
|
||||
);
|
||||
} else {
|
||||
await Client.runCmd(`npm install; npm run dev;`);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'gc':
|
||||
case 'gen.controller':
|
||||
break;
|
||||
|
||||
case 'gm':
|
||||
case 'gen.middleware':
|
||||
break;
|
||||
|
||||
case 'gs':
|
||||
case 'gen.service':
|
||||
break;
|
||||
|
||||
case 'ggt':
|
||||
case 'gen.gql.type':
|
||||
break;
|
||||
|
||||
case 'gen.gql.schema':
|
||||
break;
|
||||
|
||||
case 'ggr':
|
||||
case 'gen.resolver':
|
||||
break;
|
||||
|
||||
case 'gen.block':
|
||||
break;
|
||||
|
||||
case 'gen.cmd':
|
||||
break;
|
||||
|
||||
case 'ac':
|
||||
case 'add.cmd':
|
||||
break;
|
||||
|
||||
case 'ae':
|
||||
case 'add.env':
|
||||
break;
|
||||
|
||||
case 'ad':
|
||||
case 'add.db':
|
||||
break;
|
||||
|
||||
case 'menu':
|
||||
case 'm':
|
||||
break;
|
||||
|
||||
case 'db.migrate.sql.dump':
|
||||
case 'dmm':
|
||||
case 'dmmd':
|
||||
console.log('db.migrate.sql.dump finished');
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// const client = require('socket.io-client')(`http://localhost:${config.port}`);
|
||||
//
|
||||
// client.on('__DISCONNECT__', function () {
|
||||
// console.log('Disconnected from desktop app - Restart XGENE application'.red)
|
||||
// });
|
||||
//
|
||||
// client.on('__CONNECT__', () => {
|
||||
// console.log('>>'.blue)
|
||||
// });
|
||||
//
|
||||
// client.on('__RESPONSE__', (data) => {
|
||||
// console.log(`\n\t${data}`.green);
|
||||
// });
|
||||
//
|
||||
// client.on('__FINISHED__', async (args) => {
|
||||
// console.log('\n<<'.blue);
|
||||
// await Client.responseHandle(args);
|
||||
// process.exit(0)
|
||||
// });
|
||||
//
|
||||
|
||||
export default Client;
|
||||
@@ -1,31 +0,0 @@
|
||||
import inquirer from 'inquirer';
|
||||
import path from 'path';
|
||||
|
||||
class ComponentMgr {
|
||||
public static async add(_args) {
|
||||
const components = require(path.join(
|
||||
process.cwd(),
|
||||
'./server/app.components.js'
|
||||
));
|
||||
|
||||
const answer = await inquirer.prompt([
|
||||
{
|
||||
choices: components.components.map(component => component.title),
|
||||
message:
|
||||
'Choose after which component should we insert the new component?',
|
||||
name: 'compoonent',
|
||||
type: 'list'
|
||||
}
|
||||
]);
|
||||
|
||||
return answer.compoonent;
|
||||
}
|
||||
|
||||
// tslint:disable-next-line:no-empty
|
||||
public static async rename(_args) {}
|
||||
|
||||
// tslint:disable-next-line:no-empty
|
||||
public static async delete(_args) {}
|
||||
}
|
||||
|
||||
export default ComponentMgr;
|
||||
@@ -1,40 +0,0 @@
|
||||
import NewMgr from './NewMgr';
|
||||
|
||||
import('colors');
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
class DockerMgr extends NewMgr {
|
||||
public static async genDockerfile(args: any) {
|
||||
const dockerFilePath = path.join(process.cwd(), 'Dockerfile');
|
||||
try {
|
||||
args._.push('placeholder');
|
||||
if (await this.getNewProjectInput(args)) {
|
||||
const dockerfileContent = this.getDockerfileContent(args);
|
||||
fs.writeFileSync(dockerFilePath, dockerfileContent);
|
||||
console.log(`Docker file created successfully`.green.bold);
|
||||
console.log(`\tFile location : ${dockerFilePath}`.green);
|
||||
console.log(`\tdocker build . -t xc`.green.bold);
|
||||
} else {
|
||||
// console.log('Database connection failed')
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('Error in docker file creation', e);
|
||||
}
|
||||
}
|
||||
|
||||
private static getDockerfileContent(args) {
|
||||
return `FROM nocodb/nocodb:latest
|
||||
|
||||
ENV PORT 8080
|
||||
ENV NODE_ENV=dev
|
||||
ENV TOOL_DIR=/tool
|
||||
${args.url
|
||||
.map((url, i) => `ENV DB_URL${i > 0 ? i + 1 : ''}=${url}`)
|
||||
.join('\r\n')}
|
||||
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
export default DockerMgr;
|
||||
@@ -1,255 +0,0 @@
|
||||
// import chalkPipe from 'chalk-pipe';
|
||||
// import inquirer from 'inquirer';
|
||||
// import mkdirp from 'mkdirp';
|
||||
// import path from 'path';
|
||||
// import URL from 'url';
|
||||
import express from 'express';
|
||||
import { XcApis, XcConfigFactory } from 'xc-instant';
|
||||
|
||||
import('colors');
|
||||
|
||||
// import tcpPortUsed from 'tcp-port-used';
|
||||
|
||||
// const dbDefaults = {
|
||||
// mysql: {
|
||||
// host: 'localhost',
|
||||
// port: '3306',
|
||||
// username: 'root',
|
||||
// password: '',
|
||||
// database: ''
|
||||
// },
|
||||
// pg: {
|
||||
// host: 'localhost',
|
||||
// port: '5432',
|
||||
// username: 'postgres',
|
||||
// password: '',
|
||||
// database: ''
|
||||
// },
|
||||
// mssql: {
|
||||
// host: 'localhost',
|
||||
// port: '1433',
|
||||
// username: 'sa',
|
||||
// password: '',
|
||||
// database: ''
|
||||
// },
|
||||
// sqlite3: {
|
||||
// host: 'localhost',
|
||||
// port: '1433',
|
||||
// username: 'sa',
|
||||
// password: '',
|
||||
// database: ''
|
||||
// },
|
||||
// };
|
||||
|
||||
class InstantMgr {
|
||||
public static async getNewProjectInput(args): Promise<any> {
|
||||
if (args._.length < 2) {
|
||||
const usage = '\n$ xc instant "mysql://localhost:3306?u=root&p=password&d=database&a=rest"'
|
||||
.green.bold;
|
||||
console.log(
|
||||
`\n\nWarning! missing connection URL\n\nExample Usage:\n${usage}\n`.red
|
||||
.bold
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
const config = XcConfigFactory.makeFromUrls(args._.slice(1));
|
||||
|
||||
const server = express();
|
||||
|
||||
server.set('view engine', 'ejs');
|
||||
const app = new XcApis(config);
|
||||
|
||||
server.use(await app.init());
|
||||
|
||||
server.listen('8080', () => console.log('App started'));
|
||||
|
||||
// /* Construct database URL from prompt */
|
||||
// const dbTypes = Object.keys(dbDefaults);
|
||||
// args.url = []
|
||||
//
|
||||
// const answers = await inquirer
|
||||
// .prompt([
|
||||
// {
|
||||
// name: 'type',
|
||||
// type: 'list',
|
||||
// message: '🔥 Choose SQL Database type\t:',
|
||||
// choices: dbTypes.map(t => ({
|
||||
// name: t,
|
||||
// value: t,
|
||||
// short: t.green.bold
|
||||
// })),
|
||||
// default: 'mysql',
|
||||
// transformer (color) {
|
||||
// return chalkPipe(color)(color.green.bold);
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// name: 'host',
|
||||
// type: 'input',
|
||||
// message: '👉 Enter database host name\t:',
|
||||
// default(ans) {
|
||||
// return dbDefaults[ans.type].host
|
||||
// },
|
||||
// transformer (color) {
|
||||
// return chalkPipe(color)(color.green.bold);
|
||||
// },
|
||||
// when({type}) {
|
||||
// return type !== 'sqlite3'
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// name: 'port',
|
||||
// type: 'number',
|
||||
// message: '👉 Enter database port number\t:',
|
||||
// default(ans) {
|
||||
// return dbDefaults[ans.type].port
|
||||
// },
|
||||
// transformer (color) {
|
||||
// try {
|
||||
// return color.green.bold;
|
||||
// } catch (e) {
|
||||
// return color
|
||||
// }
|
||||
// },
|
||||
// validate (port, answers) {
|
||||
// let done = this.async();
|
||||
// NewMgr.isPortOpen(answers.host, port).then(isOpen => {
|
||||
// if (isOpen) {
|
||||
// done(null, true)
|
||||
// } else {
|
||||
// // done('Port is not open')
|
||||
// console.log(`\n\n😩 ${answers.host}:${port} is not open please start the database if you haven't\n`.red.bold)
|
||||
// process.exit(0);
|
||||
// }
|
||||
// }).catch(done)
|
||||
// },
|
||||
// when({type}) {
|
||||
// return type !== 'sqlite3'
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// name: 'username',
|
||||
// type: 'input',
|
||||
// message: '👉 Enter database username\t:',
|
||||
// default(ans) {
|
||||
// return dbDefaults[ans.type].username
|
||||
// },
|
||||
// transformer (color) {
|
||||
// return chalkPipe(color)(color.green.bold);
|
||||
// },
|
||||
// when({type}) {
|
||||
// return type !== 'sqlite3'
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// name: 'password',
|
||||
// type: 'input',
|
||||
// mask: true,
|
||||
// message: '🙈 Enter database password\t:',
|
||||
// transformer (color) {
|
||||
// return new Array(color.length).fill('*'.green.bold).join('')
|
||||
// },
|
||||
// when({type}) {
|
||||
// return type !== 'sqlite3'
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// name: 'database',
|
||||
// type: 'input',
|
||||
// default(_ans) {
|
||||
// return args._[1] + '_dev';
|
||||
// },
|
||||
// message: '👉 Enter database/schema name\t:',
|
||||
// transformer (color) {
|
||||
// return chalkPipe(color)(color.green.bold);
|
||||
// },
|
||||
// when({type}) {
|
||||
// return type !== 'sqlite3'
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// name: 'projectType',
|
||||
// type: 'list',
|
||||
// message: '🚀 Enter API type to generate\t:',
|
||||
// choices: ['REST APIs', 'GRAPHQL APIs'].map(t => ({
|
||||
// name: t,
|
||||
// value: t,
|
||||
// short: t.green.bold
|
||||
// })),
|
||||
// transformer (color) {
|
||||
// return chalkPipe(color)(color.green.bold);
|
||||
// },
|
||||
// when({type}) {
|
||||
// return type !== 'sqlite3'
|
||||
// }
|
||||
// }
|
||||
// ])
|
||||
//
|
||||
// // console.log(answers);
|
||||
//
|
||||
// if (answers.type === 'sqlite3') {
|
||||
// console.log('Please use desktop app to create Sqlite project'.green.bold)
|
||||
// process.exit(0);
|
||||
// }
|
||||
//
|
||||
// /* if not valid retry getting right input */
|
||||
// if (!answers.database) {
|
||||
// console.log('\n\tWarning! Database name can NOT be empty. Retry.\n '.red.bold);
|
||||
// this.getNewProjectInput(args);
|
||||
// }
|
||||
//
|
||||
// /* attach new project name to path and 'cd' to that folder */
|
||||
// args.folder = path.join(args.folder, args._[1]);
|
||||
// mkdirp.sync(args.folder);
|
||||
// process.chdir(args.folder);
|
||||
// // await Util.runCmd(`cd ${args.folder}`);
|
||||
//
|
||||
// /* prepare the args */
|
||||
// const url = `${answers.type}://${answers.host}:${answers.port}?u=${answers.username}&p=${answers.password}&d=${answers.database}`;
|
||||
// args._[0] = answers.projectType === 'REST APIs' ? 'gar' : 'gag';
|
||||
// args.url.push(url);
|
||||
// return NewMgr.testConnection(args)
|
||||
}
|
||||
|
||||
// public static async testConnection({url}) {
|
||||
//
|
||||
// for (const u of url) {
|
||||
// const parsedUrlData = URL.parse(u, true);
|
||||
// const queryParams = parsedUrlData.query;
|
||||
// const client = parsedUrlData.protocol.slice(0, -1);
|
||||
// const config = {
|
||||
// client,
|
||||
// connection: {
|
||||
// host: parsedUrlData.hostname,
|
||||
// port: +parsedUrlData.port,
|
||||
// user: queryParams.u,
|
||||
// password: queryParams.p,
|
||||
// database: client === 'pg' ? 'postgres' : (client === 'mssql' ? undefined : null)
|
||||
// }
|
||||
// };
|
||||
//
|
||||
//
|
||||
// try {
|
||||
// const knex = require('knex')(config)
|
||||
// await knex.raw("SELECT 1+1 as data");
|
||||
// } catch (e) {
|
||||
// console.log(`\n😩 Test connection failed for : ${url}\n`.red.bold)
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// public static async isPortOpen(host, port) {
|
||||
// try {
|
||||
// return await tcpPortUsed.check(+port, host)
|
||||
// } catch (e) {
|
||||
// console.log(e)
|
||||
// console.log(`\n😩 ${host}:${port} is not reachable please check\n`.red.bold)
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
export default InstantMgr;
|
||||
@@ -1,124 +0,0 @@
|
||||
import { Migrator } from 'xc-migrator-ts';
|
||||
const migrator = new Migrator();
|
||||
|
||||
class MigrationMgr {
|
||||
public static _getFolder(args) {
|
||||
args.folder = args.folder || process.cwd();
|
||||
}
|
||||
|
||||
public static async init(args) {
|
||||
try {
|
||||
args.type = args.type || 'mysql';
|
||||
await migrator.init(args);
|
||||
} catch (e) {
|
||||
console.log('db.migrate.init : Error occurred', e);
|
||||
}
|
||||
}
|
||||
|
||||
public static async sync(args) {
|
||||
try {
|
||||
this._getFolder(args);
|
||||
await migrator.sync(args);
|
||||
} catch (e) {
|
||||
console.log('db.migrate.sync : Error occurred', e);
|
||||
}
|
||||
}
|
||||
|
||||
public static async create(args) {
|
||||
try {
|
||||
this._getFolder(args);
|
||||
await migrator.migrationsCreate({
|
||||
dbAlias: args.dbAlias || 'primary',
|
||||
folder: args.folder
|
||||
});
|
||||
} catch (e) {
|
||||
console.log('db.migrate.create : Error occurred', e);
|
||||
}
|
||||
}
|
||||
|
||||
public static async up(args) {
|
||||
try {
|
||||
this._getFolder(args);
|
||||
|
||||
let migrationSteps = args.steps || 9999;
|
||||
|
||||
if (args.file) {
|
||||
migrationSteps = 0;
|
||||
}
|
||||
|
||||
const migratorInst = new Migrator();
|
||||
await migratorInst.migrationsUp({
|
||||
dbAlias: args.dbAlias || 'primary',
|
||||
env: args.env || 'dev',
|
||||
file: args.file || null,
|
||||
folder: args.folder,
|
||||
migrationSteps,
|
||||
onlyList: args.list,
|
||||
sqlContentMigrate: +args.sqlContentMigrate === 0 ? 0 : 1
|
||||
});
|
||||
} catch (e) {
|
||||
console.log('db.migrate.up : Error occurred', e);
|
||||
}
|
||||
}
|
||||
|
||||
public static async down(args) {
|
||||
try {
|
||||
this._getFolder(args);
|
||||
|
||||
let migrationSteps = args.steps || 9999;
|
||||
|
||||
if (args.file) {
|
||||
migrationSteps = 0;
|
||||
}
|
||||
|
||||
await migrator.migrationsDown({
|
||||
dbAlias: args.dbAlias || 'primary',
|
||||
env: args.env || 'dev',
|
||||
file: args.file || null,
|
||||
folder: args.folder,
|
||||
migrationSteps,
|
||||
onlyList: args.list,
|
||||
sqlContentMigrate: +args.sqlContentMigrate === 0 ? 0 : 1
|
||||
});
|
||||
} catch (e) {
|
||||
console.log('db.migrate.down : Error occurred', e);
|
||||
}
|
||||
}
|
||||
|
||||
public static async list(args) {
|
||||
try {
|
||||
this._getFolder(args);
|
||||
|
||||
let migrationSteps = args.steps || 9999;
|
||||
|
||||
if (args.file) {
|
||||
migrationSteps = 0;
|
||||
}
|
||||
|
||||
const data = await migrator.migrationsUp({
|
||||
dbAlias: args.dbAlias || 'primary',
|
||||
env: args.env || 'dev',
|
||||
file: args.file || null,
|
||||
folder: args.folder,
|
||||
migrationSteps,
|
||||
onlyList: true
|
||||
});
|
||||
|
||||
console.log(data.data.object.list);
|
||||
} catch (e) {
|
||||
console.log('db.migrate.up : Error occurred', e);
|
||||
}
|
||||
}
|
||||
|
||||
public static async clean(args) {
|
||||
try {
|
||||
args.type = args.type || 'mysql';
|
||||
await migrator.clean(args);
|
||||
} catch (e) {
|
||||
console.log('db.migrate.clean : Error occurred', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// expose class
|
||||
export default MigrationMgr;
|
||||
@@ -1,58 +0,0 @@
|
||||
import fsExtra from 'fs-extra';
|
||||
import glob from 'glob';
|
||||
import path from 'path';
|
||||
|
||||
class ModelMgr {
|
||||
/***
|
||||
*
|
||||
* @param args
|
||||
* @param args.models
|
||||
* @param args.dbAlias
|
||||
* @param args.folder
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
public static async removeModelBackups(args) {
|
||||
try {
|
||||
args.dbAlias = args.dbAlias || '*';
|
||||
if (args.models) {
|
||||
for (const model of args.models.split('.')) {
|
||||
for (const file of glob.sync(
|
||||
path.join(
|
||||
args.folder,
|
||||
'server',
|
||||
'models',
|
||||
args.dbAlias,
|
||||
model,
|
||||
`${model}.meta.*.js`
|
||||
)
|
||||
)) {
|
||||
await fsExtra.remove(file);
|
||||
console.log(
|
||||
`Removed successfully : ${path.basename(file)}`.green.bold
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const file of glob.sync(
|
||||
path.join(
|
||||
args.folder,
|
||||
'server',
|
||||
'models',
|
||||
args.dbAlias,
|
||||
'*',
|
||||
'*.meta.*.js'
|
||||
)
|
||||
)) {
|
||||
await fsExtra.remove(file);
|
||||
console.log(
|
||||
`Removed successfully : ${path.basename(file)}`.green.bold
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(`Error while removing backup file`.red.bold);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default ModelMgr;
|
||||
@@ -1,768 +0,0 @@
|
||||
import chalkPipe from 'chalk-pipe';
|
||||
import download from 'download-git-repo';
|
||||
import inquirer from 'inquirer';
|
||||
import mkdirp from 'mkdirp';
|
||||
import path from 'path';
|
||||
import tcpPortUsed from 'tcp-port-used';
|
||||
import URL from 'url';
|
||||
import { promisify } from 'util';
|
||||
import Util from '../util/Util';
|
||||
|
||||
import boxen from 'boxen';
|
||||
import * as fs from 'fs';
|
||||
import os from 'os';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import Lang, { STR } from '../util/Lang';
|
||||
|
||||
// @ts-ignore
|
||||
const colors = require('colors');
|
||||
|
||||
const dbDefaults = {
|
||||
sqlite3: {
|
||||
host: 'localhost',
|
||||
port: '1433',
|
||||
username: 'sa',
|
||||
password: '',
|
||||
database: ''
|
||||
},
|
||||
mysql2: {
|
||||
host: 'localhost',
|
||||
port: '3306',
|
||||
username: 'root',
|
||||
password: '',
|
||||
database: ''
|
||||
},
|
||||
pg: {
|
||||
host: 'localhost',
|
||||
port: '5432',
|
||||
username: 'postgres',
|
||||
password: '',
|
||||
database: ''
|
||||
},
|
||||
mssql: {
|
||||
host: 'localhost',
|
||||
port: '1433',
|
||||
username: 'sa',
|
||||
password: '',
|
||||
database: ''
|
||||
}
|
||||
};
|
||||
|
||||
// const apiTypeMapping = {
|
||||
// 'GRAPHQL APIs': 'graphql',
|
||||
// 'REST APIs': 'rest',
|
||||
// 'gRPC APIs': 'grpc'
|
||||
// }
|
||||
// const languageMapping = {
|
||||
// 'Javascript': 'js',
|
||||
// 'Typescript': 'ts',
|
||||
// }
|
||||
|
||||
class NewMgr {
|
||||
/**
|
||||
*
|
||||
* Does the below :
|
||||
* - Get database input and make a DB URL from it.
|
||||
* - Create new folder and 'cd' to that folder.
|
||||
* - Return true/success
|
||||
* - Else failure
|
||||
*
|
||||
* @param args
|
||||
* @returns {Promise<string|string|boolean|*>}
|
||||
*/
|
||||
public static async getNewProjectInput(args): Promise<any> {
|
||||
if (args._.length < 2) {
|
||||
const usage = '\n$ xc new project_name'.green.bold;
|
||||
console.log(
|
||||
`\n\nWarning! missing project name\n\nExample Usage:\n${usage}\n`.red
|
||||
.bold
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Construct database URL from prompt */
|
||||
const dbTypes = Object.keys(dbDefaults);
|
||||
args.url = [];
|
||||
|
||||
console.log(
|
||||
`NocoDB requires a database to store metadata of database-spreadsheets.\nPlease enter the database credentials (defaults to SQLite3)`
|
||||
.green.bold
|
||||
);
|
||||
const answers = await inquirer.prompt([
|
||||
{
|
||||
name: 'type',
|
||||
type: 'list',
|
||||
message: Lang.getString(STR.DB_TYPE), // '🔥 Choose SQL Database type\t:',
|
||||
choices: dbTypes.map(t => ({
|
||||
name: t,
|
||||
value: t,
|
||||
short: t.green.bold
|
||||
})),
|
||||
default: 'sqlite3',
|
||||
transformer(color) {
|
||||
return chalkPipe(color)(color.green.bold);
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'host',
|
||||
type: 'input',
|
||||
message: Lang.getString(STR.DB_HOST), // '👉 Enter database host name\t:',
|
||||
default(ans) {
|
||||
return dbDefaults[ans.type].host;
|
||||
},
|
||||
transformer(color) {
|
||||
return chalkPipe(color)(color.green.bold);
|
||||
},
|
||||
when({ type }) {
|
||||
return type !== 'sqlite3';
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'port',
|
||||
type: 'number',
|
||||
message: Lang.getString(STR.DB_PORT), // '👉 Enter database port number\t:',
|
||||
default(ans) {
|
||||
return dbDefaults[ans.type].port;
|
||||
},
|
||||
transformer(color) {
|
||||
try {
|
||||
return color.green.bold;
|
||||
} catch (e) {
|
||||
return color;
|
||||
}
|
||||
},
|
||||
validate(port, answers) {
|
||||
const done = this.async();
|
||||
if (
|
||||
answers.host === 'host.docker.internal' ||
|
||||
answers.host === 'docker.for.win.localhost'
|
||||
) {
|
||||
done(null, true);
|
||||
} else {
|
||||
NewMgr.isPortOpen(answers.host, port)
|
||||
.then(isOpen => {
|
||||
if (isOpen) {
|
||||
done(null, true);
|
||||
} else {
|
||||
// done('Port is not open')
|
||||
console.log(
|
||||
`\n\n😩 ${answers.host}:${port} is not open please start the database if you haven't\n`
|
||||
.red.bold
|
||||
);
|
||||
process.exit(0);
|
||||
}
|
||||
})
|
||||
.catch(done);
|
||||
}
|
||||
},
|
||||
when({ type }) {
|
||||
return type !== 'sqlite3';
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'username',
|
||||
type: 'input',
|
||||
message: Lang.getString(STR.DB_USER), // '👉 Enter database username\t:',
|
||||
default(ans) {
|
||||
return dbDefaults[ans.type].username;
|
||||
},
|
||||
transformer(color) {
|
||||
return chalkPipe(color)(color.green.bold);
|
||||
},
|
||||
when({ type }) {
|
||||
return type !== 'sqlite3';
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'password',
|
||||
type: 'input',
|
||||
mask: true,
|
||||
message: Lang.getString(STR.DB_PASSWORD), // '🙈 Enter database password\t:',
|
||||
transformer(color) {
|
||||
return new Array(color.length).fill('*'.green.bold).join('');
|
||||
},
|
||||
when({ type }) {
|
||||
return type !== 'sqlite3';
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'database',
|
||||
type: 'input',
|
||||
default(_ans) {
|
||||
return args._[1] + '_dev';
|
||||
},
|
||||
message: Lang.getString(STR.DB_SCHEMA), // '👉 Enter database/schema name\t:',
|
||||
transformer(color) {
|
||||
return chalkPipe(color)(color.green.bold);
|
||||
},
|
||||
when({ type }) {
|
||||
return type !== 'sqlite3';
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
name: 'projectType',
|
||||
type: 'list',
|
||||
message: Lang.getString(STR.PROJECT_TYPE), // '🚀 How do you want to run it\t:',
|
||||
choices: [
|
||||
'As Node.js Project',
|
||||
'As Docker' // 'Try XC Instant App (Without scaffolding code)'
|
||||
].map(t => ({
|
||||
name: t,
|
||||
value: t,
|
||||
short: t.green.bold
|
||||
})),
|
||||
transformer(color) {
|
||||
return chalkPipe(color)(color.green.bold);
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
/* if not valid retry getting right input */
|
||||
if (answers.type !== 'sqlite3' && !answers.database) {
|
||||
console.log(
|
||||
'\n\tWarning! Database name can NOT be empty. Retry.\n '.red.bold
|
||||
);
|
||||
this.getNewProjectInput(args);
|
||||
}
|
||||
|
||||
switch (answers.projectType) {
|
||||
case 'As Docker':
|
||||
answers.projectType = 'docker';
|
||||
break;
|
||||
case 'As Node.js Project':
|
||||
answers.projectType = 'mvc';
|
||||
break;
|
||||
default:
|
||||
answers.projectType = 'docker';
|
||||
break;
|
||||
}
|
||||
|
||||
if (answers.projectType === 'mvc' && !answers.isForExisting) {
|
||||
/* attach new project name to path and 'cd' to that folder */
|
||||
args.folder = path.join(args.folder, args._[1]);
|
||||
mkdirp.sync(args.folder);
|
||||
process.chdir(args.folder);
|
||||
await Util.runCmd(`cd ${Util.escapeShellArg(args.folder)}`);
|
||||
await promisify(download)(
|
||||
'direct:https://github.com/nocodb/nocodb-seed/archive/refs/heads/main.zip',
|
||||
args.folder
|
||||
);
|
||||
|
||||
if (answers.type !== 'sqlite3') {
|
||||
fs.appendFileSync(
|
||||
path.join(args.folder, '.env'),
|
||||
`NC_DB=${answers.type}://${answers.host}:${answers.port}?u=${answers.username}&p=${answers.password}&d=${answers.database}`
|
||||
);
|
||||
}
|
||||
|
||||
if (os.type() === 'Windows_NT') {
|
||||
console.log(
|
||||
boxen(
|
||||
`# Project created successfully\n\n# Please run the following commands\n\n${
|
||||
(
|
||||
'cd ' +
|
||||
Util.escapeShellArg(args.folder) +
|
||||
'\nnpm install \nnpm start\n'
|
||||
).green.bold
|
||||
}`,
|
||||
{
|
||||
borderColor: 'green',
|
||||
borderStyle: 'round',
|
||||
margin: 1,
|
||||
padding: 1
|
||||
} as any
|
||||
)
|
||||
);
|
||||
} else {
|
||||
await Util.runCmd(`npm install; npm run start;`);
|
||||
}
|
||||
} else if (answers.projectType) {
|
||||
let env = '';
|
||||
if (answers.type !== 'sqlite3') {
|
||||
env = `--env NC_DB="${answers.type}://${answers.host}:${answers.port}?u=${answers.username}&p=${answers.password}&d=${answers.database}"`;
|
||||
}
|
||||
const linuxHost = os.type() === 'Linux' ? '--net=host' : '';
|
||||
if (os.type() === 'Windows_NT') {
|
||||
// tslint:disable-next-line:ban-comma-operator
|
||||
console.log(
|
||||
boxen(
|
||||
`# Please run the following docker commands\n\n${
|
||||
`docker run -p 8080:8080 ${linuxHost} -d ${env} nocodb/nocodb:latest`
|
||||
.green.bold
|
||||
}\n`,
|
||||
{
|
||||
borderColor: 'green',
|
||||
borderStyle: 'round',
|
||||
margin: 1,
|
||||
padding: 1
|
||||
} as any
|
||||
)
|
||||
);
|
||||
} else {
|
||||
await Util.runCmd(
|
||||
`docker run -p 8080:8080 ${linuxHost} -d ${env} nocodb/nocodb:latest`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async getNewProjectInputOld(args): Promise<any> {
|
||||
if (args._.length < 2) {
|
||||
const usage = '\n$ xc new project_name'.green.bold;
|
||||
console.log(
|
||||
`\n\nWarning! missing project name\n\nExample Usage:\n${usage}\n`.red
|
||||
.bold
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Construct database URL from prompt */
|
||||
const dbTypes = Object.keys(dbDefaults);
|
||||
args.url = [];
|
||||
|
||||
const answers = await inquirer.prompt([
|
||||
{
|
||||
name: 'type',
|
||||
type: 'list',
|
||||
message: Lang.getString(STR.DB_TYPE), // '🔥 Choose SQL Database type\t:',
|
||||
choices: dbTypes.map(t => ({
|
||||
name: t,
|
||||
value: t,
|
||||
short: t.green.bold
|
||||
})),
|
||||
default: 'mysql2',
|
||||
transformer(color) {
|
||||
return chalkPipe(color)(color.green.bold);
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'host',
|
||||
type: 'input',
|
||||
message: Lang.getString(STR.DB_HOST), // '👉 Enter database host name\t:',
|
||||
default(ans) {
|
||||
return dbDefaults[ans.type].host;
|
||||
},
|
||||
transformer(color) {
|
||||
return chalkPipe(color)(color.green.bold);
|
||||
},
|
||||
when({ type }) {
|
||||
return type !== 'sqlite3';
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'port',
|
||||
type: 'number',
|
||||
message: Lang.getString(STR.DB_PORT), // '👉 Enter database port number\t:',
|
||||
default(ans) {
|
||||
return dbDefaults[ans.type].port;
|
||||
},
|
||||
transformer(color) {
|
||||
try {
|
||||
return color.green.bold;
|
||||
} catch (e) {
|
||||
return color;
|
||||
}
|
||||
},
|
||||
validate(port, answers) {
|
||||
const done = this.async();
|
||||
if (
|
||||
answers.host === 'host.docker.internal' ||
|
||||
answers.host === 'docker.for.win.localhost'
|
||||
) {
|
||||
done(null, true);
|
||||
} else {
|
||||
NewMgr.isPortOpen(answers.host, port)
|
||||
.then(isOpen => {
|
||||
if (isOpen) {
|
||||
done(null, true);
|
||||
} else {
|
||||
// done('Port is not open')
|
||||
console.log(
|
||||
`\n\n😩 ${answers.host}:${port} is not open please start the database if you haven't\n`
|
||||
.red.bold
|
||||
);
|
||||
process.exit(0);
|
||||
}
|
||||
})
|
||||
.catch(done);
|
||||
}
|
||||
},
|
||||
when({ type }) {
|
||||
return type !== 'sqlite3';
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'username',
|
||||
type: 'input',
|
||||
message: Lang.getString(STR.DB_USER), // '👉 Enter database username\t:',
|
||||
default(ans) {
|
||||
return dbDefaults[ans.type].username;
|
||||
},
|
||||
transformer(color) {
|
||||
return chalkPipe(color)(color.green.bold);
|
||||
},
|
||||
when({ type }) {
|
||||
return type !== 'sqlite3';
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'password',
|
||||
type: 'input',
|
||||
mask: true,
|
||||
message: Lang.getString(STR.DB_PASSWORD), // '🙈 Enter database password\t:',
|
||||
transformer(color) {
|
||||
return new Array(color.length).fill('*'.green.bold).join('');
|
||||
},
|
||||
when({ type }) {
|
||||
return type !== 'sqlite3';
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'database',
|
||||
type: 'input',
|
||||
default(_ans) {
|
||||
return args._[1] + '_dev';
|
||||
},
|
||||
message: Lang.getString(STR.DB_SCHEMA), // '👉 Enter database/schema name\t:',
|
||||
transformer(color) {
|
||||
return chalkPipe(color)(color.green.bold);
|
||||
},
|
||||
when({ type }) {
|
||||
return type !== 'sqlite3';
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'apiType',
|
||||
type: 'list',
|
||||
message: Lang.getString(STR.DB_API), // '🚀 Enter API type to generate\t:',
|
||||
choices: ['REST APIs', 'GRAPHQL APIs', 'gRPC APIs'].map(t => ({
|
||||
name: t,
|
||||
value: t,
|
||||
short: t.green.bold
|
||||
})),
|
||||
transformer(color) {
|
||||
return chalkPipe(color)(color.green.bold);
|
||||
},
|
||||
when({ type }) {
|
||||
return type !== 'sqlite3';
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'projectType',
|
||||
type: 'list',
|
||||
message: Lang.getString(STR.PROJECT_TYPE), // '🚀 How do you want to run it\t:',
|
||||
choices: [
|
||||
'Docker',
|
||||
'New Node.js project',
|
||||
'Existing Node.js project',
|
||||
'Try XC Instant App (Without scaffolding code)'
|
||||
].map(t => ({
|
||||
name: t,
|
||||
value: t,
|
||||
short: t.green.bold
|
||||
})),
|
||||
transformer(color) {
|
||||
return chalkPipe(color)(color.green.bold);
|
||||
},
|
||||
when({ type }) {
|
||||
return type !== 'sqlite3';
|
||||
}
|
||||
}
|
||||
// {
|
||||
// name: 'programmingLanguage',
|
||||
// type: 'list',
|
||||
// message: '🚀 Enter preferred programming language\t:',
|
||||
// choices: ['Javascript', 'Typescript'].map(t => ({
|
||||
// name: t,
|
||||
// value: t,
|
||||
// short: t.green.bold
|
||||
// })),
|
||||
// transformer(color) {
|
||||
// return chalkPipe(color)(color.green.bold);
|
||||
// },
|
||||
// when({type}) {
|
||||
// return type !== 'sqlite3'
|
||||
// }
|
||||
// }
|
||||
]);
|
||||
|
||||
// console.log(answers);
|
||||
|
||||
if (answers.type === 'sqlite3') {
|
||||
console.log('Please use desktop app to create Sqlite project'.green.bold);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
/* if not valid retry getting right input */
|
||||
if (!answers.database) {
|
||||
console.log(
|
||||
'\n\tWarning! Database name can NOT be empty. Retry.\n '.red.bold
|
||||
);
|
||||
this.getNewProjectInput(args);
|
||||
}
|
||||
//
|
||||
|
||||
/* prepare the args */
|
||||
// const url = `${answers.type}://${answers.host}:${answers.port}?u=${answers.username}&p=${answers.password}&d=${answers.database}&api=${apiTypeMapping[answers.projectType]}`;
|
||||
// args._[0] = answers.projectType === 'REST APIs' ? 'gar' : 'gag';
|
||||
switch (answers.apiType) {
|
||||
case 'REST APIs':
|
||||
answers.apiType = 'rest';
|
||||
break;
|
||||
case 'GRAPHQL APIs':
|
||||
answers.apiType = 'graphql';
|
||||
break;
|
||||
case 'gRPC APIs':
|
||||
answers.apiType = 'grpc';
|
||||
break;
|
||||
default:
|
||||
answers.apiType = 'rest';
|
||||
break;
|
||||
}
|
||||
|
||||
switch (answers.projectType) {
|
||||
case 'Docker':
|
||||
answers.projectType = 'docker';
|
||||
break;
|
||||
case 'New Node.js project':
|
||||
answers.projectType = 'mvc';
|
||||
break;
|
||||
case 'Existing Node.js project':
|
||||
answers.projectType = 'mvc';
|
||||
answers.isForExisting = true;
|
||||
break;
|
||||
default:
|
||||
answers.projectType = 'docker';
|
||||
break;
|
||||
}
|
||||
|
||||
if (answers.projectType === 'mvc' && !answers.isForExisting) {
|
||||
/* attach new project name to path and 'cd' to that folder */
|
||||
args.folder = path.join(args.folder, args._[1]);
|
||||
mkdirp.sync(args.folder);
|
||||
process.chdir(args.folder);
|
||||
await Util.runCmd(`cd ${Util.escapeShellArg(args.folder)}`);
|
||||
|
||||
await promisify(download)('gitlab:xc-public/test10', args.folder);
|
||||
const config = {
|
||||
title: args._[1],
|
||||
version: '0.6',
|
||||
envs: {
|
||||
dev: {
|
||||
db: [
|
||||
{
|
||||
client: answers.type,
|
||||
connection: {
|
||||
host: answers.host,
|
||||
port: answers.port,
|
||||
user: answers.username,
|
||||
password: answers.password,
|
||||
database: answers.database,
|
||||
multipleStatements: true
|
||||
},
|
||||
meta: {
|
||||
tn: 'xc_evolutions',
|
||||
dbAlias: 'db',
|
||||
api: {
|
||||
type: answers.apiType,
|
||||
prefix: '',
|
||||
graphqlDepthLimit: 10
|
||||
},
|
||||
inflection: {
|
||||
tn: 'none',
|
||||
cn: 'none'
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
apiClient: {
|
||||
data: []
|
||||
}
|
||||
}
|
||||
},
|
||||
workingEnv: 'dev',
|
||||
seedsFolder: 'seeds',
|
||||
queriesFolder: 'queries',
|
||||
apisFolder: 'apis',
|
||||
projectType: answers.apiType,
|
||||
type: 'docker',
|
||||
language: 'ts',
|
||||
apiClient: {
|
||||
data: []
|
||||
},
|
||||
auth: {
|
||||
jwt: {
|
||||
secret: uuidv4(),
|
||||
dbAlias: 'db'
|
||||
}
|
||||
},
|
||||
meta: {
|
||||
db: {
|
||||
client: 'sqlite3',
|
||||
connection: {
|
||||
filename: 'xc.db'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(args.folder, 'config.xc.json'),
|
||||
JSON.stringify(config, null, 2)
|
||||
);
|
||||
|
||||
await Util.runCmd(`npm install; npm run start;`);
|
||||
} else if (answers.projectType === 'mvc') {
|
||||
console.log(`
|
||||
1. Install our npm package using following command
|
||||
|
||||
\t${`npm install --save nocodb`.green}
|
||||
|
||||
2. Add the following code in your existing express project
|
||||
|
||||
\t${
|
||||
`const {Noco} = require("nocodb");
|
||||
|
||||
\tnew Noco({
|
||||
title: "${args._[1]}",
|
||||
"version": "0.6",
|
||||
"envs": {
|
||||
"dev": {
|
||||
"db": [
|
||||
{
|
||||
"client": "${answers.type}",
|
||||
"connection": {
|
||||
"host": "${answers.host}",
|
||||
"port": "${answers.port}",
|
||||
"user": "${answers.username}",
|
||||
"password": "${answers.password}",
|
||||
"database": "${answers.database}",
|
||||
"multipleStatements": true
|
||||
},
|
||||
"meta": {
|
||||
"tn": "xc_evolutions",
|
||||
"dbAlias": "db",
|
||||
"api": {
|
||||
"type": "${answers.apiType}",
|
||||
"prefix": "",
|
||||
"graphqlDepthLimit": 10
|
||||
},
|
||||
"inflection": {
|
||||
"tn": "none",
|
||||
"cn": "none"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"apiClient": {
|
||||
"data": []
|
||||
}
|
||||
}
|
||||
},
|
||||
"workingEnv": "dev",
|
||||
"seedsFolder": "seeds",
|
||||
"queriesFolder": "queries",
|
||||
"apisFolder": "apis",
|
||||
"projectType": "${answers.apiType}",
|
||||
"type": "docker",
|
||||
"language": "ts",
|
||||
"apiClient": {
|
||||
"data": []
|
||||
},
|
||||
"auth": {
|
||||
"jwt": {
|
||||
"secret": "${uuidv4()}",
|
||||
"dbAlias": "db"
|
||||
}
|
||||
},
|
||||
"meta":{
|
||||
"db": {
|
||||
"client": "sqlite3",
|
||||
"connection": {
|
||||
"filename": "xc.db"
|
||||
}
|
||||
}
|
||||
}
|
||||
}).init().then(mw => app.use(mw))`.green
|
||||
}
|
||||
|
||||
|
||||
|
||||
${`Note: ${'app'.bold} - refers to your express server instance`}
|
||||
|
||||
|
||||
|
||||
`);
|
||||
} else if (answers.projectType === 'docker') {
|
||||
const dbUrl = `${answers.type}://${answers.host}:${answers.port}?u=${answers.username}&p=${answers.password}&d=${answers.database}`;
|
||||
// console.log(`
|
||||
// You can create docker container using following command
|
||||
//
|
||||
// \t${`docker run -p 8080:8080 -p 8081:8081 -p 8082:8082 -d --name xc-instant --env DB_URL=${dbUrl} -d xgenecloud/xc:latest`.green}
|
||||
//
|
||||
//
|
||||
// Then visit http://localhost:8080/xc to access the Dashboard
|
||||
//
|
||||
// `)
|
||||
|
||||
const linuxHost = os.type() === 'Linux' ? '--net=host' : '';
|
||||
|
||||
await Util.runCmd(
|
||||
`docker run -p 8080:8080 -p 8081:8081 -p 8082:8082 ${linuxHost} --name xc-instant --env NC_DB_URL="${dbUrl}" xgenecloud/xc:latest`
|
||||
);
|
||||
}
|
||||
// args.url.push(url);
|
||||
//
|
||||
// args.language = languageMapping[answers.programmingLanguage];
|
||||
|
||||
// return OldNewMgr.testConnection(args)
|
||||
}
|
||||
|
||||
public static async testConnection({ url }) {
|
||||
for (const u of url) {
|
||||
const parsedUrlData = URL.parse(u, true);
|
||||
const queryParams = parsedUrlData.query;
|
||||
const client = parsedUrlData.protocol.slice(0, -1);
|
||||
const config = {
|
||||
client,
|
||||
connection: {
|
||||
host: parsedUrlData.hostname,
|
||||
port: +parsedUrlData.port,
|
||||
user: queryParams.u,
|
||||
password: queryParams.p,
|
||||
database:
|
||||
client === 'pg' ? 'postgres' : client === 'mssql' ? undefined : null
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
const knex = require('knex')(config);
|
||||
await knex.raw('SELECT 1+1 as data');
|
||||
} catch (e) {
|
||||
console.log(`\n😩 Test connection failed for : ${url}\n`.red.bold);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static async isPortOpen(host, port) {
|
||||
try {
|
||||
return await tcpPortUsed.check(+port, host);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
console.log(
|
||||
`\n😩 ${host}:${port} is not reachable please check\n`.red.bold
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public static async initProject(_args: any): Promise<void> {
|
||||
await promisify(download)('gitlab:xc-public/test10', process.cwd());
|
||||
await Util.runCmd(`npm install; npm run start;`);
|
||||
}
|
||||
}
|
||||
|
||||
export default NewMgr;
|
||||
@@ -1,306 +0,0 @@
|
||||
import chalkPipe from 'chalk-pipe';
|
||||
import inquirer from 'inquirer';
|
||||
import mkdirp from 'mkdirp';
|
||||
import path from 'path';
|
||||
import URL from 'url';
|
||||
|
||||
import('colors');
|
||||
|
||||
const tcpPortUsed = require('tcp-port-used');
|
||||
|
||||
const dbDefaults = {
|
||||
mysql: {
|
||||
host: 'localhost',
|
||||
port: '3306',
|
||||
username: 'root',
|
||||
password: '',
|
||||
database: ''
|
||||
},
|
||||
pg: {
|
||||
host: 'localhost',
|
||||
port: '5432',
|
||||
username: 'postgres',
|
||||
password: '',
|
||||
database: ''
|
||||
},
|
||||
mssql: {
|
||||
host: 'localhost',
|
||||
port: '1433',
|
||||
username: 'sa',
|
||||
password: '',
|
||||
database: ''
|
||||
},
|
||||
sqlite3: {
|
||||
host: 'localhost',
|
||||
port: '1433',
|
||||
username: 'sa',
|
||||
password: '',
|
||||
database: ''
|
||||
}
|
||||
};
|
||||
|
||||
const apiTypeMapping = {
|
||||
'GRAPHQL APIs': 'graphql',
|
||||
'REST APIs': 'rest',
|
||||
'gRPC APIs': 'grpc'
|
||||
};
|
||||
const languageMapping = {
|
||||
Javascript: 'js',
|
||||
Typescript: 'ts'
|
||||
};
|
||||
|
||||
class OldNewMgr {
|
||||
/**
|
||||
*
|
||||
* Does the below :
|
||||
* - Get database input and make a DB URL from it.
|
||||
* - Create new folder and 'cd' to that folder.
|
||||
* - Return true/success
|
||||
* - Else failure
|
||||
*
|
||||
* @param args
|
||||
* @returns {Promise<string|string|boolean|*>}
|
||||
*/
|
||||
public static async getNewProjectInput(args) {
|
||||
if (args._.length < 2) {
|
||||
const usage = '\n$ xc new project_name'.green.bold;
|
||||
console.log(
|
||||
`\n\nWarning! missing project name\n\nExample Usage:\n${usage}\n`.red
|
||||
.bold
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Construct database URL from prompt */
|
||||
const dbTypes = Object.keys(dbDefaults);
|
||||
args.url = [];
|
||||
|
||||
const answers = await inquirer.prompt([
|
||||
{
|
||||
name: 'type',
|
||||
type: 'list',
|
||||
message: '🔥 Choose SQL Database type\t:',
|
||||
choices: dbTypes.map(t => ({
|
||||
name: t,
|
||||
value: t,
|
||||
short: t.green.bold
|
||||
})),
|
||||
default: 'mysql',
|
||||
transformer(color) {
|
||||
return chalkPipe(color)(color.green.bold);
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'host',
|
||||
type: 'input',
|
||||
message: '👉 Enter database host name\t:',
|
||||
default(ans) {
|
||||
return dbDefaults[ans.type].host;
|
||||
},
|
||||
transformer(color) {
|
||||
return chalkPipe(color)(color.green.bold);
|
||||
},
|
||||
when({ type }) {
|
||||
return type !== 'sqlite3';
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'port',
|
||||
type: 'number',
|
||||
message: '👉 Enter database port number\t:',
|
||||
default(ans) {
|
||||
return dbDefaults[ans.type].port;
|
||||
},
|
||||
transformer(color) {
|
||||
try {
|
||||
return color.green.bold;
|
||||
} catch (e) {
|
||||
return color;
|
||||
}
|
||||
},
|
||||
validate(port, answers) {
|
||||
const done = this.async();
|
||||
OldNewMgr.isPortOpen(answers.host, port)
|
||||
.then(isOpen => {
|
||||
if (isOpen) {
|
||||
done(null, true);
|
||||
} else {
|
||||
// done('Port is not open')
|
||||
console.log(
|
||||
`\n\n😩 ${answers.host}:${port} is not open please start the database if you haven't\n`
|
||||
.red.bold
|
||||
);
|
||||
process.exit(0);
|
||||
}
|
||||
})
|
||||
.catch(done);
|
||||
},
|
||||
when({ type }) {
|
||||
return type !== 'sqlite3';
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'username',
|
||||
type: 'input',
|
||||
message: '👉 Enter database username\t:',
|
||||
default(ans) {
|
||||
return dbDefaults[ans.type].username;
|
||||
},
|
||||
transformer(color) {
|
||||
return chalkPipe(color)(color.green.bold);
|
||||
},
|
||||
when({ type }) {
|
||||
return type !== 'sqlite3';
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'password',
|
||||
type: 'input',
|
||||
mask: true,
|
||||
message: '🙈 Enter database password\t:',
|
||||
transformer(color) {
|
||||
return new Array(color.length).fill('*'.green.bold).join('');
|
||||
},
|
||||
when({ type }) {
|
||||
return type !== 'sqlite3';
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'database',
|
||||
type: 'input',
|
||||
default(_ans) {
|
||||
return args._[1] + '_dev';
|
||||
},
|
||||
message: '👉 Enter database/schema name\t:',
|
||||
transformer(color) {
|
||||
return chalkPipe(color)(color.green.bold);
|
||||
},
|
||||
when({ type }) {
|
||||
return type !== 'sqlite3';
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'projectType',
|
||||
type: 'list',
|
||||
message: '🚀 Enter API type to generate\t:',
|
||||
choices: ['REST APIs', 'GRAPHQL APIs'].map(t => ({
|
||||
name: t,
|
||||
value: t,
|
||||
short: t.green.bold
|
||||
})),
|
||||
transformer(color) {
|
||||
return chalkPipe(color)(color.green.bold);
|
||||
},
|
||||
when({ type }) {
|
||||
return type !== 'sqlite3';
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'programmingLanguage',
|
||||
type: 'list',
|
||||
message: '🚀 Enter preferred programming language\t:',
|
||||
choices: ['Javascript', 'Typescript'].map(t => ({
|
||||
name: t,
|
||||
value: t,
|
||||
short: t.green.bold
|
||||
})),
|
||||
transformer(color) {
|
||||
return chalkPipe(color)(color.green.bold);
|
||||
},
|
||||
when({ type }) {
|
||||
return type !== 'sqlite3';
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
// console.log(answers);
|
||||
|
||||
if (answers.type === 'sqlite3') {
|
||||
console.log('Please use desktop app to create Sqlite project'.green.bold);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
/* if not valid retry getting right input */
|
||||
if (!answers.database) {
|
||||
console.log(
|
||||
'\n\tWarning! Database name can NOT be empty. Retry.\n '.red.bold
|
||||
);
|
||||
this.getNewProjectInput(args);
|
||||
}
|
||||
|
||||
/* attach new project name to path and 'cd' to that folder */
|
||||
args.folder = path.join(args.folder, args._[1]);
|
||||
mkdirp.sync(args.folder);
|
||||
process.chdir(args.folder);
|
||||
// await Util.runCmd(`cd ${args.folder}`);
|
||||
|
||||
/* prepare the args */
|
||||
const url = `${answers.type}://${answers.host}:${answers.port}?u=${
|
||||
answers.username
|
||||
}&p=${answers.password}&d=${answers.database}&api=${
|
||||
apiTypeMapping[answers.projectType]
|
||||
}`;
|
||||
args._[0] = answers.projectType === 'REST APIs' ? 'gar' : 'gag';
|
||||
switch (answers.projectType) {
|
||||
case 'REST APIs':
|
||||
args._[0] = 'gar';
|
||||
break;
|
||||
case 'GRAPHQL APIs':
|
||||
args._[0] = 'gag';
|
||||
break;
|
||||
case 'gRPC APIs':
|
||||
args._[0] = 'gap';
|
||||
break;
|
||||
default:
|
||||
args._[0] = 'gar';
|
||||
break;
|
||||
}
|
||||
args.url.push(url);
|
||||
|
||||
args.language = languageMapping[answers.programmingLanguage];
|
||||
|
||||
return OldNewMgr.testConnection(args);
|
||||
}
|
||||
|
||||
public static async testConnection({ url }) {
|
||||
for (const u of url) {
|
||||
const parsedUrlData = URL.parse(u, true);
|
||||
const queryParams = parsedUrlData.query;
|
||||
const client = parsedUrlData.protocol.slice(0, -1);
|
||||
const config = {
|
||||
client,
|
||||
connection: {
|
||||
host: parsedUrlData.hostname,
|
||||
port: +parsedUrlData.port,
|
||||
user: queryParams.u,
|
||||
password: queryParams.p,
|
||||
database:
|
||||
client === 'pg' ? 'postgres' : client === 'mssql' ? undefined : null
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
const knex = require('knex')(config);
|
||||
await knex.raw('SELECT 1+1 as data');
|
||||
} catch (e) {
|
||||
console.log(`\n😩 Test connection failed for : ${url}\n`.red.bold);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static async isPortOpen(host, port) {
|
||||
try {
|
||||
return await tcpPortUsed.check(+port, host);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
console.log(
|
||||
`\n😩 ${host}:${port} is not reachable please check\n`.red.bold
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default OldNewMgr;
|
||||
@@ -1,760 +0,0 @@
|
||||
/* tslint:disable:prefer-const */
|
||||
import colors from 'colors';
|
||||
import fs from 'fs';
|
||||
import glob from 'glob';
|
||||
import jsonfile from 'jsonfile';
|
||||
import path from 'path';
|
||||
import Util from '../util/Util';
|
||||
|
||||
import Table from 'cli-table3';
|
||||
|
||||
class PermissionsMgr {
|
||||
public static async set(args) {
|
||||
if (Util.isProjectGraphql()) {
|
||||
try {
|
||||
if (args._.length < 4) {
|
||||
console.warn('Invalid arguments for : xc permissions.set');
|
||||
return;
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
let [_, models, users, ...resolvers] = args._;
|
||||
models = models.split('.');
|
||||
users = users.split('.');
|
||||
|
||||
/* get all policies */
|
||||
const policiesPath = path.join(
|
||||
process.cwd(),
|
||||
'server',
|
||||
PermissionsMgr.getPolicyPath(),
|
||||
'**',
|
||||
'*.policy.js'
|
||||
);
|
||||
|
||||
glob.sync(policiesPath).forEach(file => {
|
||||
const modelName = path.basename(file).split('.')[0];
|
||||
|
||||
if (models.includes(modelName) || models[0] === '$') {
|
||||
const filePermissions = require(file);
|
||||
|
||||
const roles = this.extractUniqueGqlPolicyRoles(filePermissions);
|
||||
|
||||
if (users[0] === '$') {
|
||||
for (const [route, rolesObj] of Object.entries(filePermissions)) {
|
||||
if (resolvers[0] === '$=1') {
|
||||
const permObj = roles.reduce((obj, role) => {
|
||||
obj[role] = true;
|
||||
return obj;
|
||||
}, {});
|
||||
|
||||
Object.assign(rolesObj, permObj);
|
||||
console.log(
|
||||
`Setting Permissions for model:${modelName} roles:${roles.join(
|
||||
', '
|
||||
)} resolver: ${route}`
|
||||
);
|
||||
} else if (resolvers[0] === '$=0') {
|
||||
const permObj = roles.reduce((obj, role) => {
|
||||
obj[role] = false;
|
||||
return obj;
|
||||
}, {});
|
||||
|
||||
Object.assign(rolesObj, permObj);
|
||||
console.log(
|
||||
`Setting Permissions for model:${modelName} roles:${roles.join(
|
||||
', '
|
||||
)} resolver: ${route}`
|
||||
);
|
||||
} else {
|
||||
resolvers.forEach(permission => {
|
||||
const permTuple = permission.split('=');
|
||||
if (route === permTuple[0]) {
|
||||
const permObj = roles.reduce((obj, role) => {
|
||||
const val = !!(permTuple.length === 1
|
||||
? 1
|
||||
: +permTuple[1] || 0);
|
||||
obj[role] = val;
|
||||
return obj;
|
||||
}, {});
|
||||
Object.assign(rolesObj, permObj);
|
||||
console.log(
|
||||
`Setting Permissions for model:${modelName} roles:${roles.join(
|
||||
', '
|
||||
)} , resolver: ${route}`
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const [route, rolesObj] of Object.entries(filePermissions)) {
|
||||
resolvers.forEach(permission => {
|
||||
const permTuple = permission.split('=');
|
||||
if (route === permTuple[0] || permTuple[0] === '$') {
|
||||
const permObj = users.reduce((obj, role) => {
|
||||
const val = !!(permTuple.length === 1
|
||||
? 1
|
||||
: +permTuple[1] || 0);
|
||||
obj[role] = val;
|
||||
return obj;
|
||||
}, {});
|
||||
Object.assign(rolesObj, permObj);
|
||||
console.log(
|
||||
`Setting Permissions for model:${modelName} roles:${users} , resolver: ${route}`
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const policyFileContent = `module.exports = ${JSON.stringify(
|
||||
filePermissions,
|
||||
null,
|
||||
2
|
||||
)};\n`;
|
||||
fs.writeFileSync(file, policyFileContent);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(`Error in xc permissions.set`, e);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
if (args._.length < 4) {
|
||||
console.warn('Invalid arguments for : xc permissions.set');
|
||||
return;
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
let [_, models, users, ...permissions] = args._;
|
||||
|
||||
models = models.split('.');
|
||||
users = users.split('.');
|
||||
|
||||
/* get all policies */
|
||||
const policiesPath = path.join(
|
||||
process.cwd(),
|
||||
'server',
|
||||
PermissionsMgr.getPolicyPath(),
|
||||
'**',
|
||||
'*.routes.js'
|
||||
);
|
||||
|
||||
glob.sync(policiesPath).forEach(file => {
|
||||
const modelName = path.basename(file).split('.')[0];
|
||||
if (models.includes(modelName) || models[0] === '$') {
|
||||
const routesList: Route[] = require(file);
|
||||
const roles = this.extractUniqueRoles(routesList);
|
||||
|
||||
if (users[0] === '$') {
|
||||
for (const route of routesList) {
|
||||
if (permissions[0] === '$=1') {
|
||||
const permObj = roles.reduce((obj, role) => {
|
||||
obj[role] = true;
|
||||
return obj;
|
||||
}, {});
|
||||
Object.assign(route.acl, permObj);
|
||||
console.log(
|
||||
`Setting Permissions for model:${modelName} roles:${roles.join(
|
||||
', '
|
||||
)} method: ${route.type}=true, route: ${route.path}`
|
||||
);
|
||||
} else if (permissions[0] === '$=0') {
|
||||
const permObj = roles.reduce((obj, role) => {
|
||||
obj[role] = false;
|
||||
return obj;
|
||||
}, {});
|
||||
Object.assign(route.acl, permObj);
|
||||
console.log(
|
||||
`Setting Permissions for model:${modelName} roles:${roles.join(
|
||||
', '
|
||||
)} method: ${route.type}=false, route: ${route.path}`
|
||||
);
|
||||
} else {
|
||||
permissions.forEach(permission => {
|
||||
const permTuple = permission.split('=');
|
||||
const val = !!(permTuple.length === 1
|
||||
? 1
|
||||
: +permTuple[1] || 0);
|
||||
const permObj = roles.reduce((obj, role) => {
|
||||
obj[role] = val;
|
||||
return obj;
|
||||
}, {});
|
||||
if (route.type === permTuple[0]) {
|
||||
Object.assign(route.acl, permObj);
|
||||
console.log(
|
||||
`Setting Permissions for model:${modelName} roles:${roles.join(
|
||||
', '
|
||||
)} method: ${permTuple[0]}=${val}, route: ${route.path}`
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const route of routesList) {
|
||||
permissions.forEach(permission => {
|
||||
const permTuple = permission.split('=');
|
||||
const val = !!(permTuple.length === 1
|
||||
? 1
|
||||
: +permTuple[1] || 0);
|
||||
const permObj = users.reduce((obj, role) => {
|
||||
obj[role] = val;
|
||||
return obj;
|
||||
}, {});
|
||||
|
||||
if (route.type === permTuple[0]) {
|
||||
Object.assign(route.acl, permObj);
|
||||
console.log(
|
||||
`Setting Permissions for model:${modelName} roles:${users.join(
|
||||
', '
|
||||
)} method: ${permTuple[0]}=${val}, route: ${route.path}`
|
||||
);
|
||||
} else if (permTuple[0] === '*') {
|
||||
Object.assign(route.acl, permObj);
|
||||
console.log(
|
||||
`Setting Permissions for model:${modelName} roles:${users.join(
|
||||
', '
|
||||
)} method: ${route.type}=${val}, route: ${route.path}`
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const policyFileContent = `module.exports = ${JSON.stringify(
|
||||
routesList,
|
||||
null,
|
||||
2
|
||||
)};\n`;
|
||||
fs.writeFileSync(file, policyFileContent);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(`Error in xc permissions.set`, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async get(args) {
|
||||
if (Util.isProjectGraphql()) {
|
||||
try {
|
||||
if (args._.length < 2) {
|
||||
console.warn('Invalid arguments for : xc permissions.get');
|
||||
return;
|
||||
}
|
||||
|
||||
let { 1: models } = args._;
|
||||
models = models.split('.');
|
||||
|
||||
/* get all policies */
|
||||
const policiesPath = path.join(
|
||||
process.cwd(),
|
||||
'server',
|
||||
PermissionsMgr.getPolicyPath(),
|
||||
'**',
|
||||
'*.policy.js'
|
||||
);
|
||||
|
||||
// instantiate
|
||||
let rows: any[] = [];
|
||||
let roles: any[] = [];
|
||||
|
||||
glob.sync(policiesPath).forEach(file => {
|
||||
// let filePermissions = require(file);
|
||||
|
||||
const modelName = path.basename(file).split('.')[0];
|
||||
|
||||
if (models.includes(modelName)) {
|
||||
const filePermissions = require(file);
|
||||
|
||||
roles = this.extractUniqueGqlPolicyRoles(filePermissions);
|
||||
|
||||
rows.push([
|
||||
{
|
||||
colSpan: roles.length + 1,
|
||||
content: colors.green(file),
|
||||
hAlign: 'center'
|
||||
}
|
||||
]);
|
||||
|
||||
for (const [route, methods] of Object.entries(filePermissions)) {
|
||||
const row: any[] = [{ content: route, vAlign: 'center' }];
|
||||
for (const role of roles) {
|
||||
row.push(methods[role] ? colors.green('✔') : colors.red('x'));
|
||||
}
|
||||
rows.push(row);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const table = new Table({
|
||||
head: ['Route', ...roles]
|
||||
});
|
||||
|
||||
table.push(...rows);
|
||||
console.log(table.toString());
|
||||
} catch (e) {
|
||||
console.error(`Error in xc permissions.get`, e);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
if (args._.length < 2) {
|
||||
console.warn('Invalid arguments for : xc permissions.get');
|
||||
return;
|
||||
}
|
||||
|
||||
let { 1: models } = args._;
|
||||
models = models.split('.');
|
||||
|
||||
/* get all policies */
|
||||
const policiesPath = path.join(
|
||||
process.cwd(),
|
||||
'server',
|
||||
PermissionsMgr.getPolicyPath(),
|
||||
'**',
|
||||
'*.routes.js'
|
||||
);
|
||||
|
||||
// instantiate
|
||||
const table = new Table({
|
||||
head: ['Route', 'Role', 'GET', 'POST', 'PUT', 'DELETE', 'PATCH']
|
||||
});
|
||||
|
||||
glob
|
||||
.sync(policiesPath)
|
||||
.sort(this.sortFiles)
|
||||
.forEach(file => {
|
||||
const modelName = path.basename(file).split('.')[0];
|
||||
|
||||
if (models.includes(modelName)) {
|
||||
const routesList: Route[] = require(file);
|
||||
const groupedRoutes = this.groupRoutes(routesList);
|
||||
|
||||
// extract unique roles
|
||||
const roles = this.extractUniqueRoles(routesList);
|
||||
|
||||
table.push([
|
||||
{
|
||||
colSpan: 7,
|
||||
content: colors.green(file),
|
||||
hAlign: 'center'
|
||||
}
|
||||
]);
|
||||
|
||||
for (const [routePath, methods] of Object.entries(
|
||||
groupedRoutes
|
||||
)) {
|
||||
let i = 0;
|
||||
for (const role of roles) {
|
||||
{
|
||||
table.push([
|
||||
...(i++
|
||||
? []
|
||||
: [
|
||||
{
|
||||
content: routePath,
|
||||
rowSpan: roles.length,
|
||||
vAlign: 'center'
|
||||
}
|
||||
]),
|
||||
role,
|
||||
methods?.get?.acl?.[role]
|
||||
? colors.green('✔')
|
||||
: colors.red('x'),
|
||||
methods?.post?.acl?.[role]
|
||||
? colors.green('✔')
|
||||
: colors.red('x'),
|
||||
methods?.put?.acl?.[role]
|
||||
? colors.green('✔')
|
||||
: colors.red('x'),
|
||||
methods?.delete?.acl?.[role]
|
||||
? colors.green('✔')
|
||||
: colors.red('x'),
|
||||
methods?.patch?.acl?.[role]
|
||||
? colors.green('✔')
|
||||
: colors.red('x')
|
||||
] as any);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
console.log(table.toString());
|
||||
} catch (e) {
|
||||
console.error(`Error in xc permissions.get`, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async userAdd(args) {
|
||||
if (Util.isProjectGraphql()) {
|
||||
try {
|
||||
if (args._.length < 2) {
|
||||
console.warn('Invalid arguments for : xc permissions.userAdd');
|
||||
return;
|
||||
}
|
||||
|
||||
const { 1: user } = args._;
|
||||
|
||||
/* get all policies */
|
||||
const policiesPath = path.join(
|
||||
process.cwd(),
|
||||
'server',
|
||||
PermissionsMgr.getPolicyPath(),
|
||||
'**',
|
||||
'*.policy.js'
|
||||
);
|
||||
|
||||
glob.sync(policiesPath).forEach(file => {
|
||||
const modelName = path.basename(file).split('.')[0];
|
||||
|
||||
const filePermissions = require(file);
|
||||
|
||||
const roles = this.extractUniqueGqlPolicyRoles(filePermissions);
|
||||
|
||||
if (roles.includes(user)) {
|
||||
console.warn(`${user} already exist in ${modelName} policy`);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const roles1 of Object.values(filePermissions)) {
|
||||
roles1[user] = true;
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Adding new role permission for model:${modelName} roles:${user}`
|
||||
);
|
||||
|
||||
const policyFileContent = `module.exports = ${JSON.stringify(
|
||||
filePermissions,
|
||||
null,
|
||||
2
|
||||
)};\n`;
|
||||
fs.writeFileSync(file, policyFileContent);
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(`Error in xc permissions.user.add`, e);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
if (args._.length < 2) {
|
||||
console.warn('Invalid arguments for : xc permissions.userAdd');
|
||||
return;
|
||||
}
|
||||
|
||||
const { 1: user } = args._;
|
||||
|
||||
/* get all policies */
|
||||
const policiesPath = path.join(
|
||||
process.cwd(),
|
||||
'server',
|
||||
PermissionsMgr.getPolicyPath(),
|
||||
'**',
|
||||
'*.routes.js'
|
||||
);
|
||||
|
||||
glob.sync(policiesPath).forEach(file => {
|
||||
const modelName = path.basename(file).split('.')[0];
|
||||
|
||||
const routes: Route[] = require(file);
|
||||
|
||||
const roles = this.extractUniqueRoles(routes);
|
||||
|
||||
if (roles.includes(user)) {
|
||||
console.warn(`${user} already exist in ${modelName} policy`);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const route of routes) {
|
||||
route.acl[user] = true;
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Adding new role permission for model:${modelName} roles:${user}`
|
||||
);
|
||||
|
||||
const policyFileContent = `module.exports = ${JSON.stringify(
|
||||
routes,
|
||||
null,
|
||||
2
|
||||
)};\n`;
|
||||
fs.writeFileSync(file, policyFileContent);
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(`Error in xc permissions.user.add`, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async userDelete(args) {
|
||||
if (Util.isProjectGraphql()) {
|
||||
try {
|
||||
if (args._.length < 2) {
|
||||
console.warn('Invalid arguments for : xc permissions.userAdd');
|
||||
return;
|
||||
}
|
||||
|
||||
const { 1: user } = args._;
|
||||
|
||||
/* get all policies */
|
||||
const policiesPath = path.join(
|
||||
process.cwd(),
|
||||
'server',
|
||||
PermissionsMgr.getPolicyPath(),
|
||||
'**',
|
||||
'*.policy.js'
|
||||
);
|
||||
|
||||
glob.sync(policiesPath).forEach(file => {
|
||||
const modelName = path.basename(file).split('.')[0];
|
||||
|
||||
const filePermissions = require(file);
|
||||
|
||||
const roles = this.extractUniqueGqlPolicyRoles(filePermissions);
|
||||
|
||||
if (!roles.includes(user)) {
|
||||
console.warn(`${user} not exist in ${modelName} policy`);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const roles1 of Object.values(filePermissions)) {
|
||||
delete roles1[user];
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Deleting user permission for model:${modelName} roles:${user}`
|
||||
);
|
||||
|
||||
const policyFileContent = `module.exports = ${JSON.stringify(
|
||||
filePermissions,
|
||||
null,
|
||||
2
|
||||
)};\n`;
|
||||
fs.writeFileSync(file, policyFileContent);
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(`Error in xc permissions.user.delete`, e);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
if (args._.length < 2) {
|
||||
console.warn('Invalid arguments for : xc permissions.userAdd');
|
||||
return;
|
||||
}
|
||||
|
||||
const { 1: user } = args._;
|
||||
|
||||
/* get all policies */
|
||||
const policiesPath = path.join(
|
||||
process.cwd(),
|
||||
'server',
|
||||
PermissionsMgr.getPolicyPath(),
|
||||
'**',
|
||||
'*.routes.js'
|
||||
);
|
||||
|
||||
glob.sync(policiesPath).forEach(file => {
|
||||
const modelName = path.basename(file).split('.')[0];
|
||||
|
||||
const routes: Route[] = require(file);
|
||||
|
||||
const roles = this.extractUniqueRoles(routes);
|
||||
|
||||
if (!roles.includes(user)) {
|
||||
console.warn(`${user} not exist in ${modelName} policy`);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const route of routes) {
|
||||
delete route.acl[user];
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Deleting user permission for model:${modelName} roles:${user}`
|
||||
);
|
||||
|
||||
const policyFileContent = `module.exports = ${JSON.stringify(
|
||||
routes,
|
||||
null,
|
||||
2
|
||||
)};\n`;
|
||||
fs.writeFileSync(file, policyFileContent);
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(`Error in xc permissions.user.delete`, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async userRename(args) {
|
||||
if (Util.isProjectGraphql()) {
|
||||
try {
|
||||
if (args._.length < 3) {
|
||||
console.warn('Invalid arguments for : xc permissions.userAdd');
|
||||
return;
|
||||
}
|
||||
|
||||
const { 1: oldUser, 2: newUser } = args._;
|
||||
|
||||
/* get all policies */
|
||||
const policiesPath = path.join(
|
||||
process.cwd(),
|
||||
'server',
|
||||
PermissionsMgr.getPolicyPath(),
|
||||
'**',
|
||||
'*.policy.js'
|
||||
);
|
||||
|
||||
glob.sync(policiesPath).forEach(file => {
|
||||
const modelName = path.basename(file).split('.')[0];
|
||||
|
||||
const filePermissions = require(file);
|
||||
|
||||
const roles = this.extractUniqueGqlPolicyRoles(filePermissions);
|
||||
|
||||
if (!roles.includes(oldUser)) {
|
||||
console.warn(`${oldUser} not exist in ${modelName} policy`);
|
||||
return;
|
||||
}
|
||||
if (roles.includes(newUser)) {
|
||||
console.warn(`${newUser} is already exist in ${modelName} policy`);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const roles1 of Object.values(filePermissions)) {
|
||||
roles1[newUser] = roles1[oldUser];
|
||||
delete roles1[oldUser];
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Renaming user permission ${oldUser} to ${newUser} for model:${modelName}`
|
||||
);
|
||||
const policyFileContent = `module.exports = ${JSON.stringify(
|
||||
filePermissions,
|
||||
null,
|
||||
2
|
||||
)};\n`;
|
||||
fs.writeFileSync(file, policyFileContent);
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(`Error in xc permissions.user.delete`, e);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
if (args._.length < 3) {
|
||||
console.warn('Invalid arguments for : xc permissions.userAdd');
|
||||
return;
|
||||
}
|
||||
|
||||
const { 1: oldUser, 2: newUser } = args._;
|
||||
|
||||
/* get all policies */
|
||||
const policiesPath = path.join(
|
||||
process.cwd(),
|
||||
'server',
|
||||
PermissionsMgr.getPolicyPath(),
|
||||
'**',
|
||||
'*.routes.js'
|
||||
);
|
||||
|
||||
glob.sync(policiesPath).forEach(file => {
|
||||
const modelName = path.basename(file).split('.')[0];
|
||||
|
||||
const routes: Route[] = require(file);
|
||||
|
||||
const roles = this.extractUniqueRoles(routes);
|
||||
|
||||
if (!roles.includes(oldUser)) {
|
||||
console.warn(`${oldUser} not exist in ${modelName} policy`);
|
||||
return;
|
||||
}
|
||||
if (roles.includes(newUser)) {
|
||||
console.warn(`${newUser} is already exist in ${modelName} policy`);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const route of routes) {
|
||||
route.acl[newUser] = route.acl[oldUser];
|
||||
delete route.acl[oldUser];
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Renaming user permission ${oldUser} to ${newUser} for model:${modelName}`
|
||||
);
|
||||
const policyFileContent = `module.exports = ${JSON.stringify(
|
||||
routes,
|
||||
null,
|
||||
2
|
||||
)};\n`;
|
||||
fs.writeFileSync(file, policyFileContent);
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(`Error in xc permissions.user.delete`, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static getPolicyPath() {
|
||||
const projectConfig = jsonfile.readFileSync(
|
||||
path.join(process.cwd(), 'config.xc.json')
|
||||
);
|
||||
return projectConfig.meta.projectType === 'rest' ? 'routers' : 'resolvers';
|
||||
}
|
||||
|
||||
private static extractUniqueGqlPolicyRoles(filePermissions) {
|
||||
return Object.values(filePermissions)
|
||||
.flatMap(roles1 => Object.keys(roles1))
|
||||
.filter((v, i, arr) => arr.indexOf(v) === i);
|
||||
}
|
||||
|
||||
private static extractUniqueRoles(routesList: Route[]) {
|
||||
const roles = routesList
|
||||
.flatMap(route => Object.keys(route.acl))
|
||||
.filter((v, i, arr) => arr.indexOf(v) === i);
|
||||
return roles;
|
||||
}
|
||||
|
||||
private static groupRoutes(routes: Route[]): GroupedRoutes {
|
||||
const groupedRoutes: GroupedRoutes = {};
|
||||
for (const route of routes) {
|
||||
groupedRoutes[route.path] = groupedRoutes[route.path] || {};
|
||||
groupedRoutes[route.path][route.type] = route;
|
||||
}
|
||||
return groupedRoutes;
|
||||
}
|
||||
|
||||
private static sortFiles(file1: string, file2: string): number {
|
||||
return (
|
||||
((file1.indexOf('.bt.') > -1 ? 1 : 0) ||
|
||||
(file1.indexOf('.hm.') > -1 ? 2 : 0)) -
|
||||
((file2.indexOf('.bt.') > -1 ? 1 : 0) ||
|
||||
(file2.indexOf('.hm.') > -1 ? 2 : 0))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default PermissionsMgr;
|
||||
|
||||
export interface Route {
|
||||
type: string;
|
||||
path: string;
|
||||
acl: {
|
||||
[key: string]: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
type httpMethods = 'get' | 'post' | 'patch' | 'put' | 'delete';
|
||||
|
||||
export interface GroupedRoutes {
|
||||
[key: string]: {
|
||||
[key in httpMethods]?: {
|
||||
type: string;
|
||||
path: string;
|
||||
acl: {
|
||||
[key: string]: boolean;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,752 +0,0 @@
|
||||
/* tslint:disable:prefer-const */
|
||||
import colors from 'colors';
|
||||
import fs from 'fs';
|
||||
import glob from 'glob';
|
||||
import jsonfile from 'jsonfile';
|
||||
import path from 'path';
|
||||
import Util from '../util/Util';
|
||||
|
||||
import Table from 'cli-table3';
|
||||
|
||||
class PermissionsMgr {
|
||||
public static async set(args) {
|
||||
if (Util.isProjectGraphql()) {
|
||||
try {
|
||||
if (args._.length < 4) {
|
||||
console.warn('Invalid arguments for : xc permissions.set');
|
||||
return;
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
let [_, models, users, ...resolvers] = args._;
|
||||
models = models.split('.');
|
||||
users = users.split('.');
|
||||
|
||||
/* get all policies */
|
||||
const policiesPath = path.join(
|
||||
process.cwd(),
|
||||
'server',
|
||||
PermissionsMgr.getPolicyPath(),
|
||||
'**',
|
||||
'*.policy.js'
|
||||
);
|
||||
|
||||
glob.sync(policiesPath).forEach(file => {
|
||||
const modelName = path.basename(file).split('.')[0];
|
||||
|
||||
if (models.includes(modelName) || models[0] === '$') {
|
||||
const filePermissions = require(file).permissions;
|
||||
|
||||
const roles = Object.values(filePermissions)
|
||||
.flatMap(roles1 => Object.keys(roles1))
|
||||
.filter((v, i, arr) => arr.indexOf(v) === i);
|
||||
|
||||
if (users[0] === '$') {
|
||||
for (const [route, rolesObj] of Object.entries(filePermissions)) {
|
||||
if (resolvers[0] === '$=1') {
|
||||
const permObj = roles.reduce((obj, role) => {
|
||||
obj[role] = true;
|
||||
return obj;
|
||||
}, {});
|
||||
|
||||
Object.assign(rolesObj, permObj);
|
||||
console.log(
|
||||
`Setting Permissions for model:${modelName} roles:${roles.join(
|
||||
', '
|
||||
)} resolver: ${route}`
|
||||
);
|
||||
} else if (resolvers[0] === '$=0') {
|
||||
const permObj = roles.reduce((obj, role) => {
|
||||
obj[role] = false;
|
||||
return obj;
|
||||
}, {});
|
||||
|
||||
Object.assign(rolesObj, permObj);
|
||||
console.log(
|
||||
`Setting Permissions for model:${modelName} roles:${roles.join(
|
||||
', '
|
||||
)} resolver: ${route}`
|
||||
);
|
||||
} else {
|
||||
resolvers.forEach(permission => {
|
||||
const permTuple = permission.split('=');
|
||||
if (route === permTuple[0]) {
|
||||
const permObj = roles.reduce((obj, role) => {
|
||||
const val = !!(permTuple.length === 1
|
||||
? 1
|
||||
: +permTuple[1] || 0);
|
||||
obj[role] = val;
|
||||
return obj;
|
||||
}, {});
|
||||
Object.assign(rolesObj, permObj);
|
||||
console.log(
|
||||
`Setting Permissions for model:${modelName} roles:${roles.join(
|
||||
', '
|
||||
)} , resolver: ${route}`
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const [route, rolesObj] of Object.entries(filePermissions)) {
|
||||
resolvers.forEach(permission => {
|
||||
const permTuple = permission.split('=');
|
||||
if (route === permTuple[0]) {
|
||||
const permObj = roles.reduce((obj, role) => {
|
||||
const val = !!(permTuple.length === 1
|
||||
? 1
|
||||
: +permTuple[1] || 0);
|
||||
obj[role] = val;
|
||||
return obj;
|
||||
}, {});
|
||||
Object.assign(rolesObj, permObj);
|
||||
console.log(
|
||||
`Setting Permissions for model:${modelName} roles:${roles.join(
|
||||
', '
|
||||
)} , resolver: ${route}`
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const policyFileContent = `module.exports.permissions = ${JSON.stringify(
|
||||
filePermissions,
|
||||
null,
|
||||
2
|
||||
)};\n`;
|
||||
fs.writeFileSync(file, policyFileContent);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(`Error in xc permissions.set`, e);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
if (args._.length < 4) {
|
||||
console.warn('Invalid arguments for : xc permissions.set');
|
||||
return;
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
let [_, models, users, ...permissions] = args._;
|
||||
|
||||
models = models.split('.');
|
||||
users = users.split('.');
|
||||
|
||||
/* get all policies */
|
||||
const policiesPath = path.join(
|
||||
process.cwd(),
|
||||
'server',
|
||||
PermissionsMgr.getPolicyPath(),
|
||||
'**',
|
||||
'*.policy.js'
|
||||
);
|
||||
|
||||
glob.sync(policiesPath).forEach(file => {
|
||||
const modelName = path.basename(file).split('.')[0];
|
||||
|
||||
if (models.includes(modelName) || models[0] === '$') {
|
||||
const filePermissions = require(file).permissions;
|
||||
|
||||
if (users[0] === '$') {
|
||||
const roles = Object.values(filePermissions)
|
||||
.flatMap(methods =>
|
||||
Object.values(methods).flatMap(roles1 => Object.keys(roles1))
|
||||
)
|
||||
.filter((v, i, arr) => arr.indexOf(v) === i);
|
||||
|
||||
for (const [route, methods] of Object.entries(filePermissions)) {
|
||||
if (permissions[0] === '$=1') {
|
||||
const permObj = roles.reduce((obj, role) => {
|
||||
obj[role] = true;
|
||||
return obj;
|
||||
}, {});
|
||||
|
||||
for (const [method, rolesObj] of Object.entries(methods)) {
|
||||
Object.assign(rolesObj, permObj);
|
||||
console.log(
|
||||
`Setting Permissions for model:${modelName} roles:${roles.join(
|
||||
', '
|
||||
)} method: ${method}=true, route: ${route}`
|
||||
);
|
||||
}
|
||||
} else if (permissions[0] === '$=0') {
|
||||
const permObj = roles.reduce((obj, role) => {
|
||||
obj[role] = false;
|
||||
return obj;
|
||||
}, {});
|
||||
for (const [method, rolesObj] of Object.entries(methods)) {
|
||||
Object.assign(rolesObj, permObj);
|
||||
console.log(
|
||||
`Setting Permissions for model:${modelName} roles:${roles.join(
|
||||
', '
|
||||
)} method: ${method}=false, route: ${route}`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
permissions.forEach(permission => {
|
||||
const permTuple = permission.split('=');
|
||||
const val = !!(permTuple.length === 1
|
||||
? 1
|
||||
: +permTuple[1] || 0);
|
||||
const permObj = roles.reduce((obj, role) => {
|
||||
obj[role] = val;
|
||||
return obj;
|
||||
}, {});
|
||||
if (methods[permTuple[0]]) {
|
||||
Object.assign(methods[permTuple[0]], permObj);
|
||||
console.log(
|
||||
`Setting Permissions for model:${modelName} roles:${roles.join(
|
||||
', '
|
||||
)} method: ${permTuple[0]}=${val}, route: ${route}`
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const [route, methods] of Object.entries(filePermissions)) {
|
||||
permissions.forEach(permission => {
|
||||
const permTuple = permission.split('=');
|
||||
const val = !!(permTuple.length === 1
|
||||
? 1
|
||||
: +permTuple[1] || 0);
|
||||
const permObj = users.reduce((obj, role) => {
|
||||
obj[role] = val;
|
||||
return obj;
|
||||
}, {});
|
||||
if (methods[permTuple[0]]) {
|
||||
Object.assign(methods[permTuple[0]], permObj);
|
||||
console.log(
|
||||
`Setting Permissions for model:${modelName} roles:${users.join(
|
||||
', '
|
||||
)} method: ${permTuple[0]}=${val}, route: ${route}`
|
||||
);
|
||||
} else if (permTuple[0] === '*') {
|
||||
for (const [method, rolesObj] of Object.entries(methods)) {
|
||||
Object.assign(rolesObj, permObj);
|
||||
console.log(
|
||||
`Setting Permissions for model:${modelName} roles:${users.join(
|
||||
', '
|
||||
)} method: ${method}=${val}, route: ${route}`
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const policyFileContent = `module.exports.permissions = ${JSON.stringify(
|
||||
filePermissions,
|
||||
null,
|
||||
2
|
||||
)};\n`;
|
||||
fs.writeFileSync(file, policyFileContent);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(`Error in xc permissions.set`, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async get(args) {
|
||||
if (Util.isProjectGraphql()) {
|
||||
try {
|
||||
if (args._.length < 2) {
|
||||
console.warn('Invalid arguments for : xc permissions.get');
|
||||
return;
|
||||
}
|
||||
|
||||
let { 1: models } = args._;
|
||||
models = models.split('.');
|
||||
|
||||
/* get all policies */
|
||||
const policiesPath = path.join(
|
||||
process.cwd(),
|
||||
'server',
|
||||
PermissionsMgr.getPolicyPath(),
|
||||
'**',
|
||||
'*.policy.js'
|
||||
);
|
||||
|
||||
// instantiate
|
||||
let rows: any[] = [];
|
||||
let roles: any[] = [];
|
||||
|
||||
glob.sync(policiesPath).forEach(file => {
|
||||
// let filePermissions = require(file).permissions;
|
||||
|
||||
const modelName = path.basename(file).split('.')[0];
|
||||
|
||||
if (models.includes(modelName)) {
|
||||
const filePermissions = require(file).permissions;
|
||||
|
||||
roles = Object.values(filePermissions)
|
||||
.flatMap(roles1 => Object.keys(roles1))
|
||||
.filter((v, i, arr) => arr.indexOf(v) === i);
|
||||
|
||||
rows.push([
|
||||
{
|
||||
colSpan: roles.length + 1,
|
||||
content: colors.green(file),
|
||||
hAlign: 'center'
|
||||
}
|
||||
]);
|
||||
|
||||
for (const [route, methods] of Object.entries(filePermissions)) {
|
||||
const row: any[] = [{ content: route, vAlign: 'center' }];
|
||||
for (const role of roles) {
|
||||
row.push(methods[role] ? colors.green('✔️') : colors.red('x'));
|
||||
}
|
||||
rows.push(row);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const table = new Table({
|
||||
head: ['Route', ...roles]
|
||||
});
|
||||
|
||||
table.push(...rows);
|
||||
console.log(table.toString());
|
||||
} catch (e) {
|
||||
console.error(`Error in xc permissions.get`, e);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
if (args._.length < 2) {
|
||||
console.warn('Invalid arguments for : xc permissions.get');
|
||||
return;
|
||||
}
|
||||
|
||||
let { 1: models } = args._;
|
||||
models = models.split('.');
|
||||
|
||||
/* get all policies */
|
||||
const policiesPath = path.join(
|
||||
process.cwd(),
|
||||
'server',
|
||||
PermissionsMgr.getPolicyPath(),
|
||||
'**',
|
||||
'*.policy.js'
|
||||
);
|
||||
|
||||
// instantiate
|
||||
const table = new Table({
|
||||
head: ['Route', 'Role', 'GET', 'POST', 'PUT', 'DELETE', 'PATCH']
|
||||
});
|
||||
|
||||
glob.sync(policiesPath).forEach(file => {
|
||||
const modelName = path.basename(file).split('.')[0];
|
||||
|
||||
if (models.includes(modelName)) {
|
||||
if (models.includes(modelName)) {
|
||||
const filePermissions: {
|
||||
readonly [key: string]: any;
|
||||
} = require(file).permissions;
|
||||
|
||||
const roles = Object.values(filePermissions)
|
||||
.flatMap(methods =>
|
||||
Object.values(methods).flatMap(roles1 => Object.keys(roles1))
|
||||
)
|
||||
.filter((v, i, arr) => arr.indexOf(v) === i);
|
||||
|
||||
table.push([
|
||||
{
|
||||
colSpan: 7,
|
||||
content: colors.green(file),
|
||||
hAlign: 'center'
|
||||
}
|
||||
]);
|
||||
|
||||
for (const [route, methods] of Object.entries(filePermissions)) {
|
||||
let i = 0;
|
||||
for (const role of roles) {
|
||||
{
|
||||
table.push([
|
||||
...(i++
|
||||
? []
|
||||
: [
|
||||
{
|
||||
content: route,
|
||||
rowSpan: roles.length,
|
||||
vAlign: 'center'
|
||||
}
|
||||
]),
|
||||
role,
|
||||
methods.get && methods.get[role]
|
||||
? colors.green('✔️')
|
||||
: colors.red('x'),
|
||||
methods.post && methods.post[role]
|
||||
? colors.green('✔️')
|
||||
: colors.red('x'),
|
||||
methods.put && methods.put[role]
|
||||
? colors.green('✔️')
|
||||
: colors.red('x'),
|
||||
methods.delete && methods.delete[role]
|
||||
? colors.green('✔️')
|
||||
: colors.red('x'),
|
||||
methods.patch && methods.patch[role]
|
||||
? colors.green('✔️')
|
||||
: colors.red('x')
|
||||
] as any);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// console.log(`Model : ${modelName} \n${JSON.stringify(filePermissions, 0, 2)} `)
|
||||
}
|
||||
});
|
||||
|
||||
console.log(table.toString());
|
||||
} catch (e) {
|
||||
console.error(`Error in xc permissions.get`, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async userAdd(args) {
|
||||
if (Util.isProjectGraphql()) {
|
||||
try {
|
||||
if (args._.length < 2) {
|
||||
console.warn('Invalid arguments for : xc permissions.userAdd');
|
||||
return;
|
||||
}
|
||||
|
||||
const { 1: user } = args._;
|
||||
|
||||
/* get all policies */
|
||||
const policiesPath = path.join(
|
||||
process.cwd(),
|
||||
'server',
|
||||
PermissionsMgr.getPolicyPath(),
|
||||
'**',
|
||||
'*.policy.js'
|
||||
);
|
||||
|
||||
glob.sync(policiesPath).forEach(file => {
|
||||
const modelName = path.basename(file).split('.')[0];
|
||||
|
||||
const filePermissions = require(file).permissions;
|
||||
|
||||
const roles = Object.values(filePermissions)
|
||||
.flatMap(roles1 => Object.keys(roles1))
|
||||
.filter((v, i, arr) => arr.indexOf(v) === i);
|
||||
|
||||
if (roles.includes(user)) {
|
||||
console.warn(`${user} already exist in ${modelName} policy`);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const roles1 of Object.values(filePermissions)) {
|
||||
roles1[user] = true;
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Adding new role permission for model:${modelName} roles:${user}`
|
||||
);
|
||||
|
||||
const policyFileContent = `module.exports.permissions = ${JSON.stringify(
|
||||
filePermissions,
|
||||
null,
|
||||
2
|
||||
)};\n`;
|
||||
fs.writeFileSync(file, policyFileContent);
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(`Error in xc permissions.user.add`, e);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
if (args._.length < 2) {
|
||||
console.warn('Invalid arguments for : xc permissions.userAdd');
|
||||
return;
|
||||
}
|
||||
|
||||
const { 1: user } = args._;
|
||||
|
||||
/* get all policies */
|
||||
const policiesPath = path.join(
|
||||
process.cwd(),
|
||||
'server',
|
||||
PermissionsMgr.getPolicyPath(),
|
||||
'**',
|
||||
'*.policy.js'
|
||||
);
|
||||
|
||||
glob.sync(policiesPath).forEach(file => {
|
||||
const modelName = path.basename(file).split('.')[0];
|
||||
|
||||
const filePermissions = require(file).permissions;
|
||||
|
||||
const roles = Object.values(filePermissions)
|
||||
.flatMap(methods =>
|
||||
Object.values(methods).flatMap(roles1 => Object.keys(roles1))
|
||||
)
|
||||
.filter((v, i, arr) => arr.indexOf(v) === i);
|
||||
|
||||
if (roles.includes(user)) {
|
||||
console.warn(`${user} already exist in ${modelName} policy`);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const methods of Object.values(filePermissions)) {
|
||||
for (const roles1 of Object.values(methods)) {
|
||||
roles1[user] = true;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Adding new role permission for model:${modelName} roles:${user}`
|
||||
);
|
||||
|
||||
const policyFileContent = `module.exports.permissions = ${JSON.stringify(
|
||||
filePermissions,
|
||||
null,
|
||||
2
|
||||
)};\n`;
|
||||
fs.writeFileSync(file, policyFileContent);
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(`Error in xc permissions.user.add`, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async userDelete(args) {
|
||||
if (Util.isProjectGraphql()) {
|
||||
try {
|
||||
if (args._.length < 2) {
|
||||
console.warn('Invalid arguments for : xc permissions.userAdd');
|
||||
return;
|
||||
}
|
||||
|
||||
const { 1: user } = args._;
|
||||
|
||||
/* get all policies */
|
||||
const policiesPath = path.join(
|
||||
process.cwd(),
|
||||
'server',
|
||||
PermissionsMgr.getPolicyPath(),
|
||||
'**',
|
||||
'*.policy.js'
|
||||
);
|
||||
|
||||
glob.sync(policiesPath).forEach(file => {
|
||||
const modelName = path.basename(file).split('.')[0];
|
||||
|
||||
const filePermissions = require(file).permissions;
|
||||
|
||||
const roles = Object.values(filePermissions)
|
||||
.flatMap(roles1 => Object.keys(roles1))
|
||||
.filter((v, i, arr) => arr.indexOf(v) === i);
|
||||
|
||||
if (!roles.includes(user)) {
|
||||
console.warn(`${user} not exist in ${modelName} policy`);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const roles1 of Object.values(filePermissions)) {
|
||||
delete roles1[user];
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Deleting user permission for model:${modelName} roles:${user}`
|
||||
);
|
||||
|
||||
const policyFileContent = `module.exports.permissions = ${JSON.stringify(
|
||||
filePermissions,
|
||||
null,
|
||||
2
|
||||
)};\n`;
|
||||
fs.writeFileSync(file, policyFileContent);
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(`Error in xc permissions.user.delete`, e);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
if (args._.length < 2) {
|
||||
console.warn('Invalid arguments for : xc permissions.userAdd');
|
||||
return;
|
||||
}
|
||||
|
||||
const { 1: user } = args._;
|
||||
|
||||
/* get all policies */
|
||||
const policiesPath = path.join(
|
||||
process.cwd(),
|
||||
'server',
|
||||
PermissionsMgr.getPolicyPath(),
|
||||
'**',
|
||||
'*.policy.js'
|
||||
);
|
||||
|
||||
glob.sync(policiesPath).forEach(file => {
|
||||
const modelName = path.basename(file).split('.')[0];
|
||||
|
||||
const filePermissions = require(file).permissions;
|
||||
|
||||
const roles = Object.values(filePermissions)
|
||||
.flatMap(methods =>
|
||||
Object.values(methods).flatMap(roles1 => Object.keys(roles1))
|
||||
)
|
||||
.filter((v, i, arr) => arr.indexOf(v) === i);
|
||||
|
||||
if (!roles.includes(user)) {
|
||||
console.warn(`${user} not exist in ${modelName} policy`);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const methods of Object.values(filePermissions)) {
|
||||
for (const roles1 of Object.values(methods)) {
|
||||
delete roles1[user];
|
||||
}
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Deleting user permission for model:${modelName} roles:${user}`
|
||||
);
|
||||
|
||||
const policyFileContent = `module.exports.permissions = ${JSON.stringify(
|
||||
filePermissions,
|
||||
null,
|
||||
2
|
||||
)};\n`;
|
||||
fs.writeFileSync(file, policyFileContent);
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(`Error in xc permissions.user.delete`, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async userRename(args) {
|
||||
if (Util.isProjectGraphql()) {
|
||||
try {
|
||||
if (args._.length < 3) {
|
||||
console.warn('Invalid arguments for : xc permissions.userAdd');
|
||||
return;
|
||||
}
|
||||
|
||||
const { 1: oldUser, 2: newUser } = args._;
|
||||
|
||||
/* get all policies */
|
||||
const policiesPath = path.join(
|
||||
process.cwd(),
|
||||
'server',
|
||||
PermissionsMgr.getPolicyPath(),
|
||||
'**',
|
||||
'*.policy.js'
|
||||
);
|
||||
|
||||
glob.sync(policiesPath).forEach(file => {
|
||||
const modelName = path.basename(file).split('.')[0];
|
||||
|
||||
const filePermissions = require(file).permissions;
|
||||
|
||||
const roles = Object.values(filePermissions)
|
||||
.flatMap(roles1 => Object.keys(roles1))
|
||||
.filter((v, i, arr) => arr.indexOf(v) === i);
|
||||
|
||||
if (!roles.includes(oldUser)) {
|
||||
console.warn(`${oldUser} not exist in ${modelName} policy`);
|
||||
return;
|
||||
}
|
||||
if (roles.includes(newUser)) {
|
||||
console.warn(`${newUser} is already exist in ${modelName} policy`);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const roles1 of Object.values(filePermissions)) {
|
||||
roles1[newUser] = roles1[oldUser];
|
||||
delete roles1[oldUser];
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Renaming user permission ${oldUser} to ${newUser} for model:${modelName}`
|
||||
);
|
||||
const policyFileContent = `module.exports.permissions = ${JSON.stringify(
|
||||
filePermissions,
|
||||
null,
|
||||
2
|
||||
)};\n`;
|
||||
fs.writeFileSync(file, policyFileContent);
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(`Error in xc permissions.user.delete`, e);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
if (args._.length < 3) {
|
||||
console.warn('Invalid arguments for : xc permissions.userAdd');
|
||||
return;
|
||||
}
|
||||
|
||||
const { 1: oldUser, 2: newUser } = args._;
|
||||
|
||||
/* get all policies */
|
||||
const policiesPath = path.join(
|
||||
process.cwd(),
|
||||
'server',
|
||||
PermissionsMgr.getPolicyPath(),
|
||||
'**',
|
||||
'*.policy.js'
|
||||
);
|
||||
|
||||
glob.sync(policiesPath).forEach(file => {
|
||||
const modelName = path.basename(file).split('.')[0];
|
||||
|
||||
const filePermissions = require(file).permissions;
|
||||
|
||||
const roles = Object.values(filePermissions)
|
||||
.flatMap(methods =>
|
||||
Object.values(methods).flatMap(roles1 => Object.keys(roles1))
|
||||
)
|
||||
.filter((v, i, arr) => arr.indexOf(v) === i);
|
||||
|
||||
if (!roles.includes(oldUser)) {
|
||||
console.warn(`${oldUser} not exist in ${modelName} policy`);
|
||||
return;
|
||||
}
|
||||
if (roles.includes(newUser)) {
|
||||
console.warn(`${newUser} is already exist in ${modelName} policy`);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const methods of Object.values(filePermissions)) {
|
||||
for (const roles1 of Object.values(methods)) {
|
||||
roles1[newUser] = roles1[oldUser];
|
||||
delete roles1[oldUser];
|
||||
}
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Renaming user permission ${oldUser} to ${newUser} for model:${modelName}`
|
||||
);
|
||||
const policyFileContent = `module.exports.permissions = ${JSON.stringify(
|
||||
filePermissions,
|
||||
null,
|
||||
2
|
||||
)};\n`;
|
||||
fs.writeFileSync(file, policyFileContent);
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(`Error in xc permissions.user.delete`, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static getPolicyPath() {
|
||||
const projectConfig = jsonfile.readFileSync(
|
||||
path.join(process.cwd(), 'config.xc.json')
|
||||
);
|
||||
return projectConfig.meta.projectType === 'rest' ? 'routers' : 'resolvers';
|
||||
}
|
||||
}
|
||||
|
||||
export default PermissionsMgr;
|
||||
@@ -1,193 +0,0 @@
|
||||
import fs from 'fs';
|
||||
import inquirer from 'inquirer';
|
||||
import open from 'open';
|
||||
import path from 'path';
|
||||
import Locales from '../util/Locales';
|
||||
import socialShareRules from './cliRules.json';
|
||||
import socialText from './SocialText';
|
||||
|
||||
class SocialMgr {
|
||||
public static async share(args) {
|
||||
try {
|
||||
const shareUrl = await SocialMgr.getShareUrl({
|
||||
text: 'A revolutionary API framework with a Desktop App.',
|
||||
type: args.type,
|
||||
url: 'https://NocoDB.com'
|
||||
});
|
||||
open(shareUrl, { wait: true });
|
||||
} catch (e) {
|
||||
console.error(`Error in xc ${args.type}`, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static async shareSocial(_args = {}) {
|
||||
try {
|
||||
const prompt: any = Locales.getPrompt();
|
||||
|
||||
const answer = await inquirer.prompt([
|
||||
{
|
||||
choices: prompt.choices,
|
||||
message: prompt.message,
|
||||
name: 'media',
|
||||
type: 'list'
|
||||
}
|
||||
]);
|
||||
|
||||
switch (answer.media) {
|
||||
case 'Next time':
|
||||
break;
|
||||
|
||||
case 'Please dont ask me':
|
||||
SocialMgr.setShareRules('dontPrompt', true);
|
||||
break;
|
||||
|
||||
case '- - -':
|
||||
break;
|
||||
|
||||
case 'Github - ⭐️ or 👀 repo':
|
||||
open('https://github.com/NocoDB/NocoDB', { wait: true });
|
||||
break;
|
||||
|
||||
default:
|
||||
const text = SocialMgr.getShareText(answer.media);
|
||||
// const url = SocialMgr._getShareContentSuffix(answer.media);
|
||||
const shareUrl = await SocialMgr.getShareUrl({
|
||||
text,
|
||||
type: answer.media,
|
||||
url: 'https://NocoDB.com'
|
||||
});
|
||||
|
||||
open(shareUrl, { wait: true });
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`Error in xc share`, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static getShareUrl({ type, url, text }): any {
|
||||
const encUrl = encodeURIComponent(url);
|
||||
const encText = encodeURIComponent(text);
|
||||
|
||||
console.log(__dirname, process.cwd());
|
||||
|
||||
switch (type) {
|
||||
case 'Twitter':
|
||||
return `https://twitter.com/intent/tweet?url=${encUrl}&text=${encText}&hashtags=xgenecloud`;
|
||||
break;
|
||||
|
||||
case 'Facebook':
|
||||
return `https://www.facebook.com/sharer/sharer.php?u=${encUrl}&title=${encText}&summary=${encText}"e=${encText}&hashtag=%23xgenecloud`;
|
||||
break;
|
||||
|
||||
case 'Linkedin':
|
||||
return `https://www.linkedin.com/shareArticle?mini=true&url=${encUrl}&title=${encText}&summary=${encText}`;
|
||||
break;
|
||||
|
||||
case 'Reddit':
|
||||
return `https://www.reddit.com/submit?url=${encUrl}&title=${encText}`;
|
||||
break;
|
||||
|
||||
case 'WhatsApp':
|
||||
return `https://api.whatsapp.com/send?text=${encText}%0D%0A${encUrl}`;
|
||||
break;
|
||||
|
||||
case 'Telegram':
|
||||
return `https://telegram.me//share/url?url=${encUrl}&text=${encText}`;
|
||||
break;
|
||||
|
||||
case 'Renren':
|
||||
return `http://widget.renren.com/dialog/share?resourceUrl=${encUrl}&srcUrl=${encUrl}&title=${encText}&description=${encText}`;
|
||||
break;
|
||||
|
||||
case 'Line':
|
||||
return `http://line.me/R/msg/text/?${encText}%0D%0A${encUrl}`;
|
||||
break;
|
||||
|
||||
case 'Vk':
|
||||
return `http://vk.com/share.php?url=${encUrl}&title=${encText}&comment=${encText}`;
|
||||
break;
|
||||
|
||||
case '新浪微博':
|
||||
return `http://service.weibo.com/share/share.php?url=${encUrl}&appkey=&title=${encText}&pic=&ralateUid=`;
|
||||
break;
|
||||
|
||||
case '豆瓣':
|
||||
return `http://www.douban.com/recommend/?url=${encUrl}&title=${encText}`;
|
||||
break;
|
||||
|
||||
case 'Wykop':
|
||||
return `https://www.addtoany.com/add_to/wykop?linkurl=${encUrl}&linkname=${encText}`;
|
||||
break;
|
||||
|
||||
case 'OKru':
|
||||
return `https://connect.ok.ru/dk?st.cmd=WidgetSharePreview&st.shareUrl=${encUrl}`;
|
||||
break;
|
||||
|
||||
case 'WeChat':
|
||||
return `https://www.addtoany.com/add_to/wechat?linkurl=${encUrl}&linkname=${encText}`;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static setShareRules(key, value) {
|
||||
socialShareRules[key] = value;
|
||||
fs.writeFileSync(
|
||||
path.join(__dirname, 'cliRules.json'),
|
||||
JSON.stringify(socialShareRules)
|
||||
);
|
||||
}
|
||||
|
||||
public static setCreatedApis(value) {
|
||||
if (socialShareRules.dontPrompt) {
|
||||
return;
|
||||
}
|
||||
socialShareRules.createdApis = value;
|
||||
socialShareRules.prompt = value;
|
||||
fs.writeFileSync(
|
||||
path.join(__dirname, 'cliRules.json'),
|
||||
JSON.stringify(socialShareRules)
|
||||
);
|
||||
}
|
||||
|
||||
public static async showPrompt() {
|
||||
try {
|
||||
if (
|
||||
socialShareRules.createdApis &&
|
||||
socialShareRules.prompt &&
|
||||
!socialShareRules.dontPrompt
|
||||
) {
|
||||
await SocialMgr.shareSocial();
|
||||
SocialMgr.setShareRules('prompt', false);
|
||||
}
|
||||
} catch (e) {
|
||||
/* ignore any error while showing social prompt*/
|
||||
}
|
||||
}
|
||||
|
||||
public static getShareText(socialMediaType) {
|
||||
return (
|
||||
SocialMgr._getShareContentPrefix(socialMediaType) +
|
||||
SocialMgr._getShareContentMid(socialMediaType) +
|
||||
SocialMgr._getShareContentSuffix(socialMediaType)
|
||||
);
|
||||
}
|
||||
|
||||
public static _getShareContentPrefix(_socialMediaType) {
|
||||
return socialText.prefix[
|
||||
Math.floor(Math.random() * socialText.prefix.length)
|
||||
];
|
||||
}
|
||||
|
||||
public static _getShareContentMid(_socialMediaType) {
|
||||
return socialText.mid[Math.floor(Math.random() * socialText.mid.length)];
|
||||
}
|
||||
|
||||
public static _getShareContentSuffix(_socialMediaType) {
|
||||
return socialText.suffix[
|
||||
Math.floor(Math.random() * socialText.suffix.length)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
export default SocialMgr;
|
||||
@@ -1,97 +0,0 @@
|
||||
export default {
|
||||
mid: [
|
||||
'\n@NocoDB - generates instant REST/GraphQL API on any database.\n+ Has GUI based schema migrations!\n+ Built in API-Client and terminal!\n+ Dark theme and much more!\n'
|
||||
],
|
||||
prefix: [
|
||||
'Super slick!',
|
||||
'Very handy!',
|
||||
'Impressive!',
|
||||
'Awesome!',
|
||||
'Excited & happy to see this idea!',
|
||||
'What an awesome idea!',
|
||||
'Pretty Awesome!',
|
||||
'Amazing!',
|
||||
'Phenomenal!',
|
||||
'Incredible!',
|
||||
'Fantastic!',
|
||||
'Great!',
|
||||
'Mind blowing!',
|
||||
'Very Cool!',
|
||||
'Stellar!',
|
||||
'Neat!',
|
||||
'Exciting!',
|
||||
'Brilliant!',
|
||||
'Extremely Interesting!',
|
||||
'So useful!',
|
||||
|
||||
'Wow, Super slick!',
|
||||
'Wow, Very handy!',
|
||||
'Wow, Impressive!',
|
||||
'Wow, Awesome!',
|
||||
'Wow, Excited & happy to see this idea!',
|
||||
'Wow, What an awesome idea!',
|
||||
'Wow, Pretty Awesome!',
|
||||
'Wow, Amazing!',
|
||||
'Wow, Phenomenal!',
|
||||
'Wow, Incredible!',
|
||||
'Wow, Fantastic!',
|
||||
'Wow, Great!',
|
||||
'Wow, Mind blowing!',
|
||||
'Wow, Very Cool!',
|
||||
'Wow, Stellar!',
|
||||
'Wow, Neat!',
|
||||
'Wow, Exciting!',
|
||||
'Wow, Brilliant!',
|
||||
'Wow, Extremely Interesting!',
|
||||
'Wow, So useful!',
|
||||
|
||||
'Woah, Super slick!',
|
||||
'Woah, Very handy!',
|
||||
'Woah, Impressive!',
|
||||
'Woah, Awesome!',
|
||||
'Woah, Excited & happy to see this idea!',
|
||||
'Woah, What an awesome idea!',
|
||||
'Woah, Pretty Awesome!',
|
||||
'Woah, Amazing!',
|
||||
'Woah, Phenomenal!',
|
||||
'Woah, Incredible!',
|
||||
'Woah, Fantastic!',
|
||||
'Woah, Great!',
|
||||
'Woah, Mind blowing!',
|
||||
'Woah, Very Cool!',
|
||||
'Woah, Stellar!',
|
||||
'Woah, Neat!',
|
||||
'Woah, Exciting!',
|
||||
'Woah, Brilliant!',
|
||||
'Woah, Extremely Interesting!',
|
||||
'Woah, So useful!',
|
||||
|
||||
'Super slick API Framework!',
|
||||
'Very handy API Framework!',
|
||||
'Impressive API Framework!',
|
||||
'Awesome API Framework!',
|
||||
'Excited & happy to see this API Framework!',
|
||||
'What an awesome API Framework!',
|
||||
'Pretty Awesome API Framework!',
|
||||
'Amazing API Framework!',
|
||||
'Phenomenal API Framework!',
|
||||
'Incredible API Framework!',
|
||||
'Fantastic API Framework!',
|
||||
'Great API Framework!',
|
||||
'Mind blowing API Framework!',
|
||||
'Very Cool API Framework!',
|
||||
'Stellar API Framework!',
|
||||
'Neat API Framework!',
|
||||
'Exciting API Framework!',
|
||||
'Brilliant API Framework!',
|
||||
'Extremely Interesting API Framework!',
|
||||
'So useful API Framework',
|
||||
|
||||
'Cool Stuff!',
|
||||
'Woha!',
|
||||
|
||||
"I'm amazed by how well this works!",
|
||||
"I'm impressed by how well this works!"
|
||||
],
|
||||
suffix: ['https://github.com/nocodb/nocodb', 'www.nocodb.com']
|
||||
};
|
||||
@@ -1,287 +0,0 @@
|
||||
import chalkPipe from 'chalk-pipe';
|
||||
import inquirer from 'inquirer';
|
||||
import path from 'path';
|
||||
import tcpPortUsed from 'tcp-port-used';
|
||||
import URL from 'url';
|
||||
import Lang, { STR } from '../util/Lang';
|
||||
import Util from '../util/Util';
|
||||
|
||||
import('colors');
|
||||
|
||||
const dbDefaults = {
|
||||
mysql2: {
|
||||
host: 'localhost',
|
||||
port: '3306',
|
||||
username: 'root',
|
||||
password: '',
|
||||
database: ''
|
||||
},
|
||||
pg: {
|
||||
host: 'localhost',
|
||||
port: '5432',
|
||||
username: 'postgres',
|
||||
password: '',
|
||||
database: ''
|
||||
},
|
||||
mssql: {
|
||||
host: 'localhost',
|
||||
port: '1433',
|
||||
username: 'sa',
|
||||
password: '',
|
||||
database: ''
|
||||
},
|
||||
sqlite3: {
|
||||
host: 'localhost',
|
||||
port: '1433',
|
||||
username: 'sa',
|
||||
password: '',
|
||||
database: ''
|
||||
}
|
||||
};
|
||||
|
||||
class TryMgr {
|
||||
/**
|
||||
*
|
||||
* Does the below :
|
||||
* - Get database input and make a DB URL from it.
|
||||
* - Create new folder and 'cd' to that folder.
|
||||
* - Return true/success
|
||||
* - Else failure
|
||||
*
|
||||
* @param args
|
||||
* @returns {Promise<string|string|boolean|*>}
|
||||
*/
|
||||
public static async getProjectInput(args): Promise<any> {
|
||||
let dbUrl;
|
||||
|
||||
if (args._[0] !== 't' && args._[0] !== 'try') {
|
||||
if (args._[1] === 'rest') {
|
||||
dbUrl = `sqlite3://sqlite3?d=${path.join(__dirname, 'sakila.db')}`;
|
||||
} else if (args._[1] === 'gql') {
|
||||
dbUrl = `sqlite3://sqlite3?d=${path.join(
|
||||
__dirname,
|
||||
'sakila.db'
|
||||
)}&api=graphql`;
|
||||
}
|
||||
} else {
|
||||
/* Construct database URL from prompt */
|
||||
const dbTypes = Object.keys(dbDefaults);
|
||||
args.url = [];
|
||||
|
||||
const finalAnswers = await inquirer.prompt([
|
||||
{
|
||||
name: 'type',
|
||||
type: 'list',
|
||||
message: Lang.getString(STR.DB_TYPE), // '🔥 Choose SQL Database type\t:',
|
||||
choices: dbTypes.map(t => ({
|
||||
name: t,
|
||||
value: t,
|
||||
short: t.green.bold
|
||||
})),
|
||||
default: 'mysql2',
|
||||
transformer(color) {
|
||||
return chalkPipe(color)(color.green.bold);
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'host',
|
||||
type: 'input',
|
||||
message: Lang.getString(STR.DB_HOST), // '👉 Enter database host name\t:',
|
||||
default(ans) {
|
||||
return dbDefaults[ans.type].host;
|
||||
},
|
||||
transformer(color) {
|
||||
return chalkPipe(color)(color.green.bold);
|
||||
},
|
||||
when({ type }) {
|
||||
return type !== 'sqlite3';
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'port',
|
||||
type: 'number',
|
||||
message: Lang.getString(STR.DB_PORT), // '👉 Enter database port number\t:',
|
||||
default(ans) {
|
||||
return dbDefaults[ans.type].port;
|
||||
},
|
||||
transformer(color) {
|
||||
try {
|
||||
return color.green.bold;
|
||||
} catch (e) {
|
||||
return color;
|
||||
}
|
||||
},
|
||||
validate(port, answers) {
|
||||
const done = this.async();
|
||||
if (
|
||||
answers.host === 'host.docker.internal' ||
|
||||
answers.host === 'docker.for.win.localhost'
|
||||
) {
|
||||
done(null, true);
|
||||
} else {
|
||||
TryMgr.isPortOpen(answers.host, port)
|
||||
.then(isOpen => {
|
||||
if (isOpen) {
|
||||
done(null, true);
|
||||
} else {
|
||||
// done('Port is not open')
|
||||
console.log(
|
||||
`\n\n😩 ${answers.host}:${port} is not open please start the database if you haven't\n`
|
||||
.red.bold
|
||||
);
|
||||
process.exit(0);
|
||||
}
|
||||
})
|
||||
.catch(done);
|
||||
}
|
||||
},
|
||||
when({ type }) {
|
||||
return type !== 'sqlite3';
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'username',
|
||||
type: 'input',
|
||||
message: Lang.getString(STR.DB_USER), // '👉 Enter database username\t:',
|
||||
default(ans) {
|
||||
return dbDefaults[ans.type].username;
|
||||
},
|
||||
transformer(color) {
|
||||
return chalkPipe(color)(color.green.bold);
|
||||
},
|
||||
when({ type }) {
|
||||
return type !== 'sqlite3';
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'password',
|
||||
type: 'input',
|
||||
mask: true,
|
||||
message: Lang.getString(STR.DB_PASSWORD), // '🙈 Enter database password\t:',
|
||||
transformer(color) {
|
||||
return new Array(color.length).fill('*'.green.bold).join('');
|
||||
},
|
||||
when({ type }) {
|
||||
return type !== 'sqlite3';
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'database',
|
||||
type: 'input',
|
||||
message: Lang.getString(STR.DB_SCHEMA), // '👉 Enter database/schema name\t:',
|
||||
transformer(color) {
|
||||
return chalkPipe(color)(color.green.bold);
|
||||
},
|
||||
when({ type }) {
|
||||
return type !== 'sqlite3';
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'apiType',
|
||||
type: 'list',
|
||||
message: Lang.getString(STR.DB_API), // '🚀 Enter API type to generate\t:',
|
||||
choices: ['REST APIs', 'GRAPHQL APIs', 'gRPC APIs'].map(t => ({
|
||||
name: t,
|
||||
value: t,
|
||||
short: t.green.bold
|
||||
})),
|
||||
transformer(color) {
|
||||
return chalkPipe(color)(color.green.bold);
|
||||
},
|
||||
when({ type }) {
|
||||
return type !== 'sqlite3';
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
// console.log(finalAnswers);
|
||||
|
||||
if (finalAnswers.type === 'sqlite3') {
|
||||
console.log(
|
||||
'Please use desktop app to create Sqlite project'.green.bold
|
||||
);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
/* if not valid retry getting right input */
|
||||
/* if (!finalAnswers.database) {
|
||||
console.log('\n\tWarning! Database name can NOT be empty. Retry.\n '.red.bold);
|
||||
this.getNewProjectInput(args);
|
||||
}*/
|
||||
//
|
||||
|
||||
/* prepare the args */
|
||||
// const url = `${finalAnswers.type}://${finalAnswers.host}:${finalAnswers.port}?u=${finalAnswers.username}&p=${finalAnswers.password}&d=${finalAnswers.database}&api=${apiTypeMapping[finalAnswers.projectType]}`;
|
||||
// args._[0] = finalAnswers.projectType === 'REST APIs' ? 'gar' : 'gag';
|
||||
switch (finalAnswers.apiType) {
|
||||
case 'REST APIs':
|
||||
finalAnswers.apiType = 'rest';
|
||||
break;
|
||||
case 'GRAPHQL APIs':
|
||||
finalAnswers.apiType = 'graphql';
|
||||
break;
|
||||
case 'gRPC APIs':
|
||||
finalAnswers.apiType = 'grpc';
|
||||
break;
|
||||
default:
|
||||
finalAnswers.apiType = 'rest';
|
||||
break;
|
||||
}
|
||||
dbUrl = `${finalAnswers.type}://${finalAnswers.host}:${finalAnswers.port}?u=${finalAnswers.username}&p=${finalAnswers.password}&d=${finalAnswers.database}&api=${finalAnswers.apiType}`;
|
||||
}
|
||||
// await Util.runCmd(`cd ${__dirname};echo "const {XcTry} = require('xc-instant'); process.env.NC_DB_URL='${finalAnswers.dbUrl}'; XcTry().then(() => console.log('App started'));" | node`);
|
||||
await Util.runCmd(
|
||||
`echo "const {XcTry} = require('xc-instant'); XcTry('${dbUrl}').then(() => console.log('App started'));" | NODE_PATH=${path.join(
|
||||
__dirname,
|
||||
'..',
|
||||
'node_modules'
|
||||
)} node`
|
||||
);
|
||||
}
|
||||
|
||||
public static async testConnection({ url }) {
|
||||
for (const u of url) {
|
||||
const parsedUrlData = URL.parse(u, true);
|
||||
const queryParams = parsedUrlData.query;
|
||||
const client = parsedUrlData.protocol.slice(0, -1);
|
||||
const config = {
|
||||
client,
|
||||
connection: {
|
||||
database:
|
||||
client === 'pg'
|
||||
? 'postgres'
|
||||
: client === 'mssql'
|
||||
? undefined
|
||||
: null,
|
||||
host: parsedUrlData.hostname,
|
||||
password: queryParams.p,
|
||||
port: +parsedUrlData.port,
|
||||
user: queryParams.u
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
const knex = require('knex')(config);
|
||||
await knex.raw('SELECT 1+1 as data');
|
||||
} catch (e) {
|
||||
console.log(`\n😩 Test connection failed for : ${url}\n`.red.bold);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static async isPortOpen(host, port) {
|
||||
try {
|
||||
return await tcpPortUsed.check(+port, host);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
console.log(
|
||||
`\n😩 ${host}:${port} is not reachable please check\n`.red.bold
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default TryMgr;
|
||||
@@ -1,166 +0,0 @@
|
||||
import axios from 'axios';
|
||||
import download from 'download';
|
||||
import osInfo from 'linux-os-info';
|
||||
import open from 'open';
|
||||
import ora from 'ora';
|
||||
import os from 'os';
|
||||
import shell from 'shelljs';
|
||||
|
||||
import('colors');
|
||||
|
||||
const PROGRESS_WIDTH = 30;
|
||||
|
||||
class AppMgr {
|
||||
public static async install(args) {
|
||||
try {
|
||||
const spinner = ora({
|
||||
text: 'Downloading Desktop App from Github..'.green.bold(),
|
||||
spinner: 'dots2',
|
||||
color: 'green'
|
||||
}).start();
|
||||
const { src, dest } = await AppMgr.getDownloadLink(args);
|
||||
|
||||
console.log(`\t${src}`);
|
||||
|
||||
await download(src, '.').on('downloadProgress', progress => {
|
||||
// console.log(progress)
|
||||
// Report download progress
|
||||
const p = PROGRESS_WIDTH * progress.percent;
|
||||
spinner.text = `Downloading Desktop App now..\n[${Array.from(
|
||||
{ length: PROGRESS_WIDTH },
|
||||
(_, i) => (i <= p ? '=' : ' ')
|
||||
).join('')}] ${(progress.transferred / (1024 * 1024)).toFixed(2)}MB/${(
|
||||
progress.total /
|
||||
(1024 * 1024)
|
||||
).toFixed(2)}MB\n`.green.bold();
|
||||
});
|
||||
// spinner.prefixText = '';
|
||||
spinner.succeed(
|
||||
`Installable downloaded successfully at ./${dest}`.green.bold()
|
||||
);
|
||||
console.log(`\nInstallable will open automatically now.`.green.bold);
|
||||
console.log(`If not, please install it manually.`.green.bold);
|
||||
if (os.type() === 'Windows_NT') {
|
||||
// open(dest, {wait: true, app: 'explorer.exe'})
|
||||
} else {
|
||||
open(dest, { wait: true });
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`Error in xc app.install`, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static async open(args) {
|
||||
try {
|
||||
const runCommand = AppMgr.getOpenCommand(args);
|
||||
if (!runCommand) {
|
||||
return;
|
||||
}
|
||||
if (shell.exec(runCommand).code !== 0) {
|
||||
shell.echo(`\n\nError running command internally`.red);
|
||||
shell.echo(`\nExiting...`.red);
|
||||
shell.exit(1);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`Error in xc app.open`, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static async getDownloadLink(args): Promise<any> {
|
||||
try {
|
||||
let src;
|
||||
let dest;
|
||||
const urls: any = {};
|
||||
|
||||
const res = await axios.get(
|
||||
'https://api.github.com/repos/xgenecloud/xc-desktop-app/releases?page=1'
|
||||
);
|
||||
|
||||
let status = 0;
|
||||
|
||||
for (let i = 0; i < res.data.length && status !== 15; i++) {
|
||||
const assets = res.data[i].assets;
|
||||
for (const { name, browser_download_url } of assets) {
|
||||
switch (
|
||||
name
|
||||
.split('.')
|
||||
.pop()
|
||||
.toLowerCase()
|
||||
) {
|
||||
case 'dmg':
|
||||
urls.dmg = urls.dmg || browser_download_url;
|
||||
status = status | 1;
|
||||
break;
|
||||
case 'deb':
|
||||
urls.deb = urls.deb || browser_download_url;
|
||||
status = status | 2;
|
||||
break;
|
||||
case 'rpm':
|
||||
urls.rpm = urls.rpm || browser_download_url;
|
||||
status = status | 4;
|
||||
break;
|
||||
case 'exe':
|
||||
urls.exe = urls.exe || browser_download_url;
|
||||
status = status | 8;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (os.type()) {
|
||||
case 'Linux':
|
||||
const linuxInfo = osInfo({ mode: 'sync' });
|
||||
if (args.debian) {
|
||||
src = urls.deb;
|
||||
} else if (args.rpm) {
|
||||
src = urls.rpm;
|
||||
} else {
|
||||
switch (linuxInfo.id) {
|
||||
case 'ubuntu':
|
||||
case 'raspberry':
|
||||
src = urls.deb;
|
||||
break;
|
||||
case 'fedora':
|
||||
src = urls.rpm;
|
||||
break;
|
||||
default:
|
||||
src = urls.rpm;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'Darwin':
|
||||
src = urls.dmg;
|
||||
break;
|
||||
case 'Windows_NT':
|
||||
src = urls.exe;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
dest = src.split('/').pop();
|
||||
return { src, dest };
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static getOpenCommand(_args): any {
|
||||
switch (os.type()) {
|
||||
case 'Linux':
|
||||
return 'xgenecloud';
|
||||
break;
|
||||
case 'Darwin':
|
||||
return 'open -a xgenecloud';
|
||||
break;
|
||||
case 'Windows_NT':
|
||||
console.info('Open xgenecloud desktop app from Windows start menu');
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default AppMgr;
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"prompt": false,
|
||||
"dontPrompt": false,
|
||||
"createdApis": false,
|
||||
"firstTimeUse": true,
|
||||
"promptForStar": false,
|
||||
"dontPromptForStar": true,
|
||||
"cliUsedCount": 0
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
/**
|
||||
* Heirarchical conversation example
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
import inquirer from 'inquirer';
|
||||
|
||||
class RunOrDownload {
|
||||
public static async prepareCmd(ipc, args) {
|
||||
args._[0] = '';
|
||||
|
||||
const answers = await inquirer.prompt([
|
||||
{
|
||||
choices: ['gen', 'add', 'show', 'run'],
|
||||
message: 'What do you want to do?',
|
||||
name: 'action',
|
||||
type: 'rawlist'
|
||||
}
|
||||
]);
|
||||
|
||||
args._[0] = answers.action;
|
||||
|
||||
switch (answers.action) {
|
||||
case 'gen':
|
||||
await this.handleGen(ipc, args);
|
||||
break;
|
||||
|
||||
case 'add':
|
||||
break;
|
||||
|
||||
case 'show':
|
||||
break;
|
||||
|
||||
case 'run':
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static async handleGen(_ipc, args) {
|
||||
const a1 = await inquirer.prompt([
|
||||
{
|
||||
choices: [
|
||||
'apis',
|
||||
'backend',
|
||||
'block',
|
||||
'controller',
|
||||
'middleware',
|
||||
'service',
|
||||
'resolver',
|
||||
'type',
|
||||
'schema',
|
||||
'apis'
|
||||
],
|
||||
message: 'What do you want to generate ?',
|
||||
name: 'action',
|
||||
pageSize: 9,
|
||||
type: 'rawlist'
|
||||
}
|
||||
]);
|
||||
|
||||
args._[0] += `:${a1.action}`;
|
||||
|
||||
switch (a1.action) {
|
||||
case 'apis':
|
||||
const a2 = await inquirer.prompt([
|
||||
{
|
||||
choices: ['rest', 'graphql'],
|
||||
message: 'Which apis you want to use?',
|
||||
name: 'action',
|
||||
type: 'rawlist'
|
||||
}
|
||||
]);
|
||||
|
||||
args._[0] += `:${a2.action}`;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// tslint:disable-next-line:no-empty
|
||||
public static async handleAdd() {}
|
||||
|
||||
// tslint:disable-next-line:no-empty
|
||||
public static async handleShow() {}
|
||||
|
||||
// tslint:disable-next-line:no-empty
|
||||
public static async handleRun() {}
|
||||
}
|
||||
|
||||
export default RunOrDownload;
|
||||
@@ -1,32 +0,0 @@
|
||||
/**
|
||||
* Heirarchical conversation example
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
import inquirer from 'inquirer';
|
||||
|
||||
class RunOrDownload {
|
||||
public static async handle(_args) {
|
||||
const answers = await inquirer.prompt([
|
||||
{
|
||||
choices: ['Open the app!', 'Download it for FREE'],
|
||||
message: 'Your XGENE desktop app is not open - do you want to ?',
|
||||
name: 'action',
|
||||
type: 'rawlist'
|
||||
}
|
||||
]);
|
||||
|
||||
switch (answers.action) {
|
||||
case 'Open app!':
|
||||
break;
|
||||
|
||||
case 'Download it for FREE':
|
||||
console.log(
|
||||
'wget(https://xgene.cloud/download?latest=true) to Downloads'
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default RunOrDownload;
|
||||
@@ -1,145 +0,0 @@
|
||||
import osLocale from 'os-locale';
|
||||
import english from './english.json';
|
||||
import translated from './translated.json';
|
||||
|
||||
/* Converted from : https://smodin.me/translate-one-text-into-multiple-languages
|
||||
* Enter database host name || Choose SQL Database type || Enter database username || Enter database password || Enter database port number || Enter database/schema name || Enter API type to generate || How do you want to run it
|
||||
* */
|
||||
|
||||
const formattedTranslate: any = {};
|
||||
for (const { symbol, text } of [english, ...translated].sort((a, b) =>
|
||||
a.symbol.localeCompare(b.symbol)
|
||||
)) {
|
||||
formattedTranslate[symbol] = text.split(/\s*\|\|\s*/);
|
||||
}
|
||||
|
||||
const dummy: any = new Date();
|
||||
const offset: any = -dummy.getTimezoneOffset();
|
||||
const locale: string = offset === 330 ? 'en-IN' : osLocale.sync();
|
||||
|
||||
const SMILEY_PREFIX = ['👉', '🔥', '👉', '🙈', '👉', '👉', '🚀', '🚀'];
|
||||
|
||||
enum STR {
|
||||
DB_HOST,
|
||||
DB_TYPE,
|
||||
DB_USER,
|
||||
DB_PASSWORD,
|
||||
DB_PORT,
|
||||
DB_SCHEMA,
|
||||
DB_API,
|
||||
PROJECT_TYPE
|
||||
}
|
||||
|
||||
class Lang {
|
||||
// @ts-ignore
|
||||
public static getString(str: STR) {
|
||||
switch (locale) {
|
||||
case 'en':
|
||||
case 'en-GB':
|
||||
case 'en-AU':
|
||||
case 'en-CA':
|
||||
case 'en-IE':
|
||||
case 'en-US':
|
||||
default:
|
||||
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.en?.[str]}\t:`;
|
||||
|
||||
case 'zh':
|
||||
case 'zh-Hans':
|
||||
case 'zh-CN':
|
||||
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.['zh-cn']?.[str]}\t:`;
|
||||
|
||||
case 'zh-Hant':
|
||||
case 'zh-HK':
|
||||
case 'zh-TW':
|
||||
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.['zh-tw']?.[str]}\t:`;
|
||||
|
||||
case 'de':
|
||||
case 'de-DE':
|
||||
case 'de-CH':
|
||||
case 'de-AT':
|
||||
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.de?.[str]}\t:`;
|
||||
case 'el':
|
||||
case 'el-GR':
|
||||
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.el?.[str]}\t:`;
|
||||
|
||||
case 'es':
|
||||
case 'es-AR':
|
||||
case 'es-419':
|
||||
case 'es-CL':
|
||||
case 'es-CO':
|
||||
case 'es-EC':
|
||||
case 'es-ES':
|
||||
case 'es-LA':
|
||||
case 'es-NI':
|
||||
case 'es-MX':
|
||||
case 'es-US':
|
||||
case 'es-VE':
|
||||
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.es?.[str]}\t:`;
|
||||
|
||||
case 'fi':
|
||||
case 'fi-FI':
|
||||
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.fi?.[str]}\t:`;
|
||||
|
||||
case 'fr':
|
||||
case 'fr-CA':
|
||||
case 'fr-FR':
|
||||
case 'fr-BE':
|
||||
case 'fr-CH':
|
||||
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.fr?.[str]}\t:`;
|
||||
|
||||
case 'it':
|
||||
case 'it-IT':
|
||||
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.it?.[str]}\t:`;
|
||||
|
||||
case 'ja':
|
||||
case 'ja-JP':
|
||||
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.ja?.[str]}\t:`;
|
||||
|
||||
case 'ko':
|
||||
case 'ko-KR':
|
||||
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.ko?.[str]}\t:`;
|
||||
|
||||
case 'nl':
|
||||
case 'nl-BE':
|
||||
case 'nl-NL':
|
||||
case 'nn-NO':
|
||||
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.nl?.[str]}\t:`;
|
||||
|
||||
case 'pt':
|
||||
case 'pt-BR':
|
||||
case 'pt-PT':
|
||||
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.pt?.[str]}\t:`;
|
||||
|
||||
case 'ru':
|
||||
case 'ru-RU':
|
||||
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.ru?.[str]}\t:`;
|
||||
|
||||
case 'sv':
|
||||
case 'sv-SE':
|
||||
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.sv?.[str]}\t:`;
|
||||
|
||||
case 'th':
|
||||
case 'th-TH':
|
||||
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.th?.[str]}\t:`;
|
||||
|
||||
case 'tl':
|
||||
case 'tl-PH':
|
||||
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.tl?.[str]}\t:`;
|
||||
|
||||
case 'tr':
|
||||
case 'tr-TR':
|
||||
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.tr?.[str]}\t:`;
|
||||
|
||||
case 'uk':
|
||||
case 'uk-UA':
|
||||
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.uk?.[str]}\t:`;
|
||||
|
||||
case 'vi':
|
||||
case 'vi-VN':
|
||||
return `${SMILEY_PREFIX[str]} ${formattedTranslate?.vi?.[str]}\t:`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Lang;
|
||||
export { STR };
|
||||
@@ -1,552 +0,0 @@
|
||||
import osLocale from 'os-locale';
|
||||
|
||||
class Locales {
|
||||
public static getPrompt() {
|
||||
const x = new Date();
|
||||
const offset = -x.getTimezoneOffset();
|
||||
|
||||
let prompt = {};
|
||||
|
||||
const locale = offset === 330 ? 'en-IN' : osLocale.sync();
|
||||
switch (locale) {
|
||||
case 'en':
|
||||
case 'en-GB':
|
||||
case 'en-AU':
|
||||
case 'en-CA':
|
||||
case 'en-IE':
|
||||
case 'en-US':
|
||||
default:
|
||||
prompt = {
|
||||
choices: [
|
||||
'Twitter',
|
||||
'Github - ⭐️ or 👀 repo',
|
||||
'Linkedin',
|
||||
'Facebook',
|
||||
'WhatsApp',
|
||||
'Telegram',
|
||||
'Reddit',
|
||||
'Next time',
|
||||
'Please dont ask me',
|
||||
'- - - - - - - -'
|
||||
],
|
||||
language: 'English',
|
||||
message: '\n\n👋 Hello! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
|
||||
.green
|
||||
};
|
||||
break;
|
||||
|
||||
case 'zh':
|
||||
case 'zh-Hans':
|
||||
case 'zh-Hant':
|
||||
case 'zh-CN':
|
||||
case 'zh-HK':
|
||||
case 'zh-SG':
|
||||
case 'zh-TW':
|
||||
prompt = {
|
||||
choices: [
|
||||
'WeChat',
|
||||
'Github - ⭐️ or 👀 repo',
|
||||
'豆瓣', // douban
|
||||
'新浪微博', // weibo
|
||||
'Renren',
|
||||
'Line',
|
||||
'Telegram',
|
||||
'Next time',
|
||||
'Please dont ask me',
|
||||
'- - - - - - - -'
|
||||
],
|
||||
language: 'Chinese',
|
||||
message: '\n\n👋 你好! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
|
||||
.green
|
||||
};
|
||||
break;
|
||||
|
||||
case 'en-IN':
|
||||
prompt = {
|
||||
choices: [
|
||||
'Twitter',
|
||||
'Github - ⭐️ or 👀 repo',
|
||||
'WhatsApp',
|
||||
'Linkedin',
|
||||
'Facebook',
|
||||
'Telegram',
|
||||
'Next time',
|
||||
'Please dont ask me',
|
||||
'- - - - - - - -'
|
||||
],
|
||||
language: 'English (India)',
|
||||
message: '\n\n👋 Hello / नमस्ते / ನ ಮ ಸ್ಕಾ ರ / ന മ സ് കാ രം / வணக்கம்! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
|
||||
.green
|
||||
};
|
||||
break;
|
||||
|
||||
case 'de':
|
||||
case 'de-DE':
|
||||
case 'de-CH':
|
||||
case 'de-AT':
|
||||
prompt = {
|
||||
choices: [
|
||||
'Twitter',
|
||||
'Github - ⭐️ or 👀 repo',
|
||||
'Linkedin',
|
||||
'Reddit',
|
||||
'Facebook',
|
||||
'WhatsApp',
|
||||
'Telegram',
|
||||
'Next time',
|
||||
'Please dont ask me',
|
||||
'- - - - - - - -'
|
||||
],
|
||||
language: 'German',
|
||||
message: '\n\n👋 Hallo! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
|
||||
.green
|
||||
};
|
||||
break;
|
||||
|
||||
case 'el':
|
||||
case 'el-GR':
|
||||
prompt = {
|
||||
choices: [
|
||||
'Twitter',
|
||||
'Github - ⭐️ or 👀 repo',
|
||||
'Linkedin',
|
||||
// 'Reddit',
|
||||
'Facebook',
|
||||
'WhatsApp',
|
||||
'Telegram',
|
||||
'Next time',
|
||||
'Please dont ask me',
|
||||
'- - - - - - - -'
|
||||
],
|
||||
language: 'Greek',
|
||||
message: '\n\n👋 Γειά σου! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
|
||||
.green
|
||||
};
|
||||
break;
|
||||
|
||||
case 'es':
|
||||
case 'es-AR':
|
||||
case 'es-419':
|
||||
case 'es-CL':
|
||||
case 'es-CO':
|
||||
case 'es-EC':
|
||||
case 'es-ES':
|
||||
case 'es-LA':
|
||||
case 'es-NI':
|
||||
case 'es-MX':
|
||||
case 'es-US':
|
||||
case 'es-VE':
|
||||
prompt = {
|
||||
choices: [
|
||||
'Twitter',
|
||||
'Github - ⭐️ or 👀 repo',
|
||||
'Linkedin',
|
||||
// 'Reddit',
|
||||
'Facebook',
|
||||
'WhatsApp',
|
||||
'Telegram',
|
||||
'Next time',
|
||||
'Please dont ask me',
|
||||
'- - - - - - - -'
|
||||
],
|
||||
language: 'Spanish',
|
||||
message: '\n\n👋 Hola! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
|
||||
.green
|
||||
};
|
||||
break;
|
||||
|
||||
case 'fa':
|
||||
case 'fa-IR':
|
||||
prompt = {
|
||||
choices: [
|
||||
'Twitter',
|
||||
'Github - ⭐️ or 👀 repo',
|
||||
'Linkedin',
|
||||
// 'Reddit',
|
||||
'Facebook',
|
||||
'WhatsApp',
|
||||
'Telegram',
|
||||
'Next time',
|
||||
'Please dont ask me',
|
||||
'- - - - - - - -'
|
||||
],
|
||||
language: 'Persian',
|
||||
message: '\n\n👋 سلام! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
|
||||
.green
|
||||
};
|
||||
break;
|
||||
|
||||
case 'fi':
|
||||
case 'fi-FI':
|
||||
prompt = {
|
||||
choices: [
|
||||
'Twitter',
|
||||
'Github - ⭐️ or 👀 repo',
|
||||
'Linkedin',
|
||||
// 'Reddit',
|
||||
'Facebook',
|
||||
'WhatsApp',
|
||||
'Telegram',
|
||||
'Next time',
|
||||
'Please dont ask me',
|
||||
'- - - - - - - -'
|
||||
],
|
||||
language: 'Finnish',
|
||||
message: '\n\n👋 سلام! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
|
||||
.green
|
||||
};
|
||||
break;
|
||||
|
||||
case 'fr':
|
||||
case 'fr-CA':
|
||||
case 'fr-FR':
|
||||
case 'fr-BE':
|
||||
case 'fr-CH':
|
||||
prompt = {
|
||||
choices: [
|
||||
'Twitter',
|
||||
'Github - ⭐️ or 👀 repo',
|
||||
'Linkedin',
|
||||
// 'Reddit',
|
||||
'Facebook',
|
||||
'WhatsApp',
|
||||
'Telegram',
|
||||
'Next time',
|
||||
'Please dont ask me',
|
||||
'- - - - - - - -'
|
||||
],
|
||||
language: 'French',
|
||||
message: '\n\n👋 Bonjour! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
|
||||
.green
|
||||
};
|
||||
break;
|
||||
|
||||
case 'ga':
|
||||
case 'ga-IE':
|
||||
prompt = {
|
||||
choices: [
|
||||
'Twitter',
|
||||
'Github - ⭐️ or 👀 repo',
|
||||
'Linkedin',
|
||||
// 'Reddit',
|
||||
'Facebook',
|
||||
'WhatsApp',
|
||||
'Telegram',
|
||||
'Next time',
|
||||
'Please dont ask me',
|
||||
'- - - - - - - -'
|
||||
],
|
||||
language: 'Irish',
|
||||
message: '\n\n👋 Dia dhuit! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
|
||||
.green
|
||||
};
|
||||
break;
|
||||
|
||||
case 'he':
|
||||
case 'he-IL':
|
||||
prompt = {
|
||||
choices: [
|
||||
'Twitter',
|
||||
'Github - ⭐️ or 👀 repo',
|
||||
'Linkedin',
|
||||
// 'Reddit',
|
||||
'Facebook',
|
||||
'WhatsApp',
|
||||
'Telegram',
|
||||
'Next time',
|
||||
'Please dont ask me',
|
||||
'- - - - - - - -'
|
||||
],
|
||||
language: 'Hebrew',
|
||||
message: '\n\n👋 שלום! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
|
||||
.green
|
||||
};
|
||||
break;
|
||||
|
||||
case 'it':
|
||||
case 'it-IT':
|
||||
prompt = {
|
||||
choices: [
|
||||
'Twitter',
|
||||
'Github - ⭐️ or 👀 repo',
|
||||
'Linkedin',
|
||||
// 'Reddit',
|
||||
'Facebook',
|
||||
'WhatsApp',
|
||||
'Telegram',
|
||||
'Next time',
|
||||
'Please dont ask me',
|
||||
'- - - - - - - -'
|
||||
],
|
||||
language: 'Italian',
|
||||
message: '\n\n👋 Ciao! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
|
||||
.green
|
||||
};
|
||||
break;
|
||||
|
||||
case 'ja':
|
||||
case 'ja-JP':
|
||||
prompt = {
|
||||
choices: [
|
||||
'Twitter',
|
||||
'Github - ⭐️ or 👀 repo',
|
||||
'Line',
|
||||
'Linkedin',
|
||||
// 'Reddit',
|
||||
'Facebook',
|
||||
'WhatsApp',
|
||||
'WeChat',
|
||||
'Telegram',
|
||||
'Next time',
|
||||
'Please dont ask me',
|
||||
'- - - - - - - -'
|
||||
],
|
||||
language: 'Japanese',
|
||||
message: '\n\n👋 こんにちは! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
|
||||
.green
|
||||
};
|
||||
break;
|
||||
|
||||
case 'ko':
|
||||
case 'ko-KR':
|
||||
prompt = {
|
||||
choices: [
|
||||
'Twitter',
|
||||
'Github - ⭐️ or 👀 repo',
|
||||
'Line',
|
||||
'Linkedin',
|
||||
// 'Reddit',
|
||||
'Facebook',
|
||||
'WhatsApp',
|
||||
'WeChat',
|
||||
'豆瓣', // douban
|
||||
'新浪微博', // weibo
|
||||
'Telegram',
|
||||
'Next time',
|
||||
'Please dont ask me',
|
||||
'- - - - - - - -'
|
||||
],
|
||||
language: 'Korean',
|
||||
message: '\n\n👋 여보세요! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
|
||||
.green
|
||||
};
|
||||
break;
|
||||
|
||||
case 'mn-MN':
|
||||
prompt = {
|
||||
choices: [
|
||||
'Twitter',
|
||||
'Github - ⭐️ or 👀 repo',
|
||||
'Linkedin',
|
||||
// 'Reddit',
|
||||
'Facebook',
|
||||
'WhatsApp',
|
||||
'Next time',
|
||||
'Please dont ask me',
|
||||
'- - - - - - - -'
|
||||
],
|
||||
language: 'Mongolian',
|
||||
message: '\n\n👋 Сайн уу! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
|
||||
.green
|
||||
};
|
||||
break;
|
||||
|
||||
case 'nl':
|
||||
case 'nl-BE':
|
||||
case 'nl-NL':
|
||||
case 'nn-NO':
|
||||
prompt = {
|
||||
choices: [
|
||||
'Twitter',
|
||||
'Github - ⭐️ or 👀 repo',
|
||||
'Linkedin',
|
||||
// 'Reddit',
|
||||
'Facebook',
|
||||
'WhatsApp',
|
||||
'Next time',
|
||||
'Please dont ask me',
|
||||
'- - - - - - - -'
|
||||
],
|
||||
language: 'Dutch',
|
||||
message: '\n\n👋 Hallo! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
|
||||
.green
|
||||
};
|
||||
break;
|
||||
|
||||
case 'pt':
|
||||
case 'pt-BR':
|
||||
case 'pt-PT':
|
||||
prompt = {
|
||||
choices: [
|
||||
'Twitter',
|
||||
'Github - ⭐️ or 👀 repo',
|
||||
'Linkedin',
|
||||
// 'Reddit',
|
||||
'Facebook',
|
||||
'WhatsApp',
|
||||
'Next time',
|
||||
'Please dont ask me',
|
||||
'- - - - - - - -'
|
||||
],
|
||||
language: 'Portuguese',
|
||||
message: '\n\n👋 Olá! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
|
||||
.green
|
||||
};
|
||||
break;
|
||||
|
||||
case 'ru':
|
||||
case 'ru-RU':
|
||||
prompt = {
|
||||
choices: [
|
||||
'Twitter',
|
||||
'Github - ⭐️ or 👀 repo',
|
||||
'OKru',
|
||||
'Telegram',
|
||||
'Linkedin',
|
||||
'Vk',
|
||||
'Wykop',
|
||||
'Facebook',
|
||||
'WhatsApp',
|
||||
'Next time',
|
||||
'Please dont ask me',
|
||||
'- - - - - - - -'
|
||||
],
|
||||
language: 'Russian',
|
||||
message: '\n\n👋 Здравствуйте! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
|
||||
.green
|
||||
};
|
||||
break;
|
||||
|
||||
case 'sv':
|
||||
case 'sv-SE':
|
||||
prompt = {
|
||||
choices: [
|
||||
'Twitter',
|
||||
'Github - ⭐️ or 👀 repo',
|
||||
'Linkedin',
|
||||
// 'Reddit',
|
||||
'Facebook',
|
||||
'WhatsApp',
|
||||
'WeChat',
|
||||
'Please dont ask me',
|
||||
'- - - - - - - -'
|
||||
],
|
||||
language: 'Swedish',
|
||||
message: '\n\n👋 Hej! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
|
||||
.green
|
||||
};
|
||||
break;
|
||||
|
||||
case 'th':
|
||||
case 'th-TH':
|
||||
prompt = {
|
||||
choices: [
|
||||
'Twitter',
|
||||
'Github - ⭐️ or 👀 repo',
|
||||
'Linkedin',
|
||||
// 'Reddit',
|
||||
'Facebook',
|
||||
'WhatsApp',
|
||||
'Telegram',
|
||||
'Next time',
|
||||
'Please dont ask me',
|
||||
'- - - - - - - -'
|
||||
],
|
||||
language: 'Thai',
|
||||
message: '\n\n👋 สวัสดี! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
|
||||
.green
|
||||
};
|
||||
break;
|
||||
|
||||
case 'tl':
|
||||
case 'tl-PH':
|
||||
prompt = {
|
||||
choices: [
|
||||
'Twitter',
|
||||
'Github - ⭐️ or 👀 repo',
|
||||
'Linkedin',
|
||||
// 'Reddit',
|
||||
'Facebook',
|
||||
'WhatsApp',
|
||||
'WeChat',
|
||||
'Telegram',
|
||||
'Please dont ask me',
|
||||
'- - - - - - - -'
|
||||
],
|
||||
language: 'Filipino',
|
||||
message: '\n\n👋 Kamusta! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
|
||||
.green
|
||||
};
|
||||
break;
|
||||
|
||||
case 'tr':
|
||||
case 'tr-TR':
|
||||
prompt = {
|
||||
choices: [
|
||||
'Twitter',
|
||||
'Github - ⭐️ or 👀 repo',
|
||||
'Linkedin',
|
||||
// 'Reddit',
|
||||
'Facebook',
|
||||
'WhatsApp',
|
||||
'Telegram',
|
||||
'Please dont ask me',
|
||||
'- - - - - - - -'
|
||||
],
|
||||
language: 'Turkish',
|
||||
message: '\n\n👋 Merhaba! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
|
||||
.green
|
||||
};
|
||||
break;
|
||||
|
||||
case 'uk':
|
||||
case 'uk-UA':
|
||||
prompt = {
|
||||
choices: [
|
||||
'Twitter',
|
||||
'Github - ⭐️ or 👀 repo',
|
||||
'OKru',
|
||||
// 'Reddit',
|
||||
'Linkedin',
|
||||
'Facebook',
|
||||
'WhatsApp',
|
||||
'Telegram',
|
||||
'Vk',
|
||||
'Wykop',
|
||||
'Next time',
|
||||
'Please dont ask me',
|
||||
'- - - - - - - -'
|
||||
],
|
||||
language: 'Ukrainian',
|
||||
message: '\n\n👋 Здравствуйте! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
|
||||
.green
|
||||
};
|
||||
break;
|
||||
|
||||
case 'vi':
|
||||
case 'vi-VN':
|
||||
prompt = {
|
||||
choices: [
|
||||
'Twitter',
|
||||
'Github - ⭐️ or 👀 repo',
|
||||
'Linkedin',
|
||||
// 'Reddit',
|
||||
'Facebook',
|
||||
'WhatsApp',
|
||||
'WeChat',
|
||||
'Telegram',
|
||||
'Please dont ask me',
|
||||
'- - - - - - - -'
|
||||
],
|
||||
language: 'Vietnamese',
|
||||
message: '\n\n👋 xin chào! 😀 \n\n🔥 Loving XgenCloud? 🔥\n\n🙏 Please mention a word about us to your friends & followers. 🙏\n\n'
|
||||
.green
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
return prompt;
|
||||
}
|
||||
}
|
||||
|
||||
export default Locales;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +0,0 @@
|
||||
export default {
|
||||
port: 23917
|
||||
};
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"language": "English",
|
||||
"symbol": "en",
|
||||
"text": "Enter database host name || Choose SQL Database type || Enter database username || Enter database password || Enter database port number || Enter database/schema name || Enter API type to generate || How do you want to run it"
|
||||
}
|
||||
@@ -1,237 +0,0 @@
|
||||
[
|
||||
{
|
||||
"language": "Arabic",
|
||||
"symbol": "ar",
|
||||
"text": "أدخل اسم مضيف قاعدة البيانات || اختر نوع قاعدة بيانات SQL || أدخل اسم مستخدم قاعدة البيانات || أدخل كلمة مرور قاعدة البيانات || أدخل رقم منفذ قاعدة البيانات || أدخل اسم قاعدة البيانات / المخطط || أدخل نوع API لإنشاء || كيف تريد تشغيله"
|
||||
},
|
||||
{
|
||||
"language": "Dutch",
|
||||
"symbol": "nl",
|
||||
"text": "Voer de hostnaam van de database || in Kies SQL-databasetype || Voer de database-gebruikersnaam in || Voer het databasewachtwoord in || Voer het poortnummer van de database in || Voer de database- / schemanaam in || Voer het API-type in om || te genereren Hoe wil je het uitvoeren?"
|
||||
},
|
||||
{
|
||||
"language": "French",
|
||||
"symbol": "fr",
|
||||
"text": "Entrez le nom d'hôte de la base de données || Choisissez le type de base de données SQL || Entrez le nom d'utilisateur de la base de données || Entrez le mot de passe de la base de données || Entrez le numéro de port de la base de données || Entrez le nom de la base de données / du schéma || Entrez le type d'API à générer || Comment voulez-vous l'exécuter"
|
||||
},
|
||||
{
|
||||
"language": "German",
|
||||
"symbol": "de",
|
||||
"text": "Geben Sie den Datenbank-Hostnamen || ein Wählen Sie den SQL-Datenbanktyp || Geben Sie den Datenbank-Benutzernamen || ein Geben Sie das Datenbankkennwort || ein Geben Sie die Datenbankportnummer || ein Geben Sie den Datenbank- / Schemanamen || ein Geben Sie den zu generierenden API-Typ || ein Wie möchten Sie es ausführen?"
|
||||
},
|
||||
{
|
||||
"language": "Italian",
|
||||
"symbol": "it",
|
||||
"text": "Immettere il nome host del database || Scegli il tipo di database SQL || Immettere il nome utente del database || Immettere la password del database || Immettere il numero di porta del database || Immettere il nome del database / schema || Inserisci il tipo di API da generare || Come vuoi eseguirlo"
|
||||
},
|
||||
{
|
||||
"language": "Japanese",
|
||||
"symbol": "ja",
|
||||
"text": "データベースのホスト名を入力してください|| SQLデータベースタイプを選択||データベースのユーザー名を入力してください||データベースのパスワードを入力してください||データベースのポート番号を入力してください||データベース/スキーマ名を入力してください||生成するAPIタイプを入力してください||どのように実行しますか"
|
||||
},
|
||||
{
|
||||
"language": "Russian",
|
||||
"symbol": "ru",
|
||||
"text": "Введите имя хоста базы данных || Выберите тип базы данных SQL || Введите имя пользователя базы данных || Введите пароль базы данных || Введите номер порта базы данных || Введите имя базы данных / схемы || Введите тип API для генерации || Как ты хочешь запустить это"
|
||||
},
|
||||
{
|
||||
"language": "Spanish",
|
||||
"symbol": "es",
|
||||
"text": "Ingrese el nombre de host de la base de datos || Elija el tipo de base de datos SQL || Ingrese el nombre de usuario de la base de datos || Ingrese la contraseña de la base de datos || Ingrese el número de puerto de la base de datos || Ingrese el nombre de la base de datos / esquema || Ingrese el tipo de API para generar || ¿Cómo quieres ejecutarlo?"
|
||||
},
|
||||
{
|
||||
"language": "Catalan",
|
||||
"symbol": "ca",
|
||||
"text": "Introduïu el nom de l'amfitrió de la base de dades || Trieu el tipus de base de dades SQL || Introduïu el nom d'usuari de la base de dades || Introduïu la contrasenya de la base de dades || Introduïu el número de port de la base de dades || Introduïu el nom de la base de dades / esquema || Introduïu el tipus d'API per generar || Com voleu executar-lo"
|
||||
},
|
||||
{
|
||||
"language": "Czech",
|
||||
"symbol": "cs",
|
||||
"text": "Zadejte název hostitele databáze || Vyberte typ databáze SQL || Zadejte uživatelské jméno databáze || Zadejte heslo do databáze || Zadejte číslo portu databáze || Zadejte název databáze / schématu || Zadejte typ API pro generování || Jak to chcete spustit?"
|
||||
},
|
||||
{
|
||||
"language": "Estonian",
|
||||
"symbol": "et",
|
||||
"text": "Sisestage andmebaasi hosti nimi || Valige SQL-i andmebaasi tüüp || Sisestage andmebaasi kasutajanimi || Sisestage andmebaasi parool || Sisestage andmebaasi pordi number || Sisestage andmebaasi / skeemi nimi || Sisestage genereerimiseks API tüüp || Kuidas soovite seda käivitada"
|
||||
},
|
||||
{
|
||||
"language": "Lithuanian",
|
||||
"symbol": "lt",
|
||||
"text": "Įveskite duomenų bazės pavadinimą || Pasirinkite SQL duomenų bazės tipą || Įveskite duomenų bazės vartotojo vardą || Įveskite duomenų bazės slaptažodį || Įveskite duomenų bazės prievado numerį || Įveskite duomenų bazės / schemos pavadinimą || Norėdami sugeneruoti įveskite API tipą Kaip norite jį paleisti"
|
||||
},
|
||||
{
|
||||
"language": "Norwegian",
|
||||
"symbol": "no",
|
||||
"text": "Skriv inn databasens vertsnavn || Velg SQL Database type || Skriv inn brukernavn for databasen || Skriv inn databasepassordet || Skriv inn databaseportnummer || Skriv inn navnet på databasen / skjemaet || Angi API-type for å generere || Hvordan vil du kjøre den"
|
||||
},
|
||||
{
|
||||
"language": "Telugu",
|
||||
"symbol": "te",
|
||||
"text": "డేటాబేస్ హోస్ట్ పేరును నమోదు చేయండి || SQL డేటాబేస్ రకాన్ని ఎంచుకోండి || డేటాబేస్ వినియోగదారు పేరును నమోదు చేయండి || డేటాబేస్ పాస్వర్డ్ను నమోదు చేయండి || డేటాబేస్ పోర్ట్ సంఖ్యను నమోదు చేయండి || డేటాబేస్ / స్కీమా పేరును నమోదు చేయండి || ఉత్పత్తి చేయడానికి API రకాన్ని నమోదు చేయండి || మీరు దీన్ని ఎలా అమలు చేయాలనుకుంటున్నారు"
|
||||
},
|
||||
{
|
||||
"language": "Urdu",
|
||||
"symbol": "ur",
|
||||
"text": "ڈیٹا بیس کے میزبان کا نام درج کریں || ایس کیو ایل ڈیٹا بیس کی قسم منتخب کریں || ڈیٹا بیس کا صارف نام داخل کریں || ڈیٹا بیس پاس ورڈ درج کریں || ڈیٹا بیس پورٹ نمبر درج کریں || ڈیٹا بیس / اسکیمہ کا نام درج کریں || پیدا کرنے کے لئے API کی قسم درج کریں || آپ اسے کیسے چلانا چاہتے ہیں؟"
|
||||
},
|
||||
{
|
||||
"language": "Chinese Simplified",
|
||||
"symbol": "zh-cn",
|
||||
"text": "输入数据库主机名||选择SQL数据库类型||输入数据库用户名||输入数据库密码||输入数据库端口号||输入数据库/方案名称||输入API类型以生成||您想如何运行它"
|
||||
},
|
||||
{
|
||||
"language": "Danish",
|
||||
"symbol": "da",
|
||||
"text": "Indtast databasens værtsnavn || Vælg SQL-databasetype || Indtast database brugernavn || Indtast adgangskode til databasen || Indtast databaseportnummer || Indtast database / skema navn || Indtast API-type for at generere || Hvordan vil du køre det"
|
||||
},
|
||||
{
|
||||
"language": "Filipino",
|
||||
"symbol": "tl",
|
||||
"text": "Ipasok ang pangalan ng host ng database || Piliin ang uri ng SQL Database || Ipasok ang username ng database || Ipasok ang database ng password || Ipasok ang numero ng port ng database || Ipasok ang pangalan ng database / schema || Ipasok ang uri ng API upang makabuo || Paano mo ito nais patakbuhin"
|
||||
},
|
||||
{
|
||||
"language": "Greek",
|
||||
"symbol": "el",
|
||||
"text": "Εισαγάγετε το όνομα κεντρικού υπολογιστή βάσης δεδομένων || Επιλέξτε τύπο βάσης δεδομένων SQL || Εισαγάγετε το όνομα χρήστη της βάσης δεδομένων || Εισαγάγετε τον κωδικό πρόσβασης βάσης δεδομένων || Εισαγάγετε τον αριθμό θύρας βάσης δεδομένων || Εισαγάγετε όνομα βάσης δεδομένων / σχήματος || Εισαγάγετε τον τύπο API για δημιουργία || Πώς θέλετε να το εκτελέσετε"
|
||||
},
|
||||
{
|
||||
"language": "Malay",
|
||||
"symbol": "ms",
|
||||
"text": "Masukkan nama host pangkalan data || Pilih jenis Pangkalan Data SQL || Masukkan nama pengguna pangkalan data || Masukkan kata laluan pangkalan data || Masukkan nombor port pangkalan data || Masukkan nama pangkalan data / skema || Masukkan jenis API untuk menghasilkan || Bagaimana anda mahu menjalankannya"
|
||||
},
|
||||
{
|
||||
"language": "Polish",
|
||||
"symbol": "pl",
|
||||
"text": "Wpisz nazwę hosta bazy danych || Wybierz typ bazy danych SQL || Wpisz nazwę użytkownika bazy danych || Wprowadź hasło do bazy danych || Wpisz numer portu bazy danych || Wpisz nazwę bazy danych / schematu || Wpisz typ API do wygenerowania || Jak chcesz to uruchomić"
|
||||
},
|
||||
{
|
||||
"language": "Serbian",
|
||||
"symbol": "sr",
|
||||
"text": "Унесите име хоста базе података || Изаберите тип базе података СКЛ || Унесите корисничко име базе података || Унесите лозинку базе података || Унесите број порта базе података || Унесите име базе података / шеме || Унесите тип АПИ-ја за генерисање || Како желите да га покренете"
|
||||
},
|
||||
{
|
||||
"language": "Swedish",
|
||||
"symbol": "sv",
|
||||
"text": "Ange databasvärdnamn || Välj SQL-databastyp || Ange databasens användarnamn || Ange databaslösenord || Ange databasportnummer || Ange databas / schemans namn || Ange API-typ för att generera || Hur vill du köra den"
|
||||
},
|
||||
{
|
||||
"language": "Thai",
|
||||
"symbol": "th",
|
||||
"text": "ป้อนชื่อโฮสต์ฐานข้อมูล || เลือกประเภทฐานข้อมูล SQL || ป้อนชื่อผู้ใช้ฐานข้อมูล || ป้อนรหัสผ่านฐานข้อมูล || ป้อนหมายเลขพอร์ตฐานข้อมูล || ป้อนฐานข้อมูล / ชื่อสคีมา || ป้อนประเภท API เพื่อสร้าง || คุณต้องการเรียกใช้อย่างไร"
|
||||
},
|
||||
{
|
||||
"language": "Bengali",
|
||||
"symbol": "bn",
|
||||
"text": "ডাটাবেস হোস্টের নাম প্রবেশ করান || এসকিউএল ডাটাবেস টাইপ চয়ন করুন || ডাটাবেস ব্যবহারকারীর নাম লিখুন || ডাটাবেস পাসওয়ার্ড প্রবেশ করান || ডাটাবেস পোর্ট নম্বর লিখুন || ডাটাবেস / স্কিমা নাম প্রবেশ করান || উত্পন্ন করতে এপিআই টাইপ লিখুন || আপনি এটি চালাতে চান কিভাবে"
|
||||
},
|
||||
{
|
||||
"language": "Chinese Traditional",
|
||||
"symbol": "zh-tw",
|
||||
"text": "輸入數據庫主機名||選擇SQL數據庫類型||輸入數據庫用戶名||輸入數據庫密碼||輸入數據庫端口號||輸入數據庫/方案名稱||輸入API類型以生成||您想如何運行它"
|
||||
},
|
||||
{
|
||||
"language": "Finnish",
|
||||
"symbol": "fi",
|
||||
"text": "Syötä tietokannan isäntänimi || Valitse SQL-tietokannan tyyppi || Syötä tietokannan käyttäjänimi || Syötä tietokannan salasana || Syötä tietokannan porttinumero || Syötä tietokannan / skeeman nimi || Syötä API-tyyppi luodaksesi || Kuinka haluat suorittaa sen"
|
||||
},
|
||||
{
|
||||
"language": "Korean",
|
||||
"symbol": "ko",
|
||||
"text": "데이터베이스 호스트 이름 입력 || SQL 데이터베이스 유형 선택 || 데이터베이스 사용자 이름 입력 || 데이터베이스 비밀번호를 입력하세요 || 데이터베이스 포트 번호를 입력하세요 || 데이터베이스 / 스키마 이름 입력 || 생성 할 API 유형을 입력하세요 || 어떻게 실행 하시겠습니까"
|
||||
},
|
||||
{
|
||||
"language": "Hebrew",
|
||||
"symbol": "iw",
|
||||
"text": "הזן את שם מארח מסד הנתונים || בחר סוג מסד נתונים של SQL || הזן את שם המשתמש של מסד הנתונים || הזן סיסמת מסד נתונים || הזן מספר יציאת מסד נתונים || הזן שם מסד נתונים / סכמה || הזן סוג API ליצירת || איך אתה רוצה להפעיל אותו"
|
||||
},
|
||||
{
|
||||
"language": "Malayalam",
|
||||
"symbol": "ml",
|
||||
"text": "ഡാറ്റാബേസ് ഹോസ്റ്റ് നാമം നൽകുക || SQL ഡാറ്റാബേസ് തരം തിരഞ്ഞെടുക്കുക || ഡാറ്റാബേസ് ഉപയോക്തൃനാമം നൽകുക || ഡാറ്റാബേസ് പാസ്വേഡ് നൽകുക || ഡാറ്റാബേസ് പോർട്ട് നമ്പർ നൽകുക || ഡാറ്റാബേസ് / സ്കീമ നാമം നൽകുക || ജനറേറ്റുചെയ്യാൻ API തരം നൽകുക || ഇത് എങ്ങനെ പ്രവർത്തിപ്പിക്കാൻ നിങ്ങൾ ആഗ്രഹിക്കുന്നു"
|
||||
},
|
||||
{
|
||||
"language": "Portuguese",
|
||||
"symbol": "pt",
|
||||
"text": "Insira o nome do host do banco de dados || Escolha o tipo de banco de dados SQL || Digite o nome de usuário do banco de dados || Digite a senha do banco de dados || Insira o número da porta do banco de dados || Insira o nome do banco de dados / esquema || Digite o tipo de API para gerar || Como você deseja executá-lo?"
|
||||
},
|
||||
{
|
||||
"language": "Slovak",
|
||||
"symbol": "sk",
|
||||
"text": "Zadajte názov hostiteľa databázy || Vyberte typ databázy SQL || Zadajte užívateľské meno databázy || Zadajte heslo do databázy || Zadajte číslo portu databázy || Zadajte názov databázy / schémy || Zadajte typ API na vygenerovanie || Ako to chcete spustiť"
|
||||
},
|
||||
{
|
||||
"language": "Tajik",
|
||||
"symbol": "tg",
|
||||
"text": "Номи ҳости пойгоҳи додаҳоро ворид кунед || Намуди пойгоҳи SQL-ро интихоб кунед || Номи корбари пойгоҳи додаҳоро ворид кунед || Пароли махзани маълумотро ворид кунед || Рақами порти базаи маълумотро ворид кунед || Номи пойгоҳи додаҳо / схемаро ворид кунед || Барои тавлиди || навъи API -ро ворид кунед Чӣ гуна шумо мехоҳед онро иҷро кунед"
|
||||
},
|
||||
{
|
||||
"language": "Turkish",
|
||||
"symbol": "tr",
|
||||
"text": "Veritabanı ana bilgisayar adını girin || SQL Veritabanı türünü seçin || Veritabanı kullanıcı adını girin || Veritabanı şifresini girin || Veritabanı port numarasını girin || Veritabanı / şema adını girin || Oluşturmak için API türünü girin || Onu nasıl çalıştırmak istersin"
|
||||
},
|
||||
{
|
||||
"language": "Vietnamese",
|
||||
"symbol": "vi",
|
||||
"text": "Nhập tên máy chủ cơ sở dữ liệu || Chọn kiểu cơ sở dữ liệu SQL || Nhập tên người dùng cơ sở dữ liệu || Nhập mật khẩu cơ sở dữ liệu || Nhập số cổng cơ sở dữ liệu || Nhập tên cơ sở dữ liệu / lược đồ || Nhập loại API để tạo || Bạn muốn chạy nó như thế nào"
|
||||
},
|
||||
{
|
||||
"language": "Bulgarian",
|
||||
"symbol": "bg",
|
||||
"text": "Въведете име на хост на базата данни || Изберете тип база данни на SQL || Въведете потребителско име на базата данни || Въведете парола за база данни || Въведете номера на порта на базата данни || Въведете име на база данни / схема || Въведете API тип, за да генерирате || Как искате да го стартирате"
|
||||
},
|
||||
{
|
||||
"language": "Croatian",
|
||||
"symbol": "hr",
|
||||
"text": "Unesite ime hosta baze podataka || Odaberite vrstu baze podataka SQL || Unesite korisničko ime baze podataka || Unesite lozinku baze podataka || Unesite broj porta baze podataka || Unesite naziv baze podataka / sheme || Unesite vrstu API-ja za generiranje || Kako to želite pokrenuti"
|
||||
},
|
||||
{
|
||||
"language": "Esperanto",
|
||||
"symbol": "eo",
|
||||
"text": "Enigu datumbazan gastigantan nomon || Elektu SQL-Datumbazan tipon || Enigu datumbazan uzantnomon || Enigu datumbazan pasvorton || Enigu datuman datumportan numeron || Enigu datumbazon / skeman nomon || Enigu API-tipon por generi || Kiel vi volas funkciigi ĝin"
|
||||
},
|
||||
{
|
||||
"language": "Indonesian",
|
||||
"symbol": "id",
|
||||
"text": "Masukkan nama host database || Pilih tipe Database SQL || Masukkan nama pengguna database || Masukkan kata sandi basis data || Masukkan nomor port database || Masukkan nama database / skema || Masukkan jenis API untuk menghasilkan || Bagaimana Anda ingin menjalankannya"
|
||||
},
|
||||
{
|
||||
"language": "Latvian",
|
||||
"symbol": "lv",
|
||||
"text": "Ievadiet datubāzes resursdatora nosaukumu || Izvēlieties SQL datu bāzes tipu || Ievadiet datubāzes lietotājvārdu || Ievadiet datu bāzes paroli || Ievadiet datubāzes porta numuru || Ievadiet datu bāzes / shēmas nosaukumu || Ievadiet API veidu, lai izveidotu || Kā jūs vēlaties to vadīt"
|
||||
},
|
||||
{
|
||||
"language": "Marathi",
|
||||
"symbol": "mr",
|
||||
"text": "डेटाबेस होस्ट नाव प्रविष्ट करा || एसक्यूएल डेटाबेस प्रकार निवडा || डेटाबेस वापरकर्तानाव प्रविष्ट करा || डेटाबेस संकेतशब्द प्रविष्ट करा || डेटाबेस पोर्ट क्रमांक प्रविष्ट करा || डेटाबेस / स्कीमा नाव प्रविष्ट करा || व्युत्पन्न करण्यासाठी एपीआय प्रकार प्रविष्ट करा || आपल्याला ते कसे चालवायचे आहे"
|
||||
},
|
||||
{
|
||||
"language": "Romanian",
|
||||
"symbol": "ro",
|
||||
"text": "Introduceți numele gazdei bazei de date || Alegeți tipul bazei de date SQL || Introduceți numele de utilizator al bazei de date || Introduceți parola bazei de date || Introduceți numărul portului bazei de date || Introduceți numele bazei de date / schemei || Introduceți tipul API pentru a genera || Cum vrei să-l rulezi"
|
||||
},
|
||||
{
|
||||
"language": "Slovenian",
|
||||
"symbol": "sl",
|
||||
"text": "Vnesite ime gostitelja baze podatkov || Izberite vrsto zbirke podatkov SQL || Vnesite uporabniško ime baze podatkov || Vnesite geslo baze podatkov || Vnesite številko vrat baze podatkov || Vnesite ime baze podatkov / sheme || Vnesite vrsto API-ja za ustvarjanje || Kako ga želite zagnati"
|
||||
},
|
||||
{
|
||||
"language": "Tamil",
|
||||
"symbol": "ta",
|
||||
"text": "தரவுத்தள ஹோஸ்ட் பெயரை உள்ளிடவும் || SQL தரவுத்தள வகையைத் தேர்வுசெய்க || தரவுத்தள பயனர்பெயரை உள்ளிடவும் || தரவுத்தள கடவுச்சொல்லை உள்ளிடவும் || தரவுத்தள போர்ட் எண்ணை உள்ளிடவும் || தரவுத்தளம் / ஸ்கீமா பெயரை உள்ளிடவும் || உருவாக்க API வகையை உள்ளிடவும் || அதை எவ்வாறு இயக்க விரும்புகிறீர்கள்"
|
||||
},
|
||||
{
|
||||
"language": "Ukrainian",
|
||||
"symbol": "uk",
|
||||
"text": "Введіть ім'я хоста бази даних || Виберіть тип бази даних SQL || Введіть ім'я користувача бази даних || Введіть пароль бази даних || Введіть номер порту бази даних || Введіть назву бази даних / схеми || Введіть тип API для створення || Як ви хочете його запустити"
|
||||
},
|
||||
{
|
||||
"language": "Kannada",
|
||||
"symbol": "kn",
|
||||
"text": "ಡೇಟಾಬೇಸ್ ಹೋಸ್ಟ್ ಹೆಸರನ್ನು ನಮೂದಿಸಿ || SQL ಡೇಟಾಬೇಸ್ ಪ್ರಕಾರವನ್ನು ಆರಿಸಿ || ಡೇಟಾಬೇಸ್ ಬಳಕೆದಾರಹೆಸರನ್ನು ನಮೂದಿಸಿ || ಡೇಟಾಬೇಸ್ ಪಾಸ್ವರ್ಡ್ ಅನ್ನು ನಮೂದಿಸಿ || ಡೇಟಾಬೇಸ್ ಪೋರ್ಟ್ ಸಂಖ್ಯೆಯನ್ನು ನಮೂದಿಸಿ || ಡೇಟಾಬೇಸ್ / ಸ್ಕೀಮಾ ಹೆಸರನ್ನು ನಮೂದಿಸಿ || ಉತ್ಪಾದಿಸಲು API ಪ್ರಕಾರವನ್ನು ನಮೂದಿಸಿ || ನೀವು ಅದನ್ನು ಹೇಗೆ ಚಲಾಯಿಸಲು ಬಯಸುತ್ತೀರಿ"
|
||||
},
|
||||
{
|
||||
"language": "Hindi",
|
||||
"symbol": "hi",
|
||||
"text": "डेटाबेस होस्ट नाम दर्ज करें || SQL डेटाबेस प्रकार चुनें || डेटाबेस उपयोगकर्ता नाम दर्ज करें || डेटाबेस पासवर्ड दर्ज करें || डेटाबेस पोर्ट नंबर दर्ज करें || डेटाबेस / स्कीमा नाम दर्ज करें || बनाने के लिए एपीआई प्रकार दर्ज करें || आप इसे कैसे चलाना चाहते हैं"
|
||||
}
|
||||
]
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,46 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2017",
|
||||
"outDir": "build/main",
|
||||
"rootDir": "src",
|
||||
"moduleResolution": "node",
|
||||
"module": "commonjs",
|
||||
"declaration": false,
|
||||
"inlineSourceMap": true,
|
||||
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
|
||||
|
||||
// "strict": true /* Enable all strict type-checking options. */,
|
||||
|
||||
/* Strict Type-Checking Options */
|
||||
// "noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
|
||||
// "strictNullChecks": true /* Enable strict null checks. */,
|
||||
// "strictFunctionTypes": true /* Enable strict checking of function types. */,
|
||||
// "strictPropertyInitialization": true /* Enable strict checking of property initialization in classes. */,
|
||||
// "noImplicitThis": true /* Raise error on 'this' expressions with an implied 'any' type. */,
|
||||
// "alwaysStrict": true /* Parse in strict mode and emit "use strict" for each source file. */,
|
||||
|
||||
/* Additional Checks */
|
||||
"noUnusedLocals": true /* Report errors on unused locals. */,
|
||||
"noUnusedParameters": true /* Report errors on unused parameters. */,
|
||||
"noImplicitReturns": true /* Report error when not all code paths in function return a value. */,
|
||||
"noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */,
|
||||
|
||||
/* Debugging Options */
|
||||
"traceResolution": false /* Report module resolution log messages. */,
|
||||
"listEmittedFiles": false /* Print names of generated files part of the compilation. */,
|
||||
"listFiles": false /* Print names of files part of the compilation. */,
|
||||
"pretty": true /* Stylize errors and messages using color and context. */,
|
||||
"resolveJsonModule": true,
|
||||
/* Experimental Options */
|
||||
// "experimentalDecorators": true /* Enables experimental support for ES7 decorators. */,
|
||||
// "emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */,
|
||||
|
||||
"lib": ["es2017","es2015"],
|
||||
"types": ["node"],
|
||||
"typeRoots": ["node_modules/@types", "src/types"]
|
||||
},
|
||||
|
||||
"include": ["src/**/*.ts"],
|
||||
"exclude": ["node_modules/**"],
|
||||
"compileOnSave": false
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"extends": "./tsconfig",
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"outDir": "build/module",
|
||||
"module": "esnext"
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules/**"
|
||||
]
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
{
|
||||
"extends": [
|
||||
"tslint:latest",
|
||||
"tslint-config-prettier",
|
||||
"tslint-immutable"
|
||||
],
|
||||
"rules": {
|
||||
"interface-name": [
|
||||
true,
|
||||
"never-prefix"
|
||||
],
|
||||
// TODO: allow devDependencies only in **/*.spec.ts files:
|
||||
// waiting on https://github.com/palantir/tslint/pull/3708
|
||||
"no-implicit-dependencies": [
|
||||
true,
|
||||
"dev"
|
||||
],
|
||||
/* tslint-immutable rules */
|
||||
// Recommended built-in rules
|
||||
"no-var-keyword": true,
|
||||
"no-parameter-reassignment": true,
|
||||
// "typedef": [
|
||||
// true,
|
||||
// "call-signature"
|
||||
// ],
|
||||
// Immutability rules
|
||||
// "readonly-keyword": true,
|
||||
// "readonly-array": true,
|
||||
// "no-let": true,
|
||||
// "no-object-mutation": true,
|
||||
// "no-delete": true,
|
||||
"no-method-signature": true,
|
||||
"no-console": false,
|
||||
// Functional style rules
|
||||
// "no-this": true,
|
||||
// "no-class": true,
|
||||
"no-mixed-interface": true,
|
||||
"no-bitwise": false,
|
||||
"variable-name": false
|
||||
// "no-expression-statement": [
|
||||
// true,
|
||||
// { "ignore-prefix": ["console.", "process.exit"] }
|
||||
// ],
|
||||
// "no-if-statement": true
|
||||
/* end tslint-immutable rules */
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
const nodeExternals = require('webpack-node-externals');
|
||||
// const CopyPlugin = require('copy-webpack-plugin');
|
||||
//
|
||||
// const TerserPlugin = require('terser-webpack-plugin');
|
||||
const webpack = require('webpack');
|
||||
// const JavaScriptObfuscator = require('webpack-obfuscator');
|
||||
const path = require('path');
|
||||
module.exports = {
|
||||
entry: './src/index.ts',
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
exclude: /node_modules/,
|
||||
use: {
|
||||
loader: 'ts-loader',
|
||||
options: {
|
||||
transpileOnly: true
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
optimization: {
|
||||
minimize: false, //Update this to true or false
|
||||
// minimizer: [new TerserPlugin()],
|
||||
nodeEnv: false
|
||||
},
|
||||
externals: [nodeExternals()],
|
||||
resolve: {
|
||||
extensions: ['.tsx', '.ts', '.js', '.json'],
|
||||
},
|
||||
output: {
|
||||
filename: 'bundle.js',
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
library: 'libs',
|
||||
libraryTarget: 'umd',
|
||||
globalObject: "typeof self !== 'undefined' ? self : this",
|
||||
},
|
||||
// node: {
|
||||
// fs: 'empty'
|
||||
// },
|
||||
plugins: [
|
||||
new webpack.BannerPlugin({banner: "#! /usr/bin/env node", raw: true}),
|
||||
],
|
||||
|
||||
target: 'node',
|
||||
};
|
||||
@@ -7,8 +7,6 @@ hide_table_of_contents: true
|
||||
|
||||
We use ``Lerna`` to manage multi-packages. We have the following [packages](https://github.com/nocodb/nocodb/tree/master/packages).
|
||||
|
||||
- ``packages/nc-cli`` : A CLI to create NocoDB app.
|
||||
|
||||
- ``packages/nocodb-sdk``: API client sdk of nocodb.
|
||||
|
||||
- ``packages/nc-gui``: NocoDB Frontend.
|
||||
|
||||
@@ -6,8 +6,6 @@ hide_table_of_contents: true
|
||||
|
||||
We use ``Lerna`` to manage multi-packages. We have the following [packages](https://github.com/nocodb/nocodb/tree/master/packages).
|
||||
|
||||
- ``packages/nc-cli`` : A CLI to create NocoDB app.
|
||||
|
||||
- ``packages/nocodb-sdk``: API client sdk of nocodb.
|
||||
|
||||
- ``packages/nc-gui``: NocoDB Frontend.
|
||||
|
||||
@@ -49,7 +49,6 @@
|
||||
],
|
||||
"ignorePaths": [
|
||||
"**/node_modules/**",
|
||||
"**/nc-cli/**",
|
||||
"**/nc-lib-gui/**",
|
||||
"**/nocodb-legacy/**",
|
||||
"**/test/**",
|
||||
|
||||
Reference in New Issue
Block a user