New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TypeScript helpers suggestion. #114
Comments
Cool! @nickmessing how would one use your |
@marshallswain, I could finalize the typings and make a PR to make them universal so people can use them with bot class-component definition and classic component definition if you want to support that. |
I know absolutely nothing about TypeScript, but I know that a lot of people
will appreciate this. I might even learn something, here, so I’d like to
support it, yeah. :) please make a PR when you have time. That would be
terrific!
…On Sun, Apr 22, 2018 at 3:25 AM Nick Messing ***@***.***> wrote:
@marshallswain <https://github.com/marshallswain>, I could finalize the
typings and make a PR to make them universal so people can use them with
bot class-component definition
<https://gist.github.com/nickmessing/f206056cb0eb8879b068f727a1aaecbb>
and classic component definition
<https://gist.github.com/nickmessing/dfc8264ecc17d68ed5aaa82bd253d4e5> if
you want to support that.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#114 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAH3WTT3-Bo75lv1FXsC0p0WseLN8_0xks5trEx5gaJpZM4TcmIA>
.
|
@rayfoss is your |
@marshallswain Features should have a good reason to exist because they take time to add and maintain. My vote is just a reflection of this feature being 99% unlikely to be of use to me. I'm waiting for native types to come to Node. Fun fact, I used to use Typescript in Angular 2. I think TS support is good for the project, as long as it doesn't get in the way for everybody else with a ton of irrelevant files and dependencies everywhere. Forcing it is definitely a bad idea, as there are many many hold outs and designers using js or flow. Remember coffeescript? |
@rayfoss Thanks for the update. I have similar sentiment. If @nickmessing's suggestions work without requiring modifying the repo, that's the perfect solution, in my opinion. I've added a link to this issue in the docs. I'm closing this issue, now. Thanks, guys. |
I have some typings for feathers-vuex too, I'm planning on putting together a PR at some point, but for now here they are. Updated 7/30/19 import { Application, Query, Params } from "@feathersjs/feathers";
import { StoreOptions, Plugin, Commit, Dispatch, Store } from "vuex";
import Vue, { PluginObject, ComponentOptions } from "vue";
import { Request } from "request";
import { PropsDefinition } from "vue/types/options";
/**
* default export
*/
declare const FeathersVuexDefault: (client: Application, options: Partial<FeathersVuexOptions>) => FeathersVuexResult;
export default FeathersVuexDefault;
interface FeathersVuexResult {
service<ModelType = any, IDType = string>(servicePath: string, options?: Partial<FeathersVuexOptions>): Plugin<FeathersVuexServiceState<ModelType, IDType>>;
auth<UserType>(options?: FeathersVuexAuthOptions): Plugin<FeathersVuexAuthState<UserType>>;
FeathersVuex: PluginObject<any>;
}
interface FeathersVuexCoreProps {
/**
* @default 'id'
*/
idField: string;
/**
* @default false
*/
autoRemove: boolean;
/**
* @default true
*/
enableEvents: boolean;
/**
* @default false
*/
addOnUpsert: boolean;
/**
* @default false
*/
diffOnPatch: boolean;
/**
* @default false
*/
skipRequestIfExists: boolean;
/**
* @default false
*/
preferUpdate: boolean;
/**
* @default false
*/
replaceItems: boolean;
}
interface FeathersVuexStoreOptions<Store> extends Pick<StoreOptions<Store>, 'state' | 'getters' | 'mutations' | 'actions'> { }
interface FeathersVuexOptions<Store = any> extends FeathersVuexStoreOptions<Store>, FeathersVuexCoreProps {
/**
* @default 'path'
*/
nameStyle?: 'short' | 'path';
namespace: string;
apiPrefix: string
modelName: string;
instanceDefaults?: any;
/**
* @debug false
*/
debug: boolean;
}
/**
* Service Model
*/
// This is an interface because it needs to return FeathersVuexModelClass & T
// from the constructor, which isn't allowed with classes
interface FeathersVuexModelClass<ModelType = any> {
namespace: string;
className: string;
modelName: string;
store: Store<any>; // todo: Type the VuexStore so we can include it here
options: FeathersVuexOptions;
new(data?: Partial<ModelType>, options?: FeathersVuexModelOptions): FeathersVuexModel<ModelType>;
create: (params?: GetParams) => Promise<FeathersVuexModel<ModelType>>;
save: (params?: GetParams) => Promise<FeathersVuexModel<ModelType>>;
patch: (params?: GetParams) => Promise<FeathersVuexModel<ModelType>>;
update: (params?: GetParams) => Promise<FeathersVuexModel<ModelType>>;
clone: () => Promise<FeathersVuexModel<ModelType>>;
reset: () => Promise<FeathersVuexModel<ModelType>>;
remove: (params?: GetParams) => Promise<FeathersVuexModel<ModelType>>;
}
export type FeathersVuexModel<T> = FeathersVuexModelClass<T> & T;
type GetParams = Exclude<Params, 'paginate'>;
type FindParams = Params;
interface FeathersVuexModelOptions {
isClone?: boolean;
skipCommit?: boolean;
}
interface ModelStatic<T> {
new(data?: Partial<T>, options?: FeathersVuexModelOptions): FeathersVuexModel<T>;
find: (params?: FindParams) => FeathersVuexModel<T>[];
findInStore: (params?: FindParams) => FeathersVuexModel<T>[];
get: (id: any, params?: GetParams) => FeathersVuexModel<T>[];
getFromStore: (id: any, params?: GetParams) => FeathersVuexModel<T>[];
}
/**
* Vue Plugin
*/
type FeathersVuexGlobalModelsIndex<T> = {
[P in keyof T]: {
new(data?: Partial<T[P]>, options?: FeathersVuexModelOptions): FeathersVuexModel<T[P]>;
find: (params?: FindParams) => FeathersVuexModel<T[P]>[];
findInStore: (params?: FindParams) => FeathersVuexModel<T[P]>[];
get: (id: any, params?: GetParams) => FeathersVuexModel<T[P]>[];
getFromStore: (id: any, params?: GetParams) => FeathersVuexModel<T[P]>[];
}
}
// This doesn't work because merging this into a string signature isn't a valid type
// Leaving it here so that hopefully someone can figure it out in the future
// type FeathersVuexGlobalModelsByPath<T> = {
// byServicePath: FeathersVuexGlobalModelsIndex<T>
// }
/**
* @description The type for the $FeathersVuex vue plugin. To type this stronger include the
* following in a typings.d.ts file
*
*
* @example
* declare module "vue/types/vue" {
* import { FeathersVuexGlobalModels } from "feathers-vuex";
* interface Vue {
* $FeathersVuex: FeathersVuexGlobalModels<Services>;
* }
* }
*
* @description Where services is something like this
* @example
* interface Services {
* users: User
* //...
* }
*
* interface User {
* name: string;
* rating: number;
* //...
* }
*
*/
export type FeathersVuexGlobalModels<T = any, P = any> = FeathersVuexGlobalModelsIndex<T> // & FeathersVuexGlobalModelsByPath<P>; // See comment above
/**
* Add FeathersVuex to the Vue prototype
*/
declare module "vue/types/vue" {
interface FeathersVuexPluginType extends FeathersVuexGlobalModels { }
interface Vue {
$FeathersVuex: FeathersVuexPluginType;
}
}
/**
* Auth module factory
*/
interface FeathersVuexAuthOptions<State = FeathersVuexAuthState> extends FeathersVuexStoreOptions<State> {
userService: string
}
interface FeathersVuexAuthState<UserType = any> {
accessToken?: string, // The JWT
payload: Object, // The JWT payload
isAuthenticatePending: boolean,
isLogoutPending: boolean,
errorOnAuthenticate: Error | undefined,
errorOnLogout: Error | undefined,
user: UserType
}
interface FeathersVuexServiceState<ModelType = any, IDType = string> extends FeathersVuexCoreProps {
ids: IDType[],
keyedById: {
[i: string]: ModelType
}, // A hash map, keyed by id of each item
currentId?: IDType, // The id of the item marked as current
copy?: ModelType, // A deep copy of the current item
servicePath: string // The full service path
paginate: boolean, // Indicates if pagination is enabled on the Feathers service.
pagination: { [key: string]: ModelType[] }, // Indicates if pagination is enabled on the Feathers service.
isFindPending: boolean,
isGetPending: boolean,
isCreatePending: boolean,
isUpdatePending: boolean,
isPatchPending: boolean,
isRemovePending: boolean,
errorOnfind: Error | undefined,
errorOnGet: Error | undefined,
errorOnCreate: Error | undefined,
errorOnUpdate: Error | undefined,
errorOnPatch: Error | undefined,
errorOnRemove: Error | undefined
}
/**
* Data Components
*/
// todo: use generic FeathersVuex*Computed
export const FeathersVuexFind: ComponentOptions<
Vue,
FeathersVuexFindData,
FeathersVuexFindMethods,
FeathersVuexFindComputed,
PropsDefinition<FeathersVuexFindProps>,
FeathersVuexFindProps>;
export const FeathersVuexGet: ComponentOptions<
Vue,
FeathersVuexGetData,
FeathersVuexGetMethods,
FeathersVuexGetComputed,
PropsDefinition<FeathersVuexGetProps>,
FeathersVuexGetProps>;
interface FeathersVuexFindData {
isFindPending: boolean;
}
interface FeathersVuexGetMethods {
findData(): Promise<void>;
fetchData(): Promise<void>;
}
interface FeathersVuexFindComputed<T = any> {
items: T[];
scope: { [key: string]: any }
pagination: { [key: string]: any }
}
interface FeathersVuexDataComponentProps {
service: string;
query?: any;
queryWhen?: boolean | ((id: string, ...args: any[]) => boolean);
fetchQuery: any;
watch?: string | string[];
local?: boolean;
editScope?: (params: FeathersVuexEditScopeArgs) => { [key: string]: any };
}
interface FeathersVuexEditScopeArgs {
item: any;
isGetPending: boolean
}
interface FeathersVuexFindProps extends FeathersVuexDataComponentProps {
qid?: string;
}
interface FeathersVuexGetData {
isFindPending: boolean;
isGetPending: boolean;
}
interface FeathersVuexFindMethods {
getArgs(queryToUse?: Query): any[];
getData(): Promise<void>;
fetchData(): Promise<void>;
}
interface FeathersVuexGetComputed<T = any> {
item: T | null;
scope: { [key: string]: any }
}
interface FeathersVuexGetProps extends FeathersVuexDataComponentProps {
id?: number | string;
}
/**
* Utilities
*/
// todo: these mixins could probably have much better return types to make use of the generic
export function makeFindMixin<T = any>(options: MakeFindMixinOptions<T>): (ComponentOptions<Vue> | typeof Vue);
export function makeGetMixin<T = any>(options: MakeGetMixinOptions<T>): (ComponentOptions<Vue> | typeof Vue);
interface DataComponentOptions {
/**
* Service name, either service or name are required
*
* note: it looks like this can also be a function, but I don't quite understand the effects
* so I'm not documenting it right now
*/
service: string;
/**
* Service name, either service or name are required
*/
name?: string;
params?: Params;
/**
* @default () => true
*/
queryWhen?: boolean | ((params: Params) => boolean);
/**
* @default false
*/
local?: boolean;
qid?: string | number | symbol;
debug?: boolean;
watch: string | boolean | string[];
}
interface MakeFindMixinOptions<T = any> extends DataComponentOptions {
fetchQuery?: Query;
items?: T[];
}
interface MakeGetMixinOptions<T = any> extends DataComponentOptions {
fetchParams?: Params;
id?: any;
item?: T;
}
/**
* Init Auth
*/
interface InitAuthOptions {
commit: Commit;
dispatch: Dispatch;
req: Request;
cookieName: string;
moduleName: string;
feathersClient: Application;
}
export function initAuth(options: InitAuthOptions): Promise<object>;
|
@NickBolles I just removed my client side project that used TypeScript, just to regenerate it as a JavaScript project. Steps I tried to add typings to feathers-vuex:
Finally, I did what I said in the beginning and removed TypeScript just so I can follow along with a tutorial using this library. |
@bartduisters There are probably other ways to achieve this without built in typings (which I believe are coming in v2), but here's how I have it setup I have a folder import { Services } from "../store";
import { FeathersVuexGlobalModels } from "feathers-vuex";
declare module "vue/types/vue" {
interface FeathersVuexPluginType extends FeathersVuexGlobalModels<Services> { }
} This will extend the Vue prototype typings with This file is picked up by typescript by declaring it in the "typeRoots" in the tsconfig.json. {
"compilerOptions": {
"typeRoots": [
"./node_modules/@types/",
"./client/@types/"
],
}
} where import { User } from "../../server/services/v1/users/users.interface";
export interface Services {
users: User;
} |
Thanks for the clarification. Will try it as soon as I try another project with TypeScript and feathers-vuex! |
Hello,
I have used
feathers-vuex
with TypeScript in a project and I made a set of helpers that I think could be really useful to other developers, here you can see the source code and below is an example of usage:TypeScript reads it really well and all suggestions and autocomplete helps a lot.
The text was updated successfully, but these errors were encountered: