add dependency on custom resource cdk - javascript

I have the following problem that i cannot add dependsOn on a cfnResource for a CustomResource
const cfnRawTable = new timestream.CfnTable(this, 'MyCfnTableRaw', {
databaseName: dbName,
// the properties below are optional
magneticStoreWriteProperties: {
enableMagneticStoreWrites: true,
},
retentionProperties: {
magneticStoreRetentionPeriodInDays: '1825',
memoryStoreRetentionPeriodInHours: '8640',
},
tableName: rawtable,
})
let insertionLambda = new cdk.CustomResource(this, 'insertionlambda', {
serviceToken:
'arn:aws:lambda:' +
cdk.Fn.ref('region') +
'738234497474:function:timestreaminsertion-' +
cdk.Fn.ref('env'),
})
cfnRawTable.addDependsOn(insertionLambda)
I get the error Argument of type 'CustomResource' is not assignable to parameter of type 'CfnResource'

I think you have todo it the other way around:
insertionLambda.addDependsOn(cfnRawTable);

 Use CDK's Construct dependencies instead:
cfnRawTable.node.addDependency(insertionLambda);
addDependsOn is a low-level CloudFormation feature that is only available in L1 CloudFormation resources. The high-level .node.addDependency is available with all Constructs.
In this case, though, it does seem from the naming that your insertion lambda depends on the table, not the other way around, like #Martin Muller pointed out. You can still use the above, just swap them around. This guess an totally be incorrect, of course, maybe your lambda is not inserting into this particular table.

If you make any reference to the resource from another, it will automatically add the dependency.
As an example, adding the cfnRawTable.attrArn to the properties argument for CustomResource will cause the dependency relationship to be created.
cdk.CustomResource(
...,
{
properties: {'tablearn': cfnRawTable.attrArn}
},
)
Alternatively, you can declare a dependency without needing to make any reference using .node.addDependency
insertionLambda.node.addDependency(CfnRawTable)

Related

NestJs ParseEnumPipe can't be resolve

I am using the NestJs framework (love it by the way) and I want to check the incoming data so it conforms with an Enum in Typscript. So I have the following:
enum ProductAction {
PURCHASE = 'PURCHASE',
}
#Patch('products/:uuid')
async patchProducts(
#Param('uuid', ParseUUIDPipe) uuid: string,
#Body('action', ParseEnumPipe) action: ProductAction,
) {
switch(action) {
... code
}
The weird thing is that when I run this code, the first pipe gets compiled
2022-07-21 16:53:51 [error] [ExceptionHandler] Nest can't resolve dependencies of the ParseEnumPipe (?, Object). Please make sure that the argument Object at index [0] is available in the FriendsModule context.
What I am doing wrong?
You should use #Body('action', new ParseEnumPipe(ProductAction)) action: ProductAction because enums aren't directly reflected for Nest to read the metadata of, and because Nest is otherwise trying to figure out how to inject Object when it really should be injecting the enum.

Angular ComponentFactory.resolveComponentFactory(Component) Param as String [duplicate]

What I'm trying to do:
Use something similar to the "resolveComponentFactory()", but with a 'string' identifier to get Component Factories.
Once obtained, start leverage the "createComponent(Factory)" method.
Plnkr Example -> enter link description here
In the example, you will see the AddItem method
addItem(componentName:string):void{
let compFactory: ComponentFactory;
switch(componentName){
case "image":
compFactory = this.compFactoryResolver.resolveComponentFactory(PictureBoxWidget);
break;
case "text":
compFactory = this.compFactoryResolver.resolveComponentFactory(TextBoxWidget);
break;
}
//How can I resolve a component based on string
//so I don't need to hard cost list of possible options
this.container.createComponent(compFactory);
}
The "compFactoryResolver:ComponentFactoryResolver" is injected in the contructor.
As you will note, having to hard code every permutation in a switch statement is less than ideal.
when logging the ComponentFactoryResolver to the console, I've observed that it contains a Map with the various factories.
CodegenComponentFactoryResolver {_parent: AppModuleInjector, _factories: Map}
However, this map is a private and can't be easily accessed (from what I can tell).
Is there a better solution then somehow rolling my own class to get access to this factory list?
I've seen a lot of messages about people trying to create dynamic components. However, these are often about creating components at run time. the components in question here are already pre-defined, I am stuck trying to access factories using a string as a key.
Any suggestions or advice are much appreciated.
Thank you kindly.
It's either defining a map of available components,
const compMap = {
text: PictureBoxWidget,
image: TextBoxWidget
};
Or defining identifiers as static class property that will be used to generate a map,
const compMap = [PictureBoxWidget, TextBoxWidget]
.map(widget => [widget.id, widget])
.reduce((widgets, [id, widget]) => Object.assign(widgets, { [id]: widget }), {});
The map is then used like
let compFactory: ComponentFactory;
if (componentName in compMap) {
compFactory = this.compFactoryResolver.resolveComponentFactory(compMap[componentName]);
} else {
throw new Error(`Unknown ${componentName} component`);
}
There's no way how component classes can be magically identified as strings, because they aren't resolved to strings in Angular 2 DI (something that was changed since Angular 1, where all DI units were annotated as strings).

Mediate and share data between different modules

I am just trying to get my head around event driven JS, so please bear with me. There are different kinds of modules within my app. Some just encapsulate data, others manage a part of the DOM. Some modules depend on others, sometimes one module depends on the state of multiple other modules, but I don't want them to communicate directly or pass one module to the other just for easy access.
I tried to create the simplest scenario possible to illustrate my problem (the actual modules are much more complex of course):
I have a dataModule that just exposes some data:
var dataModule = { data: 3 };
There is a configModule that exposes modifiers for displaying that data:
var configModule = { factor: 2 };
Finally there is a displayModule that combines and renders the data from the two other modules:
var displayModule = {
display: function(data, factor) {
console.log(data * factor);
}
};
I also have a simple implementation of pub-sub, so I could just mediate between the modules like this:
pubsub.subscribe("init", function() {
displayModule.display(dataModule.data, configModule.factor);
});
pubsub.publish("init"); // output: 6
However this way I seem to end up with a mediator that has to know all of the module-instances explicitly - is there even a way to avoid that? Also I don't know how this would work if there are multiple instances of these modules. What is the best way to avoid global instance-variables? I guess my question is what would be the most flexible way to manage something like that? Am I on the right track, or is this completely wrong? Sorry for not being very precise with my question, I just need someone to push me in the right direction.
You are on the right track, I'll try to give you that extra push you're talking about:
It you want loose coupling, pub-sub is a good way to go.
But, you don't really need that "mediator", each module should ideally be autonomous and encapsulate its own logic.
This is done in the following way: each module depends on the pubsub service, subscribe to all relevant events and act upon them. Each module also publishes events which might be relevant to others (code samples in a minute, bear with me).
I think the bit you might be missing here is that modules, which use events, will hardly never be just plain models. They will have some logic in them and can also hold a model (which they update when receiving events).
So instead of a dataModule you are more likely to have a dataLoaderModule which will publish the data model (e.g. {data: 3}), once he finishes loading.
Another great requirement you set is sharing data while avoiding global instance-variables - this is a very important concept and also a step in the right direction. What you miss in your solution for this is - Dependency Injection or at least a module system which allows defining dependencies.
You see, having an event driven application doesn't necessarily mean that every piece of the code should communicate using events. An application configuration model or a utility service is definitely something I would inject (when using DI, like in Angular), require (when using AMD/CommonJS) or import (when using ES6 modules).
(i.e. rather then communicating with a utility using events).
In your example it's unclear whether configModule is a static app configuration or some knob I can tweak from the UI. If it's a static app config - I would inject it.
Now, let's see some examples:
Assuming the following:
Instead of a dataModule we have a dataLoaderModule
configModule is a static configuration model.
We are using AMD modules (and not ES6 modules, which I prefer), since I see you stuck to using only ES5 features (I see no classes or consts).
We would have:
data-loader.js (aka dataLoaderModule)
define(['pubsub'], function (pubsub) {
// ... load data using some logic...
// and publish it
pubsub.publish('data-loaded', {data: 3});
});
configuration.js (aka configModule)
define([], function () {
return {factor: 2};
});
display.js (aka displayModule)
define(['configuration', 'pubsub'], function (configuration, pubsub) {
var displayModule = {
display: function (data, factor) {
console.log(data * factor);
}
};
pubsub.subscribe('data-loaded', function (data) {
displayModule.display(data, configuration.factor);
});
});
That's it.
You will notice that we have no global variables here (not even pubsub), instead we are requiring (or injecting) our dependencies.
Here you might be asking: "and what if I meant for my config to change from the UI?", so let's see that too:
In this case, I rather rename configModule to settingsDisplayModule (following your naming convention).
Also, in a more realistic app, UI modules will usually hold a model, so let's do that too.
And lets also call them "views" instead of "displayModules", and we will have:
data-loader.js (aka dataLoaderModule)
define(['pubsub'], function (pubsub) {
// ... load data using some logic...
// and publish it
pubsub.publish('data-loaded', {data: 3});
});
settings-view.js (aka settingsDisplayModule, aka config)
define(['pubsub'], function (pubsub) {
var settingsModel = {factor: 2};
var settingsView = {
display: function () {
console.log(settingsModel);
// and when settings (aka config) changes due to user interaction,
// we publish the new settings ...
pubsub.publish('setting-changed', settingsModel);
}
};
});
data-view.js (aka displayModule)
define(['pubsub'], function (pubsub) {
var model = {
data: null,
factor: 0
};
var view = {
display: function () {
if (model.data && model.factor) {
console.log(model.data * model.factor);
} else {
// whatever you do/show when you don't have data
}
}
};
pubsub.subscribe('data-loaded', function (data) {
model.data = data;
view.display();
});
pubsub.subscribe('setting-changed', function (settings) {
model.factor = settings.factor;
view.display();
});
});
And that's it.
Hope it helps :)
If not - comment!
You do not need a mediator. Just import data, config, and display and call display(data, config) where you need to.
// import data
// import config
function render(){
display(data, config)
}

How can requirejs provide a new "class" instance for each define with properties based on the filename?

Use case is implementing a mediator pattern where each instance is a postal.js channel.
Explaining it with the actual code would require some postal.js knowledge, so my example below is conceptually similar, but only uses requirejs.
// animalSounds.js
define([],function(){
return {
cat:'meow',
dog:'woof'
};
});
// animalFactory.js ... the requirejs plugin
define(['animalSounds'],function(animalSounds){
function animalClass(name){
this.sound = animalSounds[name];
}
return {
load:function(name, req, onload, config){
onload(new animalClass(name));
}
}
});
// cat.js
define(['animalFactory'],function(animalInstance){
animalInstance.sound === 'meow'; // should be true
});
// dog.js
define(['animalFactory'],function(animalInstance){
animalInstance.sound === 'woof'; // should be true
});
Basically it's a factory that returns a new instance whenever it's required. That part I can create fine. What I'm struggling with is getting dynamic properties from other sources based on what module is requiring it. While I could define the key as a string in each file, I'm hoping to use the filename as a key to stay DRY.
I would just minimally break the DRY principle and have cat, for instance, like this:
define(['animalFactory!cat'],function(animalInstance){
animalInstance.sound === 'meow'; // should be true
});
The fact of the matter is while it would be possible to do what you want using a loader, the resulting code would be complicated, and would obscure the logic of your application. For instance, requiring animalFactory multiple times and expecting different results (which is what you have in your question) goes against one of the fundamental principles of RequireJS: requiring the same module name over and over again should return the same value over and over again.
Note that it is possible to require the module module (it is a special module) and then use module.id to know the name of the module you are in but unfortunately, this is not available for building the dependency list on your define.

How to see all available variables in handlebars template

I'm working on my first Ember.js app and am having some trouble connecting all the dots. It would be really helpful if I could just see all the variables available within a given handlebars template.
There is a related question, but you have to know the variable that is in scope to use it:
How do I add console.log() JavaScript logic inside of a Handlebars template?
How can I output all the variables?
a good option is to debug the value of 'this' in a template using the Handlebars helpers:
1.
{{#each}}
{{log this}}
{{/each}}
or,
2. similar to #watson suggested
{{#each}}
{{debugger}}
{{/each}}
and then drill in to the Local Scope Variables for 'this' in the Dev Tools
or alternatively, 3. you could log things directly from inside your Controller init method, such as:
App.UsersController = Ember.ArrayController.extend({
init: function() {
console.log(this);
console.log(this.getProperties('.'));
}
});
Make sure you try out Firebug - you'll get a different perspective on things, which I found helpful. But don't abandon chrome completely; you will need the Ember Inspector at some point.
I'm using the same debugging helper everyone recommends, and this is how Chrome displays it:
When I expand the same object in firebug, I get the following info, including the variables I was looking for (sources[]) and some other useful properties I hadn't seen in Chrome.
I created Barhandles a few years ago. It will use the Handlebars parser to produce the AST, and then extract variable references from it. The extractSchema method will — well — extract a schema. That schema is not based on JSON Schema or Joi or anything. It's a homegrown format that captures most of the things you could possibly extract from Handlebars template.
So, this barhandlers.extractSchema('{{foo.bar}}') produces:
{
"foo": {
"_type": "object",
"_optional": false,
"bar": {
"_type": "any",
"_optional": false
}
}
}
It will take into account that an {{#if expr}} will automatically make nested references optional. It correctly handles scope changes based on {{#with expr}} constructs, and it allows you to add support for your own custom directives as well.
http://nxt.flotsam.nl/barhandles
https://medium.com/east-pole/advanced-barhandles-4a7e64c1bc0d
We used it to do validation on the data structures that we passed into the template, and it was working pretty well for that purpose.
If you really need to dump the variables in your template, you can explore the template AST and output the content of the relevant nodes (see the compiler sources). This is not an easy task because you have to find your way through trials and errors, and the code is quite low-level and there are not so many comments.
It seems Handlerbars doesn't have a shortcut for what you're asking, so the steps would be:
precompile a template (see the command line source, I think the function is called handlebars.precompile())
explore the AST
You can do this by leveraging Handlebars.parseWithoutProcessing which takes the input template string. If you use TypeScript, that returns a specific type hbs.AST.Program. You can filter for only the moustache statements, and then iterate through these statements to get the variable names.
This method also supports Handlebars helpers, so you can get the key for that, but because of this, this function is a bit more complex as you'd need to check different properties on the moustache statement:
/**
* Getting the variables from the Handlebars template.
* Supports helpers too.
* #param input
*/
const getHandlebarsVariables = (input = '') => {
const ast = Handlebars.parseWithoutProcessing(input);
return ast.body
.filter(({ type }) => type === 'MustacheStatement')
.map((statement) => statement.params[0]?.original || statement.path?.original);
};
Here's the TypeScript version, which is a bit involved due to the conditional properties, but can help explain the types a bit more:
/**
* Getting the variables from the Handlebars template.
* Supports helpers too.
* #param input
*/
const getHandlebarsVariables = (input: string): string[] => {
const ast: hbs.AST.Program = Handlebars.parseWithoutProcessing(input);
return ast.body.filter(({ type }: hbs.AST.Statement) => (
type === 'MustacheStatement'
))
.map((statement: hbs.AST.Statement) => {
const moustacheStatement: hbs.AST.MustacheStatement = statement as hbs.AST.MustacheStatement;
const paramsExpressionList = moustacheStatement.params as hbs.AST.PathExpression[];
const pathExpression = moustacheStatement.path as hbs.AST.PathExpression;
return paramsExpressionList[0]?.original || pathExpression.original;
});
};
I've made a Codepen that illustrates this. Essentially, given the following template:
Hello, {{first_name}}! The lottery prize is {{formatCurrency prize_amount}}! Good luck!
It will use window.prompt to ask the user for their name and the prize amount. The example also implements a helper formatCurrency. You can see it here: https://codepen.io/tinacious/pen/GRqYWJE
The sample Ember app you mention defines its EmberObjects right in its app.js. So basically, what's available on the objects are the properties that are defined onto them there. (e.g. subreddit has a title, etc).
If you want a globally available way to dump an object's property schema out to the console, one approach would be to create a "debug" helper that walks the members of the passed-in contexts and writes them out. Something like:
Handlebars.registerHelper('debug', function (emberObject) {
if (emberObject && emberObject.contexts) {
var out = '';
for (var context in emberObject.contexts) {
for (var prop in context) {
out += prop + ": " + context[prop] + "\n"
}
}
if (console && console.log) {
console.log("Debug\n----------------\n" + out);
}
}
});
Then call it on whatever you want to inspect:
<div>Some markup</div>{{debug}}<div>Blah</div>
This will use whatever EmberObject is in scope, so pop it inside of an {{#each}} if you want to inspect the list elements, as opposed to the object with that list.
The variables available within a template are only constrained by the model you are using to render the template.
You should set a breakpoint in your app where you render the template and see what is in your model at that point, which will should you what you have available to put in your template.

Categories